xref: /illumos-gate/usr/src/lib/libdwarf/common/pro_reloc.c (revision 4d9fdb46b215739778ebc12079842c9905586999)
1bc1f688bSRobert Mustacchi /*
2bc1f688bSRobert Mustacchi   Copyright (C) 2000,2004 Silicon Graphics, Inc.  All Rights Reserved.
3*4d9fdb46SRobert Mustacchi   Portions Copyright 2008-2016 David Anderson, Inc. All rights reserved.
4bc1f688bSRobert Mustacchi 
5bc1f688bSRobert Mustacchi   This program is free software; you can redistribute it and/or modify it
6bc1f688bSRobert Mustacchi   under the terms of version 2.1 of the GNU Lesser General Public License
7bc1f688bSRobert Mustacchi   as published by the Free Software Foundation.
8bc1f688bSRobert Mustacchi 
9bc1f688bSRobert Mustacchi   This program is distributed in the hope that it would be useful, but
10bc1f688bSRobert Mustacchi   WITHOUT ANY WARRANTY; without even the implied warranty of
11bc1f688bSRobert Mustacchi   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12bc1f688bSRobert Mustacchi 
13bc1f688bSRobert Mustacchi   Further, this software is distributed without any warranty that it is
14bc1f688bSRobert Mustacchi   free of the rightful claim of any third person regarding infringement
15bc1f688bSRobert Mustacchi   or the like.  Any license provided herein, whether implied or
16bc1f688bSRobert Mustacchi   otherwise, applies only to this software file.  Patent licenses, if
17bc1f688bSRobert Mustacchi   any, provided herein do not apply to combinations of this program with
18bc1f688bSRobert Mustacchi   other software, or any other product whatsoever.
19bc1f688bSRobert Mustacchi 
20bc1f688bSRobert Mustacchi   You should have received a copy of the GNU Lesser General Public
21bc1f688bSRobert Mustacchi   License along with this program; if not, write the Free Software
22bc1f688bSRobert Mustacchi   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
23bc1f688bSRobert Mustacchi   USA.
24bc1f688bSRobert Mustacchi 
25bc1f688bSRobert Mustacchi */
26bc1f688bSRobert Mustacchi 
27bc1f688bSRobert Mustacchi #include "config.h"
28bc1f688bSRobert Mustacchi #include "libdwarfdefs.h"
29bc1f688bSRobert Mustacchi #include <stdio.h>
30*4d9fdb46SRobert Mustacchi #ifdef HAVE_STRING_H
31bc1f688bSRobert Mustacchi #include <string.h>
32*4d9fdb46SRobert Mustacchi #endif /* HAVE_STRING_H */
33*4d9fdb46SRobert Mustacchi #ifdef HAVE_STDDEF_H
34*4d9fdb46SRobert Mustacchi #include <stddef.h>
35*4d9fdb46SRobert Mustacchi #endif /* HAVE_STDDEF_H */
36bc1f688bSRobert Mustacchi #include "pro_incl.h"
37*4d9fdb46SRobert Mustacchi #include "dwarf.h"
38*4d9fdb46SRobert Mustacchi #include "libdwarf.h"
39*4d9fdb46SRobert Mustacchi #include "pro_opaque.h"
40*4d9fdb46SRobert Mustacchi #include "pro_error.h"
41*4d9fdb46SRobert Mustacchi #include "pro_alloc.h"
42*4d9fdb46SRobert Mustacchi #include "pro_reloc.h"
43bc1f688bSRobert Mustacchi 
44bc1f688bSRobert Mustacchi 
45bc1f688bSRobert Mustacchi /*  Do initial alloc of newslots slots.
46bc1f688bSRobert Mustacchi     Fails only if malloc fails.
47bc1f688bSRobert Mustacchi 
48bc1f688bSRobert Mustacchi     Supposed to be called before any relocs allocated.
49bc1f688bSRobert Mustacchi     Ignored if after any allocated.
50bc1f688bSRobert Mustacchi 
51bc1f688bSRobert Mustacchi     Part of an optimization, so that for a known 'newslots'
52bc1f688bSRobert Mustacchi     relocations count we can preallocate the right size block.
53bc1f688bSRobert Mustacchi     Called from just 2 places.
54bc1f688bSRobert Mustacchi 
55*4d9fdb46SRobert Mustacchi     We use 'slots' so we don't have to do a new
56*4d9fdb46SRobert Mustacchi     allocation for every relocation, just a new
57*4d9fdb46SRobert Mustacchi     allocation every n slots. slots_in_block.
58*4d9fdb46SRobert Mustacchi 
59bc1f688bSRobert Mustacchi     returns DW_DLV_OK or  DW_DLV_ERROR
60bc1f688bSRobert Mustacchi */
61bc1f688bSRobert Mustacchi int
_dwarf_pro_pre_alloc_specific_reloc_slots(Dwarf_P_Debug dbg,Dwarf_P_Per_Reloc_Sect prel,Dwarf_Unsigned newslots)62*4d9fdb46SRobert Mustacchi _dwarf_pro_pre_alloc_specific_reloc_slots(Dwarf_P_Debug dbg,
63*4d9fdb46SRobert Mustacchi     Dwarf_P_Per_Reloc_Sect prel,
64bc1f688bSRobert Mustacchi     Dwarf_Unsigned newslots)
65bc1f688bSRobert Mustacchi {
66bc1f688bSRobert Mustacchi     unsigned long len = 0;
67bc1f688bSRobert Mustacchi     struct Dwarf_P_Relocation_Block_s *data = 0;
68bc1f688bSRobert Mustacchi     unsigned long slots_in_blk = (unsigned long) newslots;
69bc1f688bSRobert Mustacchi     unsigned long rel_rec_size = dbg->de_relocation_record_size;
70bc1f688bSRobert Mustacchi 
71*4d9fdb46SRobert Mustacchi     if (prel->pr_first_block) {
72bc1f688bSRobert Mustacchi         return DW_DLV_OK;       /* do nothing */
73*4d9fdb46SRobert Mustacchi     }
74bc1f688bSRobert Mustacchi 
75bc1f688bSRobert Mustacchi     len = sizeof(struct Dwarf_P_Relocation_Block_s) +
76bc1f688bSRobert Mustacchi         slots_in_blk * rel_rec_size;
77bc1f688bSRobert Mustacchi     data = (struct Dwarf_P_Relocation_Block_s *)
78bc1f688bSRobert Mustacchi         _dwarf_p_get_alloc(dbg, len);
79bc1f688bSRobert Mustacchi     if (!data) {
80bc1f688bSRobert Mustacchi         return DW_DLV_ERROR;
81bc1f688bSRobert Mustacchi     }
82bc1f688bSRobert Mustacchi     data->rb_slots_in_block = slots_in_blk;     /* could use default
83*4d9fdb46SRobert Mustacchi         here, as fallback in case our origininal
84*4d9fdb46SRobert Mustacchi         estimate wrong. When we call this we
85*4d9fdb46SRobert Mustacchi         presumably know what we are doing, so
86*4d9fdb46SRobert Mustacchi         keep this count for now */
87bc1f688bSRobert Mustacchi     data->rb_next_slot_to_use = 0;
88bc1f688bSRobert Mustacchi     data->rb_where_to_add_next =
89bc1f688bSRobert Mustacchi         ((char *) data) + sizeof(struct Dwarf_P_Relocation_Block_s);
90bc1f688bSRobert Mustacchi     data->rb_data = data->rb_where_to_add_next;
91bc1f688bSRobert Mustacchi 
92bc1f688bSRobert Mustacchi     prel->pr_first_block = data;
93bc1f688bSRobert Mustacchi     prel->pr_last_block = data;
94bc1f688bSRobert Mustacchi     prel->pr_block_count = 1;
95bc1f688bSRobert Mustacchi     return DW_DLV_OK;
96bc1f688bSRobert Mustacchi }
97bc1f688bSRobert Mustacchi 
98bc1f688bSRobert Mustacchi 
99bc1f688bSRobert Mustacchi /*Do alloc of slots.
100bc1f688bSRobert Mustacchi   Fails only if malloc fails.
101bc1f688bSRobert Mustacchi 
102bc1f688bSRobert Mustacchi   Only allocator used.
103bc1f688bSRobert Mustacchi 
104bc1f688bSRobert Mustacchi   returns DW_DLV_OK or  DW_DLV_ERROR
105bc1f688bSRobert Mustacchi */
106bc1f688bSRobert Mustacchi int
_dwarf_pro_alloc_reloc_slots(Dwarf_P_Debug dbg,int rel_sec_index)107bc1f688bSRobert Mustacchi _dwarf_pro_alloc_reloc_slots(Dwarf_P_Debug dbg, int rel_sec_index)
108bc1f688bSRobert Mustacchi {
109bc1f688bSRobert Mustacchi     unsigned long len = 0;
110bc1f688bSRobert Mustacchi     struct Dwarf_P_Relocation_Block_s *data = 0;
111bc1f688bSRobert Mustacchi     Dwarf_P_Per_Reloc_Sect prel = &dbg->de_reloc_sect[rel_sec_index];
112bc1f688bSRobert Mustacchi     unsigned long slots_in_blk = prel->pr_slots_per_block_to_alloc;
113bc1f688bSRobert Mustacchi     unsigned long rel_rec_size = dbg->de_relocation_record_size;
114bc1f688bSRobert Mustacchi 
115bc1f688bSRobert Mustacchi     len = sizeof(struct Dwarf_P_Relocation_Block_s) +
116bc1f688bSRobert Mustacchi         slots_in_blk * rel_rec_size;
117bc1f688bSRobert Mustacchi 
118bc1f688bSRobert Mustacchi     data = (struct Dwarf_P_Relocation_Block_s *)
119bc1f688bSRobert Mustacchi         _dwarf_p_get_alloc(dbg, len);
120bc1f688bSRobert Mustacchi     if (!data) {
121bc1f688bSRobert Mustacchi         return DW_DLV_ERROR;
122bc1f688bSRobert Mustacchi     }
123bc1f688bSRobert Mustacchi 
124bc1f688bSRobert Mustacchi     if (prel->pr_first_block) {
125bc1f688bSRobert Mustacchi         prel->pr_last_block->rb_next = data;
126bc1f688bSRobert Mustacchi         prel->pr_last_block = data;
127bc1f688bSRobert Mustacchi         prel->pr_block_count += 1;
128bc1f688bSRobert Mustacchi     } else {
129bc1f688bSRobert Mustacchi         prel->pr_first_block = data;
130bc1f688bSRobert Mustacchi         prel->pr_last_block = data;
131bc1f688bSRobert Mustacchi         prel->pr_block_count = 1;
132bc1f688bSRobert Mustacchi     }
133bc1f688bSRobert Mustacchi     data->rb_slots_in_block = slots_in_blk;
134bc1f688bSRobert Mustacchi     data->rb_next_slot_to_use = 0;
135bc1f688bSRobert Mustacchi     data->rb_where_to_add_next =
136bc1f688bSRobert Mustacchi         ((char *) data) + sizeof(struct Dwarf_P_Relocation_Block_s);
137bc1f688bSRobert Mustacchi     data->rb_data = data->rb_where_to_add_next;
138bc1f688bSRobert Mustacchi     return DW_DLV_OK;
139bc1f688bSRobert Mustacchi 
140bc1f688bSRobert Mustacchi }
141bc1f688bSRobert Mustacchi 
142*4d9fdb46SRobert Mustacchi /*  Reserve a slot. return DW_DLV_OK if succeeds.
143bc1f688bSRobert Mustacchi 
144bc1f688bSRobert Mustacchi     Return DW_DLV_ERROR if fails (malloc error).
145bc1f688bSRobert Mustacchi 
146bc1f688bSRobert Mustacchi     Use the relrec_to_fill to pass back a pointer to
147*4d9fdb46SRobert Mustacchi     a slot space to use.  */
148bc1f688bSRobert Mustacchi int
_dwarf_pro_reloc_get_a_slot(Dwarf_P_Debug dbg,int base_sec_index,void ** relrec_to_fill)149bc1f688bSRobert Mustacchi _dwarf_pro_reloc_get_a_slot(Dwarf_P_Debug dbg,
150bc1f688bSRobert Mustacchi     int base_sec_index, void **relrec_to_fill)
151bc1f688bSRobert Mustacchi {
152bc1f688bSRobert Mustacchi     struct Dwarf_P_Relocation_Block_s *data = 0;
153bc1f688bSRobert Mustacchi     Dwarf_P_Per_Reloc_Sect prel = &dbg->de_reloc_sect[base_sec_index];
154bc1f688bSRobert Mustacchi     unsigned long rel_rec_size = dbg->de_relocation_record_size;
155bc1f688bSRobert Mustacchi 
156bc1f688bSRobert Mustacchi     char *ret_addr = 0;
157bc1f688bSRobert Mustacchi 
158bc1f688bSRobert Mustacchi     data = prel->pr_last_block;
159bc1f688bSRobert Mustacchi     if ((data == 0) ||
160bc1f688bSRobert Mustacchi         (data->rb_next_slot_to_use >= data->rb_slots_in_block)) {
161bc1f688bSRobert Mustacchi         int res;
162bc1f688bSRobert Mustacchi 
163bc1f688bSRobert Mustacchi         res = _dwarf_pro_alloc_reloc_slots(dbg, base_sec_index);
164bc1f688bSRobert Mustacchi         if (res != DW_DLV_OK) {
165bc1f688bSRobert Mustacchi             return res;
166bc1f688bSRobert Mustacchi         }
167bc1f688bSRobert Mustacchi     }
168bc1f688bSRobert Mustacchi 
169bc1f688bSRobert Mustacchi     data = prel->pr_last_block;
170bc1f688bSRobert Mustacchi     /* now we have an empty slot */
171bc1f688bSRobert Mustacchi     ret_addr = data->rb_where_to_add_next;
172bc1f688bSRobert Mustacchi     data->rb_where_to_add_next += rel_rec_size;
173bc1f688bSRobert Mustacchi     data->rb_next_slot_to_use += 1;
174bc1f688bSRobert Mustacchi     prel->pr_reloc_total_count += 1;
175bc1f688bSRobert Mustacchi     *relrec_to_fill = (void *) ret_addr;
176bc1f688bSRobert Mustacchi     return DW_DLV_OK;
177bc1f688bSRobert Mustacchi 
178bc1f688bSRobert Mustacchi }
179bc1f688bSRobert Mustacchi 
180bc1f688bSRobert Mustacchi /*
181bc1f688bSRobert Mustacchi     On success  returns count of
182bc1f688bSRobert Mustacchi     .rel.* sections that are symbolic
183bc1f688bSRobert Mustacchi     thru count_of_relocation_sections.
184bc1f688bSRobert Mustacchi 
185bc1f688bSRobert Mustacchi     On success, returns DW_DLV_OK.
186bc1f688bSRobert Mustacchi 
187bc1f688bSRobert Mustacchi     If this is not a 'symbolic' run, returns
188bc1f688bSRobert Mustacchi     DW_DLV_NO_ENTRY.
189bc1f688bSRobert Mustacchi 
190bc1f688bSRobert Mustacchi     No errors are possible.
191bc1f688bSRobert Mustacchi */
192*4d9fdb46SRobert Mustacchi /*ARGSUSED*/
193*4d9fdb46SRobert Mustacchi int
dwarf_get_relocation_info_count(Dwarf_P_Debug dbg,Dwarf_Unsigned * count_of_relocation_sections,int * drd_buffer_version,UNUSEDARG Dwarf_Error * error)194bc1f688bSRobert Mustacchi dwarf_get_relocation_info_count(Dwarf_P_Debug dbg,
195bc1f688bSRobert Mustacchi     Dwarf_Unsigned *
196bc1f688bSRobert Mustacchi     count_of_relocation_sections,
197bc1f688bSRobert Mustacchi     int *drd_buffer_version,
198*4d9fdb46SRobert Mustacchi     UNUSEDARG Dwarf_Error * error)
199bc1f688bSRobert Mustacchi {
200bc1f688bSRobert Mustacchi     if (dbg->de_flags & DW_DLC_SYMBOLIC_RELOCATIONS) {
201*4d9fdb46SRobert Mustacchi         int i = 0;
202bc1f688bSRobert Mustacchi         unsigned int count = 0;
203bc1f688bSRobert Mustacchi 
204bc1f688bSRobert Mustacchi         for (i = 0; i < NUM_DEBUG_SECTIONS; ++i) {
205bc1f688bSRobert Mustacchi             if (dbg->de_reloc_sect[i].pr_reloc_total_count > 0) {
206bc1f688bSRobert Mustacchi                 ++count;
207bc1f688bSRobert Mustacchi             }
208bc1f688bSRobert Mustacchi         }
209bc1f688bSRobert Mustacchi         *count_of_relocation_sections = (Dwarf_Unsigned) count;
210bc1f688bSRobert Mustacchi         *drd_buffer_version = DWARF_DRD_BUFFER_VERSION;
211bc1f688bSRobert Mustacchi         return DW_DLV_OK;
212bc1f688bSRobert Mustacchi     }
213*4d9fdb46SRobert Mustacchi     /*  Reset to start at beginning of reloc groups. */
214*4d9fdb46SRobert Mustacchi     dbg->de_reloc_next_to_return = 0;
215bc1f688bSRobert Mustacchi     return DW_DLV_NO_ENTRY;
216bc1f688bSRobert Mustacchi }
217bc1f688bSRobert Mustacchi 
218bc1f688bSRobert Mustacchi int
dwarf_get_relocation_info(Dwarf_P_Debug dbg,Dwarf_Signed * elf_section_index,Dwarf_Signed * elf_section_index_link,Dwarf_Unsigned * relocation_buffer_count,Dwarf_Relocation_Data * reldata_buffer,Dwarf_Error * error)219bc1f688bSRobert Mustacchi dwarf_get_relocation_info(Dwarf_P_Debug dbg,
220bc1f688bSRobert Mustacchi     Dwarf_Signed * elf_section_index,
221bc1f688bSRobert Mustacchi     Dwarf_Signed * elf_section_index_link,
222bc1f688bSRobert Mustacchi     Dwarf_Unsigned * relocation_buffer_count,
223bc1f688bSRobert Mustacchi     Dwarf_Relocation_Data * reldata_buffer,
224bc1f688bSRobert Mustacchi     Dwarf_Error * error)
225bc1f688bSRobert Mustacchi {
226bc1f688bSRobert Mustacchi     int next = dbg->de_reloc_next_to_return;
227bc1f688bSRobert Mustacchi 
228bc1f688bSRobert Mustacchi     if (dbg->de_flags & DW_DLC_SYMBOLIC_RELOCATIONS) {
229*4d9fdb46SRobert Mustacchi         int i = 0;
230bc1f688bSRobert Mustacchi 
231bc1f688bSRobert Mustacchi         for (i = next; i < NUM_DEBUG_SECTIONS; ++i) {
232*4d9fdb46SRobert Mustacchi             /*  de_reloc_sect[] and de_elf_sects[] are
233*4d9fdb46SRobert Mustacchi                 in direct parallel. */
234bc1f688bSRobert Mustacchi             Dwarf_P_Per_Reloc_Sect prel = &dbg->de_reloc_sect[i];
235*4d9fdb46SRobert Mustacchi             int elf_sect_num =  dbg->de_elf_sects[i];
236bc1f688bSRobert Mustacchi 
237bc1f688bSRobert Mustacchi             if (prel->pr_reloc_total_count > 0) {
238*4d9fdb46SRobert Mustacchi                 /*  Set up 'next' for subsequent call to
239*4d9fdb46SRobert Mustacchi                     dwarf_get_relocation_info(). */
240bc1f688bSRobert Mustacchi                 dbg->de_reloc_next_to_return = i + 1;
241bc1f688bSRobert Mustacchi 
242*4d9fdb46SRobert Mustacchi                 /* ASSERT: prel->pr_block_count == 1 */
243bc1f688bSRobert Mustacchi                 *elf_section_index = prel->pr_sect_num_of_reloc_sect;
244*4d9fdb46SRobert Mustacchi 
245*4d9fdb46SRobert Mustacchi                 /*  Elf sec num in generated elf */
246*4d9fdb46SRobert Mustacchi                 *elf_section_index_link = elf_sect_num;
247*4d9fdb46SRobert Mustacchi 
248bc1f688bSRobert Mustacchi                 *relocation_buffer_count = prel->pr_reloc_total_count;
249bc1f688bSRobert Mustacchi                 *reldata_buffer = (Dwarf_Relocation_Data)
250bc1f688bSRobert Mustacchi                     (prel->pr_first_block->rb_data);
251bc1f688bSRobert Mustacchi                 return DW_DLV_OK;
252bc1f688bSRobert Mustacchi             }
253bc1f688bSRobert Mustacchi         }
254bc1f688bSRobert Mustacchi         DWARF_P_DBG_ERROR(dbg, DW_DLE_REL_ALLOC, DW_DLV_ERROR);
255bc1f688bSRobert Mustacchi     }
256bc1f688bSRobert Mustacchi     return DW_DLV_NO_ENTRY;
257bc1f688bSRobert Mustacchi }
258