Ulrich Drepper | b08d5a8 | 2005-07-26 05:00:05 +0000 | [diff] [blame^] | 1 | /* Internal definitions for libdwfl. |
| 2 | Copyright (C) 2005 Red Hat, Inc. |
| 3 | |
| 4 | This program is Open Source software; you can redistribute it and/or |
| 5 | modify it under the terms of the Open Software License version 1.0 as |
| 6 | published by the Open Source Initiative. |
| 7 | |
| 8 | You should have received a copy of the Open Software License along |
| 9 | with this program; if not, you may obtain a copy of the Open Software |
| 10 | License version 1.0 from http://www.opensource.org/licenses/osl.php or |
| 11 | by writing the Open Source Initiative c/o Lawrence Rosen, Esq., |
| 12 | 3001 King Ranch Road, Ukiah, CA 95482. */ |
| 13 | |
| 14 | #ifndef _LIBDWFLP_H |
| 15 | #define _LIBDWFLP_H 1 |
| 16 | |
| 17 | #ifndef PACKAGE |
| 18 | # include <config.h> |
| 19 | #endif |
| 20 | #include <libdwfl.h> |
| 21 | #include <libebl.h> |
| 22 | #include <assert.h> |
| 23 | #include <errno.h> |
| 24 | #include <stdbool.h> |
| 25 | #include <stdlib.h> |
| 26 | #include <string.h> |
| 27 | |
| 28 | /* gettext helper macros. */ |
| 29 | #define _(Str) dgettext ("elfutils", Str) |
| 30 | |
| 31 | #define DWFL_ERRORS \ |
| 32 | DWFL_ERROR (NOERROR, N_("no error")) \ |
| 33 | DWFL_ERROR (UNKNOWN_ERROR, N_("unknown error")) \ |
| 34 | DWFL_ERROR (NOMEM, N_("out of memory")) \ |
| 35 | DWFL_ERROR (ERRNO, N_("See errno")) \ |
| 36 | DWFL_ERROR (LIBELF, N_("See elf_errno")) \ |
| 37 | DWFL_ERROR (LIBDW, N_("See dwarf_errno")) \ |
| 38 | DWFL_ERROR (LIBEBL, N_("See ebl_errno (XXX missing)")) \ |
| 39 | DWFL_ERROR (NOREL, N_("Callbacks missing for ET_REL file")) \ |
| 40 | DWFL_ERROR (BADRELTYPE, N_("Unsupported relocation type")) \ |
| 41 | DWFL_ERROR (BADRELOFF, N_("r_offset is bogus")) \ |
| 42 | DWFL_ERROR (BADSTROFF, N_("offset out of range")) \ |
| 43 | DWFL_ERROR (RELUNDEF, N_("relocation refers to undefined symbol")) \ |
| 44 | DWFL_ERROR (CB, N_("Callback returned failure")) \ |
| 45 | DWFL_ERROR (NO_DWARF, N_("No DWARF information found")) \ |
| 46 | DWFL_ERROR (NO_SYMTAB, N_("No symbol table found")) \ |
| 47 | DWFL_ERROR (NO_PHDR, N_("No ELF program headers")) \ |
| 48 | DWFL_ERROR (OVERLAP, N_("address range overlaps an existing module")) \ |
| 49 | DWFL_ERROR (ADDR_OUTOFRANGE, N_("address out of range")) \ |
| 50 | DWFL_ERROR (NO_MATCH, N_("no matching address range")) \ |
| 51 | DWFL_ERROR (TRUNCATED, N_("image truncated")) \ |
| 52 | DWFL_ERROR (BADELF, N_("not a valid ELF file")) |
| 53 | |
| 54 | #define DWFL_ERROR(name, text) DWFL_E_##name, |
| 55 | typedef enum { DWFL_ERRORS DWFL_E_NUM } Dwfl_Error; |
| 56 | #undef DWFL_ERROR |
| 57 | |
| 58 | #define OTHER_ERROR(name) ((unsigned int) DWFL_E_##name << 16) |
| 59 | #define DWFL_E(name, errno) (OTHER_ERROR (name) | (errno)) |
| 60 | |
| 61 | extern int __libdwfl_canon_error (Dwfl_Error error) internal_function; |
| 62 | extern void __libdwfl_seterrno (Dwfl_Error error) internal_function; |
| 63 | |
| 64 | struct Dwfl |
| 65 | { |
| 66 | const Dwfl_Callbacks *callbacks; |
| 67 | |
| 68 | Dwfl_Module *modulelist; /* List in order used by full traversals. */ |
| 69 | |
| 70 | Dwfl_Module **modules; |
| 71 | size_t nmodules; |
| 72 | }; |
| 73 | |
| 74 | struct dwfl_file |
| 75 | { |
| 76 | char *name; |
| 77 | int fd; |
| 78 | |
| 79 | Elf *elf; |
| 80 | GElf_Addr bias; /* Actual load address - p_vaddr. */ |
| 81 | }; |
| 82 | |
| 83 | struct Dwfl_Module |
| 84 | { |
| 85 | Dwfl *dwfl; |
| 86 | struct Dwfl_Module *next; /* Link on Dwfl.moduelist. */ |
| 87 | |
| 88 | void *userdata; |
| 89 | |
| 90 | char *name; /* Iterator name for this module. */ |
| 91 | GElf_Addr low_addr, high_addr; |
| 92 | |
| 93 | struct dwfl_file main, debug; |
| 94 | Ebl *ebl; |
| 95 | bool isrel; /* True iff this is an ET_REL file. */ |
| 96 | Dwfl_Error elferr; /* Previous failure to open main file. */ |
| 97 | |
| 98 | struct dwfl_file *symfile; /* Either main or debug. */ |
| 99 | Elf_Data *symdata; /* Data in the ELF symbol table section. */ |
| 100 | size_t syments; /* sh_size / sh_entsize of that section. */ |
| 101 | const Elf_Data *symstrdata; /* Data for its string table. */ |
| 102 | Elf_Data *symxndxdata; /* Data in the extended section index table. */ |
| 103 | Dwfl_Error symerr; /* Previous failure to load symbols. */ |
| 104 | |
| 105 | Dwarf *dw; /* libdw handle for its debugging info. */ |
| 106 | Dwfl_Error dwerr; /* Previous failure to load info. */ |
| 107 | |
| 108 | /* Known CU's in this module. */ |
| 109 | struct dwfl_cu *first_cu, **cu; |
| 110 | unsigned int ncu; |
| 111 | |
| 112 | void *lazy_cu_root; /* Table indexed by Dwarf_Off of CU. */ |
| 113 | unsigned int lazycu; /* Possible users, deleted when none left. */ |
| 114 | |
| 115 | struct dwfl_arange *aranges; /* Mapping of addresses in module to CUs. */ |
| 116 | unsigned int naranges; |
| 117 | |
| 118 | bool gc; /* Mark/sweep flag. */ |
| 119 | }; |
| 120 | |
| 121 | |
| 122 | |
| 123 | /* Information cached about each CU in Dwfl_Module.dw. */ |
| 124 | struct dwfl_cu |
| 125 | { |
| 126 | /* This caches libdw information about the CU. It's also the |
| 127 | address passed back to users, so we take advantage of the |
| 128 | fact that it's placed first to cast back. */ |
| 129 | Dwarf_Die die; |
| 130 | |
| 131 | Dwfl_Module *mod; /* Pointer back to containing module. */ |
| 132 | |
| 133 | struct dwfl_cu *next; /* CU immediately following in the file. */ |
| 134 | |
| 135 | struct Dwfl_Lines *lines; |
| 136 | }; |
| 137 | |
| 138 | struct Dwfl_Lines |
| 139 | { |
| 140 | struct dwfl_cu *cu; |
| 141 | |
| 142 | /* This is what the opaque Dwfl_Line * pointers we pass to users are. |
| 143 | We need to recover pointers to our struct dwfl_cu and a record in |
| 144 | libdw's Dwarf_Line table. To minimize the memory used in addition |
| 145 | to libdw's Dwarf_Lines buffer, we just point to our own index in |
| 146 | this table, and have one pointer back to the CU. The indices here |
| 147 | match those in libdw's Dwarf_CU.lines->info table. */ |
| 148 | struct Dwfl_Line |
| 149 | { |
| 150 | unsigned int idx; /* My index in the dwfl_cu.lines table. */ |
| 151 | } idx[0]; |
| 152 | }; |
| 153 | |
| 154 | static inline struct dwfl_cu * |
| 155 | dwfl_linecu (const Dwfl_Line *line) |
| 156 | { |
| 157 | const struct Dwfl_Lines *lines = ((const void *) line |
| 158 | - offsetof (struct Dwfl_Lines, |
| 159 | idx[line->idx])); |
| 160 | return lines->cu; |
| 161 | } |
| 162 | |
| 163 | /* This describes a contiguous address range that lies in a single CU. |
| 164 | We condense runs of Dwarf_Arange entries for the same CU into this. */ |
| 165 | struct dwfl_arange |
| 166 | { |
| 167 | struct dwfl_cu *cu; |
| 168 | size_t arange; /* Index in Dwarf_Aranges. */ |
| 169 | }; |
| 170 | |
| 171 | |
| 172 | |
| 173 | |
| 174 | extern void __libdwfl_module_free (Dwfl_Module *mod) internal_function; |
| 175 | |
| 176 | |
| 177 | /* Process relocations in debugging sections in an ET_REL file. |
| 178 | MOD->debug.elf must be opened with ELF_C_READ_MMAP_PRIVATE or ELF_C_READ, |
| 179 | to make it possible to relocate the data in place (or ELF_C_RDWR or |
| 180 | ELF_C_RDWR_MMAP if you intend to modify the Elf file on disk). After |
| 181 | this, dwarf_begin_elf on MOD->debug.elf will read the relocated data. */ |
| 182 | extern Dwfl_Error __libdwfl_relocate (Dwfl_Module *) internal_function; |
| 183 | |
| 184 | /* Adjust *VALUE from section-relative to absolute. |
| 185 | MOD->dwfl->callbacks->section_address is called to determine the actual |
| 186 | address of a loaded section. */ |
| 187 | extern Dwfl_Error __libdwfl_relocate_value (Dwfl_Module *mod, |
| 188 | size_t m_shstrndx, |
| 189 | Elf32_Word shndx, |
| 190 | GElf_Addr *value) |
| 191 | internal_function; |
| 192 | |
| 193 | /* Iterate through all the CU's in the module. Start by passing a null |
| 194 | LASTCU, and then pass the last *CU returned. Success return with null |
| 195 | *CU no more CUs. */ |
| 196 | extern Dwfl_Error __libdwfl_nextcu (Dwfl_Module *mod, struct dwfl_cu *lastcu, |
| 197 | struct dwfl_cu **cu) internal_function; |
| 198 | |
| 199 | /* Find the CU by address. */ |
| 200 | extern Dwfl_Error __libdwfl_addrcu (Dwfl_Module *mod, Dwarf_Addr addr, |
| 201 | struct dwfl_cu **cu) internal_function; |
| 202 | |
| 203 | /* Ensure that CU->lines (and CU->cu->lines) is set up. */ |
| 204 | extern Dwfl_Error __libdwfl_cu_getsrclines (struct dwfl_cu *cu) |
| 205 | internal_function; |
| 206 | |
| 207 | |
| 208 | |
| 209 | |
| 210 | /* Avoid PLT entries. */ |
| 211 | INTDECL (dwfl_begin) |
| 212 | INTDECL (dwfl_errmsg) |
| 213 | INTDECL (dwfl_addrmodule) |
| 214 | INTDECL (dwfl_addrdwarf) |
| 215 | INTDECL (dwfl_addrdie) |
| 216 | INTDECL (dwfl_module_addrdie) |
| 217 | INTDECL (dwfl_module_getdwarf) |
| 218 | INTDECL (dwfl_module_getelf) |
| 219 | INTDECL (dwfl_module_getsrc) |
| 220 | INTDECL (dwfl_report_elf) |
| 221 | INTDECL (dwfl_report_begin) |
| 222 | INTDECL (dwfl_report_module) |
| 223 | INTDECL (dwfl_report_end) |
| 224 | INTDECL (dwfl_standard_find_debuginfo) |
| 225 | INTDECL (dwfl_linux_kernel_find_elf) |
| 226 | INTDECL (dwfl_linux_kernel_module_section_address) |
| 227 | INTDECL (dwfl_linux_proc_report) |
| 228 | INTDECL (dwfl_linux_proc_find_elf) |
| 229 | INTDECL (dwfl_linux_kernel_report_kernel) |
| 230 | INTDECL (dwfl_linux_kernel_report_modules) |
| 231 | |
| 232 | /* Leading arguments standard to callbacks passed a Dwfl_Module. */ |
| 233 | #define MODCB_ARGS(mod) (mod), &(mod)->userdata, (mod)->name, (mod)->low_addr |
| 234 | #define CBFAIL (errno ? DWFL_E (ERRNO, errno) : DWFL_E_CB); |
| 235 | |
| 236 | |
| 237 | #endif /* libdwflP.h */ |