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