xref: /titanic_51/usr/src/lib/libdwarf/common/dwarf_elf_access.c (revision 7fd791373689a6af05e27efec3b1ab556e02aa23)
1*7fd79137SRobert Mustacchi /*
2*7fd79137SRobert Mustacchi   Copyright (C) 2000-2005 Silicon Graphics, Inc.  All Rights Reserved.
3*7fd79137SRobert Mustacchi   Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
4*7fd79137SRobert Mustacchi   Portions Copyright 2008-2010 Arxan Technologies, Inc. All Rights Reserved.
5*7fd79137SRobert Mustacchi   Portions Copyright 2009-2010 David Anderson. All rights reserved.
6*7fd79137SRobert Mustacchi   Portions Copyright 2009-2010 Novell Inc. All rights reserved.
7*7fd79137SRobert Mustacchi 
8*7fd79137SRobert Mustacchi   This program is free software; you can redistribute it and/or modify it
9*7fd79137SRobert Mustacchi   under the terms of version 2.1 of the GNU Lesser General Public License
10*7fd79137SRobert Mustacchi   as published by the Free Software Foundation.
11*7fd79137SRobert Mustacchi 
12*7fd79137SRobert Mustacchi   This program is distributed in the hope that it would be useful, but
13*7fd79137SRobert Mustacchi   WITHOUT ANY WARRANTY; without even the implied warranty of
14*7fd79137SRobert Mustacchi   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15*7fd79137SRobert Mustacchi 
16*7fd79137SRobert Mustacchi   Further, this software is distributed without any warranty that it is
17*7fd79137SRobert Mustacchi   free of the rightful claim of any third person regarding infringement
18*7fd79137SRobert Mustacchi   or the like.  Any license provided herein, whether implied or
19*7fd79137SRobert Mustacchi   otherwise, applies only to this software file.  Patent licenses, if
20*7fd79137SRobert Mustacchi   any, provided herein do not apply to combinations of this program with
21*7fd79137SRobert Mustacchi   other software, or any other product whatsoever.
22*7fd79137SRobert Mustacchi 
23*7fd79137SRobert Mustacchi   You should have received a copy of the GNU Lesser General Public
24*7fd79137SRobert Mustacchi   License along with this program; if not, write the Free Software
25*7fd79137SRobert Mustacchi   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
26*7fd79137SRobert Mustacchi   USA.
27*7fd79137SRobert Mustacchi 
28*7fd79137SRobert Mustacchi   Contact information:  Silicon Graphics, Inc., 1500 Crittenden Lane,
29*7fd79137SRobert Mustacchi   Mountain View, CA 94043, or:
30*7fd79137SRobert Mustacchi 
31*7fd79137SRobert Mustacchi   http://www.sgi.com
32*7fd79137SRobert Mustacchi 
33*7fd79137SRobert Mustacchi   For further information regarding this notice, see:
34*7fd79137SRobert Mustacchi 
35*7fd79137SRobert Mustacchi   http://oss.sgi.com/projects/GenInfo/NoticeExplan
36*7fd79137SRobert Mustacchi 
37*7fd79137SRobert Mustacchi */
38*7fd79137SRobert Mustacchi 
39*7fd79137SRobert Mustacchi #include "config.h"
40*7fd79137SRobert Mustacchi #include "dwarf_incl.h"
41*7fd79137SRobert Mustacchi #include "dwarf_elf_access.h"
42*7fd79137SRobert Mustacchi 
43*7fd79137SRobert Mustacchi #ifdef HAVE_ELF_H
44*7fd79137SRobert Mustacchi #include <elf.h>
45*7fd79137SRobert Mustacchi #endif
46*7fd79137SRobert Mustacchi #ifdef HAVE_LIBELF_H
47*7fd79137SRobert Mustacchi #include <libelf.h>
48*7fd79137SRobert Mustacchi #else
49*7fd79137SRobert Mustacchi #ifdef HAVE_LIBELF_LIBELF_H
50*7fd79137SRobert Mustacchi #include <libelf/libelf.h>
51*7fd79137SRobert Mustacchi #endif
52*7fd79137SRobert Mustacchi #endif
53*7fd79137SRobert Mustacchi 
54*7fd79137SRobert Mustacchi #include <stdio.h>
55*7fd79137SRobert Mustacchi #include <sys/stat.h>
56*7fd79137SRobert Mustacchi #include <sys/types.h>
57*7fd79137SRobert Mustacchi #include <string.h>
58*7fd79137SRobert Mustacchi #include <stdlib.h>
59*7fd79137SRobert Mustacchi 
60*7fd79137SRobert Mustacchi #define FALSE 0
61*7fd79137SRobert Mustacchi #define TRUE  1
62*7fd79137SRobert Mustacchi 
63*7fd79137SRobert Mustacchi #ifndef EM_MIPS
64*7fd79137SRobert Mustacchi /* This is the standard elf value EM_MIPS. */
65*7fd79137SRobert Mustacchi #define EM_MIPS 8
66*7fd79137SRobert Mustacchi #endif
67*7fd79137SRobert Mustacchi 
68*7fd79137SRobert Mustacchi 
69*7fd79137SRobert Mustacchi #ifdef HAVE_ELF64_GETEHDR
70*7fd79137SRobert Mustacchi extern Elf64_Ehdr *elf64_getehdr(Elf *);
71*7fd79137SRobert Mustacchi #endif
72*7fd79137SRobert Mustacchi #ifdef HAVE_ELF64_GETSHDR
73*7fd79137SRobert Mustacchi extern Elf64_Shdr *elf64_getshdr(Elf_Scn *);
74*7fd79137SRobert Mustacchi #endif
75*7fd79137SRobert Mustacchi #ifdef WORDS_BIGENDIAN
76*7fd79137SRobert Mustacchi #define WRITE_UNALIGNED(dbg,dest,source, srclength,len_out) \
77*7fd79137SRobert Mustacchi     { \
78*7fd79137SRobert Mustacchi       dbg->de_copy_word(dest, \
79*7fd79137SRobert Mustacchi                         ((char *)source) +srclength-len_out,  \
80*7fd79137SRobert Mustacchi                         len_out) ; \
81*7fd79137SRobert Mustacchi     }
82*7fd79137SRobert Mustacchi 
83*7fd79137SRobert Mustacchi 
84*7fd79137SRobert Mustacchi #else /* LITTLE ENDIAN */
85*7fd79137SRobert Mustacchi 
86*7fd79137SRobert Mustacchi #define WRITE_UNALIGNED(dbg,dest,source, srclength,len_out) \
87*7fd79137SRobert Mustacchi     { \
88*7fd79137SRobert Mustacchi       dbg->de_copy_word( (dest) , \
89*7fd79137SRobert Mustacchi                         ((char *)source) ,  \
90*7fd79137SRobert Mustacchi                         len_out) ; \
91*7fd79137SRobert Mustacchi     }
92*7fd79137SRobert Mustacchi #endif
93*7fd79137SRobert Mustacchi 
94*7fd79137SRobert Mustacchi 
95*7fd79137SRobert Mustacchi 
96*7fd79137SRobert Mustacchi typedef struct {
97*7fd79137SRobert Mustacchi     dwarf_elf_handle elf;
98*7fd79137SRobert Mustacchi     int              is_64bit;
99*7fd79137SRobert Mustacchi     Dwarf_Small      length_size;
100*7fd79137SRobert Mustacchi     Dwarf_Small      pointer_size;
101*7fd79137SRobert Mustacchi     Dwarf_Unsigned   section_count;
102*7fd79137SRobert Mustacchi     Dwarf_Endianness endianness;
103*7fd79137SRobert Mustacchi     Dwarf_Small      machine;
104*7fd79137SRobert Mustacchi     int              libdwarf_owns_elf;
105*7fd79137SRobert Mustacchi     Elf32_Ehdr *ehdr32;
106*7fd79137SRobert Mustacchi 
107*7fd79137SRobert Mustacchi #ifdef HAVE_ELF64_GETEHDR
108*7fd79137SRobert Mustacchi     Elf64_Ehdr *ehdr64;
109*7fd79137SRobert Mustacchi #endif
110*7fd79137SRobert Mustacchi     /* Elf symtab and its strtab.  Initialized at first
111*7fd79137SRobert Mustacchi        call to do relocations, the actual data is in the Dwarf_Debug
112*7fd79137SRobert Mustacchi        struct, not allocated locally here. */
113*7fd79137SRobert Mustacchi     struct Dwarf_Section_s *symtab;
114*7fd79137SRobert Mustacchi     struct Dwarf_Section_s *strtab;
115*7fd79137SRobert Mustacchi 
116*7fd79137SRobert Mustacchi } dwarf_elf_object_access_internals_t;
117*7fd79137SRobert Mustacchi 
118*7fd79137SRobert Mustacchi struct Dwarf_Elf_Rela {
119*7fd79137SRobert Mustacchi     Dwarf_ufixed64 r_offset;
120*7fd79137SRobert Mustacchi     /*Dwarf_ufixed64 r_info; */
121*7fd79137SRobert Mustacchi     Dwarf_ufixed64 r_type;
122*7fd79137SRobert Mustacchi     Dwarf_ufixed64 r_symidx;
123*7fd79137SRobert Mustacchi     Dwarf_ufixed64 r_addend;
124*7fd79137SRobert Mustacchi };
125*7fd79137SRobert Mustacchi 
126*7fd79137SRobert Mustacchi 
127*7fd79137SRobert Mustacchi static int dwarf_elf_object_access_load_section(void* obj_in,
128*7fd79137SRobert Mustacchi     Dwarf_Half section_index,
129*7fd79137SRobert Mustacchi     Dwarf_Small** section_data,
130*7fd79137SRobert Mustacchi     int* error);
131*7fd79137SRobert Mustacchi 
132*7fd79137SRobert Mustacchi /*
133*7fd79137SRobert Mustacchi     dwarf_elf_object_access_internals_init()
134*7fd79137SRobert Mustacchi  */
135*7fd79137SRobert Mustacchi static int
136*7fd79137SRobert Mustacchi dwarf_elf_object_access_internals_init(void* obj_in,
137*7fd79137SRobert Mustacchi                               dwarf_elf_handle elf,
138*7fd79137SRobert Mustacchi                               int* error)
139*7fd79137SRobert Mustacchi {
140*7fd79137SRobert Mustacchi     dwarf_elf_object_access_internals_t*obj =
141*7fd79137SRobert Mustacchi         (dwarf_elf_object_access_internals_t*)obj_in;
142*7fd79137SRobert Mustacchi     char *ehdr_ident = 0;
143*7fd79137SRobert Mustacchi     Dwarf_Half machine = 0;
144*7fd79137SRobert Mustacchi     obj->elf = elf;
145*7fd79137SRobert Mustacchi 
146*7fd79137SRobert Mustacchi     if ((ehdr_ident = elf_getident(elf, NULL)) == NULL) {
147*7fd79137SRobert Mustacchi         *error = DW_DLE_ELF_GETIDENT_ERROR;
148*7fd79137SRobert Mustacchi         return DW_DLV_ERROR;
149*7fd79137SRobert Mustacchi     }
150*7fd79137SRobert Mustacchi 
151*7fd79137SRobert Mustacchi     obj->is_64bit = (ehdr_ident[EI_CLASS] == ELFCLASS64);
152*7fd79137SRobert Mustacchi 
153*7fd79137SRobert Mustacchi 
154*7fd79137SRobert Mustacchi     if(ehdr_ident[EI_DATA] == ELFDATA2LSB){
155*7fd79137SRobert Mustacchi         obj->endianness = DW_OBJECT_LSB;
156*7fd79137SRobert Mustacchi     }
157*7fd79137SRobert Mustacchi     else if(ehdr_ident[EI_DATA] == ELFDATA2MSB){
158*7fd79137SRobert Mustacchi         obj->endianness = DW_OBJECT_MSB;
159*7fd79137SRobert Mustacchi     }
160*7fd79137SRobert Mustacchi 
161*7fd79137SRobert Mustacchi     if (obj->is_64bit) {
162*7fd79137SRobert Mustacchi #ifdef HAVE_ELF64_GETEHDR
163*7fd79137SRobert Mustacchi         obj->ehdr64 = elf64_getehdr(elf);
164*7fd79137SRobert Mustacchi         if (obj->ehdr64 == NULL) {
165*7fd79137SRobert Mustacchi             *error = DW_DLE_ELF_GETEHDR_ERROR;
166*7fd79137SRobert Mustacchi             return DW_DLV_ERROR;
167*7fd79137SRobert Mustacchi         }
168*7fd79137SRobert Mustacchi         obj->section_count = obj->ehdr64->e_shnum;
169*7fd79137SRobert Mustacchi         machine = obj->ehdr64->e_machine;
170*7fd79137SRobert Mustacchi         obj->machine = machine;
171*7fd79137SRobert Mustacchi #else
172*7fd79137SRobert Mustacchi         *error = DW_DLE_NO_ELF64_SUPPORT;
173*7fd79137SRobert Mustacchi         return DW_DLV_ERROR;
174*7fd79137SRobert Mustacchi #endif
175*7fd79137SRobert Mustacchi     }
176*7fd79137SRobert Mustacchi     else {
177*7fd79137SRobert Mustacchi         obj->ehdr32 = elf32_getehdr(elf);
178*7fd79137SRobert Mustacchi         if (obj->ehdr32 == NULL) {
179*7fd79137SRobert Mustacchi            *error = DW_DLE_ELF_GETEHDR_ERROR;
180*7fd79137SRobert Mustacchi            return DW_DLV_ERROR;
181*7fd79137SRobert Mustacchi         }
182*7fd79137SRobert Mustacchi         obj->section_count = obj->ehdr32->e_shnum;
183*7fd79137SRobert Mustacchi         machine = obj->ehdr32->e_machine;
184*7fd79137SRobert Mustacchi         obj->machine = machine;
185*7fd79137SRobert Mustacchi     }
186*7fd79137SRobert Mustacchi 
187*7fd79137SRobert Mustacchi     /* The following length_size is Not Too Significant. Only used
188*7fd79137SRobert Mustacchi        one calculation, and an approximate one at that. */
189*7fd79137SRobert Mustacchi     obj->length_size = obj->is_64bit ? 8 : 4;
190*7fd79137SRobert Mustacchi     obj->pointer_size = obj->is_64bit ? 8 : 4;
191*7fd79137SRobert Mustacchi 
192*7fd79137SRobert Mustacchi     if (obj->is_64bit && machine != EM_MIPS) {
193*7fd79137SRobert Mustacchi         /* MIPS/IRIX makes pointer size and length size 8 for -64.
194*7fd79137SRobert Mustacchi            Other platforms make length 4 always. */
195*7fd79137SRobert Mustacchi         /* 4 here supports 32bit-offset dwarf2, as emitted by cygnus
196*7fd79137SRobert Mustacchi            tools, and the dwarfv2.1 64bit extension setting.
197*7fd79137SRobert Mustacchi            This is not the same as the size-of-an-offset, which
198*7fd79137SRobert Mustacchi            is 4 in 32bit dwarf and 8 in 64bit dwarf.  */
199*7fd79137SRobert Mustacchi         obj->length_size = 4;
200*7fd79137SRobert Mustacchi     }
201*7fd79137SRobert Mustacchi     return DW_DLV_OK;
202*7fd79137SRobert Mustacchi }
203*7fd79137SRobert Mustacchi 
204*7fd79137SRobert Mustacchi /*
205*7fd79137SRobert Mustacchi     dwarf_elf_object_access_get_byte_order
206*7fd79137SRobert Mustacchi  */
207*7fd79137SRobert Mustacchi static
208*7fd79137SRobert Mustacchi Dwarf_Endianness
209*7fd79137SRobert Mustacchi dwarf_elf_object_access_get_byte_order(void* obj_in)
210*7fd79137SRobert Mustacchi {
211*7fd79137SRobert Mustacchi     dwarf_elf_object_access_internals_t*obj =
212*7fd79137SRobert Mustacchi         (dwarf_elf_object_access_internals_t*)obj_in;
213*7fd79137SRobert Mustacchi     return obj->endianness;
214*7fd79137SRobert Mustacchi }
215*7fd79137SRobert Mustacchi 
216*7fd79137SRobert Mustacchi /*
217*7fd79137SRobert Mustacchi     dwarf_elf_object_access_get_section_count()
218*7fd79137SRobert Mustacchi  */
219*7fd79137SRobert Mustacchi static
220*7fd79137SRobert Mustacchi Dwarf_Unsigned
221*7fd79137SRobert Mustacchi dwarf_elf_object_access_get_section_count(void * obj_in)
222*7fd79137SRobert Mustacchi {
223*7fd79137SRobert Mustacchi     dwarf_elf_object_access_internals_t*obj =
224*7fd79137SRobert Mustacchi         (dwarf_elf_object_access_internals_t*)obj_in;
225*7fd79137SRobert Mustacchi     return obj->section_count;
226*7fd79137SRobert Mustacchi }
227*7fd79137SRobert Mustacchi 
228*7fd79137SRobert Mustacchi 
229*7fd79137SRobert Mustacchi /*
230*7fd79137SRobert Mustacchi     dwarf_elf_object_access_get_section()
231*7fd79137SRobert Mustacchi  */
232*7fd79137SRobert Mustacchi static
233*7fd79137SRobert Mustacchi int
234*7fd79137SRobert Mustacchi dwarf_elf_object_access_get_section_info(
235*7fd79137SRobert Mustacchi     void* obj_in,
236*7fd79137SRobert Mustacchi     Dwarf_Half section_index,
237*7fd79137SRobert Mustacchi     Dwarf_Obj_Access_Section* ret_scn,
238*7fd79137SRobert Mustacchi     int* error)
239*7fd79137SRobert Mustacchi {
240*7fd79137SRobert Mustacchi     dwarf_elf_object_access_internals_t*obj =
241*7fd79137SRobert Mustacchi         (dwarf_elf_object_access_internals_t*)obj_in;
242*7fd79137SRobert Mustacchi 
243*7fd79137SRobert Mustacchi     Elf32_Shdr *shdr32 = 0;
244*7fd79137SRobert Mustacchi 
245*7fd79137SRobert Mustacchi #ifdef HAVE_ELF64_GETSHDR
246*7fd79137SRobert Mustacchi     Elf64_Shdr *shdr64 = 0;
247*7fd79137SRobert Mustacchi #endif
248*7fd79137SRobert Mustacchi     Elf_Scn *scn = 0;
249*7fd79137SRobert Mustacchi 
250*7fd79137SRobert Mustacchi 
251*7fd79137SRobert Mustacchi     scn = elf_getscn(obj->elf, section_index);
252*7fd79137SRobert Mustacchi     if (scn == NULL) {
253*7fd79137SRobert Mustacchi         *error = DW_DLE_MDE;
254*7fd79137SRobert Mustacchi         return DW_DLV_ERROR;
255*7fd79137SRobert Mustacchi     }
256*7fd79137SRobert Mustacchi     if (obj->is_64bit) {
257*7fd79137SRobert Mustacchi #ifdef HAVE_ELF64_GETSHDR
258*7fd79137SRobert Mustacchi         shdr64 = elf64_getshdr(scn);
259*7fd79137SRobert Mustacchi         if (shdr64 == NULL) {
260*7fd79137SRobert Mustacchi             *error = DW_DLE_ELF_GETSHDR_ERROR;
261*7fd79137SRobert Mustacchi             return DW_DLV_ERROR;
262*7fd79137SRobert Mustacchi         }
263*7fd79137SRobert Mustacchi 
264*7fd79137SRobert Mustacchi         ret_scn->size = shdr64->sh_size;
265*7fd79137SRobert Mustacchi         ret_scn->addr = shdr64->sh_addr;
266*7fd79137SRobert Mustacchi         ret_scn->link = shdr64->sh_link;
267*7fd79137SRobert Mustacchi 
268*7fd79137SRobert Mustacchi         ret_scn->name = elf_strptr(obj->elf, obj->ehdr64->e_shstrndx,
269*7fd79137SRobert Mustacchi                                         shdr64->sh_name);
270*7fd79137SRobert Mustacchi         if(ret_scn->name == NULL) {
271*7fd79137SRobert Mustacchi             *error = DW_DLE_ELF_STRPTR_ERROR;
272*7fd79137SRobert Mustacchi             return DW_DLV_ERROR;
273*7fd79137SRobert Mustacchi         }
274*7fd79137SRobert Mustacchi         return DW_DLV_OK;
275*7fd79137SRobert Mustacchi #else
276*7fd79137SRobert Mustacchi         *error = DW_DLE_MISSING_ELF64_SUPPORT;
277*7fd79137SRobert Mustacchi         return DW_DLV_ERROR;
278*7fd79137SRobert Mustacchi #endif /* HAVE_ELF64_GETSHDR */
279*7fd79137SRobert Mustacchi     }
280*7fd79137SRobert Mustacchi     if ((shdr32 = elf32_getshdr(scn)) == NULL) {
281*7fd79137SRobert Mustacchi         *error = DW_DLE_ELF_GETSHDR_ERROR;
282*7fd79137SRobert Mustacchi         return DW_DLV_ERROR;
283*7fd79137SRobert Mustacchi     }
284*7fd79137SRobert Mustacchi 
285*7fd79137SRobert Mustacchi     ret_scn->size = shdr32->sh_size;
286*7fd79137SRobert Mustacchi     ret_scn->addr = shdr32->sh_addr;
287*7fd79137SRobert Mustacchi     ret_scn->link = shdr32->sh_link;
288*7fd79137SRobert Mustacchi 
289*7fd79137SRobert Mustacchi     ret_scn->name = elf_strptr(obj->elf, obj->ehdr32->e_shstrndx,
290*7fd79137SRobert Mustacchi         shdr32->sh_name);
291*7fd79137SRobert Mustacchi     if (ret_scn->name == NULL) {
292*7fd79137SRobert Mustacchi         *error = DW_DLE_ELF_STRPTR_ERROR;
293*7fd79137SRobert Mustacchi         return DW_DLV_ERROR;
294*7fd79137SRobert Mustacchi     }
295*7fd79137SRobert Mustacchi     return DW_DLV_OK;
296*7fd79137SRobert Mustacchi }
297*7fd79137SRobert Mustacchi 
298*7fd79137SRobert Mustacchi /*
299*7fd79137SRobert Mustacchi     dwarf_elf_object_access_get_length_size
300*7fd79137SRobert Mustacchi  */
301*7fd79137SRobert Mustacchi static
302*7fd79137SRobert Mustacchi Dwarf_Small
303*7fd79137SRobert Mustacchi dwarf_elf_object_access_get_length_size(void* obj_in)
304*7fd79137SRobert Mustacchi {
305*7fd79137SRobert Mustacchi     dwarf_elf_object_access_internals_t*obj =
306*7fd79137SRobert Mustacchi         (dwarf_elf_object_access_internals_t*)obj_in;
307*7fd79137SRobert Mustacchi     return obj->length_size;
308*7fd79137SRobert Mustacchi }
309*7fd79137SRobert Mustacchi 
310*7fd79137SRobert Mustacchi /*
311*7fd79137SRobert Mustacchi     dwarf_elf_object_access_get_pointer_size
312*7fd79137SRobert Mustacchi  */
313*7fd79137SRobert Mustacchi static
314*7fd79137SRobert Mustacchi Dwarf_Small
315*7fd79137SRobert Mustacchi dwarf_elf_object_access_get_pointer_size(void* obj_in)
316*7fd79137SRobert Mustacchi {
317*7fd79137SRobert Mustacchi     dwarf_elf_object_access_internals_t*obj =
318*7fd79137SRobert Mustacchi         (dwarf_elf_object_access_internals_t*)obj_in;
319*7fd79137SRobert Mustacchi     return obj->pointer_size;
320*7fd79137SRobert Mustacchi }
321*7fd79137SRobert Mustacchi 
322*7fd79137SRobert Mustacchi #define MATCH_REL_SEC(i_,s_,r_)  \
323*7fd79137SRobert Mustacchi if(i_ == s_.dss_index) { \
324*7fd79137SRobert Mustacchi     *r_ = &s_;            \
325*7fd79137SRobert Mustacchi     return DW_DLV_OK;    \
326*7fd79137SRobert Mustacchi }
327*7fd79137SRobert Mustacchi 
328*7fd79137SRobert Mustacchi static int
329*7fd79137SRobert Mustacchi find_section_to_relocate(Dwarf_Debug dbg,Dwarf_Half section_index,
330*7fd79137SRobert Mustacchi    struct Dwarf_Section_s **relocatablesec, int *error)
331*7fd79137SRobert Mustacchi {
332*7fd79137SRobert Mustacchi     MATCH_REL_SEC(section_index,dbg->de_debug_info,relocatablesec);
333*7fd79137SRobert Mustacchi     MATCH_REL_SEC(section_index,dbg->de_debug_abbrev,relocatablesec);
334*7fd79137SRobert Mustacchi     MATCH_REL_SEC(section_index,dbg->de_debug_line,relocatablesec);
335*7fd79137SRobert Mustacchi     MATCH_REL_SEC(section_index,dbg->de_debug_loc,relocatablesec);
336*7fd79137SRobert Mustacchi     MATCH_REL_SEC(section_index,dbg->de_debug_aranges,relocatablesec);
337*7fd79137SRobert Mustacchi     MATCH_REL_SEC(section_index,dbg->de_debug_macinfo,relocatablesec);
338*7fd79137SRobert Mustacchi     MATCH_REL_SEC(section_index,dbg->de_debug_pubnames,relocatablesec);
339*7fd79137SRobert Mustacchi     MATCH_REL_SEC(section_index,dbg->de_debug_ranges,relocatablesec);
340*7fd79137SRobert Mustacchi     MATCH_REL_SEC(section_index,dbg->de_debug_frame,relocatablesec);
341*7fd79137SRobert Mustacchi     MATCH_REL_SEC(section_index,dbg->de_debug_frame_eh_gnu,relocatablesec);
342*7fd79137SRobert Mustacchi     MATCH_REL_SEC(section_index,dbg->de_debug_pubtypes,relocatablesec);
343*7fd79137SRobert Mustacchi     MATCH_REL_SEC(section_index,dbg->de_debug_funcnames,relocatablesec);
344*7fd79137SRobert Mustacchi     MATCH_REL_SEC(section_index,dbg->de_debug_typenames,relocatablesec);
345*7fd79137SRobert Mustacchi     MATCH_REL_SEC(section_index,dbg->de_debug_varnames,relocatablesec);
346*7fd79137SRobert Mustacchi     MATCH_REL_SEC(section_index,dbg->de_debug_weaknames,relocatablesec);
347*7fd79137SRobert Mustacchi     /* dbg-> de_debug_str,syms); */
348*7fd79137SRobert Mustacchi     /* de_elf_symtab,syms); */
349*7fd79137SRobert Mustacchi     /* de_elf_strtab,syms); */
350*7fd79137SRobert Mustacchi     *error = DW_DLE_RELOC_SECTION_MISMATCH;
351*7fd79137SRobert Mustacchi     return DW_DLV_ERROR;
352*7fd79137SRobert Mustacchi 
353*7fd79137SRobert Mustacchi }
354*7fd79137SRobert Mustacchi #undef MATCH_REL_SEC
355*7fd79137SRobert Mustacchi 
356*7fd79137SRobert Mustacchi static void
357*7fd79137SRobert Mustacchi get_rela_elf32(Dwarf_Small *data, unsigned int i,
358*7fd79137SRobert Mustacchi   int endianness,
359*7fd79137SRobert Mustacchi   int machine, struct Dwarf_Elf_Rela *relap)
360*7fd79137SRobert Mustacchi {
361*7fd79137SRobert Mustacchi     Elf32_Rela *relp = (Elf32_Rela*)(data + (i * sizeof(Elf32_Rela)));
362*7fd79137SRobert Mustacchi     relap->r_offset = relp->r_offset;
363*7fd79137SRobert Mustacchi     /*
364*7fd79137SRobert Mustacchi     relap->r_info = relp->r_info;
365*7fd79137SRobert Mustacchi    */
366*7fd79137SRobert Mustacchi     relap->r_type = ELF32_R_TYPE(relp->r_info);
367*7fd79137SRobert Mustacchi     relap->r_symidx = ELF32_R_SYM(relp->r_info);
368*7fd79137SRobert Mustacchi     relap->r_addend = relp->r_addend;
369*7fd79137SRobert Mustacchi }
370*7fd79137SRobert Mustacchi 
371*7fd79137SRobert Mustacchi static void
372*7fd79137SRobert Mustacchi get_rela_elf64(Dwarf_Small *data, unsigned int i,
373*7fd79137SRobert Mustacchi   int endianness,
374*7fd79137SRobert Mustacchi   int machine,struct Dwarf_Elf_Rela *relap)
375*7fd79137SRobert Mustacchi {
376*7fd79137SRobert Mustacchi #ifdef HAVE_ELF64_RELA
377*7fd79137SRobert Mustacchi     Elf64_Rela * relp = (Elf64_Rela*)(data + (i * sizeof(Elf64_Rela)));
378*7fd79137SRobert Mustacchi     relap->r_offset = relp->r_offset;
379*7fd79137SRobert Mustacchi     /*
380*7fd79137SRobert Mustacchi     relap->r_info = relp->r_info;
381*7fd79137SRobert Mustacchi     */
382*7fd79137SRobert Mustacchi     if(machine == EM_MIPS && endianness == DW_OBJECT_LSB ) {
383*7fd79137SRobert Mustacchi         /* This is really wierd. Treat this very specially.
384*7fd79137SRobert Mustacchi            The Elf64 LE MIPS object used for
385*7fd79137SRobert Mustacchi            testing (that has rela) wants the
386*7fd79137SRobert Mustacchi            values as  sym  ssym type3 type2 type, treating
387*7fd79137SRobert Mustacchi            each value as independent value. But libelf xlate
388*7fd79137SRobert Mustacchi            treats it as something else so we fudge here.
389*7fd79137SRobert Mustacchi            It is unclear
390*7fd79137SRobert Mustacchi            how to precisely characterize where these relocations
391*7fd79137SRobert Mustacchi            were used.
392*7fd79137SRobert Mustacchi            SGI MIPS on IRIX never used .rela relocations.
393*7fd79137SRobert Mustacchi            The BE 64bit elf MIPS test object with rela uses traditional
394*7fd79137SRobert Mustacchi            elf relocation layouts, not this special case.  */
395*7fd79137SRobert Mustacchi #define ELF64MIPS_REL_SYM(i) ((i) & 0xffffffff)
396*7fd79137SRobert Mustacchi #define ELF64MIPS_REL_TYPE(i) ((i >> 56) &0xff)
397*7fd79137SRobert Mustacchi         /* We ignore the special TYPE2 and TYPE3, they should be
398*7fd79137SRobert Mustacchi            value R_MIPS_NONE in rela. */
399*7fd79137SRobert Mustacchi         relap->r_type = ELF64MIPS_REL_TYPE(relp->r_info);
400*7fd79137SRobert Mustacchi         relap->r_symidx = ELF64MIPS_REL_SYM(relp->r_info);
401*7fd79137SRobert Mustacchi #undef MIPS64SYM
402*7fd79137SRobert Mustacchi #undef MIPS64TYPE
403*7fd79137SRobert Mustacchi     } else
404*7fd79137SRobert Mustacchi     {
405*7fd79137SRobert Mustacchi         relap->r_type = ELF64_R_TYPE(relp->r_info);
406*7fd79137SRobert Mustacchi         relap->r_symidx = ELF64_R_SYM(relp->r_info);
407*7fd79137SRobert Mustacchi     }
408*7fd79137SRobert Mustacchi     relap->r_addend = relp->r_addend;
409*7fd79137SRobert Mustacchi #endif
410*7fd79137SRobert Mustacchi }
411*7fd79137SRobert Mustacchi 
412*7fd79137SRobert Mustacchi static void
413*7fd79137SRobert Mustacchi get_relocations_array(Dwarf_Bool is_64bit,
414*7fd79137SRobert Mustacchi     int endianness,
415*7fd79137SRobert Mustacchi     int machine,
416*7fd79137SRobert Mustacchi     Dwarf_Small *data,
417*7fd79137SRobert Mustacchi     unsigned int num_relocations,
418*7fd79137SRobert Mustacchi     struct Dwarf_Elf_Rela *relap)
419*7fd79137SRobert Mustacchi {
420*7fd79137SRobert Mustacchi     unsigned int i = 0;
421*7fd79137SRobert Mustacchi     void (*get_relocations)(Dwarf_Small *data, unsigned int i,
422*7fd79137SRobert Mustacchi          int endianness,
423*7fd79137SRobert Mustacchi          int machine,
424*7fd79137SRobert Mustacchi          struct Dwarf_Elf_Rela *relap);
425*7fd79137SRobert Mustacchi 
426*7fd79137SRobert Mustacchi     /* Handle 32/64 bit issue
427*7fd79137SRobert Mustacchi      */
428*7fd79137SRobert Mustacchi     if (is_64bit) {
429*7fd79137SRobert Mustacchi         get_relocations = get_rela_elf64;
430*7fd79137SRobert Mustacchi     } else {
431*7fd79137SRobert Mustacchi         get_relocations = get_rela_elf32;
432*7fd79137SRobert Mustacchi     }
433*7fd79137SRobert Mustacchi 
434*7fd79137SRobert Mustacchi     for (i=0; i < num_relocations; i++) {
435*7fd79137SRobert Mustacchi        get_relocations(data, i,endianness,machine, &(relap[i]));
436*7fd79137SRobert Mustacchi     }
437*7fd79137SRobert Mustacchi 
438*7fd79137SRobert Mustacchi }
439*7fd79137SRobert Mustacchi 
440*7fd79137SRobert Mustacchi static int
441*7fd79137SRobert Mustacchi get_relocation_entries(Dwarf_Bool is_64bit,
442*7fd79137SRobert Mustacchi     int endianness,
443*7fd79137SRobert Mustacchi     int machine,
444*7fd79137SRobert Mustacchi     Dwarf_Small *relocation_section,
445*7fd79137SRobert Mustacchi     Dwarf_Unsigned relocation_section_size,
446*7fd79137SRobert Mustacchi     struct Dwarf_Elf_Rela **relas,
447*7fd79137SRobert Mustacchi     unsigned int *nrelas,
448*7fd79137SRobert Mustacchi     int *error)
449*7fd79137SRobert Mustacchi {
450*7fd79137SRobert Mustacchi     unsigned int relocation_size = 0;
451*7fd79137SRobert Mustacchi 
452*7fd79137SRobert Mustacchi     if (is_64bit) {
453*7fd79137SRobert Mustacchi #ifdef HAVE_ELF64_RELA
454*7fd79137SRobert Mustacchi         relocation_size = sizeof(Elf64_Rela);
455*7fd79137SRobert Mustacchi #else
456*7fd79137SRobert Mustacchi         *error = DW_DLE_MISSING_ELF64_SUPPORT;
457*7fd79137SRobert Mustacchi         return DW_DLV_ERROR;
458*7fd79137SRobert Mustacchi #endif
459*7fd79137SRobert Mustacchi     } else {
460*7fd79137SRobert Mustacchi         relocation_size = sizeof(Elf32_Rela);
461*7fd79137SRobert Mustacchi     }
462*7fd79137SRobert Mustacchi 
463*7fd79137SRobert Mustacchi     if (relocation_section == NULL) {
464*7fd79137SRobert Mustacchi         *error = DW_DLE_RELOC_SECTION_PTR_NULL;
465*7fd79137SRobert Mustacchi         return(DW_DLV_ERROR);
466*7fd79137SRobert Mustacchi     }
467*7fd79137SRobert Mustacchi 
468*7fd79137SRobert Mustacchi     if ((relocation_section_size != 0)) {
469*7fd79137SRobert Mustacchi         size_t bytescount = 0;
470*7fd79137SRobert Mustacchi         if(relocation_section_size%relocation_size) {
471*7fd79137SRobert Mustacchi             *error = DW_DLE_RELOC_SECTION_LENGTH_ODD;
472*7fd79137SRobert Mustacchi             return DW_DLV_ERROR;
473*7fd79137SRobert Mustacchi         }
474*7fd79137SRobert Mustacchi         *nrelas = relocation_section_size/relocation_size;
475*7fd79137SRobert Mustacchi         bytescount = (*nrelas) * sizeof(struct Dwarf_Elf_Rela);
476*7fd79137SRobert Mustacchi         *relas = malloc(bytescount);
477*7fd79137SRobert Mustacchi         if (!*relas) {
478*7fd79137SRobert Mustacchi             *error = DW_DLE_MAF;
479*7fd79137SRobert Mustacchi             return(DW_DLV_ERROR);
480*7fd79137SRobert Mustacchi         }
481*7fd79137SRobert Mustacchi         memset(*relas,0,bytescount);
482*7fd79137SRobert Mustacchi         get_relocations_array(is_64bit,endianness,machine, relocation_section,
483*7fd79137SRobert Mustacchi             *nrelas, *relas);
484*7fd79137SRobert Mustacchi     }
485*7fd79137SRobert Mustacchi     return(DW_DLV_OK);
486*7fd79137SRobert Mustacchi }
487*7fd79137SRobert Mustacchi 
488*7fd79137SRobert Mustacchi static Dwarf_Bool
489*7fd79137SRobert Mustacchi is_32bit_abs_reloc(unsigned int type, Dwarf_Half machine)
490*7fd79137SRobert Mustacchi {
491*7fd79137SRobert Mustacchi     Dwarf_Bool r = 0;
492*7fd79137SRobert Mustacchi     switch (machine) {
493*7fd79137SRobert Mustacchi #if defined(EM_MIPS) && defined (R_MIPS_32)
494*7fd79137SRobert Mustacchi     case EM_MIPS:
495*7fd79137SRobert Mustacchi          r = (type == R_MIPS_32);
496*7fd79137SRobert Mustacchi          break;
497*7fd79137SRobert Mustacchi #endif
498*7fd79137SRobert Mustacchi #if defined(EM_SPARC32PLUS)  && defined (R_SPARC_UA32)
499*7fd79137SRobert Mustacchi     case EM_SPARC32PLUS:
500*7fd79137SRobert Mustacchi          r =  (type == R_SPARC_UA32);
501*7fd79137SRobert Mustacchi          break;
502*7fd79137SRobert Mustacchi #endif
503*7fd79137SRobert Mustacchi #if defined(EM_SPARCV9)  && defined (R_SPARC_UA32)
504*7fd79137SRobert Mustacchi     case EM_SPARCV9:
505*7fd79137SRobert Mustacchi          r =  (type == R_SPARC_UA32);
506*7fd79137SRobert Mustacchi          break;
507*7fd79137SRobert Mustacchi #endif
508*7fd79137SRobert Mustacchi #if defined(EM_SPARC) && defined (R_SPARC_UA32)
509*7fd79137SRobert Mustacchi     case EM_SPARC:
510*7fd79137SRobert Mustacchi          r =  (type == R_SPARC_UA32);
511*7fd79137SRobert Mustacchi          break;
512*7fd79137SRobert Mustacchi #endif
513*7fd79137SRobert Mustacchi #if defined(EM_386) && defined (R_386_32)
514*7fd79137SRobert Mustacchi     case EM_386:
515*7fd79137SRobert Mustacchi         r =  (type == R_386_32);
516*7fd79137SRobert Mustacchi         break;
517*7fd79137SRobert Mustacchi #endif
518*7fd79137SRobert Mustacchi #if defined(EM_IA_64) && defined (R_IA64_SECREL32LSB)
519*7fd79137SRobert Mustacchi     case EM_IA_64:
520*7fd79137SRobert Mustacchi         r =  (type == R_IA64_SECREL32LSB);
521*7fd79137SRobert Mustacchi         break;
522*7fd79137SRobert Mustacchi #endif
523*7fd79137SRobert Mustacchi #if defined(EM_PPC64) && defined (R_PPC64_ADDR32)
524*7fd79137SRobert Mustacchi     case EM_PPC64:
525*7fd79137SRobert Mustacchi         r =  (type == R_PPC64_ADDR32);
526*7fd79137SRobert Mustacchi         break;
527*7fd79137SRobert Mustacchi #endif
528*7fd79137SRobert Mustacchi #if defined(EM_PPC) && defined (R_PPC_ADDR32)
529*7fd79137SRobert Mustacchi     case EM_PPC:
530*7fd79137SRobert Mustacchi         r =  (type == R_PPC_ADDR32);
531*7fd79137SRobert Mustacchi         break;
532*7fd79137SRobert Mustacchi #endif
533*7fd79137SRobert Mustacchi #if defined(EM_S390) && defined (R_390_32)
534*7fd79137SRobert Mustacchi     case EM_S390:
535*7fd79137SRobert Mustacchi         r =  (type == R_390_32);
536*7fd79137SRobert Mustacchi         break;
537*7fd79137SRobert Mustacchi #endif
538*7fd79137SRobert Mustacchi #if defined(EM_X86_64) && defined (R_X86_64_32)
539*7fd79137SRobert Mustacchi     case EM_X86_64:
540*7fd79137SRobert Mustacchi         r = (type == R_X86_64_32);
541*7fd79137SRobert Mustacchi         break;
542*7fd79137SRobert Mustacchi #endif
543*7fd79137SRobert Mustacchi     }
544*7fd79137SRobert Mustacchi     return r;
545*7fd79137SRobert Mustacchi }
546*7fd79137SRobert Mustacchi 
547*7fd79137SRobert Mustacchi static Dwarf_Bool
548*7fd79137SRobert Mustacchi is_64bit_abs_reloc(unsigned int type, Dwarf_Half machine)
549*7fd79137SRobert Mustacchi {
550*7fd79137SRobert Mustacchi     Dwarf_Bool r = 0;
551*7fd79137SRobert Mustacchi     switch (machine) {
552*7fd79137SRobert Mustacchi #if defined(EM_MIPS) && defined (R_MIPS_64)
553*7fd79137SRobert Mustacchi     case EM_MIPS:
554*7fd79137SRobert Mustacchi         r =  (type == R_MIPS_64);
555*7fd79137SRobert Mustacchi         break;
556*7fd79137SRobert Mustacchi #endif
557*7fd79137SRobert Mustacchi #if defined(EM_SPARC32PLUS) && defined (R_SPARC_UA64)
558*7fd79137SRobert Mustacchi     case EM_SPARC32PLUS:
559*7fd79137SRobert Mustacchi         r =  (type == R_SPARC_UA64);
560*7fd79137SRobert Mustacchi         break;
561*7fd79137SRobert Mustacchi #endif
562*7fd79137SRobert Mustacchi #if defined(EM_SPARCV9) && defined (R_SPARC_UA64)
563*7fd79137SRobert Mustacchi     case EM_SPARCV9:
564*7fd79137SRobert Mustacchi         r = (type == R_SPARC_UA64);
565*7fd79137SRobert Mustacchi         break;
566*7fd79137SRobert Mustacchi #endif
567*7fd79137SRobert Mustacchi #if defined(EM_SPARC) && defined (R_SPARC_UA64)
568*7fd79137SRobert Mustacchi     case EM_SPARC:
569*7fd79137SRobert Mustacchi         r = (type == R_SPARC_UA64);
570*7fd79137SRobert Mustacchi         break;
571*7fd79137SRobert Mustacchi #endif
572*7fd79137SRobert Mustacchi #if defined(EM_IA_64) && defined (R_IA64_SECREL32LSB)
573*7fd79137SRobert Mustacchi     case EM_IA_64:
574*7fd79137SRobert Mustacchi         r =  (type == R_IA64_DIR64LSB);
575*7fd79137SRobert Mustacchi         break;
576*7fd79137SRobert Mustacchi #endif
577*7fd79137SRobert Mustacchi #if defined(EM_PPC64) && defined (R_PPC64_ADDR64)
578*7fd79137SRobert Mustacchi     case EM_PPC64:
579*7fd79137SRobert Mustacchi         r =  (type == R_PPC64_ADDR64);
580*7fd79137SRobert Mustacchi         break;
581*7fd79137SRobert Mustacchi #endif
582*7fd79137SRobert Mustacchi #if defined(EM_S390) && defined (R_390_64)
583*7fd79137SRobert Mustacchi     case EM_S390:
584*7fd79137SRobert Mustacchi         r =  (type == R_390_64);
585*7fd79137SRobert Mustacchi         break;
586*7fd79137SRobert Mustacchi #endif
587*7fd79137SRobert Mustacchi #if defined(EM_X86_64) && defined (R_X86_64_64)
588*7fd79137SRobert Mustacchi     case EM_X86_64:
589*7fd79137SRobert Mustacchi         r =  (type == R_X86_64_64);
590*7fd79137SRobert Mustacchi         break;
591*7fd79137SRobert Mustacchi #endif
592*7fd79137SRobert Mustacchi     }
593*7fd79137SRobert Mustacchi     return r;
594*7fd79137SRobert Mustacchi }
595*7fd79137SRobert Mustacchi 
596*7fd79137SRobert Mustacchi 
597*7fd79137SRobert Mustacchi static void
598*7fd79137SRobert Mustacchi update_entry(Dwarf_Debug dbg,
599*7fd79137SRobert Mustacchi     Dwarf_Bool is_64bit, Dwarf_Endianness endianess,
600*7fd79137SRobert Mustacchi     Dwarf_Half machine, struct Dwarf_Elf_Rela *rela,
601*7fd79137SRobert Mustacchi     Dwarf_Small *target_section, Dwarf_Small *section_data)
602*7fd79137SRobert Mustacchi {
603*7fd79137SRobert Mustacchi     unsigned int type = 0;
604*7fd79137SRobert Mustacchi     unsigned int sym_idx = 0;
605*7fd79137SRobert Mustacchi #ifdef HAVE_ELF64_SYM
606*7fd79137SRobert Mustacchi     Elf64_Sym sym_buf;
607*7fd79137SRobert Mustacchi     Elf64_Sym *sym = 0;
608*7fd79137SRobert Mustacchi #else
609*7fd79137SRobert Mustacchi     Elf32_Sym sym_buf;
610*7fd79137SRobert Mustacchi     Elf32_Sym *sym = 0;
611*7fd79137SRobert Mustacchi #endif
612*7fd79137SRobert Mustacchi     Elf32_Sym *sym32 = 0;
613*7fd79137SRobert Mustacchi     Dwarf_ufixed64 offset = 0;
614*7fd79137SRobert Mustacchi     Dwarf_sfixed64 addend = 0;
615*7fd79137SRobert Mustacchi     Dwarf_Unsigned reloc_size = 0;
616*7fd79137SRobert Mustacchi 
617*7fd79137SRobert Mustacchi 
618*7fd79137SRobert Mustacchi     /* Dwarf_Elf_Rela dereferencing */
619*7fd79137SRobert Mustacchi     offset = rela->r_offset;
620*7fd79137SRobert Mustacchi     addend = rela->r_addend;
621*7fd79137SRobert Mustacchi     type = rela->r_type;
622*7fd79137SRobert Mustacchi     sym_idx = rela->r_symidx;
623*7fd79137SRobert Mustacchi 
624*7fd79137SRobert Mustacchi     if (is_64bit) {
625*7fd79137SRobert Mustacchi #ifdef HAVE_ELF64_SYM
626*7fd79137SRobert Mustacchi        sym = &((Elf64_Sym*)section_data)[sym_idx];
627*7fd79137SRobert Mustacchi #endif
628*7fd79137SRobert Mustacchi     } else {
629*7fd79137SRobert Mustacchi        sym32 = &((Elf32_Sym*)section_data)[sym_idx];
630*7fd79137SRobert Mustacchi 
631*7fd79137SRobert Mustacchi        /* Convert Elf32_Sym struct to Elf64_Sym struct. We point at
632*7fd79137SRobert Mustacchi         * an Elf64_Sym local variable (sym_buf) to allow us to use the
633*7fd79137SRobert Mustacchi         * same pointer (sym) for both 32-bit and 64-bit instances.
634*7fd79137SRobert Mustacchi         */
635*7fd79137SRobert Mustacchi        sym = &sym_buf;
636*7fd79137SRobert Mustacchi        sym->st_name = sym32->st_name;
637*7fd79137SRobert Mustacchi        sym->st_info = sym32->st_info;
638*7fd79137SRobert Mustacchi        sym->st_other = sym32->st_other;
639*7fd79137SRobert Mustacchi        sym->st_shndx = sym32->st_shndx;
640*7fd79137SRobert Mustacchi        sym->st_value = sym32->st_value;
641*7fd79137SRobert Mustacchi        sym->st_size = sym32->st_size;
642*7fd79137SRobert Mustacchi     }
643*7fd79137SRobert Mustacchi 
644*7fd79137SRobert Mustacchi     /* Determine relocation size */
645*7fd79137SRobert Mustacchi     if (is_32bit_abs_reloc(type, machine)) {
646*7fd79137SRobert Mustacchi         reloc_size = 4;
647*7fd79137SRobert Mustacchi     } else if (is_64bit_abs_reloc(type, machine)) {
648*7fd79137SRobert Mustacchi         reloc_size = 8;
649*7fd79137SRobert Mustacchi     } else {
650*7fd79137SRobert Mustacchi         return;
651*7fd79137SRobert Mustacchi     }
652*7fd79137SRobert Mustacchi 
653*7fd79137SRobert Mustacchi 
654*7fd79137SRobert Mustacchi     {
655*7fd79137SRobert Mustacchi         /* Assuming we do not need to do a READ_UNALIGNED here
656*7fd79137SRobert Mustacchi            at target_section + offset and add its value to
657*7fd79137SRobert Mustacchi            outval.  Some ABIs say no read (for example MIPS),
658*7fd79137SRobert Mustacchi            but if some do then which ones? */
659*7fd79137SRobert Mustacchi         Dwarf_Unsigned outval = sym->st_value + addend;
660*7fd79137SRobert Mustacchi         WRITE_UNALIGNED(dbg,target_section + offset,
661*7fd79137SRobert Mustacchi                   &outval,sizeof(outval),reloc_size);
662*7fd79137SRobert Mustacchi     }
663*7fd79137SRobert Mustacchi }
664*7fd79137SRobert Mustacchi 
665*7fd79137SRobert Mustacchi 
666*7fd79137SRobert Mustacchi 
667*7fd79137SRobert Mustacchi static int
668*7fd79137SRobert Mustacchi apply_rela_entries(Dwarf_Debug dbg,
669*7fd79137SRobert Mustacchi     Dwarf_Bool is_64bit,
670*7fd79137SRobert Mustacchi     Dwarf_Endianness endianess,
671*7fd79137SRobert Mustacchi     Dwarf_Half machine,
672*7fd79137SRobert Mustacchi     Dwarf_Small *target_section,
673*7fd79137SRobert Mustacchi     Dwarf_Small *symtab_section,
674*7fd79137SRobert Mustacchi     struct Dwarf_Elf_Rela *relas, unsigned int nrelas,
675*7fd79137SRobert Mustacchi     int *error)
676*7fd79137SRobert Mustacchi {
677*7fd79137SRobert Mustacchi     if ((target_section != NULL)  && (relas != NULL)) {
678*7fd79137SRobert Mustacchi         unsigned int i;
679*7fd79137SRobert Mustacchi         for (i = 0; i < nrelas; i++) {
680*7fd79137SRobert Mustacchi             update_entry(dbg, is_64bit,
681*7fd79137SRobert Mustacchi                 endianess,
682*7fd79137SRobert Mustacchi                 machine,
683*7fd79137SRobert Mustacchi                 &(relas)[i],
684*7fd79137SRobert Mustacchi                 target_section,
685*7fd79137SRobert Mustacchi                 symtab_section);
686*7fd79137SRobert Mustacchi         }
687*7fd79137SRobert Mustacchi     }
688*7fd79137SRobert Mustacchi     return DW_DLV_OK;
689*7fd79137SRobert Mustacchi }
690*7fd79137SRobert Mustacchi 
691*7fd79137SRobert Mustacchi 
692*7fd79137SRobert Mustacchi static int
693*7fd79137SRobert Mustacchi loop_through_relocations(
694*7fd79137SRobert Mustacchi    Dwarf_Debug dbg,
695*7fd79137SRobert Mustacchi    dwarf_elf_object_access_internals_t* obj,
696*7fd79137SRobert Mustacchi    struct Dwarf_Section_s *relocatablesec,
697*7fd79137SRobert Mustacchi    int *error)
698*7fd79137SRobert Mustacchi {
699*7fd79137SRobert Mustacchi     Dwarf_Small *target_section = 0;
700*7fd79137SRobert Mustacchi     Dwarf_Small *symtab_section = obj->symtab->dss_data;
701*7fd79137SRobert Mustacchi     Dwarf_Small *relocation_section  = relocatablesec->dss_reloc_data;
702*7fd79137SRobert Mustacchi     Dwarf_Unsigned relocation_section_size =
703*7fd79137SRobert Mustacchi               relocatablesec->dss_reloc_size;
704*7fd79137SRobert Mustacchi     int ret = DW_DLV_ERROR;
705*7fd79137SRobert Mustacchi     struct Dwarf_Elf_Rela *relas = 0;
706*7fd79137SRobert Mustacchi     unsigned int nrelas = 0;
707*7fd79137SRobert Mustacchi     Dwarf_Small *mspace = 0;
708*7fd79137SRobert Mustacchi 
709*7fd79137SRobert Mustacchi     ret = get_relocation_entries(obj->is_64bit,
710*7fd79137SRobert Mustacchi         obj->endianness,
711*7fd79137SRobert Mustacchi         obj->machine,
712*7fd79137SRobert Mustacchi         relocation_section,
713*7fd79137SRobert Mustacchi         relocation_section_size,
714*7fd79137SRobert Mustacchi         &relas, &nrelas, error);
715*7fd79137SRobert Mustacchi     if(ret != DW_DLV_OK) {
716*7fd79137SRobert Mustacchi         free(relas);
717*7fd79137SRobert Mustacchi         return ret;
718*7fd79137SRobert Mustacchi     }
719*7fd79137SRobert Mustacchi 
720*7fd79137SRobert Mustacchi     /* Some systems read Elf in read-only memory via mmap or the like.
721*7fd79137SRobert Mustacchi        So the only safe thing is to copy the current data into
722*7fd79137SRobert Mustacchi        malloc space and refer to the malloc space instead of the
723*7fd79137SRobert Mustacchi        space returned by the elf library */
724*7fd79137SRobert Mustacchi     mspace = malloc(relocatablesec->dss_size);
725*7fd79137SRobert Mustacchi     if(!mspace) {
726*7fd79137SRobert Mustacchi         *error = DW_DLE_RELOC_SECTION_MALLOC_FAIL;
727*7fd79137SRobert Mustacchi         return DW_DLV_ERROR;
728*7fd79137SRobert Mustacchi     }
729*7fd79137SRobert Mustacchi     memcpy(mspace,relocatablesec->dss_data,relocatablesec->dss_size);
730*7fd79137SRobert Mustacchi     relocatablesec->dss_data = mspace;
731*7fd79137SRobert Mustacchi     target_section = relocatablesec->dss_data;
732*7fd79137SRobert Mustacchi     relocatablesec->dss_data_was_malloc = 1;
733*7fd79137SRobert Mustacchi 
734*7fd79137SRobert Mustacchi     ret = apply_rela_entries(
735*7fd79137SRobert Mustacchi         dbg,
736*7fd79137SRobert Mustacchi         obj->is_64bit,
737*7fd79137SRobert Mustacchi         obj->endianness, obj->machine,
738*7fd79137SRobert Mustacchi         target_section,
739*7fd79137SRobert Mustacchi         symtab_section,
740*7fd79137SRobert Mustacchi         relas, nrelas, error);
741*7fd79137SRobert Mustacchi 
742*7fd79137SRobert Mustacchi     free(relas);
743*7fd79137SRobert Mustacchi 
744*7fd79137SRobert Mustacchi     return ret;
745*7fd79137SRobert Mustacchi }
746*7fd79137SRobert Mustacchi 
747*7fd79137SRobert Mustacchi /*
748*7fd79137SRobert Mustacchi     Find the section data in dbg and find all the relevant
749*7fd79137SRobert Mustacchi     sections.  Then do relocations.
750*7fd79137SRobert Mustacchi */
751*7fd79137SRobert Mustacchi static int
752*7fd79137SRobert Mustacchi dwarf_elf_object_relocate_a_section(void* obj_in,
753*7fd79137SRobert Mustacchi     Dwarf_Half section_index,
754*7fd79137SRobert Mustacchi     Dwarf_Debug dbg,
755*7fd79137SRobert Mustacchi     int* error)
756*7fd79137SRobert Mustacchi {
757*7fd79137SRobert Mustacchi     int res = DW_DLV_ERROR;
758*7fd79137SRobert Mustacchi     dwarf_elf_object_access_internals_t*obj = 0;
759*7fd79137SRobert Mustacchi     struct Dwarf_Section_s * relocatablesec = 0;
760*7fd79137SRobert Mustacchi     if (section_index == 0) {
761*7fd79137SRobert Mustacchi         return DW_DLV_NO_ENTRY;
762*7fd79137SRobert Mustacchi     }
763*7fd79137SRobert Mustacchi     obj = (dwarf_elf_object_access_internals_t*)obj_in;
764*7fd79137SRobert Mustacchi 
765*7fd79137SRobert Mustacchi     /* The section to relocate must already be loaded into memory. */
766*7fd79137SRobert Mustacchi     res = find_section_to_relocate(dbg, section_index,&relocatablesec,error);
767*7fd79137SRobert Mustacchi     if(res != DW_DLV_OK) {
768*7fd79137SRobert Mustacchi          return res;
769*7fd79137SRobert Mustacchi     }
770*7fd79137SRobert Mustacchi 
771*7fd79137SRobert Mustacchi     /* Sun and possibly others do not always set sh_link in .debug_* sections.
772*7fd79137SRobert Mustacchi        So we cannot do full  consistency checks. */
773*7fd79137SRobert Mustacchi     if(relocatablesec->dss_reloc_index == 0 ) {
774*7fd79137SRobert Mustacchi         /* Something is wrong. */
775*7fd79137SRobert Mustacchi         *error = DW_DLE_RELOC_SECTION_MISSING_INDEX;
776*7fd79137SRobert Mustacchi         return DW_DLV_ERROR;
777*7fd79137SRobert Mustacchi     }
778*7fd79137SRobert Mustacchi     /* Now load the relocations themselves. */
779*7fd79137SRobert Mustacchi     res =  dwarf_elf_object_access_load_section(obj_in,
780*7fd79137SRobert Mustacchi             relocatablesec->dss_reloc_index,
781*7fd79137SRobert Mustacchi             &relocatablesec->dss_reloc_data, error);
782*7fd79137SRobert Mustacchi     if(res != DW_DLV_OK) {
783*7fd79137SRobert Mustacchi             return res;
784*7fd79137SRobert Mustacchi     }
785*7fd79137SRobert Mustacchi 
786*7fd79137SRobert Mustacchi     /* Now get the symtab. */
787*7fd79137SRobert Mustacchi     if  (!obj->symtab) {
788*7fd79137SRobert Mustacchi        obj->symtab = &dbg->de_elf_symtab;
789*7fd79137SRobert Mustacchi        obj->strtab = &dbg->de_elf_strtab;
790*7fd79137SRobert Mustacchi     }
791*7fd79137SRobert Mustacchi     if( obj->symtab->dss_index != relocatablesec->dss_reloc_link) {
792*7fd79137SRobert Mustacchi         /* Something is wrong. */
793*7fd79137SRobert Mustacchi         *error = DW_DLE_RELOC_MISMATCH_RELOC_INDEX;
794*7fd79137SRobert Mustacchi         return DW_DLV_ERROR;
795*7fd79137SRobert Mustacchi     }
796*7fd79137SRobert Mustacchi     if( obj->strtab->dss_index != obj->symtab->dss_link) {
797*7fd79137SRobert Mustacchi         /* Something is wrong. */
798*7fd79137SRobert Mustacchi         *error = DW_DLE_RELOC_MISMATCH_STRTAB_INDEX;
799*7fd79137SRobert Mustacchi         return DW_DLV_ERROR;
800*7fd79137SRobert Mustacchi     }
801*7fd79137SRobert Mustacchi     if(!obj->symtab->dss_data) {
802*7fd79137SRobert Mustacchi         /* Now load the symtab */
803*7fd79137SRobert Mustacchi         res =  dwarf_elf_object_access_load_section(obj_in,
804*7fd79137SRobert Mustacchi             obj->symtab->dss_index,
805*7fd79137SRobert Mustacchi             &obj->symtab->dss_data, error);
806*7fd79137SRobert Mustacchi         if(res != DW_DLV_OK) {
807*7fd79137SRobert Mustacchi             return res;
808*7fd79137SRobert Mustacchi         }
809*7fd79137SRobert Mustacchi     }
810*7fd79137SRobert Mustacchi     if(! obj->strtab->dss_data) {
811*7fd79137SRobert Mustacchi         /* Now load the strtab */
812*7fd79137SRobert Mustacchi         res = dwarf_elf_object_access_load_section(obj_in,
813*7fd79137SRobert Mustacchi             obj->strtab->dss_index,
814*7fd79137SRobert Mustacchi             &obj->strtab->dss_data,error);
815*7fd79137SRobert Mustacchi         if(res != DW_DLV_OK){
816*7fd79137SRobert Mustacchi             return res;
817*7fd79137SRobert Mustacchi         }
818*7fd79137SRobert Mustacchi     }
819*7fd79137SRobert Mustacchi 
820*7fd79137SRobert Mustacchi     /* We have all the data we need in memory. */
821*7fd79137SRobert Mustacchi     res = loop_through_relocations(dbg,obj,relocatablesec,error);
822*7fd79137SRobert Mustacchi 
823*7fd79137SRobert Mustacchi     return res;
824*7fd79137SRobert Mustacchi }
825*7fd79137SRobert Mustacchi 
826*7fd79137SRobert Mustacchi /*
827*7fd79137SRobert Mustacchi     dwarf_elf_object_access_load_section
828*7fd79137SRobert Mustacchi  */
829*7fd79137SRobert Mustacchi static int
830*7fd79137SRobert Mustacchi dwarf_elf_object_access_load_section(void* obj_in,
831*7fd79137SRobert Mustacchi     Dwarf_Half section_index,
832*7fd79137SRobert Mustacchi     Dwarf_Small** section_data,
833*7fd79137SRobert Mustacchi     int* error)
834*7fd79137SRobert Mustacchi {
835*7fd79137SRobert Mustacchi     dwarf_elf_object_access_internals_t*obj =
836*7fd79137SRobert Mustacchi         (dwarf_elf_object_access_internals_t*)obj_in;
837*7fd79137SRobert Mustacchi     if (section_index == 0) {
838*7fd79137SRobert Mustacchi         return DW_DLV_NO_ENTRY;
839*7fd79137SRobert Mustacchi     }
840*7fd79137SRobert Mustacchi 
841*7fd79137SRobert Mustacchi     {
842*7fd79137SRobert Mustacchi         Elf_Scn *scn = 0;
843*7fd79137SRobert Mustacchi         Elf_Data *data = 0;
844*7fd79137SRobert Mustacchi 
845*7fd79137SRobert Mustacchi         scn = elf_getscn(obj->elf, section_index);
846*7fd79137SRobert Mustacchi         if (scn == NULL) {
847*7fd79137SRobert Mustacchi             *error = DW_DLE_MDE;
848*7fd79137SRobert Mustacchi             return DW_DLV_ERROR;
849*7fd79137SRobert Mustacchi         }
850*7fd79137SRobert Mustacchi 
851*7fd79137SRobert Mustacchi         /*
852*7fd79137SRobert Mustacchi            When using libelf as a producer, section data may be stored
853*7fd79137SRobert Mustacchi            in multiple buffers. In libdwarf however, we only use libelf
854*7fd79137SRobert Mustacchi            as a consumer (there is a dwarf producer API, but it doesn't
855*7fd79137SRobert Mustacchi            use libelf). Because of this, this single call to elf_getdata
856*7fd79137SRobert Mustacchi            will retrieve the entire section in a single contiguous
857*7fd79137SRobert Mustacchi            buffer. */
858*7fd79137SRobert Mustacchi         data = elf_getdata(scn, NULL);
859*7fd79137SRobert Mustacchi         if (data == NULL) {
860*7fd79137SRobert Mustacchi                   *error = DW_DLE_MDE;
861*7fd79137SRobert Mustacchi                   return DW_DLV_ERROR;
862*7fd79137SRobert Mustacchi         }
863*7fd79137SRobert Mustacchi         *section_data = data->d_buf;
864*7fd79137SRobert Mustacchi     }
865*7fd79137SRobert Mustacchi     return DW_DLV_OK;
866*7fd79137SRobert Mustacchi }
867*7fd79137SRobert Mustacchi 
868*7fd79137SRobert Mustacchi 
869*7fd79137SRobert Mustacchi /* dwarf_elf_access method table. */
870*7fd79137SRobert Mustacchi static const struct Dwarf_Obj_Access_Methods_s dwarf_elf_object_access_methods =
871*7fd79137SRobert Mustacchi {
872*7fd79137SRobert Mustacchi     dwarf_elf_object_access_get_section_info,
873*7fd79137SRobert Mustacchi     dwarf_elf_object_access_get_byte_order,
874*7fd79137SRobert Mustacchi     dwarf_elf_object_access_get_length_size,
875*7fd79137SRobert Mustacchi     dwarf_elf_object_access_get_pointer_size,
876*7fd79137SRobert Mustacchi     dwarf_elf_object_access_get_section_count,
877*7fd79137SRobert Mustacchi     dwarf_elf_object_access_load_section,
878*7fd79137SRobert Mustacchi     dwarf_elf_object_relocate_a_section
879*7fd79137SRobert Mustacchi };
880*7fd79137SRobert Mustacchi 
881*7fd79137SRobert Mustacchi 
882*7fd79137SRobert Mustacchi /*
883*7fd79137SRobert Mustacchi     Interface for the ELF object file implementation.
884*7fd79137SRobert Mustacchi  */
885*7fd79137SRobert Mustacchi int
886*7fd79137SRobert Mustacchi dwarf_elf_object_access_init(dwarf_elf_handle elf,
887*7fd79137SRobert Mustacchi     int libdwarf_owns_elf,
888*7fd79137SRobert Mustacchi     Dwarf_Obj_Access_Interface** ret_obj,
889*7fd79137SRobert Mustacchi     int *err)
890*7fd79137SRobert Mustacchi {
891*7fd79137SRobert Mustacchi     int res = 0;
892*7fd79137SRobert Mustacchi     dwarf_elf_object_access_internals_t *internals = 0;
893*7fd79137SRobert Mustacchi     Dwarf_Obj_Access_Interface *intfc = 0;
894*7fd79137SRobert Mustacchi 
895*7fd79137SRobert Mustacchi     internals = malloc(sizeof(dwarf_elf_object_access_internals_t));
896*7fd79137SRobert Mustacchi     if(!internals) {
897*7fd79137SRobert Mustacchi         /* Impossible case, we hope. Give up. */
898*7fd79137SRobert Mustacchi         return DW_DLV_ERROR;
899*7fd79137SRobert Mustacchi     }
900*7fd79137SRobert Mustacchi     memset(internals,0,sizeof(*internals));
901*7fd79137SRobert Mustacchi     res = dwarf_elf_object_access_internals_init(internals, elf, err);
902*7fd79137SRobert Mustacchi     if(res != DW_DLV_OK){
903*7fd79137SRobert Mustacchi         free(internals);
904*7fd79137SRobert Mustacchi         return DW_DLV_ERROR;
905*7fd79137SRobert Mustacchi     }
906*7fd79137SRobert Mustacchi     internals->libdwarf_owns_elf = libdwarf_owns_elf;
907*7fd79137SRobert Mustacchi 
908*7fd79137SRobert Mustacchi     intfc = malloc(sizeof(Dwarf_Obj_Access_Interface));
909*7fd79137SRobert Mustacchi     if(!intfc) {
910*7fd79137SRobert Mustacchi         /* Impossible case, we hope. Give up. */
911*7fd79137SRobert Mustacchi         free(internals);
912*7fd79137SRobert Mustacchi         return DW_DLV_ERROR;
913*7fd79137SRobert Mustacchi     }
914*7fd79137SRobert Mustacchi     /* Initialize the interface struct */
915*7fd79137SRobert Mustacchi     intfc->object = internals;
916*7fd79137SRobert Mustacchi     intfc->methods = &dwarf_elf_object_access_methods;
917*7fd79137SRobert Mustacchi 
918*7fd79137SRobert Mustacchi     *ret_obj = intfc;
919*7fd79137SRobert Mustacchi     return DW_DLV_OK;
920*7fd79137SRobert Mustacchi }
921*7fd79137SRobert Mustacchi 
922*7fd79137SRobert Mustacchi 
923*7fd79137SRobert Mustacchi 
924*7fd79137SRobert Mustacchi /*
925*7fd79137SRobert Mustacchi     Clean up the Dwarf_Obj_Access_Interface returned by elf_access_init.
926*7fd79137SRobert Mustacchi  */
927*7fd79137SRobert Mustacchi void
928*7fd79137SRobert Mustacchi dwarf_elf_object_access_finish(Dwarf_Obj_Access_Interface* obj)
929*7fd79137SRobert Mustacchi {
930*7fd79137SRobert Mustacchi     if(!obj) {
931*7fd79137SRobert Mustacchi         return;
932*7fd79137SRobert Mustacchi     }
933*7fd79137SRobert Mustacchi     if(obj->object) {
934*7fd79137SRobert Mustacchi         dwarf_elf_object_access_internals_t *internals =
935*7fd79137SRobert Mustacchi             (dwarf_elf_object_access_internals_t *)obj->object;
936*7fd79137SRobert Mustacchi         if(internals->libdwarf_owns_elf){
937*7fd79137SRobert Mustacchi             elf_end(internals->elf);
938*7fd79137SRobert Mustacchi         }
939*7fd79137SRobert Mustacchi     }
940*7fd79137SRobert Mustacchi     free(obj->object);
941*7fd79137SRobert Mustacchi     free(obj);
942*7fd79137SRobert Mustacchi }
943*7fd79137SRobert Mustacchi 
944*7fd79137SRobert Mustacchi /*
945*7fd79137SRobert Mustacchi     This function returns the Elf * pointer
946*7fd79137SRobert Mustacchi     associated with a Dwarf_Debug.
947*7fd79137SRobert Mustacchi 
948*7fd79137SRobert Mustacchi     This function only makes sense if ELF is implied.
949*7fd79137SRobert Mustacchi  */
950*7fd79137SRobert Mustacchi int
951*7fd79137SRobert Mustacchi dwarf_get_elf(Dwarf_Debug dbg, dwarf_elf_handle * elf,
952*7fd79137SRobert Mustacchi               Dwarf_Error * error)
953*7fd79137SRobert Mustacchi {
954*7fd79137SRobert Mustacchi     struct Dwarf_Obj_Access_Interface_s * obj = 0;
955*7fd79137SRobert Mustacchi     if (dbg == NULL) {
956*7fd79137SRobert Mustacchi         _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
957*7fd79137SRobert Mustacchi         return (DW_DLV_ERROR);
958*7fd79137SRobert Mustacchi     }
959*7fd79137SRobert Mustacchi 
960*7fd79137SRobert Mustacchi     obj = dbg->de_obj_file;
961*7fd79137SRobert Mustacchi     if(obj) {
962*7fd79137SRobert Mustacchi        dwarf_elf_object_access_internals_t *internals =
963*7fd79137SRobert Mustacchi            (dwarf_elf_object_access_internals_t*)obj->object;
964*7fd79137SRobert Mustacchi        if(internals->elf == NULL) {
965*7fd79137SRobert Mustacchi            _dwarf_error(dbg, error, DW_DLE_FNO);
966*7fd79137SRobert Mustacchi            return (DW_DLV_ERROR);
967*7fd79137SRobert Mustacchi        }
968*7fd79137SRobert Mustacchi        *elf = internals->elf;
969*7fd79137SRobert Mustacchi        return DW_DLV_OK;
970*7fd79137SRobert Mustacchi 
971*7fd79137SRobert Mustacchi     }
972*7fd79137SRobert Mustacchi     _dwarf_error(dbg, error, DW_DLE_FNO);
973*7fd79137SRobert Mustacchi     return DW_DLV_ERROR;
974*7fd79137SRobert Mustacchi }
975*7fd79137SRobert Mustacchi 
976*7fd79137SRobert Mustacchi 
977