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