xref: /illumos-gate/usr/src/lib/libdwarf/common/dwarf_elf_access.c (revision 16b76d3cb933ff92018a2a75594449010192eacb)
1 /*
2   Copyright (C) 2000-2005 Silicon Graphics, Inc.  All Rights Reserved.
3   Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
4   Portions Copyright 2008-2010 Arxan Technologies, Inc. All Rights Reserved.
5   Portions Copyright 2009-2019 David Anderson. All rights reserved.
6   Portions Copyright 2009-2010 Novell Inc. All rights reserved.
7   Portions Copyright 2012 SN Systems Ltd. All rights reserved.
8 
9   This program is free software; you can redistribute it
10   and/or modify it under the terms of version 2.1 of the
11   GNU Lesser General Public License as published by the Free
12   Software Foundation.
13 
14   This program is distributed in the hope that it would be
15   useful, but WITHOUT ANY WARRANTY; without even the implied
16   warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
17   PURPOSE.
18 
19   Further, this software is distributed without any warranty
20   that it is free of the rightful claim of any third person
21   regarding infringement or the like.  Any license provided
22   herein, whether implied or otherwise, applies only to this
23   software file.  Patent licenses, if any, provided herein
24   do not apply to combinations of this program with other
25   software, or any other product whatsoever.
26 
27   You should have received a copy of the GNU Lesser General
28   Public License along with this program; if not, write the
29   Free Software Foundation, Inc., 51 Franklin Street - Fifth
30   Floor, Boston MA 02110-1301, USA.
31 
32 */
33 
34 /*  This file is ONLY used for libelf and with libelf
35     For */
36 
37 #include "config.h"
38 #ifdef DWARF_WITH_LIBELF
39 #include "dwarf_incl.h"
40 #include "dwarf_error.h"
41 #include "dwarf_elf_access.h"
42 #include "dwarf_elf_rel_detector.h"
43 
44 /* Include the ELF definitions depending on system headers if any. */
45 #include "dwarf_elf_defines.h"
46 
47 #include <stdio.h>
48 #include <sys/stat.h>
49 #include <sys/types.h>
50 #ifdef HAVE_UNISTD_H
51 #include <unistd.h> /* for close */
52 #endif /* HAVE_UNISTD_H */
53 #include <string.h>
54 #ifdef HAVE_STDLIB_H
55 #include <stdlib.h>
56 #endif /* HAVE_STDLIB_H */
57 #ifdef HAVE_MALLOC_H
58 /* Useful include for some Windows compilers. */
59 #include <malloc.h>
60 #endif /* HAVE_MALLOC_H */
61 
62 #define FALSE 0
63 #define TRUE  1
64 
65 #ifdef HAVE_ELF64_GETEHDR
66 extern Elf64_Ehdr *elf64_getehdr(Elf *);
67 #endif
68 #ifdef HAVE_ELF64_GETSHDR
69 extern Elf64_Shdr *elf64_getshdr(Elf_Scn *);
70 #endif
71 
72 #ifdef WORDS_BIGENDIAN
73 #define READ_UNALIGNED_SAFE(dbg,dest, source, length) \
74     do {                                             \
75         Dwarf_Unsigned _ltmp = 0;                    \
76         dbg->de_copy_word( (((char *)(&_ltmp)) +     \
77             sizeof(_ltmp) - length),source, length); \
78         dest = _ltmp;                                \
79     } while (0)
80 
81 #define WRITE_UNALIGNED_LOCAL(dbg,dest,source, srclength,len_out) \
82     {                                             \
83         dbg->de_copy_word(dest,                   \
84             ((char *)source) +srclength-len_out,  \
85             len_out) ;                            \
86     }
87 #else /* LITTLE ENDIAN */
88 #define READ_UNALIGNED_SAFE(dbg,dest, source, srclength) \
89     do  {                                     \
90         Dwarf_Unsigned _ltmp = 0;             \
91         dbg->de_copy_word( (char *)(&_ltmp),  \
92             source, srclength) ;              \
93         dest = _ltmp;                         \
94     } while (0)
95 
96 #define WRITE_UNALIGNED_LOCAL(dbg,dest,source, srclength,len_out) \
97     {                               \
98         dbg->de_copy_word( (dest) , \
99             ((char *)source) ,      \
100             len_out) ;              \
101     }
102 #endif /* *-ENDIAN */
103 
104 
105 
106 /*   ident[0] == 'E' for elf when using libelf. ident[1] = 1 */
107 typedef struct {
108     char             ident[8];
109     const char *     path;
110     int              is_64bit;
111     Dwarf_Small      length_size;
112     Dwarf_Small      pointer_size;
113     Dwarf_Unsigned   section_count;
114     Dwarf_Endianness endianness;
115     Dwarf_Small      machine;
116     char             libdwarf_owns_elf;
117     dwarf_elf_handle elf;
118 
119     Elf32_Ehdr *ehdr32;
120 #ifdef HAVE_ELF64_GETEHDR
121     Elf64_Ehdr *ehdr64;
122 #endif
123     /*  Elf symtab and its strtab.  Initialized at first
124         call to do relocations, the actual data is in the Dwarf_Debug
125         struct, not allocated locally here. */
126     struct Dwarf_Section_s *symtab;
127     struct Dwarf_Section_s *strtab;
128 
129 } dwarf_elf_object_access_internals_t;
130 
131 /*  Using this for rel and rela.
132     For Rel, r_addend is left zero and not used.
133 */
134 struct Dwarf_Elf_Rela {
135     Dwarf_Unsigned r_offset;
136     /*Dwarf_Unsigned r_info; */
137     Dwarf_Unsigned r_type;
138     Dwarf_Unsigned r_symidx;
139     Dwarf_Unsigned r_addend;
140     /* if is_rela is non-zero r_addend is meaningless */
141     char  r_is_rela;
142 };
143 
144 
145 static int dwarf_elf_object_access_load_section(void* obj_in,
146     Dwarf_Half section_index,
147     Dwarf_Small** section_data,
148     int* error);
149 
150 /*  dwarf_elf_object_access_internals_init()
151     On error, set *error with libdwarf error code.
152 */
153 static int
154 dwarf_elf_object_access_internals_init(void* obj_in,
155     dwarf_elf_handle elf,
156     int* error)
157 {
158     dwarf_elf_object_access_internals_t*obj =
159         (dwarf_elf_object_access_internals_t*)obj_in;
160     char *ehdr_ident = 0;
161     Dwarf_Half machine = 0;
162     obj->elf = elf;
163 
164     if ((ehdr_ident = elf_getident(elf, NULL)) == NULL) {
165         *error = DW_DLE_ELF_GETIDENT_ERROR;
166         return DW_DLV_ERROR;
167     }
168 
169     obj->is_64bit = (ehdr_ident[EI_CLASS] == ELFCLASS64);
170 
171 
172     if (ehdr_ident[EI_DATA] == ELFDATA2LSB){
173         obj->endianness = DW_OBJECT_LSB;
174     } else if (ehdr_ident[EI_DATA] == ELFDATA2MSB){
175         obj->endianness = DW_OBJECT_MSB;
176     }
177 
178     if (obj->is_64bit) {
179 #ifdef HAVE_ELF64_GETEHDR
180         obj->ehdr64 = elf64_getehdr(elf);
181         if (obj->ehdr64 == NULL) {
182             *error = DW_DLE_ELF_GETEHDR_ERROR;
183             return DW_DLV_ERROR;
184         }
185         obj->section_count = obj->ehdr64->e_shnum;
186         machine = obj->ehdr64->e_machine;
187         obj->machine = machine;
188 #else
189         *error = DW_DLE_NO_ELF64_SUPPORT;
190         return DW_DLV_ERROR;
191 #endif
192     } else {
193         obj->ehdr32 = elf32_getehdr(elf);
194         if (obj->ehdr32 == NULL) {
195             *error = DW_DLE_ELF_GETEHDR_ERROR;
196             return DW_DLV_ERROR;
197         }
198         obj->section_count = obj->ehdr32->e_shnum;
199         machine = obj->ehdr32->e_machine;
200         obj->machine = machine;
201     }
202 
203     /*  The following length_size is Not Too Significant. Only used
204         one calculation, and an approximate one at that. */
205     obj->length_size = obj->is_64bit ? 8 : 4;
206     obj->pointer_size = obj->is_64bit ? 8 : 4;
207     obj->ident[0] = 'E';
208     obj->ident[1] = 1;
209 
210 #ifdef _WIN32
211     if (obj->is_64bit && machine == EM_PPC64) {
212         /*  The SNC compiler generates the EM_PPC64 machine type for the
213             PS3 platform, but is a 32 bits pointer size in user mode. */
214         obj->pointer_size = 4;
215     }
216 #endif /* _WIN32 */
217 
218     if (obj->is_64bit && machine != EM_MIPS) {
219         /*  MIPS/IRIX makes pointer size and length size 8 for -64.
220             Other platforms make length 4 always. */
221         /*  4 here supports 32bit-offset dwarf2, as emitted by cygnus
222             tools, and the dwarfv2.1 64bit extension setting.
223             This is not the same as the size-of-an-offset, which
224             is 4 in 32bit dwarf and 8 in 64bit dwarf.  */
225         obj->length_size = 4;
226     }
227     return DW_DLV_OK;
228 }
229 
230 /* dwarf_elf_object_access_get_byte_order */
231 static
232 Dwarf_Endianness
233 dwarf_elf_object_access_get_byte_order(void* obj_in)
234 {
235     dwarf_elf_object_access_internals_t*obj =
236         (dwarf_elf_object_access_internals_t*)obj_in;
237     return obj->endianness;
238 }
239 
240 /* dwarf_elf_object_access_get_section_count() */
241 static
242 Dwarf_Unsigned
243 dwarf_elf_object_access_get_section_count(void * obj_in)
244 {
245     dwarf_elf_object_access_internals_t*obj =
246         (dwarf_elf_object_access_internals_t*)obj_in;
247     return obj->section_count;
248 }
249 
250 
251 static int
252 _dwarf_get_elf_flags_func(
253     void* obj_in,
254     Dwarf_Half section_index,
255     Dwarf_Unsigned *flags_out,
256     Dwarf_Unsigned *addralign_out,
257     int *error)
258 {
259    dwarf_elf_object_access_internals_t*obj =
260         (dwarf_elf_object_access_internals_t*)obj_in;
261 
262     Elf32_Shdr *shdr32 = 0;
263 
264 #ifdef HAVE_ELF64_GETSHDR
265     Elf64_Shdr *shdr64 = 0;
266 #endif
267     Elf_Scn *scn = 0;
268 
269 
270     scn = elf_getscn(obj->elf, section_index);
271     if (scn == NULL) {
272         *error = DW_DLE_MDE;
273         return DW_DLV_ERROR;
274     }
275     if (obj->is_64bit) {
276 #ifdef HAVE_ELF64_GETSHDR
277         shdr64 = elf64_getshdr(scn);
278         if (shdr64 == NULL) {
279             *error = DW_DLE_ELF_GETSHDR_ERROR;
280             return DW_DLV_ERROR;
281         }
282 
283         /*  Get also section 'sh_type' and sh_info' fields, so the caller
284             can use it for additional tasks that require that info. */
285         *flags_out = shdr64->sh_flags;
286         *addralign_out = shdr64->sh_addralign;
287         return DW_DLV_OK;
288 #else
289         *error = DW_DLE_MISSING_ELF64_SUPPORT;
290         return DW_DLV_ERROR;
291 #endif /* HAVE_ELF64_GETSHDR */
292     }
293     if ((shdr32 = elf32_getshdr(scn)) == NULL) {
294         *error = DW_DLE_ELF_GETSHDR_ERROR;
295         return DW_DLV_ERROR;
296     }
297 
298     /*  Get also the section type, so the caller can use it for
299         additional tasks that require to know the section type. */
300     *flags_out = shdr32->sh_flags;
301     *addralign_out = shdr32->sh_addralign;
302     return DW_DLV_OK;
303 }
304 
305 
306 /*  dwarf_elf_object_access_get_section()
307 
308     If writing a function vaguely like this for a non-elf object,
309     be sure that when section-index is passed in as zero that
310     you set the fields in *ret_scn_doas to reflect an empty section
311     with an empty string as the section name.  Adjust your
312     section indexes of your non-elf-reading-code
313     for all the necessary functions in Dwarf_Obj_Access_Methods_s
314     accordingly.
315 
316     Should have gotten sh_flags, sh_addralign too.
317     But Dwarf_Obj_Access_Section is publically defined so changing
318     it is quite painful for everyone.
319 */
320 static
321 int
322 dwarf_elf_object_access_get_section_info(
323     void* obj_in,
324     Dwarf_Half section_index,
325     Dwarf_Obj_Access_Section* ret_scn_doas,
326     int* error)
327 {
328     dwarf_elf_object_access_internals_t*obj =
329         (dwarf_elf_object_access_internals_t*)obj_in;
330 
331     Elf32_Shdr *shdr32 = 0;
332 
333 #ifdef HAVE_ELF64_GETSHDR
334     Elf64_Shdr *shdr64 = 0;
335 #endif
336     Elf_Scn *scn = 0;
337 
338 
339     scn = elf_getscn(obj->elf, section_index);
340     if (scn == NULL) {
341         *error = DW_DLE_MDE;
342         return DW_DLV_ERROR;
343     }
344     if (obj->is_64bit) {
345 #ifdef HAVE_ELF64_GETSHDR
346         shdr64 = elf64_getshdr(scn);
347         if (shdr64 == NULL) {
348             *error = DW_DLE_ELF_GETSHDR_ERROR;
349             return DW_DLV_ERROR;
350         }
351 
352         /*  Get also section 'sh_type' and sh_info' fields, so the caller
353             can use it for additional tasks that require that info. */
354         ret_scn_doas->type = shdr64->sh_type;
355         ret_scn_doas->size = shdr64->sh_size;
356         ret_scn_doas->addr = shdr64->sh_addr;
357         ret_scn_doas->link = shdr64->sh_link;
358         ret_scn_doas->info = shdr64->sh_info;
359         ret_scn_doas->entrysize = shdr64->sh_entsize;
360         ret_scn_doas->name = elf_strptr(obj->elf, obj->ehdr64->e_shstrndx,
361             shdr64->sh_name);
362         if (ret_scn_doas->name == NULL) {
363             *error = DW_DLE_ELF_STRPTR_ERROR;
364             return DW_DLV_ERROR;
365         }
366         return DW_DLV_OK;
367 #else
368         *error = DW_DLE_MISSING_ELF64_SUPPORT;
369         return DW_DLV_ERROR;
370 #endif /* HAVE_ELF64_GETSHDR */
371     }
372     if ((shdr32 = elf32_getshdr(scn)) == NULL) {
373         *error = DW_DLE_ELF_GETSHDR_ERROR;
374         return DW_DLV_ERROR;
375     }
376 
377     /*  Get also the section type, so the caller can use it for
378         additional tasks that require to know the section type. */
379     ret_scn_doas->type = shdr32->sh_type;
380     ret_scn_doas->size = shdr32->sh_size;
381     ret_scn_doas->addr = shdr32->sh_addr;
382     ret_scn_doas->link = shdr32->sh_link;
383     ret_scn_doas->info = shdr32->sh_info;
384     ret_scn_doas->entrysize = shdr32->sh_entsize;
385     ret_scn_doas->name = elf_strptr(obj->elf, obj->ehdr32->e_shstrndx,
386         shdr32->sh_name);
387     if (ret_scn_doas->name == NULL) {
388         *error = DW_DLE_ELF_STRPTR_ERROR;
389         return DW_DLV_ERROR;
390     }
391     return DW_DLV_OK;
392 }
393 
394 /* dwarf_elf_object_access_get_length_size */
395 static
396 Dwarf_Small
397 dwarf_elf_object_access_get_length_size(void* obj_in)
398 {
399     dwarf_elf_object_access_internals_t*obj =
400         (dwarf_elf_object_access_internals_t*)obj_in;
401     return obj->length_size;
402 }
403 
404 /* dwarf_elf_object_access_get_pointer_size */
405 static
406 Dwarf_Small
407 dwarf_elf_object_access_get_pointer_size(void* obj_in)
408 {
409     dwarf_elf_object_access_internals_t*obj =
410         (dwarf_elf_object_access_internals_t*)obj_in;
411     return obj->pointer_size;
412 }
413 
414 #define MATCH_REL_SEC(i_,s_,r_)  \
415 if (i_ == s_.dss_index) { \
416     *r_ = &s_;            \
417     return DW_DLV_OK;    \
418 }
419 
420 static int
421 find_section_to_relocate(Dwarf_Debug dbg,Dwarf_Half section_index,
422    struct Dwarf_Section_s **relocatablesec, int *error)
423 {
424     MATCH_REL_SEC(section_index,dbg->de_debug_info,relocatablesec);
425     MATCH_REL_SEC(section_index,dbg->de_debug_abbrev,relocatablesec);
426     MATCH_REL_SEC(section_index,dbg->de_debug_line,relocatablesec);
427     MATCH_REL_SEC(section_index,dbg->de_debug_loc,relocatablesec);
428     MATCH_REL_SEC(section_index,dbg->de_debug_aranges,relocatablesec);
429     MATCH_REL_SEC(section_index,dbg->de_debug_macinfo,relocatablesec);
430     MATCH_REL_SEC(section_index,dbg->de_debug_pubnames,relocatablesec);
431     MATCH_REL_SEC(section_index,dbg->de_debug_ranges,relocatablesec);
432     MATCH_REL_SEC(section_index,dbg->de_debug_frame,relocatablesec);
433     MATCH_REL_SEC(section_index,dbg->de_debug_frame_eh_gnu,relocatablesec);
434     MATCH_REL_SEC(section_index,dbg->de_debug_pubtypes,relocatablesec);
435     MATCH_REL_SEC(section_index,dbg->de_debug_funcnames,relocatablesec);
436     MATCH_REL_SEC(section_index,dbg->de_debug_typenames,relocatablesec);
437     MATCH_REL_SEC(section_index,dbg->de_debug_varnames,relocatablesec);
438     MATCH_REL_SEC(section_index,dbg->de_debug_weaknames,relocatablesec);
439     MATCH_REL_SEC(section_index,dbg->de_debug_types,relocatablesec);
440     MATCH_REL_SEC(section_index,dbg->de_debug_macro,relocatablesec);
441     MATCH_REL_SEC(section_index,dbg->de_debug_rnglists,relocatablesec);
442     MATCH_REL_SEC(section_index,dbg->de_debug_loclists,relocatablesec);
443     MATCH_REL_SEC(section_index,dbg->de_debug_aranges,relocatablesec);
444     MATCH_REL_SEC(section_index,dbg->de_debug_sup,relocatablesec);
445     MATCH_REL_SEC(section_index,dbg->de_debug_str_offsets,relocatablesec);
446     MATCH_REL_SEC(section_index,dbg->de_debug_addr,relocatablesec);
447     /* dbg-> de_debug_tu_index,reloctablesec); */
448     /* dbg-> de_debug_cu_index,reloctablesec); */
449     /* dbg-> de_debug_gdbindex,reloctablesec); */
450     /* dbg-> de_debug_str,syms); */
451     /* de_elf_symtab,syms); */
452     /* de_elf_strtab,syms); */
453     *error = DW_DLE_RELOC_SECTION_MISMATCH;
454     return DW_DLV_ERROR;
455 
456 }
457 #undef MATCH_REL_SEC
458 
459 static void
460 get_rela_elf32(Dwarf_Small *data, unsigned int i,
461   UNUSEDARG int endianness,
462   UNUSEDARG int machine,
463   struct Dwarf_Elf_Rela *relap)
464 {
465     Elf32_Rela *relp = 0;
466 
467     relp = (Elf32_Rela*)(data + (i * sizeof(Elf32_Rela)));
468     relap->r_offset = relp->r_offset;
469     /* relap->r_info = relp->r_info; */
470     relap->r_type = ELF32_R_TYPE(relp->r_info);
471     relap->r_symidx = ELF32_R_SYM(relp->r_info);
472     relap->r_is_rela = TRUE;
473     relap->r_addend = relp->r_addend;
474 }
475 static void
476 get_rel_elf32(Dwarf_Small *data, unsigned int i,
477   UNUSEDARG int endianness,
478   UNUSEDARG int machine,
479   struct Dwarf_Elf_Rela *relap)
480 {
481     Elf32_Rel *relp = 0;
482 
483     relp = (Elf32_Rel*)(data + (i * sizeof(Elf32_Rel)));
484     relap->r_offset = relp->r_offset;
485     /* relap->r_info = relp->r_info; */
486     relap->r_type = ELF32_R_TYPE(relp->r_info);
487     relap->r_symidx = ELF32_R_SYM(relp->r_info);
488     relap->r_is_rela = FALSE;
489     relap->r_addend = 0;
490 }
491 
492 
493 static void
494 get_rela_elf64(Dwarf_Small *data, unsigned int i,
495   int endianness,
496   int machine,
497   struct Dwarf_Elf_Rela *relap)
498 {
499 #ifdef HAVE_ELF64_RELA
500     Elf64_Rela * relp = 0;
501     relp = (Elf64_Rela*)(data + (i * sizeof(Elf64_Rela)));
502     relap->r_offset = relp->r_offset;
503     /* relap->r_info = relp->r_info; */
504 #define ELF64MIPS_REL_SYM(i) ((i) & 0xffffffff)
505 #define ELF64MIPS_REL_TYPE(i) ((i >> 56) &0xff)
506     if (machine == EM_MIPS && endianness == DW_OBJECT_LSB ){
507         /*  This is really wierd. Treat this very specially.
508             The Elf64 LE MIPS object used for
509             testing (that has rela) wants the
510             values as  sym  ssym type3 type2 type, treating
511             each value as independent value. But libelf xlate
512             treats it as something else so we fudge here.
513             It is unclear
514             how to precisely characterize where these relocations
515             were used.
516             SGI MIPS on IRIX never used .rela relocations.
517             The BE 64bit elf MIPS test object with rela uses traditional
518             elf relocation layouts, not this special case.  */
519         /*  We ignore the special TYPE2 and TYPE3, they should be
520             value R_MIPS_NONE in rela. */
521         relap->r_type = ELF64MIPS_REL_TYPE(relp->r_info);
522         relap->r_symidx = ELF64MIPS_REL_SYM(relp->r_info);
523 #undef MIPS64SYM
524 #undef MIPS64TYPE
525     } else
526     {
527         relap->r_type = ELF64_R_TYPE(relp->r_info);
528         relap->r_symidx = ELF64_R_SYM(relp->r_info);
529     }
530     relap->r_addend = relp->r_addend;
531     relap->r_is_rela = TRUE;
532 #endif
533 }
534 
535 static void
536 get_rel_elf64(Dwarf_Small *data, unsigned int i,
537   int endianness,
538   int machine,
539   struct Dwarf_Elf_Rela *relap)
540 {
541 #ifdef HAVE_ELF64_RELA
542     Elf64_Rel * relp = 0;
543     relp = (Elf64_Rel*)(data + (i * sizeof(Elf64_Rel)));
544     relap->r_offset = relp->r_offset;
545     /* relap->r_info = relp->r_info; */
546 #define ELF64MIPS_REL_SYM(i) ((i) & 0xffffffff)
547 #define ELF64MIPS_REL_TYPE(i) ((i >> 56) &0xff)
548     if (machine == EM_MIPS && endianness == DW_OBJECT_LSB ){
549         /*  This is really wierd. Treat this very specially.
550             The Elf64 LE MIPS object used for
551             testing (that has rela) wants the
552             values as  sym  ssym type3 type2 type, treating
553             each value as independent value. But libelf xlate
554             treats it as something else so we fudge here.
555             It is unclear
556             how to precisely characterize where these relocations
557             were used.
558             SGI MIPS on IRIX never used .rela relocations.
559             The BE 64bit elf MIPS test object with rela uses traditional
560             elf relocation layouts, not this special case.  */
561         /*  We ignore the special TYPE2 and TYPE3, they should be
562             value R_MIPS_NONE in rela. */
563         relap->r_type = ELF64MIPS_REL_TYPE(relp->r_info);
564         relap->r_symidx = ELF64MIPS_REL_SYM(relp->r_info);
565 #undef MIPS64SYM
566 #undef MIPS64TYPE
567     } else
568     {
569         relap->r_type = ELF64_R_TYPE(relp->r_info);
570         relap->r_symidx = ELF64_R_SYM(relp->r_info);
571     }
572     relap->r_addend = 0;
573     relap->r_is_rela = FALSE;
574 #endif
575 }
576 
577 
578 static void
579 get_relocations_array(Dwarf_Bool is_64bit,
580     int endianness,
581     int machine,
582     int is_rela,
583     Dwarf_Small *data,
584     unsigned int num_relocations,
585     struct Dwarf_Elf_Rela *relap)
586 {
587     unsigned int i = 0;
588     void (*get_relocations)(Dwarf_Small *data, unsigned int i,
589         int endianness,
590         int machine,
591         struct Dwarf_Elf_Rela *relap);
592 
593     /* Handle 32/64 bit issue */
594     if (is_64bit) {
595         if ( is_rela) {
596             get_relocations = get_rela_elf64;
597         } else {
598             get_relocations = get_rel_elf64;
599         }
600     } else {
601         if ( is_rela) {
602             get_relocations = get_rela_elf32;
603         } else {
604             get_relocations = get_rel_elf32;
605         }
606     }
607 
608     for (i=0; i < num_relocations; i++) {
609         get_relocations(data, i,endianness,machine,
610             &(relap[i]));
611     }
612 
613 }
614 
615 static int
616 get_relocation_entries(Dwarf_Bool is_64bit,
617     int endianness,
618     int machine,
619     Dwarf_Small *relocation_section,
620     Dwarf_Unsigned relocation_section_size,
621     Dwarf_Unsigned relocation_section_entrysize,
622     struct Dwarf_Elf_Rela **relas,
623     unsigned int *nrelas,
624     int is_rela,
625     int *error)
626 {
627     unsigned int relocation_size = 0;
628 
629     if (is_64bit) {
630 #ifdef HAVE_ELF64_RELA
631         relocation_size = is_rela?sizeof(Elf64_Rela):sizeof(Elf64_Rel);
632 #else
633         *error = DW_DLE_MISSING_ELF64_SUPPORT;
634         return DW_DLV_ERROR;
635 #endif
636     } else {
637         relocation_size = is_rela?sizeof(Elf32_Rela):sizeof(Elf32_Rel);
638     }
639     if (relocation_size != relocation_section_entrysize) {
640         /*  Means our struct definition does not match the
641             real object. */
642 
643         *error = DW_DLE_RELOC_SECTION_LENGTH_ODD;
644         return DW_DLV_ERROR;
645     }
646 
647     if (relocation_section == NULL) {
648         *error = DW_DLE_RELOC_SECTION_PTR_NULL;
649         return(DW_DLV_ERROR);
650     }
651 
652     if ((relocation_section_size != 0)) {
653         size_t bytescount = 0;
654         if (relocation_section_size%relocation_size) {
655             *error = DW_DLE_RELOC_SECTION_LENGTH_ODD;
656             return DW_DLV_ERROR;
657         }
658         *nrelas = relocation_section_size/relocation_size;
659         bytescount = (*nrelas) * sizeof(struct Dwarf_Elf_Rela);
660         *relas = malloc(bytescount);
661         if (!*relas) {
662             *error = DW_DLE_MAF;
663             return(DW_DLV_ERROR);
664         }
665         memset(*relas,0,bytescount);
666         get_relocations_array(is_64bit,endianness,machine,
667             is_rela,
668             relocation_section,
669             *nrelas, *relas);
670     }
671     return(DW_DLV_OK);
672 }
673 
674 /*  Returns DW_DLV_OK if it works, else DW_DLV_ERROR.
675     The caller may decide to ignore the errors or report them. */
676 static int
677 update_entry(Dwarf_Debug dbg,
678     Dwarf_Bool is_64bit,
679     UNUSEDARG Dwarf_Endianness endianess,
680     UNUSEDARG Dwarf_Half machine,
681     struct Dwarf_Elf_Rela *rela,
682     Dwarf_Small *target_section,
683     Dwarf_Unsigned target_section_size,
684     Dwarf_Small *symtab_section_data,
685     Dwarf_Unsigned symtab_section_size,
686     Dwarf_Unsigned symtab_section_entrysize,
687     int is_rela,
688     int *error)
689 {
690     unsigned int type = 0;
691     unsigned int sym_idx = 0;
692 #ifdef HAVE_ELF64_SYM
693     Elf64_Sym sym_buf;
694     Elf64_Sym *sym = 0;
695 #else
696     Elf32_Sym sym_buf;
697     Elf32_Sym *sym = 0;
698 #endif
699     Elf32_Sym *sym32 = 0;
700     Dwarf_Unsigned offset = 0;
701     Dwarf_Signed addend = 0;
702     Dwarf_Unsigned reloc_size = 0;
703     Dwarf_Unsigned symtab_entry_count = 0;
704 
705     if (symtab_section_entrysize == 0) {
706         *error = DW_DLE_SYMTAB_SECTION_ENTRYSIZE_ZERO;
707         return DW_DLV_ERROR;
708     }
709     symtab_entry_count = symtab_section_size/symtab_section_entrysize;
710 
711     /* Dwarf_Elf_Rela dereferencing */
712     offset = rela->r_offset;
713     addend = rela->r_addend;
714     type = rela->r_type;
715     sym_idx = rela->r_symidx;
716     if (sym_idx >= symtab_entry_count) {
717         *error = DW_DLE_RELOC_SECTION_SYMBOL_INDEX_BAD;
718         return DW_DLV_ERROR;
719     }
720     if (offset >= target_section_size) {
721         /*  If offset really big, any add will overflow.
722             So lets stop early if offset is corrupt. */
723         *error = DW_DLE_RELOC_INVALID;
724         return DW_DLV_ERROR;
725     }
726     if (is_64bit) {
727 #ifdef HAVE_ELF64_SYM
728         sym = &((Elf64_Sym*)symtab_section_data)[sym_idx];
729 #else
730         /* We cannot handle this object without 64_SYMs. */
731         *error = DW_DLE_RELOC_SECTION_RELOC_TARGET_SIZE_UNKNOWN;
732         return DW_DLV_ERROR;
733 #endif
734     } else {
735         sym32 = &((Elf32_Sym*)symtab_section_data)[sym_idx];
736 
737         /*  Convert Elf32_Sym struct to Elf64_Sym struct. We point at
738             an Elf64_Sym local variable (sym_buf) to allow us to use the
739             same pointer (sym) for both 32-bit and 64-bit instances.  */
740         sym = &sym_buf;
741         sym->st_name = sym32->st_name;
742         sym->st_info = sym32->st_info;
743         sym->st_other = sym32->st_other;
744         sym->st_shndx = sym32->st_shndx;
745         sym->st_value = sym32->st_value;
746         sym->st_size = sym32->st_size;
747     }
748 
749     /* Determine relocation size */
750     if (_dwarf_is_32bit_abs_reloc(type, machine)) {
751         reloc_size = 4;
752     } else if (_dwarf_is_64bit_abs_reloc(type, machine)) {
753         reloc_size = 8;
754     } else {
755         *error = DW_DLE_RELOC_SECTION_RELOC_TARGET_SIZE_UNKNOWN;
756         return DW_DLV_ERROR;
757     }
758     if ( (offset + reloc_size) < offset) {
759         /* Another check for overflow. */
760         *error = DW_DLE_RELOC_INVALID;
761         return DW_DLV_ERROR;
762     }
763     if ( (offset + reloc_size) > target_section_size) {
764         *error = DW_DLE_RELOC_INVALID;
765         return DW_DLV_ERROR;
766     }
767     { /* .rel. (addend is zero) or .rela */
768         Dwarf_Small *targ = target_section+offset;
769         Dwarf_Unsigned presentval = 0;
770         Dwarf_Unsigned outval = 0;
771         /*  See also: READ_UNALIGNED_SAFE in
772             dwarf_elfread.c  */
773 
774         if (!is_rela) {
775             READ_UNALIGNED_SAFE(dbg,presentval,
776                 targ,reloc_size);
777         }
778         /*  There is no addend in .rel.
779             Normally presentval is correct
780             and st_value will be zero.
781             But a few compilers have
782             presentval zero and st_value set. */
783         outval = presentval + sym->st_value + addend ;
784         WRITE_UNALIGNED_LOCAL(dbg,targ,
785             &outval,sizeof(outval),reloc_size);
786     }
787     return DW_DLV_OK;
788 }
789 
790 
791 
792 /*  Somewhat arbitrarily, we attempt to apply all the relocations we can
793     and still notify the caller of at least one error if we found
794     any errors.  */
795 static int
796 apply_rela_entries(Dwarf_Debug dbg,
797     Dwarf_Bool is_64bit,
798     Dwarf_Endianness endianess,
799     Dwarf_Half machine,
800     Dwarf_Small *target_section,
801     Dwarf_Unsigned target_section_size,
802     Dwarf_Small *symtab_section,
803     Dwarf_Unsigned symtab_section_size,
804     Dwarf_Unsigned symtab_section_entrysize,
805     int   is_rela,
806     struct Dwarf_Elf_Rela *relas, unsigned int nrelas,
807     int *error)
808 {
809     int return_res = DW_DLV_OK;
810     if ((target_section != NULL)  && (relas != NULL)) {
811         unsigned int i;
812         if (symtab_section_entrysize == 0) {
813             *error = DW_DLE_SYMTAB_SECTION_ENTRYSIZE_ZERO;
814             return DW_DLV_ERROR;
815         }
816         if (symtab_section_size%symtab_section_entrysize) {
817             *error = DW_DLE_SYMTAB_SECTION_LENGTH_ODD;
818             return DW_DLV_ERROR;
819         }
820         for (i = 0; i < nrelas; i++) {
821             int res = update_entry(dbg, is_64bit,
822                 endianess,
823                 machine,
824                 &(relas)[i],
825                 target_section,
826                 target_section_size,
827                 symtab_section,
828                 symtab_section_size,
829                 symtab_section_entrysize,
830                 is_rela,
831                 error);
832             if (res != DW_DLV_OK) {
833                 return_res = res;
834             }
835         }
836     }
837     return return_res;
838 }
839 
840 
841 static int
842 loop_through_relocations(
843    Dwarf_Debug dbg,
844    dwarf_elf_object_access_internals_t* obj,
845    struct Dwarf_Section_s *relocatablesec,
846    int *error)
847 {
848     Dwarf_Small *target_section = 0;
849     Dwarf_Small *symtab_section = obj->symtab->dss_data;
850     Dwarf_Unsigned symtab_section_entrysize = obj->symtab->dss_entrysize;
851     Dwarf_Unsigned symtab_section_size = obj->symtab->dss_size;
852     Dwarf_Small *relocation_section  = relocatablesec->dss_reloc_data;
853     Dwarf_Unsigned relocation_section_size =
854         relocatablesec->dss_reloc_size;
855     Dwarf_Unsigned relocation_section_entrysize = relocatablesec->dss_reloc_entrysize;
856     int ret = DW_DLV_ERROR;
857     struct Dwarf_Elf_Rela *relas = 0;
858     unsigned int nrelas = 0;
859     Dwarf_Small *mspace = 0;
860     int is_rela = relocatablesec->dss_is_rela;
861 
862     ret = get_relocation_entries(obj->is_64bit,
863         obj->endianness,
864         obj->machine,
865         relocation_section,
866         relocation_section_size,
867         relocation_section_entrysize,
868         &relas, &nrelas, is_rela,error);
869     if (ret != DW_DLV_OK) {
870         free(relas);
871         return ret;
872     }
873 
874     if(!relocatablesec->dss_data_was_malloc) {
875         /*  Some systems read Elf in read-only memory via mmap or the like.
876             So the only safe thing is to copy the current data into
877             malloc space and refer to the malloc space instead of the
878             space returned by the elf library */
879         mspace = malloc(relocatablesec->dss_size);
880         if (!mspace) {
881             free(relas);
882             *error = DW_DLE_RELOC_SECTION_MALLOC_FAIL;
883             return DW_DLV_ERROR;
884         }
885         memcpy(mspace,relocatablesec->dss_data,relocatablesec->dss_size);
886         relocatablesec->dss_data = mspace;
887         relocatablesec->dss_data_was_malloc = TRUE;
888     }
889     target_section = relocatablesec->dss_data;
890     ret = apply_rela_entries(
891         dbg,
892         obj->is_64bit,
893         obj->endianness, obj->machine,
894         target_section,
895         relocatablesec->dss_size,
896         symtab_section,
897         symtab_section_size,
898         symtab_section_entrysize,
899         is_rela,
900         relas, nrelas, error);
901     free(relas);
902     return ret;
903 }
904 
905 /*  Find the section data in dbg and find all the relevant
906     sections.  Then do relocations.
907 */
908 static int
909 dwarf_elf_object_relocate_a_section(void* obj_in,
910     Dwarf_Half section_index,
911     Dwarf_Debug dbg,
912     int* error)
913 {
914     int res = DW_DLV_ERROR;
915     dwarf_elf_object_access_internals_t*obj = 0;
916     struct Dwarf_Section_s * relocatablesec = 0;
917     if (section_index == 0) {
918         return DW_DLV_NO_ENTRY;
919     }
920     obj = (dwarf_elf_object_access_internals_t*)obj_in;
921 
922     /* The section to relocate must already be loaded into memory. */
923     res = find_section_to_relocate(dbg, section_index,&relocatablesec,error);
924     if (res != DW_DLV_OK) {
925         return res;
926     }
927 
928     /*  Sun and possibly others do not always set sh_link in .debug_* sections.
929         So we cannot do full  consistency checks. */
930     if (relocatablesec->dss_reloc_index == 0 ) {
931         /* Something is wrong. */
932         *error = DW_DLE_RELOC_SECTION_MISSING_INDEX;
933         return DW_DLV_ERROR;
934     }
935     /* Now load the relocations themselves. */
936     res =  dwarf_elf_object_access_load_section(obj_in,
937         relocatablesec->dss_reloc_index,
938         &relocatablesec->dss_reloc_data, error);
939     if (res != DW_DLV_OK) {
940         return res;
941     }
942 
943     /* Now get the symtab. */
944     if (!obj->symtab) {
945         obj->symtab = &dbg->de_elf_symtab;
946         obj->strtab = &dbg->de_elf_strtab;
947     }
948     if (obj->symtab->dss_index != relocatablesec->dss_reloc_link) {
949         /* Something is wrong. */
950         *error = DW_DLE_RELOC_MISMATCH_RELOC_INDEX;
951         return DW_DLV_ERROR;
952     }
953     if (obj->strtab->dss_index != obj->symtab->dss_link) {
954         /* Something is wrong. */
955         *error = DW_DLE_RELOC_MISMATCH_STRTAB_INDEX;
956         return DW_DLV_ERROR;
957     }
958     if (!obj->symtab->dss_data) {
959         /* Now load the symtab */
960         res =  dwarf_elf_object_access_load_section(obj_in,
961             obj->symtab->dss_index,
962             &obj->symtab->dss_data, error);
963         if (res != DW_DLV_OK) {
964             return res;
965         }
966     }
967     if (!obj->strtab->dss_data) {
968         /* Now load the strtab */
969         res = dwarf_elf_object_access_load_section(obj_in,
970             obj->strtab->dss_index,
971             &obj->strtab->dss_data,error);
972         if (res != DW_DLV_OK){
973             return res;
974         }
975     }
976 
977 
978     /* We have all the data we need in memory. */
979     res = loop_through_relocations(dbg,obj,relocatablesec,error);
980 
981     return res;
982 }
983 
984 /*  dwarf_elf_object_access_load_section()
985     We are only asked to load sections that
986     libdwarf really needs.
987     It would be much better if a 'user data pointer'
988     were passed through these interfaces so one
989     part of libdwarf could pass through to this.
990     Or even just if a Dwarf_Debug were passed in.
991     Sigh. */
992 static int
993 dwarf_elf_object_access_load_section(void* obj_in,
994     Dwarf_Half section_index,
995     Dwarf_Small** section_data,
996     int* error)
997 {
998     dwarf_elf_object_access_internals_t*obj =
999         (dwarf_elf_object_access_internals_t*)obj_in;
1000     if (section_index == 0) {
1001         return DW_DLV_NO_ENTRY;
1002     }
1003 
1004     {
1005         Elf_Scn *scn = 0;
1006         Elf_Data *data = 0;
1007 
1008         scn = elf_getscn(obj->elf, section_index);
1009         if (scn == NULL) {
1010             /*  The section_index does not exist or
1011                 obj->elf is NULL. */
1012             *error = DW_DLE_MDE;
1013             return DW_DLV_ERROR;
1014         }
1015 
1016         /*  When using libelf as a producer, section data may be stored
1017             in multiple buffers. In libdwarf however, we only use libelf
1018             as a consumer (there is a dwarf producer API, but it doesn't
1019             use libelf). Because of this, this single call to elf_getdata
1020             will retrieve the entire section in a single contiguous
1021             buffer. */
1022         data = elf_getdata(scn, NULL);
1023         if (data == NULL) {
1024             /*  Most likely means that the Elf section header
1025                 is damaged/corrupt and the data is
1026                 impossible to read into
1027                 memory.   The size specified in the
1028                 Elf section is too large to allocate memory
1029                 for so the data could not be loaded. */
1030             *error = DW_DLE_MDE;
1031             return DW_DLV_ERROR;
1032         }
1033         if (!data->d_buf) {
1034             /*  If NULL it means 'the section has no data'
1035                 according to libelf documentation.
1036                 No DWARF-related section should ever have
1037                 'no data'.  Happens if a section type is
1038                 SHT_NOBITS and no section libdwarf
1039                 wants to look at should be SHT_NOBITS. */
1040             *error = DW_DLE_MDE;
1041             return DW_DLV_ERROR;
1042         }
1043         *section_data = data->d_buf;
1044     }
1045     return DW_DLV_OK;
1046 }
1047 
1048 
1049 /*  dwarf_elf_access method table for use with libelf.
1050     See also the methods table in dwarf_elfread.c for non-libelf.
1051 */
1052 
1053 static const struct Dwarf_Obj_Access_Methods_s dwarf_elf_object_access_methods =
1054 {
1055     dwarf_elf_object_access_get_section_info,
1056     dwarf_elf_object_access_get_byte_order,
1057     dwarf_elf_object_access_get_length_size,
1058     dwarf_elf_object_access_get_pointer_size,
1059     dwarf_elf_object_access_get_section_count,
1060     dwarf_elf_object_access_load_section,
1061     dwarf_elf_object_relocate_a_section
1062 };
1063 
1064 
1065 /*  Interface for the ELF object file implementation.
1066     On error this should set *err with the
1067     libdwarf error code.
1068 */
1069 int
1070 dwarf_elf_object_access_init(dwarf_elf_handle elf,
1071     int libdwarf_owns_elf,
1072     Dwarf_Obj_Access_Interface** ret_obj,
1073     int *err)
1074 {
1075     int res = 0;
1076     dwarf_elf_object_access_internals_t *internals = 0;
1077     Dwarf_Obj_Access_Interface *intfc = 0;
1078 
1079     internals = malloc(sizeof(dwarf_elf_object_access_internals_t));
1080     if (!internals) {
1081         *err = DW_DLE_ALLOC_FAIL;
1082         /* Impossible case, we hope. Give up. */
1083         return DW_DLV_ERROR;
1084     }
1085     memset(internals,0,sizeof(*internals));
1086     res = dwarf_elf_object_access_internals_init(internals, elf, err);
1087     if (res != DW_DLV_OK){
1088         /* *err is already set. */
1089         free(internals);
1090         return DW_DLV_ERROR;
1091     }
1092     internals->libdwarf_owns_elf = libdwarf_owns_elf;
1093 
1094     intfc = malloc(sizeof(Dwarf_Obj_Access_Interface));
1095     if (!intfc) {
1096         /* Impossible case, we hope. Give up. */
1097         *err = DW_DLE_ALLOC_FAIL;
1098         free(internals);
1099         return DW_DLV_ERROR;
1100     }
1101     /* Initialize the interface struct */
1102     intfc->object = internals;
1103     intfc->methods = &dwarf_elf_object_access_methods;
1104 
1105     /*  An access method hidden from non-elf. Needed to
1106         handle new-ish SHF_COMPRESSED flag in elf.  */
1107     _dwarf_get_elf_flags_func_ptr = _dwarf_get_elf_flags_func;
1108 
1109 
1110     *ret_obj = intfc;
1111     return DW_DLV_OK;
1112 }
1113 
1114 
1115 
1116 /* Clean up the Dwarf_Obj_Access_Interface returned by elf_access_init.  */
1117 void
1118 dwarf_elf_object_access_finish(Dwarf_Obj_Access_Interface* obj)
1119 {
1120     if (!obj) {
1121         return;
1122     }
1123     if (obj->object) {
1124         dwarf_elf_object_access_internals_t *internals =
1125             (dwarf_elf_object_access_internals_t *)obj->object;
1126         if (internals->libdwarf_owns_elf){
1127             /*  Happens with dwarf_init_path(),
1128                 dwarf_init(), or dwarf_init_b()
1129                 interfaces. */
1130             elf_end(internals->elf);
1131         }
1132     }
1133     free(obj->object);
1134     free(obj);
1135 }
1136 
1137 /*  This function returns the Elf * pointer
1138     associated with a Dwarf_Debug.
1139 
1140     This function only makes sense if ELF is implied
1141     and there actually is an Elf * pointer available.
1142 */
1143 int
1144 dwarf_get_elf(Dwarf_Debug dbg, dwarf_elf_handle * elf,
1145     Dwarf_Error * error)
1146 {
1147     struct Dwarf_Obj_Access_Interface_s * obj = 0;
1148     if (dbg == NULL) {
1149         _dwarf_error(NULL, error, DW_DLE_DBG_NULL);
1150         return (DW_DLV_ERROR);
1151     }
1152 
1153     obj = dbg->de_obj_file;
1154     if (obj && obj->object) {
1155         dwarf_elf_object_access_internals_t *internals = 0;
1156         char typeletter = *(char *)(obj->object);
1157 
1158         if (typeletter != 'E') {
1159             /* Not libelf Elf */
1160             return DW_DLV_NO_ENTRY;
1161         }
1162         internals = (dwarf_elf_object_access_internals_t*)obj->object;
1163         if (internals->elf == NULL) {
1164             _dwarf_error(dbg, error, DW_DLE_FNO);
1165             return (DW_DLV_ERROR);
1166         }
1167         *elf = internals->elf;
1168         return DW_DLV_OK;
1169     }
1170     _dwarf_error(dbg, error, DW_DLE_FNO);
1171     return DW_DLV_ERROR;
1172 }
1173 #else
1174 int dwarf_elf_access_dummy_var_avoid_warn = 0;
1175 #endif /* DWARF_WITH_LIBELF */
1176