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