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