xref: /illumos-gate/usr/src/lib/libdwarf/common/dwarf_elfread.c (revision 4d9fdb46b215739778ebc12079842c9905586999)
1 /*
2 Copyright (c) 2019, David Anderson
3 All rights reserved.
4 cc
5 Redistribution and use in source and binary forms, with
6 or without modification, are permitted provided that the
7 following conditions are met:
8 
9     Redistributions of source code must retain the above
10     copyright notice, this list of conditions and the following
11     disclaimer.
12 
13     Redistributions in binary form must reproduce the above
14     copyright notice, this list of conditions and the following
15     disclaimer in the documentation and/or other materials
16     provided with the distribution.
17 
18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19 CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32 
33 /*  This file reads the parts of an Elf
34     file appropriate to reading DWARF debugging data.
35     Overview:
36     _dwarf_elf_nlsetup() Does all elf setup.
37         calls _dwarf_elf_access_init()
38             calls _dwarf_elf_object_access_internals_init()
39                 Creates internals record 'M',
40                     dwarf_elf_object_access_internals_t
41                 Sets flags/data in internals record
42                 Loads elf object data needed later.
43                 Sets methods struct to access elf object.
44         calls _dwarf_object_init_b() Creates Dwarf_Debug, independent
45             of any elf code.
46         Sets internals record into dbg.
47     ----------------------
48     _dwarf_destruct_elf_nlaccess(). This frees
49         the elf internals record created in
50         _dwarf_elf_object_access_internals_init()
51         in case of errors during setup or when
52         dwarf_finish() is called.  Works safely for
53         partially or fully set-up elf internals record.
54 
55     Other than in _dwarf_elf_nlsetup() the elf code
56     knows nothing about Dwarf_Debug, and the rest of
57     libdwarf knows nothing about the content of the
58     object-type-specific (for Elf here)
59     internals record.
60 */
61 
62 #include "config.h"
63 #include <stdio.h>
64 #ifdef HAVE_MALLOC_H
65 /* Useful include for some Windows compilers. */
66 #include <malloc.h>
67 #endif /* HAVE_MALLOC_H */
68 #ifdef HAVE_STDLIB_H
69 #include <stdlib.h>
70 #endif /* HAVE_STDLIB_H */
71 #include <string.h>
72 #include <stdlib.h>
73 #include <sys/types.h> /* open() */
74 #include <sys/stat.h> /* open() */
75 #include <fcntl.h> /* open() */
76 #include <time.h>
77 #ifdef HAVE_UNISTD_H
78 #include <unistd.h> /* lseek read close */
79 #elif defined(_WIN32) && defined(_MSC_VER)
80 #include <io.h>
81 #endif /* HAVE_UNISTD_H */
82 
83 /* Windows specific header files */
84 #if defined(_WIN32) && defined(HAVE_STDAFX_H)
85 #include "stdafx.h"
86 #endif /* HAVE_STDAFX_H */
87 
88 #include "libdwarf.h"
89 #include "libdwarfdefs.h"
90 #include "dwarf_base_types.h"
91 #include "dwarf_opaque.h"
92 #include "dwarf_error.h" /* for _dwarf_error() declaration */
93 #include "dwarf_reading.h"
94 #include "memcpy_swap.h"
95 #include "dwarf_object_read_common.h"
96 #include "dwarf_object_detector.h"
97 #include "dwarf_elfstructs.h"
98 #include "dwarf_elf_defines.h"
99 #include "dwarf_elf_rel_detector.h"
100 #include "dwarf_elfread.h"
101 
102 
103 #ifndef TYP
104 #define TYP(n,l) char n[l]
105 #endif /* TYPE */
106 
107 #ifdef WORDS_BIGENDIAN
108 #define READ_UNALIGNED_SAFE(dbg,dest, source, length) \
109     do {                                             \
110         Dwarf_Unsigned _ltmp = 0;                    \
111         dbg->de_copy_word( (((char *)(&_ltmp)) +     \
112             sizeof(_ltmp) - length),source, length); \
113         dest = _ltmp;                                \
114     } while (0)
115 
116 #define WRITE_UNALIGNED_LOCAL(dbg,dest,source, srclength,len_out) \
117     {                                             \
118         dbg->de_copy_word(dest,                   \
119             ((char *)source) +srclength-len_out,  \
120             len_out) ;                            \
121     }
122 #else /* LITTLE ENDIAN */
123 #define READ_UNALIGNED_SAFE(dbg,dest, source, srclength) \
124     do  {                                     \
125         Dwarf_Unsigned _ltmp = 0;             \
126         dbg->de_copy_word( (char *)(&_ltmp),  \
127             source, srclength) ;              \
128         dest = _ltmp;                         \
129     } while (0)
130 
131 #define WRITE_UNALIGNED_LOCAL(dbg,dest,source, srclength,len_out) \
132     {                               \
133         dbg->de_copy_word( (dest) , \
134             ((char *)source) ,      \
135             len_out) ;              \
136     }
137 #endif /* *-ENDIAN */
138 
139 
140 #ifdef WORDS_BIGENDIAN
141 #define ASNAR(func,t,s)                         \
142     do {                                        \
143         unsigned tbyte = sizeof(t) - sizeof(s); \
144         t = 0;                                  \
145         func(((char *)&t)+tbyte ,&s[0],sizeof(s));  \
146     } while (0)
147 #else /* LITTLE ENDIAN */
148 #define ASNAR(func,t,s)                         \
149     do {                                        \
150         t = 0;                                  \
151         func(&t,&s[0],sizeof(s));               \
152     } while (0)
153 #endif /* end LITTLE- BIG-ENDIAN */
154 
155 
156 static int
157 _dwarf_elf_object_access_init(
158     int  fd,
159     unsigned ftype,
160     unsigned endian,
161     unsigned offsetsize,
162     size_t filesize,
163     Dwarf_Unsigned access,
164     Dwarf_Obj_Access_Interface **binary_interface,
165     int *localerrnum);
166 
167 
elf_get_nolibelf_byte_order(void * obj)168 static Dwarf_Endianness elf_get_nolibelf_byte_order (void *obj)
169 {
170     dwarf_elf_object_access_internals_t *elf =
171         (dwarf_elf_object_access_internals_t*)(obj);
172     return elf->f_endian;
173 }
174 
175 
elf_get_nolibelf_length_size(void * obj)176 static Dwarf_Small elf_get_nolibelf_length_size (void *obj)
177 {
178     dwarf_elf_object_access_internals_t *elf =
179         (dwarf_elf_object_access_internals_t*)(obj);
180     return elf->f_offsetsize/8;
181 }
182 
183 
elf_get_nolibelf_pointer_size(void * obj)184 static Dwarf_Small elf_get_nolibelf_pointer_size (void *obj)
185 {
186     dwarf_elf_object_access_internals_t *elf =
187         (dwarf_elf_object_access_internals_t*)(obj);
188     return elf->f_pointersize/8;
189 }
190 
191 
elf_get_nolibelf_section_count(void * obj)192 static Dwarf_Unsigned elf_get_nolibelf_section_count (void *obj)
193 {
194     dwarf_elf_object_access_internals_t *elf =
195         (dwarf_elf_object_access_internals_t*)(obj);
196     return elf->f_loc_shdr.g_count;
197 }
198 
elf_get_nolibelf_section_info(void * obj,Dwarf_Half section_index,Dwarf_Obj_Access_Section * return_section,UNUSEDARG int * error)199 static int elf_get_nolibelf_section_info (void *obj,
200     Dwarf_Half section_index,
201     Dwarf_Obj_Access_Section *return_section,
202     UNUSEDARG int *error)
203 {
204     dwarf_elf_object_access_internals_t *elf =
205         (dwarf_elf_object_access_internals_t*)(obj);
206 
207 
208     if (section_index < elf->f_loc_shdr.g_count) {
209         struct generic_shdr *sp = 0;
210 
211         sp = elf->f_shdr + section_index;
212         return_section->addr      = sp->gh_addr;
213         return_section->type      = sp->gh_type;
214         return_section->size      = sp->gh_size;
215         return_section->name      = sp->gh_namestring;
216         return_section->link      = sp->gh_link;
217         return_section->info      = sp->gh_info;
218         return_section->entrysize = sp->gh_entsize;
219         return DW_DLV_OK;
220     }
221     return DW_DLV_NO_ENTRY;
222 }
223 
224 static int
elf_load_nolibelf_section(void * obj,Dwarf_Half section_index,Dwarf_Small ** return_data,int * error)225 elf_load_nolibelf_section (void *obj, Dwarf_Half section_index,
226     Dwarf_Small **return_data, int *error)
227 {
228     dwarf_elf_object_access_internals_t *elf =
229         (dwarf_elf_object_access_internals_t*)(obj);
230 
231     if (0 < section_index &&
232         section_index < elf->f_loc_shdr.g_count) {
233         int res = 0;
234 
235         struct generic_shdr *sp =
236             elf->f_shdr + section_index;
237         if (sp->gh_content) {
238             *return_data = (Dwarf_Small *)sp->gh_content;
239             return DW_DLV_OK;
240         }
241         if (!sp->gh_size) {
242             return DW_DLV_NO_ENTRY;
243         }
244         if ((sp->gh_size + sp->gh_offset) >
245             elf->f_filesize) {
246             *error = DW_DLE_ELF_SECTION_ERROR;
247             return DW_DLV_ERROR;
248         }
249 
250         sp->gh_content = malloc((size_t)sp->gh_size);
251         if(!sp->gh_content) {
252             *error = DW_DLE_ALLOC_FAIL;
253             return DW_DLV_ERROR;
254         }
255         res = RRMOA(elf->f_fd,
256             sp->gh_content, (off_t)sp->gh_offset,
257             (size_t)sp->gh_size, (off_t)elf->f_filesize, error);
258         if (res != DW_DLV_OK) {
259             free(sp->gh_content);
260             sp->gh_content = 0;
261             return res;
262         }
263         *return_data = (Dwarf_Small *)sp->gh_content;
264         return DW_DLV_OK;
265     }
266     return DW_DLV_NO_ENTRY;
267 }
268 
269 static int
_dwarf_get_elf_flags_func_nl(void * obj_in,Dwarf_Half section_index,Dwarf_Unsigned * flags_out,Dwarf_Unsigned * addralign_out,int * error)270 _dwarf_get_elf_flags_func_nl(
271     void* obj_in,
272     Dwarf_Half section_index,
273     Dwarf_Unsigned *flags_out,
274     Dwarf_Unsigned *addralign_out,
275     int *error)
276 {
277     dwarf_elf_object_access_internals_t *ep = 0;
278     struct generic_shdr *shp = 0;
279 
280     ep = (dwarf_elf_object_access_internals_t *)obj_in;
281     if (section_index == 0) {
282         /*  Nothing to do. Empty section */
283         return DW_DLV_OK;
284     }
285     if (section_index >= ep->f_loc_shdr.g_count) {
286         *error = DW_DLE_SECTION_INDEX_BAD;
287         return DW_DLV_ERROR;
288     }
289     shp = ep->f_shdr + section_index;
290     *flags_out = shp->gh_flags;
291     *addralign_out = shp->gh_addralign;
292     return DW_DLV_OK;
293 }
294 
295 
296 #define MATCH_REL_SEC(i_,s_,r_)  \
297 if (i_ == s_.dss_index) { \
298     *r_ = &s_;            \
299     return DW_DLV_OK;    \
300 }
301 
302 static int
find_section_to_relocate(Dwarf_Debug dbg,Dwarf_Half section_index,struct Dwarf_Section_s ** relocatablesec,int * error)303 find_section_to_relocate(Dwarf_Debug dbg,Dwarf_Half section_index,
304    struct Dwarf_Section_s **relocatablesec, int *error)
305 {
306     MATCH_REL_SEC(section_index,dbg->de_debug_info,relocatablesec);
307     MATCH_REL_SEC(section_index,dbg->de_debug_abbrev,relocatablesec);
308     MATCH_REL_SEC(section_index,dbg->de_debug_line,relocatablesec);
309     MATCH_REL_SEC(section_index,dbg->de_debug_loc,relocatablesec);
310     MATCH_REL_SEC(section_index,dbg->de_debug_aranges,relocatablesec);
311     MATCH_REL_SEC(section_index,dbg->de_debug_macinfo,relocatablesec);
312     MATCH_REL_SEC(section_index,dbg->de_debug_pubnames,relocatablesec);
313     MATCH_REL_SEC(section_index,dbg->de_debug_ranges,relocatablesec);
314     MATCH_REL_SEC(section_index,dbg->de_debug_frame,relocatablesec);
315     MATCH_REL_SEC(section_index,dbg->de_debug_frame_eh_gnu,relocatablesec);
316     MATCH_REL_SEC(section_index,dbg->de_debug_pubtypes,relocatablesec);
317     MATCH_REL_SEC(section_index,dbg->de_debug_funcnames,relocatablesec);
318     MATCH_REL_SEC(section_index,dbg->de_debug_typenames,relocatablesec);
319     MATCH_REL_SEC(section_index,dbg->de_debug_varnames,relocatablesec);
320     MATCH_REL_SEC(section_index,dbg->de_debug_weaknames,relocatablesec);
321     MATCH_REL_SEC(section_index,dbg->de_debug_types,relocatablesec);
322     MATCH_REL_SEC(section_index,dbg->de_debug_macro,relocatablesec);
323     MATCH_REL_SEC(section_index,dbg->de_debug_rnglists,relocatablesec);
324     MATCH_REL_SEC(section_index,dbg->de_debug_loclists,relocatablesec);
325     MATCH_REL_SEC(section_index,dbg->de_debug_aranges,relocatablesec);
326     MATCH_REL_SEC(section_index,dbg->de_debug_sup,relocatablesec);
327     MATCH_REL_SEC(section_index,dbg->de_debug_str_offsets,relocatablesec);
328     MATCH_REL_SEC(section_index,dbg->de_debug_addr,relocatablesec);
329     /* dbg-> de_debug_tu_index,reloctablesec); */
330     /* dbg-> de_debug_cu_index,reloctablesec); */
331     /* dbg-> de_debug_gdbindex,reloctablesec); */
332     /* dbg-> de_debug_str,syms); */
333     /* de_elf_symtab,syms); */
334     /* de_elf_strtab,syms); */
335     *error = DW_DLE_RELOC_SECTION_MISMATCH;
336     return DW_DLV_ERROR;
337 }
338 
339 
340 /*  Returns DW_DLV_OK if it works, else DW_DLV_ERROR.
341     The caller may decide to ignore the errors or report them. */
342 static int
update_entry(Dwarf_Debug dbg,dwarf_elf_object_access_internals_t * obj,struct generic_rela * rela,Dwarf_Small * target_section,Dwarf_Unsigned target_section_size,int * error)343 update_entry(Dwarf_Debug dbg,
344     dwarf_elf_object_access_internals_t*obj,
345     struct generic_rela *rela,
346     Dwarf_Small *target_section,
347     Dwarf_Unsigned target_section_size,
348     int *error)
349 {
350     unsigned int type = 0;
351     unsigned int sym_idx = 0;
352     Dwarf_Unsigned offset = 0;
353     Dwarf_Signed addend = 0;
354     Dwarf_Unsigned reloc_size = 0;
355     Dwarf_Half machine  = obj->f_machine;
356     struct generic_symentry *symp = 0;
357     int is_rela = rela->gr_is_rela;
358 
359     offset = rela->gr_offset;
360     addend = rela->gr_addend;
361     type = (unsigned int)rela->gr_type;
362     sym_idx = (unsigned int)rela->gr_sym;
363     if (sym_idx >= obj->f_loc_symtab.g_count) {
364         *error = DW_DLE_RELOC_SECTION_SYMBOL_INDEX_BAD;
365         return DW_DLV_ERROR;
366     }
367     symp = obj->f_symtab + sym_idx;
368     if (offset >= target_section_size) {
369         /*  If offset really big, any add will overflow.
370             So lets stop early if offset is corrupt. */
371         *error = DW_DLE_RELOC_INVALID;
372         return DW_DLV_ERROR;
373     }
374 
375     /* Determine relocation size */
376     if (_dwarf_is_32bit_abs_reloc(type, machine)) {
377         reloc_size = 4;
378     } else if (_dwarf_is_64bit_abs_reloc(type, machine)) {
379         reloc_size = 8;
380     } else {
381         *error = DW_DLE_RELOC_SECTION_RELOC_TARGET_SIZE_UNKNOWN;
382         return DW_DLV_ERROR;
383     }
384     if ( (offset + reloc_size) < offset) {
385         /* Another check for overflow. */
386         *error = DW_DLE_RELOC_INVALID;
387         return DW_DLV_ERROR;
388     }
389     if ( (offset + reloc_size) > target_section_size) {
390         *error = DW_DLE_RELOC_INVALID;
391         return DW_DLV_ERROR;
392     }
393     /*  Assuming we do not need to do a READ_UNALIGNED here
394         at target_section + offset and add its value to
395         outval.  Some ABIs say no read (for example MIPS),
396         but if some do then which ones? */
397     {   /* .rel. (addend is 0), or .rela. */
398         Dwarf_Small *targ = target_section+offset;
399         Dwarf_Unsigned presentval = 0;
400         Dwarf_Unsigned outval = 0;
401         /*  See also: READ_UNALIGNED_SAFE in
402             dwarf_elf_access.c  */
403 
404         if (!is_rela) {
405             READ_UNALIGNED_SAFE(dbg,presentval,
406                 targ,reloc_size);
407         }
408         /*  There is no addend in .rel.
409             Normally presentval is correct
410             and st_value will be zero.
411             But a few compilers have
412             presentval zero and st_value set. */
413         outval = presentval + symp->gs_value + addend;
414         WRITE_UNALIGNED_LOCAL(dbg,targ,
415             &outval,sizeof(outval),reloc_size);
416     }
417     return DW_DLV_OK;
418 }
419 
420 
421 
422 /*  Somewhat arbitrarily, we attempt to apply all the
423     relocations we can
424     and still notify the caller of at least one error if we found
425     any errors.  */
426 
427 static int
apply_rela_entries(Dwarf_Debug dbg,Dwarf_Half r_section_index,dwarf_elf_object_access_internals_t * obj,struct Dwarf_Section_s * relocatablesec,int * error)428 apply_rela_entries(
429     Dwarf_Debug dbg,
430     /* Section_index of the relocation section, .rela entries  */
431     Dwarf_Half r_section_index,
432     dwarf_elf_object_access_internals_t*obj,
433     /* relocatablesec is the .debug_info(etc)  in Dwarf_Debug */
434     struct Dwarf_Section_s * relocatablesec,
435     int *error)
436 {
437     int return_res = DW_DLV_OK;
438     struct generic_shdr * rels_shp = 0;
439     Dwarf_Unsigned relcount;
440     Dwarf_Unsigned i = 0;
441 
442     if (r_section_index >= obj->f_loc_shdr.g_count) {
443         *error = DW_DLE_SECTION_INDEX_BAD;
444         return DW_DLV_ERROR;
445     }
446     rels_shp = obj->f_shdr + r_section_index;
447     relcount = rels_shp->gh_relcount;
448     if (!relcount) {
449         /*  Nothing to do. */
450         return DW_DLV_OK;
451     }
452     if (!rels_shp->gh_rels) {
453         /*  something wrong. */
454         *error = DW_DLE_RELOCS_ERROR;
455         return DW_DLV_ERROR;
456     }
457     for (i = 0; i < relcount; i++) {
458         int res = update_entry(dbg,obj,
459             rels_shp->gh_rels+i,
460             relocatablesec->dss_data,
461             relocatablesec->dss_size,
462             error);
463         if (res != DW_DLV_OK) {
464             /* We try to keep going, not stop. */
465             return_res = res;
466         }
467     }
468     return return_res;
469 }
470 
471 /*  Find the section data in dbg and find all the relevant
472     sections.  Then do relocations.
473 
474     section_index is the index of a .debug_info (for example)
475     so we have to find the section(s) with relocations
476     targeting section_index.
477     Normally there is exactly one such, though.
478 */
479 static int
elf_relocations_nolibelf(void * obj_in,Dwarf_Half section_index,Dwarf_Debug dbg,int * error)480 elf_relocations_nolibelf(void* obj_in,
481     Dwarf_Half section_index,
482     Dwarf_Debug dbg,
483     int* error)
484 {
485     int res = DW_DLV_ERROR;
486     dwarf_elf_object_access_internals_t*obj = 0;
487     struct Dwarf_Section_s * relocatablesec = 0;
488     unsigned section_with_reloc_records = 0;
489 
490     if (section_index == 0) {
491         return DW_DLV_NO_ENTRY;
492     }
493     obj = (dwarf_elf_object_access_internals_t*)obj_in;
494 
495     /*  The section to relocate must already be loaded into memory.
496         This just turns section_index into a pointer
497         to a de_debug_info or other  section record in
498         Dwarf_Debug. */
499     res = find_section_to_relocate(dbg, section_index,
500         &relocatablesec, error);
501     if (res != DW_DLV_OK) {
502         return res;
503     }
504     /*  Now we know the  Dwarf_Section_s section
505         we need to relocate.
506         So lets find the rela section(s) targeting this.
507     */
508 
509     /*  Sun and possibly others do not always set
510         sh_link in .debug_* sections.
511         So we cannot do full  consistency checks.
512         FIXME: This approach assumes there is only one
513         relocation section applying to section section_index! */
514     section_with_reloc_records = relocatablesec->dss_reloc_index;
515     if (!section_with_reloc_records) {
516         /* Something is wrong. */
517         *error = DW_DLE_RELOC_SECTION_MISSING_INDEX;
518         return DW_DLV_ERROR;
519     }
520     /* The relocations, if they exist, have been loaded. */
521     /* The symtab was already loaded. */
522     if (!obj->f_symtab || !obj->f_symtab_sect_strings) {
523         *error = DW_DLE_DEBUG_SYMTAB_ERR;
524         return DW_DLV_ERROR;
525     }
526     if (obj->f_symtab_sect_index != relocatablesec->dss_reloc_link) {
527         /* Something is wrong. */
528         *error = DW_DLE_RELOC_MISMATCH_RELOC_INDEX;
529         return DW_DLV_ERROR;
530     }
531     /* We have all the data we need in memory. */
532     /*  Now we apply the relocs in section_with_reloc_records to the
533         target, relocablesec */
534     res = apply_rela_entries(dbg,section_with_reloc_records,
535         obj, relocatablesec,error);
536     return res;
537 }
538 
539 void
_dwarf_destruct_elf_nlaccess(struct Dwarf_Obj_Access_Interface_s * aip)540 _dwarf_destruct_elf_nlaccess(
541     struct Dwarf_Obj_Access_Interface_s *aip)
542 {
543     dwarf_elf_object_access_internals_t *ep = 0;
544     struct generic_shdr *shp = 0;
545     Dwarf_Unsigned shcount = 0;
546     Dwarf_Unsigned i = 0;
547 
548     ep = (dwarf_elf_object_access_internals_t *)aip->object;
549     free(ep->f_ehdr);
550     shp = ep->f_shdr;
551     shcount = ep->f_loc_shdr.g_count;
552     for(i = 0; i < shcount; ++i,++shp) {
553         free(shp->gh_rels);
554         shp->gh_rels = 0;
555         free(shp->gh_content);
556         shp->gh_content = 0;
557         free(shp->gh_sht_group_array);
558         shp->gh_sht_group_array = 0;
559         shp->gh_sht_group_array_count = 0;
560     }
561     free(ep->f_shdr);
562     ep->f_loc_shdr.g_count = 0;
563     free(ep->f_phdr);
564     free(ep->f_elf_shstrings_data);
565     free(ep->f_dynamic);
566     free(ep->f_symtab_sect_strings);
567     free(ep->f_dynsym_sect_strings);
568     free(ep->f_symtab);
569     free(ep->f_dynsym);
570 
571     /* if TRUE close f_fd on destruct.*/
572     if (ep->f_destruct_close_fd) {
573         close(ep->f_fd);
574     }
575     ep->f_ident[0] = 'X';
576     free(ep->f_path);
577     free(ep);
578     free(aip);
579 }
580 
581 
582 int
_dwarf_elf_nlsetup(int fd,char * true_path,unsigned ftype,unsigned endian,unsigned offsetsize,size_t filesize,Dwarf_Unsigned access,unsigned groupnumber,Dwarf_Handler errhand,Dwarf_Ptr errarg,Dwarf_Debug * dbg,Dwarf_Error * error)583 _dwarf_elf_nlsetup(int fd,
584     char *true_path,
585     unsigned ftype,
586     unsigned endian,
587     unsigned offsetsize,
588     size_t filesize,
589     Dwarf_Unsigned access,
590     unsigned groupnumber,
591     Dwarf_Handler errhand,
592     Dwarf_Ptr errarg,
593     Dwarf_Debug *dbg,Dwarf_Error *error)
594 {
595     Dwarf_Obj_Access_Interface *binary_interface = 0;
596     dwarf_elf_object_access_internals_t *intfc = 0;
597     int res = DW_DLV_OK;
598     int localerrnum = 0;
599 
600     res = _dwarf_elf_object_access_init(
601         fd,
602         ftype,endian,offsetsize,filesize,access,
603         &binary_interface,
604         &localerrnum);
605     if (res != DW_DLV_OK) {
606         if (res == DW_DLV_NO_ENTRY) {
607             return res;
608         }
609         _dwarf_error(NULL, error, localerrnum);
610         return DW_DLV_ERROR;
611     }
612     /*  allocates and initializes Dwarf_Debug,
613         generic code */
614     res = dwarf_object_init_b(binary_interface, errhand, errarg,
615         groupnumber, dbg, error);
616     if (res != DW_DLV_OK){
617         _dwarf_destruct_elf_nlaccess(binary_interface);
618         return res;
619     }
620     intfc = binary_interface->object;
621     intfc->f_path = strdup(true_path);
622     return res;
623 }
624 
625 /*  dwarf_elf_access method table for use with non-libelf.
626     See also the methods table in dwarf_elf_access.c for libelf.
627 */
628 static Dwarf_Obj_Access_Methods const elf_nlmethods = {
629     elf_get_nolibelf_section_info,
630     elf_get_nolibelf_byte_order,
631     elf_get_nolibelf_length_size,
632     elf_get_nolibelf_pointer_size,
633     elf_get_nolibelf_section_count,
634     elf_load_nolibelf_section,
635     elf_relocations_nolibelf
636 };
637 
638 /*  On any error this frees internals argument. */
639 static int
_dwarf_elf_object_access_internals_init(dwarf_elf_object_access_internals_t * internals,int fd,unsigned ftype,unsigned endian,unsigned offsetsize,size_t filesize,UNUSEDARG Dwarf_Unsigned access,int * errcode)640 _dwarf_elf_object_access_internals_init(
641     dwarf_elf_object_access_internals_t * internals,
642     int  fd,
643     unsigned ftype,
644     unsigned endian,
645     unsigned offsetsize,
646     size_t filesize,
647     UNUSEDARG Dwarf_Unsigned access,
648     int *errcode)
649 {
650     dwarf_elf_object_access_internals_t * intfc = internals;
651     Dwarf_Unsigned i  = 0;
652     struct Dwarf_Obj_Access_Interface_s *localdoas;
653     int res = 0;
654 
655     /*  Must malloc as _dwarf_destruct_elf_access()
656         forces that due to other uses. */
657     localdoas = (struct Dwarf_Obj_Access_Interface_s *)
658         malloc(sizeof(struct Dwarf_Obj_Access_Interface_s));
659     if (!localdoas) {
660         free(internals);
661         *errcode = DW_DLE_ALLOC_FAIL;
662         return DW_DLV_ERROR;
663     }
664     memset(localdoas,0,sizeof(struct Dwarf_Obj_Access_Interface_s));
665     /*  E is used with libelf. F with this elf reader. */
666     intfc->f_ident[0]    = 'F';
667     intfc->f_ident[1]    = '1';
668     intfc->f_fd          = fd;
669     intfc->f_is_64bit    = ((offsetsize==64)?TRUE:FALSE);
670     intfc->f_offsetsize  = offsetsize;
671     intfc->f_pointersize = offsetsize;
672     intfc->f_filesize    = filesize;
673     intfc->f_ftype       = ftype;
674     intfc->f_destruct_close_fd = FALSE;
675 
676 #ifdef WORDS_BIGENDIAN
677     if (endian == DW_ENDIAN_LITTLE ) {
678         intfc->f_copy_word = _dwarf_memcpy_swap_bytes;
679         intfc->f_endian = DW_OBJECT_LSB;
680     } else {
681         intfc->f_copy_word = _dwarf_memcpy_noswap_bytes;
682         intfc->f_endian = DW_OBJECT_MSB;
683     }
684 #else  /* LITTLE ENDIAN */
685     if (endian == DW_ENDIAN_LITTLE ) {
686         intfc->f_copy_word = _dwarf_memcpy_noswap_bytes;
687         intfc->f_endian = DW_OBJECT_LSB;
688     } else {
689         intfc->f_copy_word = _dwarf_memcpy_swap_bytes;
690         intfc->f_endian = DW_OBJECT_MSB;
691     }
692 #endif /* LITTLE- BIG-ENDIAN */
693     _dwarf_get_elf_flags_func_ptr = _dwarf_get_elf_flags_func_nl;
694     /*  The following sets f_machine. */
695     res = _dwarf_load_elf_header(intfc,errcode);
696     if (res != DW_DLV_OK) {
697         localdoas->object = intfc;
698         localdoas->methods = 0;
699         _dwarf_destruct_elf_nlaccess(localdoas);
700         localdoas = 0;
701         return res;
702     }
703     /* Not loading progheaders */
704     res = _dwarf_load_elf_sectheaders(intfc,errcode);
705     if (res != DW_DLV_OK) {
706         localdoas->object = intfc;
707         localdoas->methods = 0;
708         _dwarf_destruct_elf_nlaccess(localdoas);
709         localdoas = 0;
710         return res;
711     }
712     /* We are not looking at symbol strings for now. */
713     res = _dwarf_load_elf_symstr(intfc,errcode);
714     if (res == DW_DLV_ERROR) {
715         localdoas->object = intfc;
716         localdoas->methods = 0;
717         _dwarf_destruct_elf_nlaccess(localdoas);
718         localdoas = 0;
719         return res;
720     }
721     res  = _dwarf_load_elf_symtab_symbols(intfc,errcode);
722     if (res == DW_DLV_ERROR) {
723         localdoas->object = intfc;
724         localdoas->methods = 0;
725         _dwarf_destruct_elf_nlaccess(localdoas);
726         localdoas = 0;
727         return res;
728     }
729     for ( i = 1; i < intfc->f_loc_shdr.g_count; ++i) {
730         struct generic_shdr *shp = 0;
731         Dwarf_Unsigned section_type = 0;
732         enum RelocRela localrel = RelocIsRela;
733 
734         shp = intfc->f_shdr +i;
735         section_type = shp->gh_type;
736         if (section_type == SHT_REL ||
737             (!strncmp(".rel.",shp->gh_namestring,5))) {
738             localrel = RelocIsRel;
739         } else if (section_type == SHT_RELA ||
740             (!strncmp(".rela.",shp->gh_namestring,6))) {
741             localrel = RelocIsRela;
742         } else {
743             continue;
744         }
745         /*  ASSERT: local rel is either RelocIsRel or
746             RelocIsRela. Never any other value. */
747         /*  Possibly we should check if the target section
748             is one we care about before loading rela
749             FIXME */
750         res = _dwarf_load_elf_relx(intfc,i,localrel,errcode);
751         if (res == DW_DLV_ERROR) {
752             localdoas->object = intfc;
753             localdoas->methods = 0;
754             _dwarf_destruct_elf_nlaccess(localdoas);
755             localdoas = 0;
756             return res;
757         }
758     }
759     free(localdoas);
760     localdoas = 0;
761     return DW_DLV_OK;
762 }
763 
764 
765 static int
_dwarf_elf_object_access_init(int fd,unsigned ftype,unsigned endian,unsigned offsetsize,size_t filesize,Dwarf_Unsigned access,Dwarf_Obj_Access_Interface ** binary_interface,int * localerrnum)766 _dwarf_elf_object_access_init(
767     int  fd,
768     unsigned ftype,
769     unsigned endian,
770     unsigned offsetsize,
771     size_t filesize,
772     Dwarf_Unsigned access,
773     Dwarf_Obj_Access_Interface **binary_interface,
774     int *localerrnum)
775 {
776 
777     int res = 0;
778     dwarf_elf_object_access_internals_t *internals = 0;
779     Dwarf_Obj_Access_Interface *intfc = 0;
780 
781     internals = malloc(sizeof(dwarf_elf_object_access_internals_t));
782     if (!internals) {
783         *localerrnum = DW_DLE_ALLOC_FAIL;
784         /* Impossible case, we hope. Give up. */
785         return DW_DLV_ERROR;
786     }
787     memset(internals,0,sizeof(*internals));
788     res = _dwarf_elf_object_access_internals_init(internals,
789         fd,
790         ftype, endian, offsetsize, filesize,
791         access,
792         localerrnum);
793     if (res != DW_DLV_OK){
794         return res;
795     }
796 
797     intfc = malloc(sizeof(Dwarf_Obj_Access_Interface));
798     if (!intfc) {
799         /* Impossible case, we hope. Give up. */
800         free(internals);
801         *localerrnum = DW_DLE_ALLOC_FAIL;
802         return DW_DLV_ERROR;
803     }
804     /* Initialize the interface struct */
805     intfc->object = internals;
806     intfc->methods = &elf_nlmethods;
807     *binary_interface = intfc;
808     return DW_DLV_OK;
809 }
810