107dc1947SRichard Lowe /*
207dc1947SRichard Lowe   Copyright (C) 2000-2005 Silicon Graphics, Inc.  All Rights Reserved.
307dc1947SRichard Lowe   Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
407dc1947SRichard Lowe   Portions Copyright 2008-2010 Arxan Technologies, Inc. All Rights Reserved.
5*4d9fdb46SRobert Mustacchi   Portions Copyright 2009-2019 David Anderson. All rights reserved.
607dc1947SRichard Lowe   Portions Copyright 2009-2010 Novell Inc. All rights reserved.
7*4d9fdb46SRobert Mustacchi   Portions Copyright 2012 SN Systems Ltd. All rights reserved.
8*4d9fdb46SRobert Mustacchi 
9*4d9fdb46SRobert Mustacchi   This program is free software; you can redistribute it
10*4d9fdb46SRobert Mustacchi   and/or modify it under the terms of version 2.1 of the
11*4d9fdb46SRobert Mustacchi   GNU Lesser General Public License as published by the Free
12*4d9fdb46SRobert Mustacchi   Software Foundation.
13*4d9fdb46SRobert Mustacchi 
14*4d9fdb46SRobert Mustacchi   This program is distributed in the hope that it would be
15*4d9fdb46SRobert Mustacchi   useful, but WITHOUT ANY WARRANTY; without even the implied
16*4d9fdb46SRobert Mustacchi   warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
17*4d9fdb46SRobert Mustacchi   PURPOSE.
18*4d9fdb46SRobert Mustacchi 
19*4d9fdb46SRobert Mustacchi   Further, this software is distributed without any warranty
20*4d9fdb46SRobert Mustacchi   that it is free of the rightful claim of any third person
21*4d9fdb46SRobert Mustacchi   regarding infringement or the like.  Any license provided
22*4d9fdb46SRobert Mustacchi   herein, whether implied or otherwise, applies only to this
23*4d9fdb46SRobert Mustacchi   software file.  Patent licenses, if any, provided herein
24*4d9fdb46SRobert Mustacchi   do not apply to combinations of this program with other
25*4d9fdb46SRobert Mustacchi   software, or any other product whatsoever.
26*4d9fdb46SRobert Mustacchi 
27*4d9fdb46SRobert Mustacchi   You should have received a copy of the GNU Lesser General
28*4d9fdb46SRobert Mustacchi   Public License along with this program; if not, write the
29*4d9fdb46SRobert Mustacchi   Free Software Foundation, Inc., 51 Franklin Street - Fifth
30*4d9fdb46SRobert Mustacchi   Floor, Boston MA 02110-1301, USA.
3107dc1947SRichard Lowe 
3207dc1947SRichard Lowe */
3307dc1947SRichard Lowe 
34*4d9fdb46SRobert Mustacchi /*  This file is ONLY used for libelf and with libelf
35*4d9fdb46SRobert Mustacchi     For */
36*4d9fdb46SRobert Mustacchi 
3707dc1947SRichard Lowe #include "config.h"
38*4d9fdb46SRobert Mustacchi #ifdef DWARF_WITH_LIBELF
3907dc1947SRichard Lowe #include "dwarf_incl.h"
40*4d9fdb46SRobert Mustacchi #include "dwarf_error.h"
4107dc1947SRichard Lowe #include "dwarf_elf_access.h"
42*4d9fdb46SRobert Mustacchi #include "dwarf_elf_rel_detector.h"
4307dc1947SRichard Lowe 
44*4d9fdb46SRobert Mustacchi /* Include the ELF definitions depending on system headers if any. */
45*4d9fdb46SRobert Mustacchi #include "dwarf_elf_defines.h"
4607dc1947SRichard Lowe 
4707dc1947SRichard Lowe #include <stdio.h>
4807dc1947SRichard Lowe #include <sys/stat.h>
4907dc1947SRichard Lowe #include <sys/types.h>
50*4d9fdb46SRobert Mustacchi #ifdef HAVE_UNISTD_H
51*4d9fdb46SRobert Mustacchi #include <unistd.h> /* for close */
52*4d9fdb46SRobert Mustacchi #endif /* HAVE_UNISTD_H */
5307dc1947SRichard Lowe #include <string.h>
54*4d9fdb46SRobert Mustacchi #ifdef HAVE_STDLIB_H
5507dc1947SRichard Lowe #include <stdlib.h>
56*4d9fdb46SRobert Mustacchi #endif /* HAVE_STDLIB_H */
57*4d9fdb46SRobert Mustacchi #ifdef HAVE_MALLOC_H
58*4d9fdb46SRobert Mustacchi /* Useful include for some Windows compilers. */
59*4d9fdb46SRobert Mustacchi #include <malloc.h>
60*4d9fdb46SRobert Mustacchi #endif /* HAVE_MALLOC_H */
6107dc1947SRichard Lowe 
6207dc1947SRichard Lowe #define FALSE 0
6307dc1947SRichard Lowe #define TRUE  1
6407dc1947SRichard Lowe 
6507dc1947SRichard Lowe #ifdef HAVE_ELF64_GETEHDR
6607dc1947SRichard Lowe extern Elf64_Ehdr *elf64_getehdr(Elf *);
6707dc1947SRichard Lowe #endif
6807dc1947SRichard Lowe #ifdef HAVE_ELF64_GETSHDR
6907dc1947SRichard Lowe extern Elf64_Shdr *elf64_getshdr(Elf_Scn *);
7007dc1947SRichard Lowe #endif
71*4d9fdb46SRobert Mustacchi 
7207dc1947SRichard Lowe #ifdef WORDS_BIGENDIAN
73*4d9fdb46SRobert Mustacchi #define READ_UNALIGNED_SAFE(dbg,dest, source, length) \
74*4d9fdb46SRobert Mustacchi     do {                                             \
75*4d9fdb46SRobert Mustacchi         Dwarf_Unsigned _ltmp = 0;                    \
76*4d9fdb46SRobert Mustacchi         dbg->de_copy_word( (((char *)(&_ltmp)) +     \
77*4d9fdb46SRobert Mustacchi             sizeof(_ltmp) - length),source, length); \
78*4d9fdb46SRobert Mustacchi         dest = _ltmp;                                \
79*4d9fdb46SRobert Mustacchi     } while (0)
80*4d9fdb46SRobert Mustacchi 
81*4d9fdb46SRobert Mustacchi #define WRITE_UNALIGNED_LOCAL(dbg,dest,source, srclength,len_out) \
82*4d9fdb46SRobert Mustacchi     {                                             \
83*4d9fdb46SRobert Mustacchi         dbg->de_copy_word(dest,                   \
84*4d9fdb46SRobert Mustacchi             ((char *)source) +srclength-len_out,  \
85*4d9fdb46SRobert Mustacchi             len_out) ;                            \
8607dc1947SRichard Lowe     }
8707dc1947SRichard Lowe #else /* LITTLE ENDIAN */
88*4d9fdb46SRobert Mustacchi #define READ_UNALIGNED_SAFE(dbg,dest, source, srclength) \
89*4d9fdb46SRobert Mustacchi     do  {                                     \
90*4d9fdb46SRobert Mustacchi         Dwarf_Unsigned _ltmp = 0;             \
91*4d9fdb46SRobert Mustacchi         dbg->de_copy_word( (char *)(&_ltmp),  \
92*4d9fdb46SRobert Mustacchi             source, srclength) ;              \
93*4d9fdb46SRobert Mustacchi         dest = _ltmp;                         \
94*4d9fdb46SRobert Mustacchi     } while (0)
95*4d9fdb46SRobert Mustacchi 
96*4d9fdb46SRobert Mustacchi #define WRITE_UNALIGNED_LOCAL(dbg,dest,source, srclength,len_out) \
97*4d9fdb46SRobert Mustacchi     {                               \
98*4d9fdb46SRobert Mustacchi         dbg->de_copy_word( (dest) , \
99*4d9fdb46SRobert Mustacchi             ((char *)source) ,      \
100*4d9fdb46SRobert Mustacchi             len_out) ;              \
10107dc1947SRichard Lowe     }
102*4d9fdb46SRobert Mustacchi #endif /* *-ENDIAN */
10307dc1947SRichard Lowe 
10407dc1947SRichard Lowe 
10507dc1947SRichard Lowe 
106*4d9fdb46SRobert Mustacchi /*   ident[0] == 'E' for elf when using libelf. ident[1] = 1 */
10707dc1947SRichard Lowe typedef struct {
108*4d9fdb46SRobert Mustacchi     char             ident[8];
109*4d9fdb46SRobert Mustacchi     const char *     path;
11007dc1947SRichard Lowe     int              is_64bit;
11107dc1947SRichard Lowe     Dwarf_Small      length_size;
11207dc1947SRichard Lowe     Dwarf_Small      pointer_size;
11307dc1947SRichard Lowe     Dwarf_Unsigned   section_count;
11407dc1947SRichard Lowe     Dwarf_Endianness endianness;
11507dc1947SRichard Lowe     Dwarf_Small      machine;
116*4d9fdb46SRobert Mustacchi     char             libdwarf_owns_elf;
117*4d9fdb46SRobert Mustacchi     dwarf_elf_handle elf;
11807dc1947SRichard Lowe 
119*4d9fdb46SRobert Mustacchi     Elf32_Ehdr *ehdr32;
12007dc1947SRichard Lowe #ifdef HAVE_ELF64_GETEHDR
12107dc1947SRichard Lowe     Elf64_Ehdr *ehdr64;
12207dc1947SRichard Lowe #endif
123*4d9fdb46SRobert Mustacchi     /*  Elf symtab and its strtab.  Initialized at first
124*4d9fdb46SRobert Mustacchi         call to do relocations, the actual data is in the Dwarf_Debug
125*4d9fdb46SRobert Mustacchi         struct, not allocated locally here. */
126*4d9fdb46SRobert Mustacchi     struct Dwarf_Section_s *symtab;
127*4d9fdb46SRobert Mustacchi     struct Dwarf_Section_s *strtab;
12807dc1947SRichard Lowe 
12907dc1947SRichard Lowe } dwarf_elf_object_access_internals_t;
13007dc1947SRichard Lowe 
131*4d9fdb46SRobert Mustacchi /*  Using this for rel and rela.
132*4d9fdb46SRobert Mustacchi     For Rel, r_addend is left zero and not used.
133*4d9fdb46SRobert Mustacchi */
13407dc1947SRichard Lowe struct Dwarf_Elf_Rela {
135*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned r_offset;
136*4d9fdb46SRobert Mustacchi     /*Dwarf_Unsigned r_info; */
137*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned r_type;
138*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned r_symidx;
139*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned r_addend;
140*4d9fdb46SRobert Mustacchi     /* if is_rela is non-zero r_addend is meaningless */
141*4d9fdb46SRobert Mustacchi     char  r_is_rela;
14207dc1947SRichard Lowe };
14307dc1947SRichard Lowe 
14407dc1947SRichard Lowe 
145*4d9fdb46SRobert Mustacchi static int dwarf_elf_object_access_load_section(void* obj_in,
146*4d9fdb46SRobert Mustacchi     Dwarf_Half section_index,
147*4d9fdb46SRobert Mustacchi     Dwarf_Small** section_data,
14807dc1947SRichard Lowe     int* error);
14907dc1947SRichard Lowe 
150*4d9fdb46SRobert Mustacchi /*  dwarf_elf_object_access_internals_init()
151*4d9fdb46SRobert Mustacchi     On error, set *error with libdwarf error code.
152*4d9fdb46SRobert Mustacchi */
153*4d9fdb46SRobert Mustacchi static int
dwarf_elf_object_access_internals_init(void * obj_in,dwarf_elf_handle elf,int * error)154*4d9fdb46SRobert Mustacchi dwarf_elf_object_access_internals_init(void* obj_in,
155*4d9fdb46SRobert Mustacchi     dwarf_elf_handle elf,
156*4d9fdb46SRobert Mustacchi     int* error)
15707dc1947SRichard Lowe {
158*4d9fdb46SRobert Mustacchi     dwarf_elf_object_access_internals_t*obj =
15907dc1947SRichard Lowe         (dwarf_elf_object_access_internals_t*)obj_in;
16007dc1947SRichard Lowe     char *ehdr_ident = 0;
16107dc1947SRichard Lowe     Dwarf_Half machine = 0;
16207dc1947SRichard Lowe     obj->elf = elf;
16307dc1947SRichard Lowe 
16407dc1947SRichard Lowe     if ((ehdr_ident = elf_getident(elf, NULL)) == NULL) {
16507dc1947SRichard Lowe         *error = DW_DLE_ELF_GETIDENT_ERROR;
16607dc1947SRichard Lowe         return DW_DLV_ERROR;
16707dc1947SRichard Lowe     }
16807dc1947SRichard Lowe 
16907dc1947SRichard Lowe     obj->is_64bit = (ehdr_ident[EI_CLASS] == ELFCLASS64);
17007dc1947SRichard Lowe 
17107dc1947SRichard Lowe 
172*4d9fdb46SRobert Mustacchi     if (ehdr_ident[EI_DATA] == ELFDATA2LSB){
17307dc1947SRichard Lowe         obj->endianness = DW_OBJECT_LSB;
174*4d9fdb46SRobert Mustacchi     } else if (ehdr_ident[EI_DATA] == ELFDATA2MSB){
17507dc1947SRichard Lowe         obj->endianness = DW_OBJECT_MSB;
17607dc1947SRichard Lowe     }
17707dc1947SRichard Lowe 
17807dc1947SRichard Lowe     if (obj->is_64bit) {
17907dc1947SRichard Lowe #ifdef HAVE_ELF64_GETEHDR
18007dc1947SRichard Lowe         obj->ehdr64 = elf64_getehdr(elf);
18107dc1947SRichard Lowe         if (obj->ehdr64 == NULL) {
18207dc1947SRichard Lowe             *error = DW_DLE_ELF_GETEHDR_ERROR;
18307dc1947SRichard Lowe             return DW_DLV_ERROR;
18407dc1947SRichard Lowe         }
18507dc1947SRichard Lowe         obj->section_count = obj->ehdr64->e_shnum;
18607dc1947SRichard Lowe         machine = obj->ehdr64->e_machine;
18707dc1947SRichard Lowe         obj->machine = machine;
18807dc1947SRichard Lowe #else
18907dc1947SRichard Lowe         *error = DW_DLE_NO_ELF64_SUPPORT;
19007dc1947SRichard Lowe         return DW_DLV_ERROR;
19107dc1947SRichard Lowe #endif
192*4d9fdb46SRobert Mustacchi     } else {
19307dc1947SRichard Lowe         obj->ehdr32 = elf32_getehdr(elf);
19407dc1947SRichard Lowe         if (obj->ehdr32 == NULL) {
195*4d9fdb46SRobert Mustacchi             *error = DW_DLE_ELF_GETEHDR_ERROR;
196*4d9fdb46SRobert Mustacchi             return DW_DLV_ERROR;
19707dc1947SRichard Lowe         }
19807dc1947SRichard Lowe         obj->section_count = obj->ehdr32->e_shnum;
19907dc1947SRichard Lowe         machine = obj->ehdr32->e_machine;
20007dc1947SRichard Lowe         obj->machine = machine;
20107dc1947SRichard Lowe     }
20207dc1947SRichard Lowe 
203*4d9fdb46SRobert Mustacchi     /*  The following length_size is Not Too Significant. Only used
204*4d9fdb46SRobert Mustacchi         one calculation, and an approximate one at that. */
20507dc1947SRichard Lowe     obj->length_size = obj->is_64bit ? 8 : 4;
206*4d9fdb46SRobert Mustacchi     obj->pointer_size = obj->is_64bit ? 8 : 4;
207*4d9fdb46SRobert Mustacchi     obj->ident[0] = 'E';
208*4d9fdb46SRobert Mustacchi     obj->ident[1] = 1;
209*4d9fdb46SRobert Mustacchi 
210*4d9fdb46SRobert Mustacchi #ifdef _WIN32
211*4d9fdb46SRobert Mustacchi     if (obj->is_64bit && machine == EM_PPC64) {
212*4d9fdb46SRobert Mustacchi         /*  The SNC compiler generates the EM_PPC64 machine type for the
213*4d9fdb46SRobert Mustacchi             PS3 platform, but is a 32 bits pointer size in user mode. */
214*4d9fdb46SRobert Mustacchi         obj->pointer_size = 4;
215*4d9fdb46SRobert Mustacchi     }
216*4d9fdb46SRobert Mustacchi #endif /* _WIN32 */
21707dc1947SRichard Lowe 
21807dc1947SRichard Lowe     if (obj->is_64bit && machine != EM_MIPS) {
219*4d9fdb46SRobert Mustacchi         /*  MIPS/IRIX makes pointer size and length size 8 for -64.
220*4d9fdb46SRobert Mustacchi             Other platforms make length 4 always. */
221*4d9fdb46SRobert Mustacchi         /*  4 here supports 32bit-offset dwarf2, as emitted by cygnus
222*4d9fdb46SRobert Mustacchi             tools, and the dwarfv2.1 64bit extension setting.
223*4d9fdb46SRobert Mustacchi             This is not the same as the size-of-an-offset, which
224*4d9fdb46SRobert Mustacchi             is 4 in 32bit dwarf and 8 in 64bit dwarf.  */
22507dc1947SRichard Lowe         obj->length_size = 4;
22607dc1947SRichard Lowe     }
22707dc1947SRichard Lowe     return DW_DLV_OK;
22807dc1947SRichard Lowe }
22907dc1947SRichard Lowe 
230*4d9fdb46SRobert Mustacchi /* dwarf_elf_object_access_get_byte_order */
23107dc1947SRichard Lowe static
232*4d9fdb46SRobert Mustacchi Dwarf_Endianness
dwarf_elf_object_access_get_byte_order(void * obj_in)23307dc1947SRichard Lowe dwarf_elf_object_access_get_byte_order(void* obj_in)
23407dc1947SRichard Lowe {
235*4d9fdb46SRobert Mustacchi     dwarf_elf_object_access_internals_t*obj =
23607dc1947SRichard Lowe         (dwarf_elf_object_access_internals_t*)obj_in;
23707dc1947SRichard Lowe     return obj->endianness;
23807dc1947SRichard Lowe }
23907dc1947SRichard Lowe 
240*4d9fdb46SRobert Mustacchi /* dwarf_elf_object_access_get_section_count() */
24107dc1947SRichard Lowe static
242*4d9fdb46SRobert Mustacchi Dwarf_Unsigned
dwarf_elf_object_access_get_section_count(void * obj_in)24307dc1947SRichard Lowe dwarf_elf_object_access_get_section_count(void * obj_in)
24407dc1947SRichard Lowe {
245*4d9fdb46SRobert Mustacchi     dwarf_elf_object_access_internals_t*obj =
24607dc1947SRichard Lowe         (dwarf_elf_object_access_internals_t*)obj_in;
24707dc1947SRichard Lowe     return obj->section_count;
24807dc1947SRichard Lowe }
24907dc1947SRichard Lowe 
25007dc1947SRichard Lowe 
251*4d9fdb46SRobert Mustacchi static int
_dwarf_get_elf_flags_func(void * obj_in,Dwarf_Half section_index,Dwarf_Unsigned * flags_out,Dwarf_Unsigned * addralign_out,int * error)252*4d9fdb46SRobert Mustacchi _dwarf_get_elf_flags_func(
253*4d9fdb46SRobert Mustacchi     void* obj_in,
254*4d9fdb46SRobert Mustacchi     Dwarf_Half section_index,
255*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned *flags_out,
256*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned *addralign_out,
257*4d9fdb46SRobert Mustacchi     int *error)
258*4d9fdb46SRobert Mustacchi {
259*4d9fdb46SRobert Mustacchi    dwarf_elf_object_access_internals_t*obj =
260*4d9fdb46SRobert Mustacchi         (dwarf_elf_object_access_internals_t*)obj_in;
261*4d9fdb46SRobert Mustacchi 
262*4d9fdb46SRobert Mustacchi     Elf32_Shdr *shdr32 = 0;
263*4d9fdb46SRobert Mustacchi 
264*4d9fdb46SRobert Mustacchi #ifdef HAVE_ELF64_GETSHDR
265*4d9fdb46SRobert Mustacchi     Elf64_Shdr *shdr64 = 0;
266*4d9fdb46SRobert Mustacchi #endif
267*4d9fdb46SRobert Mustacchi     Elf_Scn *scn = 0;
268*4d9fdb46SRobert Mustacchi 
269*4d9fdb46SRobert Mustacchi 
270*4d9fdb46SRobert Mustacchi     scn = elf_getscn(obj->elf, section_index);
271*4d9fdb46SRobert Mustacchi     if (scn == NULL) {
272*4d9fdb46SRobert Mustacchi         *error = DW_DLE_MDE;
273*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
274*4d9fdb46SRobert Mustacchi     }
275*4d9fdb46SRobert Mustacchi     if (obj->is_64bit) {
276*4d9fdb46SRobert Mustacchi #ifdef HAVE_ELF64_GETSHDR
277*4d9fdb46SRobert Mustacchi         shdr64 = elf64_getshdr(scn);
278*4d9fdb46SRobert Mustacchi         if (shdr64 == NULL) {
279*4d9fdb46SRobert Mustacchi             *error = DW_DLE_ELF_GETSHDR_ERROR;
280*4d9fdb46SRobert Mustacchi             return DW_DLV_ERROR;
281*4d9fdb46SRobert Mustacchi         }
282*4d9fdb46SRobert Mustacchi 
283*4d9fdb46SRobert Mustacchi         /*  Get also section 'sh_type' and sh_info' fields, so the caller
284*4d9fdb46SRobert Mustacchi             can use it for additional tasks that require that info. */
285*4d9fdb46SRobert Mustacchi         *flags_out = shdr64->sh_flags;
286*4d9fdb46SRobert Mustacchi         *addralign_out = shdr64->sh_addralign;
287*4d9fdb46SRobert Mustacchi         return DW_DLV_OK;
288*4d9fdb46SRobert Mustacchi #else
289*4d9fdb46SRobert Mustacchi         *error = DW_DLE_MISSING_ELF64_SUPPORT;
290*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
291*4d9fdb46SRobert Mustacchi #endif /* HAVE_ELF64_GETSHDR */
292*4d9fdb46SRobert Mustacchi     }
293*4d9fdb46SRobert Mustacchi     if ((shdr32 = elf32_getshdr(scn)) == NULL) {
294*4d9fdb46SRobert Mustacchi         *error = DW_DLE_ELF_GETSHDR_ERROR;
295*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
296*4d9fdb46SRobert Mustacchi     }
297*4d9fdb46SRobert Mustacchi 
298*4d9fdb46SRobert Mustacchi     /*  Get also the section type, so the caller can use it for
299*4d9fdb46SRobert Mustacchi         additional tasks that require to know the section type. */
300*4d9fdb46SRobert Mustacchi     *flags_out = shdr32->sh_flags;
301*4d9fdb46SRobert Mustacchi     *addralign_out = shdr32->sh_addralign;
302*4d9fdb46SRobert Mustacchi     return DW_DLV_OK;
303*4d9fdb46SRobert Mustacchi }
304*4d9fdb46SRobert Mustacchi 
305*4d9fdb46SRobert Mustacchi 
306*4d9fdb46SRobert Mustacchi /*  dwarf_elf_object_access_get_section()
307*4d9fdb46SRobert Mustacchi 
308*4d9fdb46SRobert Mustacchi     If writing a function vaguely like this for a non-elf object,
309*4d9fdb46SRobert Mustacchi     be sure that when section-index is passed in as zero that
310*4d9fdb46SRobert Mustacchi     you set the fields in *ret_scn_doas to reflect an empty section
311*4d9fdb46SRobert Mustacchi     with an empty string as the section name.  Adjust your
312*4d9fdb46SRobert Mustacchi     section indexes of your non-elf-reading-code
313*4d9fdb46SRobert Mustacchi     for all the necessary functions in Dwarf_Obj_Access_Methods_s
314*4d9fdb46SRobert Mustacchi     accordingly.
315*4d9fdb46SRobert Mustacchi 
316*4d9fdb46SRobert Mustacchi     Should have gotten sh_flags, sh_addralign too.
317*4d9fdb46SRobert Mustacchi     But Dwarf_Obj_Access_Section is publically defined so changing
318*4d9fdb46SRobert Mustacchi     it is quite painful for everyone.
319*4d9fdb46SRobert Mustacchi */
320*4d9fdb46SRobert Mustacchi static
321*4d9fdb46SRobert Mustacchi int
dwarf_elf_object_access_get_section_info(void * obj_in,Dwarf_Half section_index,Dwarf_Obj_Access_Section * ret_scn_doas,int * error)32207dc1947SRichard Lowe dwarf_elf_object_access_get_section_info(
323*4d9fdb46SRobert Mustacchi     void* obj_in,
324*4d9fdb46SRobert Mustacchi     Dwarf_Half section_index,
325*4d9fdb46SRobert Mustacchi     Dwarf_Obj_Access_Section* ret_scn_doas,
32607dc1947SRichard Lowe     int* error)
32707dc1947SRichard Lowe {
328*4d9fdb46SRobert Mustacchi     dwarf_elf_object_access_internals_t*obj =
32907dc1947SRichard Lowe         (dwarf_elf_object_access_internals_t*)obj_in;
33007dc1947SRichard Lowe 
33107dc1947SRichard Lowe     Elf32_Shdr *shdr32 = 0;
33207dc1947SRichard Lowe 
33307dc1947SRichard Lowe #ifdef HAVE_ELF64_GETSHDR
33407dc1947SRichard Lowe     Elf64_Shdr *shdr64 = 0;
33507dc1947SRichard Lowe #endif
33607dc1947SRichard Lowe     Elf_Scn *scn = 0;
33707dc1947SRichard Lowe 
33807dc1947SRichard Lowe 
33907dc1947SRichard Lowe     scn = elf_getscn(obj->elf, section_index);
34007dc1947SRichard Lowe     if (scn == NULL) {
34107dc1947SRichard Lowe         *error = DW_DLE_MDE;
34207dc1947SRichard Lowe         return DW_DLV_ERROR;
34307dc1947SRichard Lowe     }
34407dc1947SRichard Lowe     if (obj->is_64bit) {
34507dc1947SRichard Lowe #ifdef HAVE_ELF64_GETSHDR
34607dc1947SRichard Lowe         shdr64 = elf64_getshdr(scn);
34707dc1947SRichard Lowe         if (shdr64 == NULL) {
34807dc1947SRichard Lowe             *error = DW_DLE_ELF_GETSHDR_ERROR;
34907dc1947SRichard Lowe             return DW_DLV_ERROR;
35007dc1947SRichard Lowe         }
35107dc1947SRichard Lowe 
352*4d9fdb46SRobert Mustacchi         /*  Get also section 'sh_type' and sh_info' fields, so the caller
353*4d9fdb46SRobert Mustacchi             can use it for additional tasks that require that info. */
354*4d9fdb46SRobert Mustacchi         ret_scn_doas->type = shdr64->sh_type;
355*4d9fdb46SRobert Mustacchi         ret_scn_doas->size = shdr64->sh_size;
356*4d9fdb46SRobert Mustacchi         ret_scn_doas->addr = shdr64->sh_addr;
357*4d9fdb46SRobert Mustacchi         ret_scn_doas->link = shdr64->sh_link;
358*4d9fdb46SRobert Mustacchi         ret_scn_doas->info = shdr64->sh_info;
359*4d9fdb46SRobert Mustacchi         ret_scn_doas->entrysize = shdr64->sh_entsize;
360*4d9fdb46SRobert Mustacchi         ret_scn_doas->name = elf_strptr(obj->elf, obj->ehdr64->e_shstrndx,
361*4d9fdb46SRobert Mustacchi             shdr64->sh_name);
362*4d9fdb46SRobert Mustacchi         if (ret_scn_doas->name == NULL) {
36307dc1947SRichard Lowe             *error = DW_DLE_ELF_STRPTR_ERROR;
36407dc1947SRichard Lowe             return DW_DLV_ERROR;
36507dc1947SRichard Lowe         }
36607dc1947SRichard Lowe         return DW_DLV_OK;
36707dc1947SRichard Lowe #else
36807dc1947SRichard Lowe         *error = DW_DLE_MISSING_ELF64_SUPPORT;
36907dc1947SRichard Lowe         return DW_DLV_ERROR;
37007dc1947SRichard Lowe #endif /* HAVE_ELF64_GETSHDR */
371*4d9fdb46SRobert Mustacchi     }
37207dc1947SRichard Lowe     if ((shdr32 = elf32_getshdr(scn)) == NULL) {
37307dc1947SRichard Lowe         *error = DW_DLE_ELF_GETSHDR_ERROR;
37407dc1947SRichard Lowe         return DW_DLV_ERROR;
37507dc1947SRichard Lowe     }
37607dc1947SRichard Lowe 
377*4d9fdb46SRobert Mustacchi     /*  Get also the section type, so the caller can use it for
378*4d9fdb46SRobert Mustacchi         additional tasks that require to know the section type. */
379*4d9fdb46SRobert Mustacchi     ret_scn_doas->type = shdr32->sh_type;
380*4d9fdb46SRobert Mustacchi     ret_scn_doas->size = shdr32->sh_size;
381*4d9fdb46SRobert Mustacchi     ret_scn_doas->addr = shdr32->sh_addr;
382*4d9fdb46SRobert Mustacchi     ret_scn_doas->link = shdr32->sh_link;
383*4d9fdb46SRobert Mustacchi     ret_scn_doas->info = shdr32->sh_info;
384*4d9fdb46SRobert Mustacchi     ret_scn_doas->entrysize = shdr32->sh_entsize;
385*4d9fdb46SRobert Mustacchi     ret_scn_doas->name = elf_strptr(obj->elf, obj->ehdr32->e_shstrndx,
38607dc1947SRichard Lowe         shdr32->sh_name);
387*4d9fdb46SRobert Mustacchi     if (ret_scn_doas->name == NULL) {
38807dc1947SRichard Lowe         *error = DW_DLE_ELF_STRPTR_ERROR;
38907dc1947SRichard Lowe         return DW_DLV_ERROR;
39007dc1947SRichard Lowe     }
39107dc1947SRichard Lowe     return DW_DLV_OK;
39207dc1947SRichard Lowe }
39307dc1947SRichard Lowe 
394*4d9fdb46SRobert Mustacchi /* dwarf_elf_object_access_get_length_size */
39507dc1947SRichard Lowe static
396*4d9fdb46SRobert Mustacchi Dwarf_Small
dwarf_elf_object_access_get_length_size(void * obj_in)39707dc1947SRichard Lowe dwarf_elf_object_access_get_length_size(void* obj_in)
39807dc1947SRichard Lowe {
399*4d9fdb46SRobert Mustacchi     dwarf_elf_object_access_internals_t*obj =
40007dc1947SRichard Lowe         (dwarf_elf_object_access_internals_t*)obj_in;
40107dc1947SRichard Lowe     return obj->length_size;
40207dc1947SRichard Lowe }
40307dc1947SRichard Lowe 
404*4d9fdb46SRobert Mustacchi /* dwarf_elf_object_access_get_pointer_size */
40507dc1947SRichard Lowe static
406*4d9fdb46SRobert Mustacchi Dwarf_Small
dwarf_elf_object_access_get_pointer_size(void * obj_in)40707dc1947SRichard Lowe dwarf_elf_object_access_get_pointer_size(void* obj_in)
40807dc1947SRichard Lowe {
409*4d9fdb46SRobert Mustacchi     dwarf_elf_object_access_internals_t*obj =
41007dc1947SRichard Lowe         (dwarf_elf_object_access_internals_t*)obj_in;
41107dc1947SRichard Lowe     return obj->pointer_size;
41207dc1947SRichard Lowe }
41307dc1947SRichard Lowe 
41407dc1947SRichard Lowe #define MATCH_REL_SEC(i_,s_,r_)  \
415*4d9fdb46SRobert Mustacchi if (i_ == s_.dss_index) { \
41607dc1947SRichard Lowe     *r_ = &s_;            \
41707dc1947SRichard Lowe     return DW_DLV_OK;    \
41807dc1947SRichard Lowe }
41907dc1947SRichard Lowe 
42007dc1947SRichard Lowe static int
find_section_to_relocate(Dwarf_Debug dbg,Dwarf_Half section_index,struct Dwarf_Section_s ** relocatablesec,int * error)42107dc1947SRichard Lowe find_section_to_relocate(Dwarf_Debug dbg,Dwarf_Half section_index,
42207dc1947SRichard Lowe    struct Dwarf_Section_s **relocatablesec, int *error)
42307dc1947SRichard Lowe {
42407dc1947SRichard Lowe     MATCH_REL_SEC(section_index,dbg->de_debug_info,relocatablesec);
42507dc1947SRichard Lowe     MATCH_REL_SEC(section_index,dbg->de_debug_abbrev,relocatablesec);
42607dc1947SRichard Lowe     MATCH_REL_SEC(section_index,dbg->de_debug_line,relocatablesec);
42707dc1947SRichard Lowe     MATCH_REL_SEC(section_index,dbg->de_debug_loc,relocatablesec);
42807dc1947SRichard Lowe     MATCH_REL_SEC(section_index,dbg->de_debug_aranges,relocatablesec);
42907dc1947SRichard Lowe     MATCH_REL_SEC(section_index,dbg->de_debug_macinfo,relocatablesec);
43007dc1947SRichard Lowe     MATCH_REL_SEC(section_index,dbg->de_debug_pubnames,relocatablesec);
43107dc1947SRichard Lowe     MATCH_REL_SEC(section_index,dbg->de_debug_ranges,relocatablesec);
43207dc1947SRichard Lowe     MATCH_REL_SEC(section_index,dbg->de_debug_frame,relocatablesec);
43307dc1947SRichard Lowe     MATCH_REL_SEC(section_index,dbg->de_debug_frame_eh_gnu,relocatablesec);
43407dc1947SRichard Lowe     MATCH_REL_SEC(section_index,dbg->de_debug_pubtypes,relocatablesec);
43507dc1947SRichard Lowe     MATCH_REL_SEC(section_index,dbg->de_debug_funcnames,relocatablesec);
43607dc1947SRichard Lowe     MATCH_REL_SEC(section_index,dbg->de_debug_typenames,relocatablesec);
43707dc1947SRichard Lowe     MATCH_REL_SEC(section_index,dbg->de_debug_varnames,relocatablesec);
43807dc1947SRichard Lowe     MATCH_REL_SEC(section_index,dbg->de_debug_weaknames,relocatablesec);
439*4d9fdb46SRobert Mustacchi     MATCH_REL_SEC(section_index,dbg->de_debug_types,relocatablesec);
440*4d9fdb46SRobert Mustacchi     MATCH_REL_SEC(section_index,dbg->de_debug_macro,relocatablesec);
441*4d9fdb46SRobert Mustacchi     MATCH_REL_SEC(section_index,dbg->de_debug_rnglists,relocatablesec);
442*4d9fdb46SRobert Mustacchi     MATCH_REL_SEC(section_index,dbg->de_debug_loclists,relocatablesec);
443*4d9fdb46SRobert Mustacchi     MATCH_REL_SEC(section_index,dbg->de_debug_aranges,relocatablesec);
444*4d9fdb46SRobert Mustacchi     MATCH_REL_SEC(section_index,dbg->de_debug_sup,relocatablesec);
445*4d9fdb46SRobert Mustacchi     MATCH_REL_SEC(section_index,dbg->de_debug_str_offsets,relocatablesec);
446*4d9fdb46SRobert Mustacchi     MATCH_REL_SEC(section_index,dbg->de_debug_addr,relocatablesec);
447*4d9fdb46SRobert Mustacchi     /* dbg-> de_debug_tu_index,reloctablesec); */
448*4d9fdb46SRobert Mustacchi     /* dbg-> de_debug_cu_index,reloctablesec); */
449*4d9fdb46SRobert Mustacchi     /* dbg-> de_debug_gdbindex,reloctablesec); */
45007dc1947SRichard Lowe     /* dbg-> de_debug_str,syms); */
45107dc1947SRichard Lowe     /* de_elf_symtab,syms); */
45207dc1947SRichard Lowe     /* de_elf_strtab,syms); */
45307dc1947SRichard Lowe     *error = DW_DLE_RELOC_SECTION_MISMATCH;
45407dc1947SRichard Lowe     return DW_DLV_ERROR;
455*4d9fdb46SRobert Mustacchi 
45607dc1947SRichard Lowe }
45707dc1947SRichard Lowe #undef MATCH_REL_SEC
45807dc1947SRichard Lowe 
45907dc1947SRichard Lowe static void
get_rela_elf32(Dwarf_Small * data,unsigned int i,UNUSEDARG int endianness,UNUSEDARG int machine,struct Dwarf_Elf_Rela * relap)46007dc1947SRichard Lowe get_rela_elf32(Dwarf_Small *data, unsigned int i,
461*4d9fdb46SRobert Mustacchi   UNUSEDARG int endianness,
462*4d9fdb46SRobert Mustacchi   UNUSEDARG int machine,
463*4d9fdb46SRobert Mustacchi   struct Dwarf_Elf_Rela *relap)
46407dc1947SRichard Lowe {
465*4d9fdb46SRobert Mustacchi     Elf32_Rela *relp = 0;
466*4d9fdb46SRobert Mustacchi 
467*4d9fdb46SRobert Mustacchi     relp = (Elf32_Rela*)(data + (i * sizeof(Elf32_Rela)));
46807dc1947SRichard Lowe     relap->r_offset = relp->r_offset;
469*4d9fdb46SRobert Mustacchi     /* relap->r_info = relp->r_info; */
47007dc1947SRichard Lowe     relap->r_type = ELF32_R_TYPE(relp->r_info);
47107dc1947SRichard Lowe     relap->r_symidx = ELF32_R_SYM(relp->r_info);
472*4d9fdb46SRobert Mustacchi     relap->r_is_rela = TRUE;
47307dc1947SRichard Lowe     relap->r_addend = relp->r_addend;
47407dc1947SRichard Lowe }
475*4d9fdb46SRobert Mustacchi static void
get_rel_elf32(Dwarf_Small * data,unsigned int i,UNUSEDARG int endianness,UNUSEDARG int machine,struct Dwarf_Elf_Rela * relap)476*4d9fdb46SRobert Mustacchi get_rel_elf32(Dwarf_Small *data, unsigned int i,
477*4d9fdb46SRobert Mustacchi   UNUSEDARG int endianness,
478*4d9fdb46SRobert Mustacchi   UNUSEDARG int machine,
479*4d9fdb46SRobert Mustacchi   struct Dwarf_Elf_Rela *relap)
480*4d9fdb46SRobert Mustacchi {
481*4d9fdb46SRobert Mustacchi     Elf32_Rel *relp = 0;
482*4d9fdb46SRobert Mustacchi 
483*4d9fdb46SRobert Mustacchi     relp = (Elf32_Rel*)(data + (i * sizeof(Elf32_Rel)));
484*4d9fdb46SRobert Mustacchi     relap->r_offset = relp->r_offset;
485*4d9fdb46SRobert Mustacchi     /* relap->r_info = relp->r_info; */
486*4d9fdb46SRobert Mustacchi     relap->r_type = ELF32_R_TYPE(relp->r_info);
487*4d9fdb46SRobert Mustacchi     relap->r_symidx = ELF32_R_SYM(relp->r_info);
488*4d9fdb46SRobert Mustacchi     relap->r_is_rela = FALSE;
489*4d9fdb46SRobert Mustacchi     relap->r_addend = 0;
490*4d9fdb46SRobert Mustacchi }
491*4d9fdb46SRobert Mustacchi 
49207dc1947SRichard Lowe 
49307dc1947SRichard Lowe static void
get_rela_elf64(Dwarf_Small * data,unsigned int i,int endianness,int machine,struct Dwarf_Elf_Rela * relap)494*4d9fdb46SRobert Mustacchi get_rela_elf64(Dwarf_Small *data, unsigned int i,
49507dc1947SRichard Lowe   int endianness,
496*4d9fdb46SRobert Mustacchi   int machine,
497*4d9fdb46SRobert Mustacchi   struct Dwarf_Elf_Rela *relap)
49807dc1947SRichard Lowe {
49907dc1947SRichard Lowe #ifdef HAVE_ELF64_RELA
500*4d9fdb46SRobert Mustacchi     Elf64_Rela * relp = 0;
501*4d9fdb46SRobert Mustacchi     relp = (Elf64_Rela*)(data + (i * sizeof(Elf64_Rela)));
50207dc1947SRichard Lowe     relap->r_offset = relp->r_offset;
503*4d9fdb46SRobert Mustacchi     /* relap->r_info = relp->r_info; */
50407dc1947SRichard Lowe #define ELF64MIPS_REL_SYM(i) ((i) & 0xffffffff)
50507dc1947SRichard Lowe #define ELF64MIPS_REL_TYPE(i) ((i >> 56) &0xff)
506*4d9fdb46SRobert Mustacchi     if (machine == EM_MIPS && endianness == DW_OBJECT_LSB ){
507*4d9fdb46SRobert Mustacchi         /*  This is really wierd. Treat this very specially.
508*4d9fdb46SRobert Mustacchi             The Elf64 LE MIPS object used for
509*4d9fdb46SRobert Mustacchi             testing (that has rela) wants the
510*4d9fdb46SRobert Mustacchi             values as  sym  ssym type3 type2 type, treating
511*4d9fdb46SRobert Mustacchi             each value as independent value. But libelf xlate
512*4d9fdb46SRobert Mustacchi             treats it as something else so we fudge here.
513*4d9fdb46SRobert Mustacchi             It is unclear
514*4d9fdb46SRobert Mustacchi             how to precisely characterize where these relocations
515*4d9fdb46SRobert Mustacchi             were used.
516*4d9fdb46SRobert Mustacchi             SGI MIPS on IRIX never used .rela relocations.
517*4d9fdb46SRobert Mustacchi             The BE 64bit elf MIPS test object with rela uses traditional
518*4d9fdb46SRobert Mustacchi             elf relocation layouts, not this special case.  */
519*4d9fdb46SRobert Mustacchi         /*  We ignore the special TYPE2 and TYPE3, they should be
520*4d9fdb46SRobert Mustacchi             value R_MIPS_NONE in rela. */
52107dc1947SRichard Lowe         relap->r_type = ELF64MIPS_REL_TYPE(relp->r_info);
52207dc1947SRichard Lowe         relap->r_symidx = ELF64MIPS_REL_SYM(relp->r_info);
52307dc1947SRichard Lowe #undef MIPS64SYM
52407dc1947SRichard Lowe #undef MIPS64TYPE
525*4d9fdb46SRobert Mustacchi     } else
52607dc1947SRichard Lowe     {
52707dc1947SRichard Lowe         relap->r_type = ELF64_R_TYPE(relp->r_info);
52807dc1947SRichard Lowe         relap->r_symidx = ELF64_R_SYM(relp->r_info);
52907dc1947SRichard Lowe     }
53007dc1947SRichard Lowe     relap->r_addend = relp->r_addend;
531*4d9fdb46SRobert Mustacchi     relap->r_is_rela = TRUE;
53207dc1947SRichard Lowe #endif
53307dc1947SRichard Lowe }
53407dc1947SRichard Lowe 
53507dc1947SRichard Lowe static void
get_rel_elf64(Dwarf_Small * data,unsigned int i,int endianness,int machine,struct Dwarf_Elf_Rela * relap)536*4d9fdb46SRobert Mustacchi get_rel_elf64(Dwarf_Small *data, unsigned int i,
537*4d9fdb46SRobert Mustacchi   int endianness,
538*4d9fdb46SRobert Mustacchi   int machine,
539*4d9fdb46SRobert Mustacchi   struct Dwarf_Elf_Rela *relap)
540*4d9fdb46SRobert Mustacchi {
541*4d9fdb46SRobert Mustacchi #ifdef HAVE_ELF64_RELA
542*4d9fdb46SRobert Mustacchi     Elf64_Rel * relp = 0;
543*4d9fdb46SRobert Mustacchi     relp = (Elf64_Rel*)(data + (i * sizeof(Elf64_Rel)));
544*4d9fdb46SRobert Mustacchi     relap->r_offset = relp->r_offset;
545*4d9fdb46SRobert Mustacchi     /* relap->r_info = relp->r_info; */
546*4d9fdb46SRobert Mustacchi #define ELF64MIPS_REL_SYM(i) ((i) & 0xffffffff)
547*4d9fdb46SRobert Mustacchi #define ELF64MIPS_REL_TYPE(i) ((i >> 56) &0xff)
548*4d9fdb46SRobert Mustacchi     if (machine == EM_MIPS && endianness == DW_OBJECT_LSB ){
549*4d9fdb46SRobert Mustacchi         /*  This is really wierd. Treat this very specially.
550*4d9fdb46SRobert Mustacchi             The Elf64 LE MIPS object used for
551*4d9fdb46SRobert Mustacchi             testing (that has rela) wants the
552*4d9fdb46SRobert Mustacchi             values as  sym  ssym type3 type2 type, treating
553*4d9fdb46SRobert Mustacchi             each value as independent value. But libelf xlate
554*4d9fdb46SRobert Mustacchi             treats it as something else so we fudge here.
555*4d9fdb46SRobert Mustacchi             It is unclear
556*4d9fdb46SRobert Mustacchi             how to precisely characterize where these relocations
557*4d9fdb46SRobert Mustacchi             were used.
558*4d9fdb46SRobert Mustacchi             SGI MIPS on IRIX never used .rela relocations.
559*4d9fdb46SRobert Mustacchi             The BE 64bit elf MIPS test object with rela uses traditional
560*4d9fdb46SRobert Mustacchi             elf relocation layouts, not this special case.  */
561*4d9fdb46SRobert Mustacchi         /*  We ignore the special TYPE2 and TYPE3, they should be
562*4d9fdb46SRobert Mustacchi             value R_MIPS_NONE in rela. */
563*4d9fdb46SRobert Mustacchi         relap->r_type = ELF64MIPS_REL_TYPE(relp->r_info);
564*4d9fdb46SRobert Mustacchi         relap->r_symidx = ELF64MIPS_REL_SYM(relp->r_info);
565*4d9fdb46SRobert Mustacchi #undef MIPS64SYM
566*4d9fdb46SRobert Mustacchi #undef MIPS64TYPE
567*4d9fdb46SRobert Mustacchi     } else
568*4d9fdb46SRobert Mustacchi     {
569*4d9fdb46SRobert Mustacchi         relap->r_type = ELF64_R_TYPE(relp->r_info);
570*4d9fdb46SRobert Mustacchi         relap->r_symidx = ELF64_R_SYM(relp->r_info);
571*4d9fdb46SRobert Mustacchi     }
572*4d9fdb46SRobert Mustacchi     relap->r_addend = 0;
573*4d9fdb46SRobert Mustacchi     relap->r_is_rela = FALSE;
574*4d9fdb46SRobert Mustacchi #endif
575*4d9fdb46SRobert Mustacchi }
576*4d9fdb46SRobert Mustacchi 
577*4d9fdb46SRobert Mustacchi 
578*4d9fdb46SRobert Mustacchi static void
get_relocations_array(Dwarf_Bool is_64bit,int endianness,int machine,int is_rela,Dwarf_Small * data,unsigned int num_relocations,struct Dwarf_Elf_Rela * relap)579*4d9fdb46SRobert Mustacchi get_relocations_array(Dwarf_Bool is_64bit,
58007dc1947SRichard Lowe     int endianness,
58107dc1947SRichard Lowe     int machine,
582*4d9fdb46SRobert Mustacchi     int is_rela,
583*4d9fdb46SRobert Mustacchi     Dwarf_Small *data,
584*4d9fdb46SRobert Mustacchi     unsigned int num_relocations,
58507dc1947SRichard Lowe     struct Dwarf_Elf_Rela *relap)
58607dc1947SRichard Lowe {
58707dc1947SRichard Lowe     unsigned int i = 0;
588*4d9fdb46SRobert Mustacchi     void (*get_relocations)(Dwarf_Small *data, unsigned int i,
589*4d9fdb46SRobert Mustacchi         int endianness,
590*4d9fdb46SRobert Mustacchi         int machine,
591*4d9fdb46SRobert Mustacchi         struct Dwarf_Elf_Rela *relap);
59207dc1947SRichard Lowe 
593*4d9fdb46SRobert Mustacchi     /* Handle 32/64 bit issue */
59407dc1947SRichard Lowe     if (is_64bit) {
595*4d9fdb46SRobert Mustacchi         if ( is_rela) {
596*4d9fdb46SRobert Mustacchi             get_relocations = get_rela_elf64;
597*4d9fdb46SRobert Mustacchi         } else {
598*4d9fdb46SRobert Mustacchi             get_relocations = get_rel_elf64;
599*4d9fdb46SRobert Mustacchi         }
60007dc1947SRichard Lowe     } else {
601*4d9fdb46SRobert Mustacchi         if ( is_rela) {
602*4d9fdb46SRobert Mustacchi             get_relocations = get_rela_elf32;
603*4d9fdb46SRobert Mustacchi         } else {
604*4d9fdb46SRobert Mustacchi             get_relocations = get_rel_elf32;
605*4d9fdb46SRobert Mustacchi         }
60607dc1947SRichard Lowe     }
60707dc1947SRichard Lowe 
60807dc1947SRichard Lowe     for (i=0; i < num_relocations; i++) {
609*4d9fdb46SRobert Mustacchi         get_relocations(data, i,endianness,machine,
610*4d9fdb46SRobert Mustacchi             &(relap[i]));
61107dc1947SRichard Lowe     }
61207dc1947SRichard Lowe 
61307dc1947SRichard Lowe }
61407dc1947SRichard Lowe 
61507dc1947SRichard Lowe static int
get_relocation_entries(Dwarf_Bool is_64bit,int endianness,int machine,Dwarf_Small * relocation_section,Dwarf_Unsigned relocation_section_size,Dwarf_Unsigned relocation_section_entrysize,struct Dwarf_Elf_Rela ** relas,unsigned int * nrelas,int is_rela,int * error)61607dc1947SRichard Lowe get_relocation_entries(Dwarf_Bool is_64bit,
61707dc1947SRichard Lowe     int endianness,
61807dc1947SRichard Lowe     int machine,
61907dc1947SRichard Lowe     Dwarf_Small *relocation_section,
62007dc1947SRichard Lowe     Dwarf_Unsigned relocation_section_size,
621*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned relocation_section_entrysize,
62207dc1947SRichard Lowe     struct Dwarf_Elf_Rela **relas,
62307dc1947SRichard Lowe     unsigned int *nrelas,
624*4d9fdb46SRobert Mustacchi     int is_rela,
62507dc1947SRichard Lowe     int *error)
62607dc1947SRichard Lowe {
62707dc1947SRichard Lowe     unsigned int relocation_size = 0;
62807dc1947SRichard Lowe 
62907dc1947SRichard Lowe     if (is_64bit) {
63007dc1947SRichard Lowe #ifdef HAVE_ELF64_RELA
631*4d9fdb46SRobert Mustacchi         relocation_size = is_rela?sizeof(Elf64_Rela):sizeof(Elf64_Rel);
63207dc1947SRichard Lowe #else
63307dc1947SRichard Lowe         *error = DW_DLE_MISSING_ELF64_SUPPORT;
63407dc1947SRichard Lowe         return DW_DLV_ERROR;
63507dc1947SRichard Lowe #endif
63607dc1947SRichard Lowe     } else {
637*4d9fdb46SRobert Mustacchi         relocation_size = is_rela?sizeof(Elf32_Rela):sizeof(Elf32_Rel);
638*4d9fdb46SRobert Mustacchi     }
639*4d9fdb46SRobert Mustacchi     if (relocation_size != relocation_section_entrysize) {
640*4d9fdb46SRobert Mustacchi         /*  Means our struct definition does not match the
641*4d9fdb46SRobert Mustacchi             real object. */
642*4d9fdb46SRobert Mustacchi 
643*4d9fdb46SRobert Mustacchi         *error = DW_DLE_RELOC_SECTION_LENGTH_ODD;
644*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
64507dc1947SRichard Lowe     }
64607dc1947SRichard Lowe 
64707dc1947SRichard Lowe     if (relocation_section == NULL) {
64807dc1947SRichard Lowe         *error = DW_DLE_RELOC_SECTION_PTR_NULL;
64907dc1947SRichard Lowe         return(DW_DLV_ERROR);
65007dc1947SRichard Lowe     }
65107dc1947SRichard Lowe 
65207dc1947SRichard Lowe     if ((relocation_section_size != 0)) {
65307dc1947SRichard Lowe         size_t bytescount = 0;
654*4d9fdb46SRobert Mustacchi         if (relocation_section_size%relocation_size) {
65507dc1947SRichard Lowe             *error = DW_DLE_RELOC_SECTION_LENGTH_ODD;
65607dc1947SRichard Lowe             return DW_DLV_ERROR;
65707dc1947SRichard Lowe         }
65807dc1947SRichard Lowe         *nrelas = relocation_section_size/relocation_size;
65907dc1947SRichard Lowe         bytescount = (*nrelas) * sizeof(struct Dwarf_Elf_Rela);
66007dc1947SRichard Lowe         *relas = malloc(bytescount);
66107dc1947SRichard Lowe         if (!*relas) {
66207dc1947SRichard Lowe             *error = DW_DLE_MAF;
66307dc1947SRichard Lowe             return(DW_DLV_ERROR);
66407dc1947SRichard Lowe         }
66507dc1947SRichard Lowe         memset(*relas,0,bytescount);
666*4d9fdb46SRobert Mustacchi         get_relocations_array(is_64bit,endianness,machine,
667*4d9fdb46SRobert Mustacchi             is_rela,
668*4d9fdb46SRobert Mustacchi             relocation_section,
66907dc1947SRichard Lowe             *nrelas, *relas);
67007dc1947SRichard Lowe     }
67107dc1947SRichard Lowe     return(DW_DLV_OK);
67207dc1947SRichard Lowe }
67307dc1947SRichard Lowe 
674*4d9fdb46SRobert Mustacchi /*  Returns DW_DLV_OK if it works, else DW_DLV_ERROR.
675*4d9fdb46SRobert Mustacchi     The caller may decide to ignore the errors or report them. */
676*4d9fdb46SRobert Mustacchi static int
update_entry(Dwarf_Debug dbg,Dwarf_Bool is_64bit,UNUSEDARG Dwarf_Endianness endianess,UNUSEDARG Dwarf_Half machine,struct Dwarf_Elf_Rela * rela,Dwarf_Small * target_section,Dwarf_Unsigned target_section_size,Dwarf_Small * symtab_section_data,Dwarf_Unsigned symtab_section_size,Dwarf_Unsigned symtab_section_entrysize,int is_rela,int * error)67707dc1947SRichard Lowe update_entry(Dwarf_Debug dbg,
678*4d9fdb46SRobert Mustacchi     Dwarf_Bool is_64bit,
679*4d9fdb46SRobert Mustacchi     UNUSEDARG Dwarf_Endianness endianess,
680*4d9fdb46SRobert Mustacchi     UNUSEDARG Dwarf_Half machine,
681*4d9fdb46SRobert Mustacchi     struct Dwarf_Elf_Rela *rela,
682*4d9fdb46SRobert Mustacchi     Dwarf_Small *target_section,
683*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned target_section_size,
684*4d9fdb46SRobert Mustacchi     Dwarf_Small *symtab_section_data,
685*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned symtab_section_size,
686*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned symtab_section_entrysize,
687*4d9fdb46SRobert Mustacchi     int is_rela,
688*4d9fdb46SRobert Mustacchi     int *error)
68907dc1947SRichard Lowe {
690*4d9fdb46SRobert Mustacchi     unsigned int type = 0;
69107dc1947SRichard Lowe     unsigned int sym_idx = 0;
69207dc1947SRichard Lowe #ifdef HAVE_ELF64_SYM
69307dc1947SRichard Lowe     Elf64_Sym sym_buf;
69407dc1947SRichard Lowe     Elf64_Sym *sym = 0;
69507dc1947SRichard Lowe #else
69607dc1947SRichard Lowe     Elf32_Sym sym_buf;
697*4d9fdb46SRobert Mustacchi     Elf32_Sym *sym = 0;
69807dc1947SRichard Lowe #endif
69907dc1947SRichard Lowe     Elf32_Sym *sym32 = 0;
700*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned offset = 0;
701*4d9fdb46SRobert Mustacchi     Dwarf_Signed addend = 0;
70207dc1947SRichard Lowe     Dwarf_Unsigned reloc_size = 0;
703*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned symtab_entry_count = 0;
70407dc1947SRichard Lowe 
705*4d9fdb46SRobert Mustacchi     if (symtab_section_entrysize == 0) {
706*4d9fdb46SRobert Mustacchi         *error = DW_DLE_SYMTAB_SECTION_ENTRYSIZE_ZERO;
707*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
708*4d9fdb46SRobert Mustacchi     }
709*4d9fdb46SRobert Mustacchi     symtab_entry_count = symtab_section_size/symtab_section_entrysize;
71007dc1947SRichard Lowe 
71107dc1947SRichard Lowe     /* Dwarf_Elf_Rela dereferencing */
71207dc1947SRichard Lowe     offset = rela->r_offset;
71307dc1947SRichard Lowe     addend = rela->r_addend;
71407dc1947SRichard Lowe     type = rela->r_type;
71507dc1947SRichard Lowe     sym_idx = rela->r_symidx;
716*4d9fdb46SRobert Mustacchi     if (sym_idx >= symtab_entry_count) {
717*4d9fdb46SRobert Mustacchi         *error = DW_DLE_RELOC_SECTION_SYMBOL_INDEX_BAD;
718*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
719*4d9fdb46SRobert Mustacchi     }
720*4d9fdb46SRobert Mustacchi     if (offset >= target_section_size) {
721*4d9fdb46SRobert Mustacchi         /*  If offset really big, any add will overflow.
722*4d9fdb46SRobert Mustacchi             So lets stop early if offset is corrupt. */
723*4d9fdb46SRobert Mustacchi         *error = DW_DLE_RELOC_INVALID;
724*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
725*4d9fdb46SRobert Mustacchi     }
72607dc1947SRichard Lowe     if (is_64bit) {
72707dc1947SRichard Lowe #ifdef HAVE_ELF64_SYM
728*4d9fdb46SRobert Mustacchi         sym = &((Elf64_Sym*)symtab_section_data)[sym_idx];
729*4d9fdb46SRobert Mustacchi #else
730*4d9fdb46SRobert Mustacchi         /* We cannot handle this object without 64_SYMs. */
731*4d9fdb46SRobert Mustacchi         *error = DW_DLE_RELOC_SECTION_RELOC_TARGET_SIZE_UNKNOWN;
732*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
73307dc1947SRichard Lowe #endif
73407dc1947SRichard Lowe     } else {
735*4d9fdb46SRobert Mustacchi         sym32 = &((Elf32_Sym*)symtab_section_data)[sym_idx];
736*4d9fdb46SRobert Mustacchi 
737*4d9fdb46SRobert Mustacchi         /*  Convert Elf32_Sym struct to Elf64_Sym struct. We point at
738*4d9fdb46SRobert Mustacchi             an Elf64_Sym local variable (sym_buf) to allow us to use the
739*4d9fdb46SRobert Mustacchi             same pointer (sym) for both 32-bit and 64-bit instances.  */
740*4d9fdb46SRobert Mustacchi         sym = &sym_buf;
741*4d9fdb46SRobert Mustacchi         sym->st_name = sym32->st_name;
742*4d9fdb46SRobert Mustacchi         sym->st_info = sym32->st_info;
743*4d9fdb46SRobert Mustacchi         sym->st_other = sym32->st_other;
744*4d9fdb46SRobert Mustacchi         sym->st_shndx = sym32->st_shndx;
745*4d9fdb46SRobert Mustacchi         sym->st_value = sym32->st_value;
746*4d9fdb46SRobert Mustacchi         sym->st_size = sym32->st_size;
74707dc1947SRichard Lowe     }
74807dc1947SRichard Lowe 
74907dc1947SRichard Lowe     /* Determine relocation size */
750*4d9fdb46SRobert Mustacchi     if (_dwarf_is_32bit_abs_reloc(type, machine)) {
75107dc1947SRichard Lowe         reloc_size = 4;
752*4d9fdb46SRobert Mustacchi     } else if (_dwarf_is_64bit_abs_reloc(type, machine)) {
75307dc1947SRichard Lowe         reloc_size = 8;
75407dc1947SRichard Lowe     } else {
755*4d9fdb46SRobert Mustacchi         *error = DW_DLE_RELOC_SECTION_RELOC_TARGET_SIZE_UNKNOWN;
756*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
75707dc1947SRichard Lowe     }
758*4d9fdb46SRobert Mustacchi     if ( (offset + reloc_size) < offset) {
759*4d9fdb46SRobert Mustacchi         /* Another check for overflow. */
760*4d9fdb46SRobert Mustacchi         *error = DW_DLE_RELOC_INVALID;
761*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
762*4d9fdb46SRobert Mustacchi     }
763*4d9fdb46SRobert Mustacchi     if ( (offset + reloc_size) > target_section_size) {
764*4d9fdb46SRobert Mustacchi         *error = DW_DLE_RELOC_INVALID;
765*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
766*4d9fdb46SRobert Mustacchi     }
767*4d9fdb46SRobert Mustacchi     { /* .rel. (addend is zero) or .rela */
768*4d9fdb46SRobert Mustacchi         Dwarf_Small *targ = target_section+offset;
769*4d9fdb46SRobert Mustacchi         Dwarf_Unsigned presentval = 0;
770*4d9fdb46SRobert Mustacchi         Dwarf_Unsigned outval = 0;
771*4d9fdb46SRobert Mustacchi         /*  See also: READ_UNALIGNED_SAFE in
772*4d9fdb46SRobert Mustacchi             dwarf_elfread.c  */
773*4d9fdb46SRobert Mustacchi 
774*4d9fdb46SRobert Mustacchi         if (!is_rela) {
775*4d9fdb46SRobert Mustacchi             READ_UNALIGNED_SAFE(dbg,presentval,
776*4d9fdb46SRobert Mustacchi                 targ,reloc_size);
777*4d9fdb46SRobert Mustacchi         }
778*4d9fdb46SRobert Mustacchi         /*  There is no addend in .rel.
779*4d9fdb46SRobert Mustacchi             Normally presentval is correct
780*4d9fdb46SRobert Mustacchi             and st_value will be zero.
781*4d9fdb46SRobert Mustacchi             But a few compilers have
782*4d9fdb46SRobert Mustacchi             presentval zero and st_value set. */
783*4d9fdb46SRobert Mustacchi         outval = presentval + sym->st_value + addend ;
784*4d9fdb46SRobert Mustacchi         WRITE_UNALIGNED_LOCAL(dbg,targ,
785*4d9fdb46SRobert Mustacchi             &outval,sizeof(outval),reloc_size);
78607dc1947SRichard Lowe     }
787*4d9fdb46SRobert Mustacchi     return DW_DLV_OK;
78807dc1947SRichard Lowe }
78907dc1947SRichard Lowe 
79007dc1947SRichard Lowe 
79107dc1947SRichard Lowe 
792*4d9fdb46SRobert Mustacchi /*  Somewhat arbitrarily, we attempt to apply all the relocations we can
793*4d9fdb46SRobert Mustacchi     and still notify the caller of at least one error if we found
794*4d9fdb46SRobert Mustacchi     any errors.  */
795*4d9fdb46SRobert Mustacchi static int
apply_rela_entries(Dwarf_Debug dbg,Dwarf_Bool is_64bit,Dwarf_Endianness endianess,Dwarf_Half machine,Dwarf_Small * target_section,Dwarf_Unsigned target_section_size,Dwarf_Small * symtab_section,Dwarf_Unsigned symtab_section_size,Dwarf_Unsigned symtab_section_entrysize,int is_rela,struct Dwarf_Elf_Rela * relas,unsigned int nrelas,int * error)79607dc1947SRichard Lowe apply_rela_entries(Dwarf_Debug dbg,
79707dc1947SRichard Lowe     Dwarf_Bool is_64bit,
79807dc1947SRichard Lowe     Dwarf_Endianness endianess,
79907dc1947SRichard Lowe     Dwarf_Half machine,
80007dc1947SRichard Lowe     Dwarf_Small *target_section,
801*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned target_section_size,
80207dc1947SRichard Lowe     Dwarf_Small *symtab_section,
803*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned symtab_section_size,
804*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned symtab_section_entrysize,
805*4d9fdb46SRobert Mustacchi     int   is_rela,
80607dc1947SRichard Lowe     struct Dwarf_Elf_Rela *relas, unsigned int nrelas,
80707dc1947SRichard Lowe     int *error)
80807dc1947SRichard Lowe {
809*4d9fdb46SRobert Mustacchi     int return_res = DW_DLV_OK;
81007dc1947SRichard Lowe     if ((target_section != NULL)  && (relas != NULL)) {
81107dc1947SRichard Lowe         unsigned int i;
812*4d9fdb46SRobert Mustacchi         if (symtab_section_entrysize == 0) {
813*4d9fdb46SRobert Mustacchi             *error = DW_DLE_SYMTAB_SECTION_ENTRYSIZE_ZERO;
814*4d9fdb46SRobert Mustacchi             return DW_DLV_ERROR;
815*4d9fdb46SRobert Mustacchi         }
816*4d9fdb46SRobert Mustacchi         if (symtab_section_size%symtab_section_entrysize) {
817*4d9fdb46SRobert Mustacchi             *error = DW_DLE_SYMTAB_SECTION_LENGTH_ODD;
818*4d9fdb46SRobert Mustacchi             return DW_DLV_ERROR;
819*4d9fdb46SRobert Mustacchi         }
82007dc1947SRichard Lowe         for (i = 0; i < nrelas; i++) {
821*4d9fdb46SRobert Mustacchi             int res = update_entry(dbg, is_64bit,
82207dc1947SRichard Lowe                 endianess,
82307dc1947SRichard Lowe                 machine,
82407dc1947SRichard Lowe                 &(relas)[i],
82507dc1947SRichard Lowe                 target_section,
826*4d9fdb46SRobert Mustacchi                 target_section_size,
827*4d9fdb46SRobert Mustacchi                 symtab_section,
828*4d9fdb46SRobert Mustacchi                 symtab_section_size,
829*4d9fdb46SRobert Mustacchi                 symtab_section_entrysize,
830*4d9fdb46SRobert Mustacchi                 is_rela,
831*4d9fdb46SRobert Mustacchi                 error);
832*4d9fdb46SRobert Mustacchi             if (res != DW_DLV_OK) {
833*4d9fdb46SRobert Mustacchi                 return_res = res;
834*4d9fdb46SRobert Mustacchi             }
83507dc1947SRichard Lowe         }
83607dc1947SRichard Lowe     }
837*4d9fdb46SRobert Mustacchi     return return_res;
83807dc1947SRichard Lowe }
83907dc1947SRichard Lowe 
84007dc1947SRichard Lowe 
84107dc1947SRichard Lowe static int
loop_through_relocations(Dwarf_Debug dbg,dwarf_elf_object_access_internals_t * obj,struct Dwarf_Section_s * relocatablesec,int * error)84207dc1947SRichard Lowe loop_through_relocations(
84307dc1947SRichard Lowe    Dwarf_Debug dbg,
84407dc1947SRichard Lowe    dwarf_elf_object_access_internals_t* obj,
84507dc1947SRichard Lowe    struct Dwarf_Section_s *relocatablesec,
84607dc1947SRichard Lowe    int *error)
84707dc1947SRichard Lowe {
84807dc1947SRichard Lowe     Dwarf_Small *target_section = 0;
84907dc1947SRichard Lowe     Dwarf_Small *symtab_section = obj->symtab->dss_data;
850*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned symtab_section_entrysize = obj->symtab->dss_entrysize;
851*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned symtab_section_size = obj->symtab->dss_size;
85207dc1947SRichard Lowe     Dwarf_Small *relocation_section  = relocatablesec->dss_reloc_data;
85307dc1947SRichard Lowe     Dwarf_Unsigned relocation_section_size =
854*4d9fdb46SRobert Mustacchi         relocatablesec->dss_reloc_size;
855*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned relocation_section_entrysize = relocatablesec->dss_reloc_entrysize;
85607dc1947SRichard Lowe     int ret = DW_DLV_ERROR;
85707dc1947SRichard Lowe     struct Dwarf_Elf_Rela *relas = 0;
85807dc1947SRichard Lowe     unsigned int nrelas = 0;
85907dc1947SRichard Lowe     Dwarf_Small *mspace = 0;
860*4d9fdb46SRobert Mustacchi     int is_rela = relocatablesec->dss_is_rela;
86107dc1947SRichard Lowe 
86207dc1947SRichard Lowe     ret = get_relocation_entries(obj->is_64bit,
86307dc1947SRichard Lowe         obj->endianness,
86407dc1947SRichard Lowe         obj->machine,
865*4d9fdb46SRobert Mustacchi         relocation_section,
866*4d9fdb46SRobert Mustacchi         relocation_section_size,
867*4d9fdb46SRobert Mustacchi         relocation_section_entrysize,
868*4d9fdb46SRobert Mustacchi         &relas, &nrelas, is_rela,error);
869*4d9fdb46SRobert Mustacchi     if (ret != DW_DLV_OK) {
87007dc1947SRichard Lowe         free(relas);
87107dc1947SRichard Lowe         return ret;
87207dc1947SRichard Lowe     }
87307dc1947SRichard Lowe 
874*4d9fdb46SRobert Mustacchi     if(!relocatablesec->dss_data_was_malloc) {
875*4d9fdb46SRobert Mustacchi         /*  Some systems read Elf in read-only memory via mmap or the like.
876*4d9fdb46SRobert Mustacchi             So the only safe thing is to copy the current data into
877*4d9fdb46SRobert Mustacchi             malloc space and refer to the malloc space instead of the
878*4d9fdb46SRobert Mustacchi             space returned by the elf library */
879*4d9fdb46SRobert Mustacchi         mspace = malloc(relocatablesec->dss_size);
880*4d9fdb46SRobert Mustacchi         if (!mspace) {
881*4d9fdb46SRobert Mustacchi             free(relas);
882*4d9fdb46SRobert Mustacchi             *error = DW_DLE_RELOC_SECTION_MALLOC_FAIL;
883*4d9fdb46SRobert Mustacchi             return DW_DLV_ERROR;
884*4d9fdb46SRobert Mustacchi         }
885*4d9fdb46SRobert Mustacchi         memcpy(mspace,relocatablesec->dss_data,relocatablesec->dss_size);
886*4d9fdb46SRobert Mustacchi         relocatablesec->dss_data = mspace;
887*4d9fdb46SRobert Mustacchi         relocatablesec->dss_data_was_malloc = TRUE;
88807dc1947SRichard Lowe     }
88907dc1947SRichard Lowe     target_section = relocatablesec->dss_data;
89007dc1947SRichard Lowe     ret = apply_rela_entries(
89107dc1947SRichard Lowe         dbg,
89207dc1947SRichard Lowe         obj->is_64bit,
893*4d9fdb46SRobert Mustacchi         obj->endianness, obj->machine,
894*4d9fdb46SRobert Mustacchi         target_section,
895*4d9fdb46SRobert Mustacchi         relocatablesec->dss_size,
89607dc1947SRichard Lowe         symtab_section,
897*4d9fdb46SRobert Mustacchi         symtab_section_size,
898*4d9fdb46SRobert Mustacchi         symtab_section_entrysize,
899*4d9fdb46SRobert Mustacchi         is_rela,
90007dc1947SRichard Lowe         relas, nrelas, error);
90107dc1947SRichard Lowe     free(relas);
90207dc1947SRichard Lowe     return ret;
90307dc1947SRichard Lowe }
90407dc1947SRichard Lowe 
905*4d9fdb46SRobert Mustacchi /*  Find the section data in dbg and find all the relevant
90607dc1947SRichard Lowe     sections.  Then do relocations.
90707dc1947SRichard Lowe */
90807dc1947SRichard Lowe static int
dwarf_elf_object_relocate_a_section(void * obj_in,Dwarf_Half section_index,Dwarf_Debug dbg,int * error)90907dc1947SRichard Lowe dwarf_elf_object_relocate_a_section(void* obj_in,
91007dc1947SRichard Lowe     Dwarf_Half section_index,
91107dc1947SRichard Lowe     Dwarf_Debug dbg,
91207dc1947SRichard Lowe     int* error)
91307dc1947SRichard Lowe {
91407dc1947SRichard Lowe     int res = DW_DLV_ERROR;
915*4d9fdb46SRobert Mustacchi     dwarf_elf_object_access_internals_t*obj = 0;
91607dc1947SRichard Lowe     struct Dwarf_Section_s * relocatablesec = 0;
91707dc1947SRichard Lowe     if (section_index == 0) {
91807dc1947SRichard Lowe         return DW_DLV_NO_ENTRY;
91907dc1947SRichard Lowe     }
92007dc1947SRichard Lowe     obj = (dwarf_elf_object_access_internals_t*)obj_in;
92107dc1947SRichard Lowe 
92207dc1947SRichard Lowe     /* The section to relocate must already be loaded into memory. */
92307dc1947SRichard Lowe     res = find_section_to_relocate(dbg, section_index,&relocatablesec,error);
924*4d9fdb46SRobert Mustacchi     if (res != DW_DLV_OK) {
925*4d9fdb46SRobert Mustacchi         return res;
92607dc1947SRichard Lowe     }
92707dc1947SRichard Lowe 
928*4d9fdb46SRobert Mustacchi     /*  Sun and possibly others do not always set sh_link in .debug_* sections.
929*4d9fdb46SRobert Mustacchi         So we cannot do full  consistency checks. */
930*4d9fdb46SRobert Mustacchi     if (relocatablesec->dss_reloc_index == 0 ) {
93107dc1947SRichard Lowe         /* Something is wrong. */
93207dc1947SRichard Lowe         *error = DW_DLE_RELOC_SECTION_MISSING_INDEX;
93307dc1947SRichard Lowe         return DW_DLV_ERROR;
93407dc1947SRichard Lowe     }
93507dc1947SRichard Lowe     /* Now load the relocations themselves. */
93607dc1947SRichard Lowe     res =  dwarf_elf_object_access_load_section(obj_in,
937*4d9fdb46SRobert Mustacchi         relocatablesec->dss_reloc_index,
938*4d9fdb46SRobert Mustacchi         &relocatablesec->dss_reloc_data, error);
939*4d9fdb46SRobert Mustacchi     if (res != DW_DLV_OK) {
940*4d9fdb46SRobert Mustacchi         return res;
94107dc1947SRichard Lowe     }
94207dc1947SRichard Lowe 
94307dc1947SRichard Lowe     /* Now get the symtab. */
944*4d9fdb46SRobert Mustacchi     if (!obj->symtab) {
945*4d9fdb46SRobert Mustacchi         obj->symtab = &dbg->de_elf_symtab;
946*4d9fdb46SRobert Mustacchi         obj->strtab = &dbg->de_elf_strtab;
94707dc1947SRichard Lowe     }
948*4d9fdb46SRobert Mustacchi     if (obj->symtab->dss_index != relocatablesec->dss_reloc_link) {
94907dc1947SRichard Lowe         /* Something is wrong. */
95007dc1947SRichard Lowe         *error = DW_DLE_RELOC_MISMATCH_RELOC_INDEX;
95107dc1947SRichard Lowe         return DW_DLV_ERROR;
95207dc1947SRichard Lowe     }
953*4d9fdb46SRobert Mustacchi     if (obj->strtab->dss_index != obj->symtab->dss_link) {
95407dc1947SRichard Lowe         /* Something is wrong. */
95507dc1947SRichard Lowe         *error = DW_DLE_RELOC_MISMATCH_STRTAB_INDEX;
95607dc1947SRichard Lowe         return DW_DLV_ERROR;
95707dc1947SRichard Lowe     }
958*4d9fdb46SRobert Mustacchi     if (!obj->symtab->dss_data) {
95907dc1947SRichard Lowe         /* Now load the symtab */
96007dc1947SRichard Lowe         res =  dwarf_elf_object_access_load_section(obj_in,
96107dc1947SRichard Lowe             obj->symtab->dss_index,
96207dc1947SRichard Lowe             &obj->symtab->dss_data, error);
963*4d9fdb46SRobert Mustacchi         if (res != DW_DLV_OK) {
96407dc1947SRichard Lowe             return res;
96507dc1947SRichard Lowe         }
96607dc1947SRichard Lowe     }
967*4d9fdb46SRobert Mustacchi     if (!obj->strtab->dss_data) {
96807dc1947SRichard Lowe         /* Now load the strtab */
969*4d9fdb46SRobert Mustacchi         res = dwarf_elf_object_access_load_section(obj_in,
97007dc1947SRichard Lowe             obj->strtab->dss_index,
97107dc1947SRichard Lowe             &obj->strtab->dss_data,error);
972*4d9fdb46SRobert Mustacchi         if (res != DW_DLV_OK){
97307dc1947SRichard Lowe             return res;
97407dc1947SRichard Lowe         }
97507dc1947SRichard Lowe     }
97607dc1947SRichard Lowe 
977*4d9fdb46SRobert Mustacchi 
97807dc1947SRichard Lowe     /* We have all the data we need in memory. */
97907dc1947SRichard Lowe     res = loop_through_relocations(dbg,obj,relocatablesec,error);
98007dc1947SRichard Lowe 
98107dc1947SRichard Lowe     return res;
98207dc1947SRichard Lowe }
98307dc1947SRichard Lowe 
984*4d9fdb46SRobert Mustacchi /*  dwarf_elf_object_access_load_section()
985*4d9fdb46SRobert Mustacchi     We are only asked to load sections that
986*4d9fdb46SRobert Mustacchi     libdwarf really needs.
987*4d9fdb46SRobert Mustacchi     It would be much better if a 'user data pointer'
988*4d9fdb46SRobert Mustacchi     were passed through these interfaces so one
989*4d9fdb46SRobert Mustacchi     part of libdwarf could pass through to this.
990*4d9fdb46SRobert Mustacchi     Or even just if a Dwarf_Debug were passed in.
991*4d9fdb46SRobert Mustacchi     Sigh. */
992*4d9fdb46SRobert Mustacchi static int
dwarf_elf_object_access_load_section(void * obj_in,Dwarf_Half section_index,Dwarf_Small ** section_data,int * error)993*4d9fdb46SRobert Mustacchi dwarf_elf_object_access_load_section(void* obj_in,
994*4d9fdb46SRobert Mustacchi     Dwarf_Half section_index,
995*4d9fdb46SRobert Mustacchi     Dwarf_Small** section_data,
99607dc1947SRichard Lowe     int* error)
99707dc1947SRichard Lowe {
998*4d9fdb46SRobert Mustacchi     dwarf_elf_object_access_internals_t*obj =
99907dc1947SRichard Lowe         (dwarf_elf_object_access_internals_t*)obj_in;
100007dc1947SRichard Lowe     if (section_index == 0) {
100107dc1947SRichard Lowe         return DW_DLV_NO_ENTRY;
100207dc1947SRichard Lowe     }
100307dc1947SRichard Lowe 
100407dc1947SRichard Lowe     {
100507dc1947SRichard Lowe         Elf_Scn *scn = 0;
100607dc1947SRichard Lowe         Elf_Data *data = 0;
100707dc1947SRichard Lowe 
100807dc1947SRichard Lowe         scn = elf_getscn(obj->elf, section_index);
100907dc1947SRichard Lowe         if (scn == NULL) {
1010*4d9fdb46SRobert Mustacchi             /*  The section_index does not exist or
1011*4d9fdb46SRobert Mustacchi                 obj->elf is NULL. */
101207dc1947SRichard Lowe             *error = DW_DLE_MDE;
101307dc1947SRichard Lowe             return DW_DLV_ERROR;
101407dc1947SRichard Lowe         }
101507dc1947SRichard Lowe 
1016*4d9fdb46SRobert Mustacchi         /*  When using libelf as a producer, section data may be stored
1017*4d9fdb46SRobert Mustacchi             in multiple buffers. In libdwarf however, we only use libelf
1018*4d9fdb46SRobert Mustacchi             as a consumer (there is a dwarf producer API, but it doesn't
1019*4d9fdb46SRobert Mustacchi             use libelf). Because of this, this single call to elf_getdata
1020*4d9fdb46SRobert Mustacchi             will retrieve the entire section in a single contiguous
1021*4d9fdb46SRobert Mustacchi             buffer. */
102207dc1947SRichard Lowe         data = elf_getdata(scn, NULL);
102307dc1947SRichard Lowe         if (data == NULL) {
1024*4d9fdb46SRobert Mustacchi             /*  Most likely means that the Elf section header
1025*4d9fdb46SRobert Mustacchi                 is damaged/corrupt and the data is
1026*4d9fdb46SRobert Mustacchi                 impossible to read into
1027*4d9fdb46SRobert Mustacchi                 memory.   The size specified in the
1028*4d9fdb46SRobert Mustacchi                 Elf section is too large to allocate memory
1029*4d9fdb46SRobert Mustacchi                 for so the data could not be loaded. */
1030*4d9fdb46SRobert Mustacchi             *error = DW_DLE_MDE;
1031*4d9fdb46SRobert Mustacchi             return DW_DLV_ERROR;
1032*4d9fdb46SRobert Mustacchi         }
1033*4d9fdb46SRobert Mustacchi         if (!data->d_buf) {
1034*4d9fdb46SRobert Mustacchi             /*  If NULL it means 'the section has no data'
1035*4d9fdb46SRobert Mustacchi                 according to libelf documentation.
1036*4d9fdb46SRobert Mustacchi                 No DWARF-related section should ever have
1037*4d9fdb46SRobert Mustacchi                 'no data'.  Happens if a section type is
1038*4d9fdb46SRobert Mustacchi                 SHT_NOBITS and no section libdwarf
1039*4d9fdb46SRobert Mustacchi                 wants to look at should be SHT_NOBITS. */
1040*4d9fdb46SRobert Mustacchi             *error = DW_DLE_MDE;
1041*4d9fdb46SRobert Mustacchi             return DW_DLV_ERROR;
104207dc1947SRichard Lowe         }
104307dc1947SRichard Lowe         *section_data = data->d_buf;
104407dc1947SRichard Lowe     }
104507dc1947SRichard Lowe     return DW_DLV_OK;
104607dc1947SRichard Lowe }
104707dc1947SRichard Lowe 
104807dc1947SRichard Lowe 
1049*4d9fdb46SRobert Mustacchi /*  dwarf_elf_access method table for use with libelf.
1050*4d9fdb46SRobert Mustacchi     See also the methods table in dwarf_elfread.c for non-libelf.
1051*4d9fdb46SRobert Mustacchi */
1052*4d9fdb46SRobert Mustacchi 
1053*4d9fdb46SRobert Mustacchi static const struct Dwarf_Obj_Access_Methods_s dwarf_elf_object_access_methods =
105407dc1947SRichard Lowe {
105507dc1947SRichard Lowe     dwarf_elf_object_access_get_section_info,
105607dc1947SRichard Lowe     dwarf_elf_object_access_get_byte_order,
105707dc1947SRichard Lowe     dwarf_elf_object_access_get_length_size,
105807dc1947SRichard Lowe     dwarf_elf_object_access_get_pointer_size,
105907dc1947SRichard Lowe     dwarf_elf_object_access_get_section_count,
106007dc1947SRichard Lowe     dwarf_elf_object_access_load_section,
1061*4d9fdb46SRobert Mustacchi     dwarf_elf_object_relocate_a_section
106207dc1947SRichard Lowe };
106307dc1947SRichard Lowe 
106407dc1947SRichard Lowe 
1065*4d9fdb46SRobert Mustacchi /*  Interface for the ELF object file implementation.
1066*4d9fdb46SRobert Mustacchi     On error this should set *err with the
1067*4d9fdb46SRobert Mustacchi     libdwarf error code.
1068*4d9fdb46SRobert Mustacchi */
1069*4d9fdb46SRobert Mustacchi int
dwarf_elf_object_access_init(dwarf_elf_handle elf,int libdwarf_owns_elf,Dwarf_Obj_Access_Interface ** ret_obj,int * err)1070*4d9fdb46SRobert Mustacchi dwarf_elf_object_access_init(dwarf_elf_handle elf,
107107dc1947SRichard Lowe     int libdwarf_owns_elf,
107207dc1947SRichard Lowe     Dwarf_Obj_Access_Interface** ret_obj,
107307dc1947SRichard Lowe     int *err)
107407dc1947SRichard Lowe {
107507dc1947SRichard Lowe     int res = 0;
107607dc1947SRichard Lowe     dwarf_elf_object_access_internals_t *internals = 0;
107707dc1947SRichard Lowe     Dwarf_Obj_Access_Interface *intfc = 0;
107807dc1947SRichard Lowe 
107907dc1947SRichard Lowe     internals = malloc(sizeof(dwarf_elf_object_access_internals_t));
1080*4d9fdb46SRobert Mustacchi     if (!internals) {
1081*4d9fdb46SRobert Mustacchi         *err = DW_DLE_ALLOC_FAIL;
108207dc1947SRichard Lowe         /* Impossible case, we hope. Give up. */
108307dc1947SRichard Lowe         return DW_DLV_ERROR;
108407dc1947SRichard Lowe     }
108507dc1947SRichard Lowe     memset(internals,0,sizeof(*internals));
108607dc1947SRichard Lowe     res = dwarf_elf_object_access_internals_init(internals, elf, err);
1087*4d9fdb46SRobert Mustacchi     if (res != DW_DLV_OK){
1088*4d9fdb46SRobert Mustacchi         /* *err is already set. */
108907dc1947SRichard Lowe         free(internals);
109007dc1947SRichard Lowe         return DW_DLV_ERROR;
109107dc1947SRichard Lowe     }
109207dc1947SRichard Lowe     internals->libdwarf_owns_elf = libdwarf_owns_elf;
1093*4d9fdb46SRobert Mustacchi 
109407dc1947SRichard Lowe     intfc = malloc(sizeof(Dwarf_Obj_Access_Interface));
1095*4d9fdb46SRobert Mustacchi     if (!intfc) {
109607dc1947SRichard Lowe         /* Impossible case, we hope. Give up. */
1097*4d9fdb46SRobert Mustacchi         *err = DW_DLE_ALLOC_FAIL;
109807dc1947SRichard Lowe         free(internals);
109907dc1947SRichard Lowe         return DW_DLV_ERROR;
110007dc1947SRichard Lowe     }
110107dc1947SRichard Lowe     /* Initialize the interface struct */
110207dc1947SRichard Lowe     intfc->object = internals;
110307dc1947SRichard Lowe     intfc->methods = &dwarf_elf_object_access_methods;
110407dc1947SRichard Lowe 
1105*4d9fdb46SRobert Mustacchi     /*  An access method hidden from non-elf. Needed to
1106*4d9fdb46SRobert Mustacchi         handle new-ish SHF_COMPRESSED flag in elf.  */
1107*4d9fdb46SRobert Mustacchi     _dwarf_get_elf_flags_func_ptr = _dwarf_get_elf_flags_func;
1108*4d9fdb46SRobert Mustacchi 
1109*4d9fdb46SRobert Mustacchi 
111007dc1947SRichard Lowe     *ret_obj = intfc;
111107dc1947SRichard Lowe     return DW_DLV_OK;
111207dc1947SRichard Lowe }
111307dc1947SRichard Lowe 
111407dc1947SRichard Lowe 
111507dc1947SRichard Lowe 
1116*4d9fdb46SRobert Mustacchi /* Clean up the Dwarf_Obj_Access_Interface returned by elf_access_init.  */
1117*4d9fdb46SRobert Mustacchi void
dwarf_elf_object_access_finish(Dwarf_Obj_Access_Interface * obj)111807dc1947SRichard Lowe dwarf_elf_object_access_finish(Dwarf_Obj_Access_Interface* obj)
111907dc1947SRichard Lowe {
1120*4d9fdb46SRobert Mustacchi     if (!obj) {
112107dc1947SRichard Lowe         return;
112207dc1947SRichard Lowe     }
1123*4d9fdb46SRobert Mustacchi     if (obj->object) {
1124*4d9fdb46SRobert Mustacchi         dwarf_elf_object_access_internals_t *internals =
112507dc1947SRichard Lowe             (dwarf_elf_object_access_internals_t *)obj->object;
1126*4d9fdb46SRobert Mustacchi         if (internals->libdwarf_owns_elf){
1127*4d9fdb46SRobert Mustacchi             /*  Happens with dwarf_init_path(),
1128*4d9fdb46SRobert Mustacchi                 dwarf_init(), or dwarf_init_b()
1129*4d9fdb46SRobert Mustacchi                 interfaces. */
113007dc1947SRichard Lowe             elf_end(internals->elf);
113107dc1947SRichard Lowe         }
113207dc1947SRichard Lowe     }
113307dc1947SRichard Lowe     free(obj->object);
113407dc1947SRichard Lowe     free(obj);
113507dc1947SRichard Lowe }
113607dc1947SRichard Lowe 
1137*4d9fdb46SRobert Mustacchi /*  This function returns the Elf * pointer
113807dc1947SRichard Lowe     associated with a Dwarf_Debug.
113907dc1947SRichard Lowe 
1140*4d9fdb46SRobert Mustacchi     This function only makes sense if ELF is implied
1141*4d9fdb46SRobert Mustacchi     and there actually is an Elf * pointer available.
1142*4d9fdb46SRobert Mustacchi */
114307dc1947SRichard Lowe int
dwarf_get_elf(Dwarf_Debug dbg,dwarf_elf_handle * elf,Dwarf_Error * error)114407dc1947SRichard Lowe dwarf_get_elf(Dwarf_Debug dbg, dwarf_elf_handle * elf,
1145*4d9fdb46SRobert Mustacchi     Dwarf_Error * error)
1146*4d9fdb46SRobert Mustacchi {
114707dc1947SRichard Lowe     struct Dwarf_Obj_Access_Interface_s * obj = 0;
114807dc1947SRichard Lowe     if (dbg == NULL) {
114907dc1947SRichard Lowe         _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
115007dc1947SRichard Lowe         return (DW_DLV_ERROR);
115107dc1947SRichard Lowe     }
115207dc1947SRichard Lowe 
1153*4d9fdb46SRobert Mustacchi     obj = dbg->de_obj_file;
1154*4d9fdb46SRobert Mustacchi     if (obj && obj->object) {
1155*4d9fdb46SRobert Mustacchi         dwarf_elf_object_access_internals_t *internals = 0;
1156*4d9fdb46SRobert Mustacchi         char typeletter = *(char *)(obj->object);
1157*4d9fdb46SRobert Mustacchi 
1158*4d9fdb46SRobert Mustacchi         if (typeletter != 'E') {
1159*4d9fdb46SRobert Mustacchi             /* Not libelf Elf */
1160*4d9fdb46SRobert Mustacchi             return DW_DLV_NO_ENTRY;
1161*4d9fdb46SRobert Mustacchi         }
1162*4d9fdb46SRobert Mustacchi         internals = (dwarf_elf_object_access_internals_t*)obj->object;
1163*4d9fdb46SRobert Mustacchi         if (internals->elf == NULL) {
1164*4d9fdb46SRobert Mustacchi             _dwarf_error(dbg, error, DW_DLE_FNO);
1165*4d9fdb46SRobert Mustacchi             return (DW_DLV_ERROR);
1166*4d9fdb46SRobert Mustacchi         }
1167*4d9fdb46SRobert Mustacchi         *elf = internals->elf;
1168*4d9fdb46SRobert Mustacchi         return DW_DLV_OK;
116907dc1947SRichard Lowe     }
117007dc1947SRichard Lowe     _dwarf_error(dbg, error, DW_DLE_FNO);
117107dc1947SRichard Lowe     return DW_DLV_ERROR;
117207dc1947SRichard Lowe }
1173*4d9fdb46SRobert Mustacchi #else
1174*4d9fdb46SRobert Mustacchi int dwarf_elf_access_dummy_var_avoid_warn = 0;
1175*4d9fdb46SRobert Mustacchi #endif /* DWARF_WITH_LIBELF */
1176