1 /* Internal definitions for libdwfl.
2 Copyright (C) 2005-2011 Red Hat, Inc.
3 This file is part of Red Hat elfutils.
5 Red Hat elfutils is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by the
7 Free Software Foundation; version 2 of the License.
9 Red Hat elfutils is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
14 You should have received a copy of the GNU General Public License along
15 with Red Hat elfutils; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
18 In addition, as a special exception, Red Hat, Inc. gives You the
19 additional right to link the code of Red Hat elfutils with code licensed
20 under any Open Source Initiative certified open source license
21 (http://www.opensource.org/licenses/index.php) which requires the
22 distribution of source code with any binary distribution and to
23 distribute linked combinations of the two. Non-GPL Code permitted under
24 this exception must only link to the code of Red Hat elfutils through
25 those well defined interfaces identified in the file named EXCEPTION
26 found in the source code files (the "Approved Interfaces"). The files
27 of Non-GPL Code may instantiate templates or use macros or inline
28 functions from the Approved Interfaces without causing the resulting
29 work to be covered by the GNU General Public License. Only Red Hat,
30 Inc. may make changes or additions to the list of Approved Interfaces.
31 Red Hat's grant of this exception is conditioned upon your not adding
32 any new exceptions. If you wish to add a new Approved Interface or
33 exception, please contact Red Hat. You must obey the GNU General Public
34 License in all respects for all of the Red Hat elfutils code and other
35 code used in conjunction with Red Hat elfutils except the Non-GPL Code
36 covered by this exception. If you modify this file, you may extend this
37 exception to your version of the file, but you are not obligated to do
38 so. If you do not wish to provide this exception without modification,
39 you must delete this exception statement from your version and license
40 this file solely under the GPL without exception.
42 Red Hat elfutils is an included package of the Open Invention Network.
43 An included package of the Open Invention Network is a package for which
44 Open Invention Network licensees cross-license their patents. No patent
45 license is granted, either expressly or impliedly, by designation as an
46 included package. Should you wish to participate in the Open Invention
47 Network licensing program, please visit www.openinventionnetwork.com
48 <http://www.openinventionnetwork.com>. */
64 #include "../libdw/libdwP.h" /* We need its INTDECLs. */
66 /* gettext helper macros. */
67 #define _(Str) dgettext ("elfutils", Str)
70 DWFL_ERROR (NOERROR, N_("no error")) \
71 DWFL_ERROR (UNKNOWN_ERROR, N_("unknown error")) \
72 DWFL_ERROR (NOMEM, N_("out of memory")) \
73 DWFL_ERROR (ERRNO, N_("See errno")) \
74 DWFL_ERROR (LIBELF, N_("See elf_errno")) \
75 DWFL_ERROR (LIBDW, N_("See dwarf_errno")) \
76 DWFL_ERROR (LIBEBL, N_("See ebl_errno (XXX missing)")) \
77 DWFL_ERROR (ZLIB, N_("gzip decompression failed")) \
78 DWFL_ERROR (BZLIB, N_("bzip2 decompression failed")) \
79 DWFL_ERROR (LZMA, N_("LZMA decompression failed")) \
80 DWFL_ERROR (UNKNOWN_MACHINE, N_("no support library found for machine")) \
81 DWFL_ERROR (NOREL, N_("Callbacks missing for ET_REL file")) \
82 DWFL_ERROR (BADRELTYPE, N_("Unsupported relocation type")) \
83 DWFL_ERROR (BADRELOFF, N_("r_offset is bogus")) \
84 DWFL_ERROR (BADSTROFF, N_("offset out of range")) \
85 DWFL_ERROR (RELUNDEF, N_("relocation refers to undefined symbol")) \
86 DWFL_ERROR (CB, N_("Callback returned failure")) \
87 DWFL_ERROR (NO_DWARF, N_("No DWARF information found")) \
88 DWFL_ERROR (NO_SYMTAB, N_("No symbol table found")) \
89 DWFL_ERROR (NO_PHDR, N_("No ELF program headers")) \
90 DWFL_ERROR (OVERLAP, N_("address range overlaps an existing module")) \
91 DWFL_ERROR (ADDR_OUTOFRANGE, N_("address out of range")) \
92 DWFL_ERROR (NO_MATCH, N_("no matching address range")) \
93 DWFL_ERROR (TRUNCATED, N_("image truncated")) \
94 DWFL_ERROR (ALREADY_ELF, N_("ELF file opened")) \
95 DWFL_ERROR (BADELF, N_("not a valid ELF file")) \
96 DWFL_ERROR (WEIRD_TYPE, N_("cannot handle DWARF type description")) \
97 DWFL_ERROR (WRONG_ID_ELF, N_("ELF file does not match build ID"))
99 #define DWFL_ERROR(name, text) DWFL_E_##name,
100 typedef enum { DWFL_ERRORS DWFL_E_NUM } Dwfl_Error;
103 #define OTHER_ERROR(name) ((unsigned int) DWFL_E_##name << 16)
104 #define DWFL_E(name, errno) (OTHER_ERROR (name) | (errno))
106 extern int __libdwfl_canon_error (Dwfl_Error) internal_function;
107 extern void __libdwfl_seterrno (Dwfl_Error) internal_function;
111 const Dwfl_Callbacks *callbacks;
113 Dwfl_Module *modulelist; /* List in order used by full traversals. */
115 GElf_Addr offline_next_address;
117 GElf_Addr segment_align; /* Smallest granularity of segments. */
119 /* Binary search table in three parallel malloc'd arrays. */
120 size_t lookup_elts; /* Elements in use. */
121 size_t lookup_alloc; /* Elements allococated. */
122 GElf_Addr *lookup_addr; /* Start address of segment. */
123 Dwfl_Module **lookup_module; /* Module associated with segment, or null. */
124 int *lookup_segndx; /* User segment index, or -1. */
126 /* Cache from last dwfl_report_segment call. */
127 const void *lookup_tail_ident;
128 GElf_Off lookup_tail_vaddr;
129 GElf_Off lookup_tail_offset;
133 #define OFFLINE_REDZONE 0x10000
139 bool valid; /* The build ID note has been matched. */
140 bool relocated; /* Partial relocation of all sections done. */
144 /* This is the lowest p_vaddr in this ELF file, aligned to p_align.
145 For a file without phdrs, this is zero. */
148 /* This is an address chosen for synchronization between the main file
149 and the debug file. See dwfl_module_getdwarf.c for how it's chosen. */
150 GElf_Addr address_sync;
156 struct Dwfl_Module *next; /* Link on Dwfl.modulelist. */
160 char *name; /* Iterator name for this module. */
161 GElf_Addr low_addr, high_addr;
163 struct dwfl_file main, debug;
166 GElf_Half e_type; /* GElf_Ehdr.e_type cache. */
167 Dwfl_Error elferr; /* Previous failure to open main file. */
169 struct dwfl_relocation *reloc_info; /* Relocatable sections. */
171 struct dwfl_file *symfile; /* Either main or debug. */
172 Elf_Data *symdata; /* Data in the ELF symbol table section. */
173 size_t syments; /* sh_size / sh_entsize of that section. */
174 Elf_Data *symstrdata; /* Data for its string table. */
175 Elf_Data *symxndxdata; /* Data in the extended section index table. */
177 Dwarf *dw; /* libdw handle for its debugging info. */
179 Dwfl_Error symerr; /* Previous failure to load symbols. */
180 Dwfl_Error dwerr; /* Previous failure to load DWARF. */
182 /* Known CU's in this module. */
183 struct dwfl_cu *first_cu, **cu;
185 void *lazy_cu_root; /* Table indexed by Dwarf_Off of CU. */
187 struct dwfl_arange *aranges; /* Mapping of addresses in module to CUs. */
189 void *build_id_bits; /* malloc'd copy of build ID bits. */
190 GElf_Addr build_id_vaddr; /* Address where they reside, 0 if unknown. */
191 int build_id_len; /* -1 for prior failure, 0 if unset. */
194 unsigned int lazycu; /* Possible users, deleted when none left. */
195 unsigned int naranges;
197 Dwarf_CFI *dwarf_cfi; /* Cached DWARF CFI for this module. */
198 Dwarf_CFI *eh_cfi; /* Cached EH CFI for this module. */
200 int segment; /* Index of first segment table entry. */
201 bool gc; /* Mark/sweep flag. */
206 /* Information cached about each CU in Dwfl_Module.dw. */
209 /* This caches libdw information about the CU. It's also the
210 address passed back to users, so we take advantage of the
211 fact that it's placed first to cast back. */
214 Dwfl_Module *mod; /* Pointer back to containing module. */
216 struct dwfl_cu *next; /* CU immediately following in the file. */
218 struct Dwfl_Lines *lines;
225 /* This is what the opaque Dwfl_Line * pointers we pass to users are.
226 We need to recover pointers to our struct dwfl_cu and a record in
227 libdw's Dwarf_Line table. To minimize the memory used in addition
228 to libdw's Dwarf_Lines buffer, we just point to our own index in
229 this table, and have one pointer back to the CU. The indices here
230 match those in libdw's Dwarf_CU.lines->info table. */
233 unsigned int idx; /* My index in the dwfl_cu.lines table. */
237 static inline struct dwfl_cu *
238 dwfl_linecu_inline (const Dwfl_Line *line)
240 const struct Dwfl_Lines *lines = ((const void *) line
241 - offsetof (struct Dwfl_Lines,
245 #define dwfl_linecu dwfl_linecu_inline
247 static inline GElf_Addr
248 dwfl_adjusted_address (Dwfl_Module *mod, GElf_Addr addr)
250 return addr + mod->main_bias;
253 static inline GElf_Addr
254 dwfl_deadjust_address (Dwfl_Module *mod, GElf_Addr addr)
256 return addr - mod->main_bias;
259 static inline Dwarf_Addr
260 dwfl_adjusted_dwarf_addr (Dwfl_Module *mod, Dwarf_Addr addr)
262 return dwfl_adjusted_address (mod, (addr
263 - mod->debug.address_sync
264 + mod->main.address_sync));
267 static inline Dwarf_Addr
268 dwfl_deadjust_dwarf_addr (Dwfl_Module *mod, Dwarf_Addr addr)
270 return (dwfl_deadjust_address (mod, addr)
271 - mod->main.address_sync
272 + mod->debug.address_sync);
275 static inline GElf_Addr
276 dwfl_adjusted_st_value (Dwfl_Module *mod, GElf_Addr addr)
278 if (mod->symfile == &mod->main)
279 return dwfl_adjusted_address (mod, addr);
280 return dwfl_adjusted_dwarf_addr (mod, addr);
283 static inline GElf_Addr
284 dwfl_deadjust_st_value (Dwfl_Module *mod, GElf_Addr addr)
286 if (mod->symfile == &mod->main)
287 return dwfl_deadjust_address (mod, addr);
288 return dwfl_deadjust_dwarf_addr (mod, addr);
291 /* This describes a contiguous address range that lies in a single CU.
292 We condense runs of Dwarf_Arange entries for the same CU into this. */
296 size_t arange; /* Index in Dwarf_Aranges. */
301 extern void __libdwfl_module_free (Dwfl_Module *mod) internal_function;
303 /* Find the main ELF file, update MOD->elferr and/or MOD->main.elf. */
304 extern void __libdwfl_getelf (Dwfl_Module *mod) internal_function;
306 /* Process relocations in debugging sections in an ET_REL file.
307 FILE must be opened with ELF_C_READ_MMAP_PRIVATE or ELF_C_READ,
308 to make it possible to relocate the data in place (or ELF_C_RDWR or
309 ELF_C_RDWR_MMAP if you intend to modify the Elf file on disk). After
310 this, dwarf_begin_elf on FILE will read the relocated data.
312 When DEBUG is false, apply partial relocation to all sections. */
313 extern Dwfl_Error __libdwfl_relocate (Dwfl_Module *mod, Elf *file, bool debug)
316 /* Process (simple) relocations in arbitrary section TSCN of an ET_REL file.
317 RELOCSCN is SHT_REL or SHT_RELA and TSCN is its sh_info target section. */
318 extern Dwfl_Error __libdwfl_relocate_section (Dwfl_Module *mod, Elf *relocated,
319 Elf_Scn *relocscn, Elf_Scn *tscn,
323 /* Adjust *VALUE from section-relative to absolute.
324 MOD->dwfl->callbacks->section_address is called to determine the actual
325 address of a loaded section. */
326 extern Dwfl_Error __libdwfl_relocate_value (Dwfl_Module *mod, Elf *elf,
327 size_t *shstrndx_cache,
333 /* Ensure that MOD->ebl is set up. */
334 extern Dwfl_Error __libdwfl_module_getebl (Dwfl_Module *mod) internal_function;
336 /* Install a new Dwarf_CFI in *SLOT (MOD->eh_cfi or MOD->dwarf_cfi). */
337 extern Dwarf_CFI *__libdwfl_set_cfi (Dwfl_Module *mod, Dwarf_CFI **slot,
341 /* Iterate through all the CU's in the module. Start by passing a null
342 LASTCU, and then pass the last *CU returned. Success return with null
344 extern Dwfl_Error __libdwfl_nextcu (Dwfl_Module *mod, struct dwfl_cu *lastcu,
345 struct dwfl_cu **cu) internal_function;
347 /* Find the CU by address. */
348 extern Dwfl_Error __libdwfl_addrcu (Dwfl_Module *mod, Dwarf_Addr addr,
349 struct dwfl_cu **cu) internal_function;
351 /* Ensure that CU->lines (and CU->cu->lines) is set up. */
352 extern Dwfl_Error __libdwfl_cu_getsrclines (struct dwfl_cu *cu)
355 /* Look in ELF for an NT_GNU_BUILD_ID note. If SET is true, store it
356 in MOD and return its length. If SET is false, instead compare it
357 to that stored in MOD and return 2 if they match, 1 if they do not.
358 Returns -1 for errors, 0 if no note is found. */
359 extern int __libdwfl_find_build_id (Dwfl_Module *mod, bool set, Elf *elf)
362 /* Open a main or debuginfo file by its build ID, returns the fd. */
363 extern int __libdwfl_open_by_build_id (Dwfl_Module *mod, bool debug,
364 char **file_name) internal_function;
366 extern uint32_t __libdwfl_crc32 (uint32_t crc, unsigned char *buf, size_t len)
368 extern int __libdwfl_crc32_file (int fd, uint32_t *resp) attribute_hidden;
371 /* Meat of dwfl_report_elf, given elf_begin just called.
372 Consumes ELF on success, not on failure. */
373 extern Dwfl_Module *__libdwfl_report_elf (Dwfl *dwfl, const char *name,
374 const char *file_name, int fd,
375 Elf *elf, GElf_Addr base, bool sanity)
378 /* Meat of dwfl_report_offline. */
379 extern Dwfl_Module *__libdwfl_report_offline (Dwfl *dwfl, const char *name,
380 const char *file_name,
381 int fd, bool closefd,
382 int (*predicate) (const char *,
386 /* Decompression wrappers: decompress whole file into memory. */
387 extern Dwfl_Error __libdw_gunzip (int fd, off64_t start_offset,
388 void *mapped, size_t mapped_size,
389 void **whole, size_t *whole_size)
391 extern Dwfl_Error __libdw_bunzip2 (int fd, off64_t start_offset,
392 void *mapped, size_t mapped_size,
393 void **whole, size_t *whole_size)
395 extern Dwfl_Error __libdw_unlzma (int fd, off64_t start_offset,
396 void *mapped, size_t mapped_size,
397 void **whole, size_t *whole_size)
400 /* Skip the image header before a file image: updates *START_OFFSET. */
401 extern Dwfl_Error __libdw_image_header (int fd, off64_t *start_offset,
402 void *mapped, size_t mapped_size)
405 /* Open Elf handle on *FDP. This handles decompression and checks
406 elf_kind. Succeed only for ELF_K_ELF, or also ELF_K_AR if ARCHIVE_OK.
407 Returns DWFL_E_NOERROR and sets *ELFP on success, resets *FDP to -1 if
408 it's no longer used. Resets *FDP on failure too iff CLOSE_ON_FAIL. */
409 extern Dwfl_Error __libdw_open_file (int *fdp, Elf **elfp,
410 bool close_on_fail, bool archive_ok)
413 /* These are working nicely for --core, but are not ready to be
414 exported interfaces quite yet. */
416 /* Type of callback function ...
418 typedef bool Dwfl_Memory_Callback (Dwfl *dwfl, int segndx,
419 void **buffer, size_t *buffer_available,
420 GElf_Addr vaddr, size_t minread, void *arg);
422 /* Type of callback function ...
424 typedef bool Dwfl_Module_Callback (Dwfl_Module *mod, void **userdata,
425 const char *name, Dwarf_Addr base,
426 void **buffer, size_t *buffer_available,
427 GElf_Off cost, GElf_Off worthwhile,
428 GElf_Off whole, GElf_Off contiguous,
429 void *arg, Elf **elfp);
433 extern int dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
434 Dwfl_Memory_Callback *memory_callback,
435 void *memory_callback_arg,
436 Dwfl_Module_Callback *read_eagerly,
437 void *read_eagerly_arg);
439 /* Report a module for entry in the dynamic linker's struct link_map list.
440 For each link_map entry, if an existing module resides at its address,
441 this just modifies that module's name and suggested file name. If
442 no such module exists, this calls dwfl_report_elf on the l_name string.
444 If AUXV is not null, it points to AUXV_SIZE bytes of auxiliary vector
445 data as contained in an NT_AUXV note or read from a /proc/pid/auxv
446 file. When this is available, it guides the search. If AUXV is null
447 or the memory it points to is not accessible, then this search can
448 only find where to begin if the correct executable file was
449 previously reported and preloaded as with dwfl_report_elf.
451 Returns the number of modules found, or -1 for errors. */
452 extern int dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size,
453 Dwfl_Memory_Callback *memory_callback,
454 void *memory_callback_arg);
457 /* Avoid PLT entries. */
459 INTDECL (dwfl_errmsg)
461 INTDECL (dwfl_addrmodule)
462 INTDECL (dwfl_addrsegment)
463 INTDECL (dwfl_addrdwarf)
464 INTDECL (dwfl_addrdie)
465 INTDECL (dwfl_core_file_report)
466 INTDECL (dwfl_getmodules)
467 INTDECL (dwfl_module_addrdie)
468 INTDECL (dwfl_module_address_section)
469 INTDECL (dwfl_module_addrsym)
470 INTDECL (dwfl_module_build_id)
471 INTDECL (dwfl_module_getdwarf)
472 INTDECL (dwfl_module_getelf)
473 INTDECL (dwfl_module_getsym)
474 INTDECL (dwfl_module_getsymtab)
475 INTDECL (dwfl_module_getsrc)
476 INTDECL (dwfl_module_report_build_id)
477 INTDECL (dwfl_report_elf)
478 INTDECL (dwfl_report_begin)
479 INTDECL (dwfl_report_begin_add)
480 INTDECL (dwfl_report_module)
481 INTDECL (dwfl_report_segment)
482 INTDECL (dwfl_report_offline)
483 INTDECL (dwfl_report_end)
484 INTDECL (dwfl_build_id_find_elf)
485 INTDECL (dwfl_build_id_find_debuginfo)
486 INTDECL (dwfl_standard_find_debuginfo)
487 INTDECL (dwfl_link_map_report)
488 INTDECL (dwfl_linux_kernel_find_elf)
489 INTDECL (dwfl_linux_kernel_module_section_address)
490 INTDECL (dwfl_linux_proc_report)
491 INTDECL (dwfl_linux_proc_maps_report)
492 INTDECL (dwfl_linux_proc_find_elf)
493 INTDECL (dwfl_linux_kernel_report_kernel)
494 INTDECL (dwfl_linux_kernel_report_modules)
495 INTDECL (dwfl_linux_kernel_report_offline)
496 INTDECL (dwfl_offline_section_address)
497 INTDECL (dwfl_module_relocate_address)
498 INTDECL (dwfl_module_dwarf_cfi)
499 INTDECL (dwfl_module_eh_cfi)
501 /* Leading arguments standard to callbacks passed a Dwfl_Module. */
502 #define MODCB_ARGS(mod) (mod), &(mod)->userdata, (mod)->name, (mod)->low_addr
503 #define CBFAIL (errno ? DWFL_E (ERRNO, errno) : DWFL_E_CB);
506 /* The default used by dwfl_standard_find_debuginfo. */
507 #define DEFAULT_DEBUGINFO_PATH ":.debug:/usr/lib/debug"
510 #endif /* libdwflP.h */