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