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