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