|
1 /* |
|
2 |
|
3 Copyright (C) 2000,2001,2004 Silicon Graphics, Inc. All Rights Reserved. |
|
4 Portions Copyright 2002 Sun Microsystems, Inc. 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 Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, |
|
27 Mountain View, CA 94043, or: |
|
28 |
|
29 http://www.sgi.com |
|
30 |
|
31 For further information regarding this notice, see: |
|
32 |
|
33 http://oss.sgi.com/projects/GenInfo/NoticeExplan |
|
34 |
|
35 */ |
|
36 |
|
37 |
|
38 |
|
39 #include "config.h" |
|
40 #include "libdwarfdefs.h" |
|
41 #include <stdio.h> |
|
42 #include <string.h> |
|
43 #ifdef HAVE_ELFACCESS_H |
|
44 #include <elfaccess.h> |
|
45 #else |
|
46 /* Set r_info as defined by ELF generic ABI */ |
|
47 #define Set_REL32_info(r,s,t) ((r).r_info = ELF32_R_INFO(s,t)) |
|
48 #define Set_REL64_info(r,s,t) ((r).r_info = ELF64_R_INFO(s,t)) |
|
49 #endif |
|
50 #include "pro_incl.h" |
|
51 #include "pro_section.h" |
|
52 #include "pro_reloc.h" |
|
53 #include "pro_reloc_stream.h" |
|
54 |
|
55 /* |
|
56 Return DW_DLV_ERROR on malloc error or reltarget_length error. |
|
57 Return DW_DLV_OK otherwise |
|
58 |
|
59 |
|
60 |
|
61 */ |
|
62 /*ARGSUSED*/ int |
|
63 _dwarf_pro_reloc_name_stream64(Dwarf_P_Debug dbg, |
|
64 int base_sec_index, |
|
65 Dwarf_Unsigned offset, /* r_offset of reloc */ |
|
66 Dwarf_Unsigned symidx, |
|
67 enum Dwarf_Rel_Type type, |
|
68 int reltarget_length) |
|
69 { |
|
70 #if HAVE_ELF64_GETEHDR |
|
71 REL64 *elf64_reloc; |
|
72 void *relrec_to_fill; |
|
73 int res; |
|
74 int rel_type; |
|
75 |
|
76 res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index, |
|
77 &relrec_to_fill); |
|
78 if (res != DW_DLV_OK) |
|
79 return res; |
|
80 |
|
81 |
|
82 if (type == dwarf_drt_data_reloc) { |
|
83 if (reltarget_length == dbg->de_offset_size) { |
|
84 rel_type = dbg->de_offset_reloc; |
|
85 } else if (reltarget_length == dbg->de_pointer_size) { |
|
86 rel_type = dbg->de_ptr_reloc; |
|
87 } else { |
|
88 return DW_DLV_ERROR; |
|
89 } |
|
90 } else if (type == dwarf_drt_segment_rel) { |
|
91 rel_type = dbg->de_exc_reloc; |
|
92 } else { |
|
93 /* We are in trouble: improper use of stream relocations. |
|
94 Someone else will diagnose */ |
|
95 rel_type = 0; |
|
96 } |
|
97 |
|
98 elf64_reloc = (REL64 *)relrec_to_fill; |
|
99 elf64_reloc->r_offset = offset; |
|
100 Set_REL64_info(*elf64_reloc, symidx, rel_type); |
|
101 return DW_DLV_OK; |
|
102 #else /* !HAVE_ELF64_GETEHDR */ |
|
103 return DW_DLV_ERROR; |
|
104 #endif /* #if HAVE_ELF64_GETEHDR */ |
|
105 } |
|
106 |
|
107 /* |
|
108 Return DW_DLV_ERROR on malloc error or reltarget_length error. |
|
109 Return DW_DLV_OK otherwise |
|
110 a binary reloc: 32bit ABI |
|
111 */ |
|
112 int |
|
113 _dwarf_pro_reloc_name_stream32(Dwarf_P_Debug dbg, int base_sec_index, Dwarf_Unsigned offset, /* r_offset |
|
114 of |
|
115 reloc |
|
116 */ |
|
117 Dwarf_Unsigned symidx, |
|
118 enum Dwarf_Rel_Type type, |
|
119 int reltarget_length) |
|
120 { |
|
121 REL32 *elf32_reloc; |
|
122 void *relrec_to_fill; |
|
123 int res; |
|
124 int rel_type; |
|
125 |
|
126 res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index, |
|
127 &relrec_to_fill); |
|
128 if (res != DW_DLV_OK) |
|
129 return res; |
|
130 if (type == dwarf_drt_data_reloc) { |
|
131 if (reltarget_length == dbg->de_offset_size) { |
|
132 rel_type = dbg->de_offset_reloc; |
|
133 } else if (reltarget_length == dbg->de_pointer_size) { |
|
134 rel_type = dbg->de_ptr_reloc; |
|
135 } else { |
|
136 return DW_DLV_ERROR; |
|
137 } |
|
138 } else if (type == dwarf_drt_segment_rel) { |
|
139 rel_type = dbg->de_exc_reloc; |
|
140 } else { |
|
141 /* We are in trouble: improper use of stream relocations. |
|
142 Someone else will diagnose */ |
|
143 rel_type = 0; |
|
144 } |
|
145 |
|
146 elf32_reloc = (REL32*)relrec_to_fill; |
|
147 elf32_reloc->r_offset = (Elf32_Addr) offset; |
|
148 Set_REL32_info(*elf32_reloc, (Dwarf_Word) symidx, rel_type); |
|
149 return DW_DLV_OK; |
|
150 |
|
151 /* get a slot, fill in the slot entry */ |
|
152 } |
|
153 |
|
154 |
|
155 |
|
156 /* |
|
157 Return DW_DLV_OK. |
|
158 Never can really do anything: lengths cannot |
|
159 be represented as end-start in a stream. |
|
160 |
|
161 */ |
|
162 /*ARGSUSED*/ int |
|
163 _dwarf_pro_reloc_length_stream(Dwarf_P_Debug dbg, int base_sec_index, Dwarf_Unsigned offset, /* r_offset |
|
164 of |
|
165 reloc |
|
166 */ |
|
167 Dwarf_Unsigned start_symidx, |
|
168 Dwarf_Unsigned end_symidx, |
|
169 enum Dwarf_Rel_Type type, |
|
170 int reltarget_length) |
|
171 { |
|
172 /* get a slot, fill in the slot entry */ |
|
173 return DW_DLV_OK; |
|
174 } |
|
175 |
|
176 |
|
177 /* |
|
178 Ensure each stream is a single buffer and |
|
179 add that single buffer to the set of stream buffers. |
|
180 |
|
181 By creating a new buffer and copying if necessary. |
|
182 |
|
183 Free the input set of buffers if we consolidate. |
|
184 Return -1 on error (malloc failure) |
|
185 |
|
186 |
|
187 Return DW_DLV_OK on success. Any other return indicates |
|
188 malloc failed. |
|
189 |
|
190 */ |
|
191 int |
|
192 _dwarf_stream_relocs_to_disk(Dwarf_P_Debug dbg, |
|
193 Dwarf_Signed * new_sec_count) |
|
194 { |
|
195 unsigned long total_size = 0; |
|
196 Dwarf_Small *data; |
|
197 int sec_index; |
|
198 unsigned long i; |
|
199 Dwarf_Error err; |
|
200 Dwarf_Error *error = &err; |
|
201 |
|
202 Dwarf_Signed sec_count = 0; |
|
203 |
|
204 Dwarf_P_Per_Reloc_Sect p_reloc = &dbg->de_reloc_sect[0]; |
|
205 |
|
206 for (i = 0; i < NUM_DEBUG_SECTIONS; ++i, ++p_reloc) { |
|
207 unsigned long ct = p_reloc->pr_reloc_total_count; |
|
208 unsigned len; |
|
209 struct Dwarf_P_Relocation_Block_s *p_blk; |
|
210 struct Dwarf_P_Relocation_Block_s *p_blk_last; |
|
211 Dwarf_P_Per_Reloc_Sect prb; |
|
212 |
|
213 if (ct == 0) { |
|
214 continue; |
|
215 } |
|
216 prb = &dbg->de_reloc_sect[i]; |
|
217 len = dbg->de_relocation_record_size; |
|
218 ++sec_count; |
|
219 |
|
220 total_size = ct * len; |
|
221 sec_index = prb->pr_sect_num_of_reloc_sect; |
|
222 if (sec_index == 0) { |
|
223 /* call de_func or de_func_b, getting section number of |
|
224 reloc sec */ |
|
225 int rel_section_index; |
|
226 Dwarf_Unsigned name_idx; |
|
227 int int_name; |
|
228 int err; |
|
229 |
|
230 if (dbg->de_func_b) { |
|
231 rel_section_index = |
|
232 dbg->de_func_b(_dwarf_rel_section_names[i], |
|
233 /* size */ |
|
234 dbg->de_relocation_record_size, |
|
235 /* type */ SHT_REL, |
|
236 /* flags */ 0, |
|
237 /* link to symtab, which we cannot |
|
238 know */ 0, |
|
239 /* info == link to sec rels apply to |
|
240 */ |
|
241 dbg->de_elf_sects[i], |
|
242 &name_idx, &err); |
|
243 } else { |
|
244 rel_section_index = |
|
245 dbg->de_func(_dwarf_rel_section_names[i], |
|
246 /* size */ |
|
247 dbg->de_relocation_record_size, |
|
248 /* type */ SHT_REL, |
|
249 /* flags */ 0, |
|
250 /* link to symtab, which we cannot |
|
251 know */ 0, |
|
252 /* info == link to sec rels apply to */ |
|
253 dbg->de_elf_sects[i], &int_name, &err); |
|
254 name_idx = int_name; |
|
255 } |
|
256 if (rel_section_index == -1) { |
|
257 { |
|
258 _dwarf_p_error(dbg, error, DW_DLE_ELF_SECT_ERR); |
|
259 return (DW_DLV_ERROR); |
|
260 } |
|
261 |
|
262 } |
|
263 prb->pr_sect_num_of_reloc_sect = rel_section_index; |
|
264 sec_index = rel_section_index; |
|
265 } |
|
266 GET_CHUNK(dbg, sec_index, data, total_size, &err); |
|
267 p_blk = p_reloc->pr_first_block; |
|
268 |
|
269 /* following loop executes at least once. Effects the |
|
270 consolidation to a single block or, if already a single |
|
271 block, simply copies to the output buffer. And frees the |
|
272 input block. The new block is in the de_debug_sects list. */ |
|
273 while (p_blk) { |
|
274 |
|
275 unsigned long len = |
|
276 p_blk->rb_where_to_add_next - p_blk->rb_data; |
|
277 |
|
278 memcpy(data, p_blk->rb_data, len); |
|
279 |
|
280 |
|
281 data += len; |
|
282 |
|
283 p_blk_last = p_blk; |
|
284 p_blk = p_blk->rb_next; |
|
285 |
|
286 _dwarf_p_dealloc(dbg, (Dwarf_Small *) p_blk_last); |
|
287 } |
|
288 /* ASSERT: sum of len copied == total_size */ |
|
289 |
|
290 /* |
|
291 We have copied the input, now drop the pointers to it. For |
|
292 debugging, leave the other data untouched. */ |
|
293 p_reloc->pr_first_block = 0; |
|
294 p_reloc->pr_last_block = 0; |
|
295 } |
|
296 |
|
297 *new_sec_count = sec_count; |
|
298 return DW_DLV_OK; |
|
299 } |