1 /*
2
3 Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
4 Portions Copyright 2016 David Anderson. All Rights Reserved.
5
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of version 2.1 of the GNU Lesser General Public License
8 as published by the Free Software Foundation.
9
10 This program is distributed in the hope that it would be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
14 Further, this software is distributed without any warranty that it is
15 free of the rightful claim of any third person regarding infringement
16 or the like. Any license provided herein, whether implied or
17 otherwise, applies only to this software file. Patent licenses, if
18 any, provided herein do not apply to combinations of this program with
19 other software, or any other product whatsoever.
20
21 You should have received a copy of the GNU Lesser General Public
22 License along with this program; if not, write the Free Software
23 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
24 USA.
25
26 */
27
28 #include "config.h"
29 #include "libdwarfdefs.h"
30 #include <stdio.h>
31 #ifdef HAVE_STRING_H
32 #include <string.h>
33 #endif /* HAVE_STRING_H */
34 #ifdef HAVE_STDDEF_H
35 #include <stddef.h>
36 #endif /* HAVE_STDDEF_H */
37 /*#include <elfaccess.h> */
38 #include "pro_incl.h"
39 #include "dwarf.h"
40 #include "libdwarf.h"
41 #include "pro_opaque.h"
42 #include "pro_error.h"
43 #include "pro_alloc.h"
44 #include "pro_section.h"
45 #include "pro_reloc.h"
46 #include "pro_reloc_symbolic.h"
47
48 #ifndef SHT_REL
49 #define SHT_REL 9
50 #endif /* SHT_REL */
51 #ifndef SHN_UNDEF
52 #define SHN_UNDEF 0
53 #endif /* SHN_UNDEF */
54
55 /* Return DW_DLV_ERROR on malloc error.
56 Return DW_DLV_OK otherwise */
57
58 int
_dwarf_pro_reloc_name_symbolic(Dwarf_P_Debug dbg,int base_sec_index,Dwarf_Unsigned offset,Dwarf_Unsigned symidx,enum Dwarf_Rel_Type type,int reltarget_length)59 _dwarf_pro_reloc_name_symbolic(Dwarf_P_Debug dbg,
60 int base_sec_index,
61 Dwarf_Unsigned offset, /* r_offset of reloc */
62 Dwarf_Unsigned symidx,
63 enum Dwarf_Rel_Type type,
64 int reltarget_length)
65 {
66 /* get a slot, fill in the slot entry */
67 void *relrec_to_fill = 0;
68 int res = 0;
69 struct Dwarf_Relocation_Data_s *slotp;
70
71 res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index,
72 &relrec_to_fill);
73 if (res != DW_DLV_OK)
74 return res;
75 slotp = (struct Dwarf_Relocation_Data_s *) relrec_to_fill;
76 slotp->drd_type = type;
77 slotp->drd_length = reltarget_length;
78 slotp->drd_offset = offset;
79 slotp->drd_symbol_index = symidx;
80 return DW_DLV_OK;
81 }
82
83
84
85 /* Return DW_DLV_ERROR on malloc error.
86 Return DW_DLV_OK otherwise */
87 int
_dwarf_pro_reloc_length_symbolic(Dwarf_P_Debug dbg,int base_sec_index,Dwarf_Unsigned offset,Dwarf_Unsigned start_symidx,Dwarf_Unsigned end_symidx,enum Dwarf_Rel_Type type,int reltarget_length)88 _dwarf_pro_reloc_length_symbolic(Dwarf_P_Debug dbg,
89 int base_sec_index,
90 Dwarf_Unsigned offset, /* r_offset of reloc */
91 Dwarf_Unsigned start_symidx,
92 Dwarf_Unsigned end_symidx,
93 enum Dwarf_Rel_Type type,
94 int reltarget_length)
95 {
96 /* get a slot, fill in the slot entry */
97 void *relrec_to_fill = 0;
98 int res = 0;
99 struct Dwarf_Relocation_Data_s *slotp1 = 0;
100 struct Dwarf_Relocation_Data_s *slotp2 = 0;
101
102 res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index,
103 &relrec_to_fill);
104 if (res != DW_DLV_OK)
105 return res;
106 slotp1 = (struct Dwarf_Relocation_Data_s *) relrec_to_fill;
107 res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index,
108 &relrec_to_fill);
109 if (res != DW_DLV_OK)
110 return res;
111 slotp2 = (struct Dwarf_Relocation_Data_s *) relrec_to_fill;
112
113 /* ASSERT: type == dwarf_drt_first_of_length_type_pair */
114 slotp1->drd_type = type;
115 slotp1->drd_length = reltarget_length;
116 slotp1->drd_offset = offset;
117 slotp1->drd_symbol_index = start_symidx;
118
119 slotp2->drd_type = dwarf_drt_second_of_length_pair;
120 slotp2->drd_length = reltarget_length;
121 slotp2->drd_offset = offset;
122 slotp2->drd_symbol_index = end_symidx;
123 return DW_DLV_OK;
124 }
125
126 /* Ensure each stream is a single buffer and
127 add that single buffer to the set of stream buffers.
128
129 By creating a new buffer and copying if necessary.
130 (If > 1 block, reduce to 1 block)
131
132 Free the input set of buffers if we consolidate.
133
134 We pass back *new_sec_count as zero because we
135 are not creating normal sections for a .o, but
136 symbolic relocations, separately counted.
137
138 Return -1 on error (malloc failure)
139
140 Return DW_DLV_OK on success. Any other return indicates
141 malloc failed. */
142 int
_dwarf_symbolic_relocs_to_disk(Dwarf_P_Debug dbg,Dwarf_Signed * new_sec_count)143 _dwarf_symbolic_relocs_to_disk(Dwarf_P_Debug dbg,
144 Dwarf_Signed * new_sec_count)
145 {
146 int i = 0;
147 Dwarf_Error error = 0;
148
149 for (i = 0; i < NUM_DEBUG_SECTIONS; ++i) {
150 int sec_index = 0;
151 Dwarf_P_Per_Reloc_Sect p_reloc = dbg->de_reloc_sect + i;
152 unsigned long ct = p_reloc->pr_reloc_total_count;
153 int err = 0;
154 if (ct == 0) {
155 /* No relocations in here. Nothing to do. */
156 continue;
157 }
158
159 /* total_size = ct *len; */
160 sec_index = p_reloc->pr_sect_num_of_reloc_sect;
161 if (sec_index == 0) {
162 /* sec_index zero means we have not processed this
163 section of relocations yet. */
164 /* Call de_callback_func
165 getting section number of reloc section. */
166 int rel_section_index = 0;
167 Dwarf_Unsigned name_idx = 0;
168
169 /* This is a bit of a fake, as we do not really have true
170 elf sections at all. Just the data such might contain.
171 But this lets the caller eventually link things
172 together: without this call we would not know what rel
173 data goes with what section when we are asked for the
174 real arrays. */
175
176 if (dbg->de_callback_func) {
177 /* For symbolic relocations de_callback_func
178 may well return 0. */
179 rel_section_index =
180 dbg->de_callback_func(_dwarf_rel_section_names[i],
181 dbg->de_relocation_record_size,
182 /* type */ SHT_REL,
183 /* flags */ 0,
184 /* link to symtab, which we cannot
185 know */ SHN_UNDEF,
186 /* sec rels apply to */
187 dbg->de_elf_sects[i],
188 &name_idx,
189 dbg->de_user_data,&err);
190 }
191 if (rel_section_index == -1) {
192 {
193 _dwarf_p_error(dbg, &error, DW_DLE_ELF_SECT_ERR);
194 return (DW_DLV_ERROR);
195 }
196 }
197 p_reloc->pr_sect_num_of_reloc_sect = rel_section_index;
198 }
199
200
201 /* If pr_block_count 0 or 1 then the blocks are
202 an array (with 0 or 1 entries) so we'll just
203 return to the for loop. No more work to do here. */
204 if (p_reloc->pr_block_count < 2) {
205 continue;
206 }
207 {
208 /* Since more than one relocation on the section
209 we now convert the list of relocation blocks
210 into a proper array of blocks. */
211 struct Dwarf_P_Relocation_Block_s *new_blk = 0;
212 struct Dwarf_P_Relocation_Block_s *p_blk = 0;
213 Dwarf_Small *data = 0;
214 int res = 0;
215
216 p_blk = p_reloc->pr_first_block;
217 /* Do not zero pr_sect_num_of_reloc_sect */
218 p_reloc->pr_reloc_total_count = 0;
219 p_reloc->pr_first_block = 0;
220 p_reloc->pr_last_block = 0;
221 p_reloc->pr_block_count = 0;
222 /* Now we know a number making a single
223 array. Replaces DEFAULT_SLOTS_PER_BLOCK */
224 p_reloc->pr_slots_per_block_to_alloc = ct;
225
226 /* Creating new single block for all 'ct' entries.
227 Assigns a pointer value to pr_first_block
228 (which means our p_reloc).
229 It updates p_reloc->pr_first_block */
230 res = _dwarf_pro_pre_alloc_specific_reloc_slots(dbg,
231 p_reloc,ct);
232 if (res != DW_DLV_OK) {
233 return res;
234 }
235
236 new_blk = p_reloc->pr_first_block;
237 data = (Dwarf_Small *) new_blk->rb_data;
238
239 /* The following loop does the consolidation to a single
240 block and frees the input block(s).
241 p_blk points to the old singly-linked-list
242 and is the
243 only access to that list.
244 data is a pointer to the new array of ct entries
245 which is our target(destination) of the copies.
246 */
247 do {
248 struct Dwarf_P_Relocation_Block_s *p_blk_last = 0;
249 /* len identifies the data in all the slots
250 in use in this block. */
251 unsigned long len =
252 p_blk->rb_where_to_add_next - p_blk->rb_data;
253 memcpy(data, p_blk->rb_data, len);
254 data += len;
255 p_blk_last = p_blk;
256 p_blk = p_blk->rb_next;
257 _dwarf_p_dealloc(dbg, (Dwarf_Small *) p_blk_last);
258 } while (p_blk);
259 /* ASSERT: the dangling p_blk list all dealloc'd
260 which is really a no-op, all deallocations
261 take place at producer_finish(). */
262 /* ASSERT: sum of len copied == total_size */
263 new_blk->rb_next_slot_to_use = ct;
264 new_blk->rb_where_to_add_next = (char *) data;
265 p_reloc->pr_reloc_total_count = ct;
266
267 /* Have now created a single block, but no
268 change in slots used (pr_reloc_total_count) */
269 }
270 }
271 /* There is no section data with symbolic,
272 so there is no count. */
273 *new_sec_count = 0;
274 return DW_DLV_OK;
275 }
276