Rewrite kernel image support: use calculation instead of brute force, support uncompr...
[platform/upstream/elfutils.git] / libdwfl / libdwflP.h
1 /* Internal definitions for libdwfl.
2    Copyright (C) 2005, 2006, 2007, 2008, 2009 Red Hat, Inc.
3    This file is part of Red Hat elfutils.
4
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.
8
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.
13
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.
17
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.
41
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>.  */
49
50 #ifndef _LIBDWFLP_H
51 #define _LIBDWFLP_H     1
52
53 #ifndef PACKAGE_NAME
54 # include <config.h>
55 #endif
56 #include <libdwfl.h>
57 #include <libebl.h>
58 #include <assert.h>
59 #include <errno.h>
60 #include <stdbool.h>
61 #include <stdlib.h>
62 #include <string.h>
63
64 #include "../libdw/libdwP.h"    /* We need its INTDECLs.  */
65
66 /* gettext helper macros.  */
67 #define _(Str) dgettext ("elfutils", Str)
68
69 #define DWFL_ERRORS                                                           \
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
98 #define DWFL_ERROR(name, text) DWFL_E_##name,
99 typedef enum { DWFL_ERRORS DWFL_E_NUM } Dwfl_Error;
100 #undef  DWFL_ERROR
101
102 #define OTHER_ERROR(name)       ((unsigned int) DWFL_E_##name << 16)
103 #define DWFL_E(name, errno)     (OTHER_ERROR (name) | (errno))
104
105 extern int __libdwfl_canon_error (Dwfl_Error) internal_function;
106 extern void __libdwfl_seterrno (Dwfl_Error) internal_function;
107
108 struct Dwfl
109 {
110   const Dwfl_Callbacks *callbacks;
111
112   Dwfl_Module *modulelist;    /* List in order used by full traversals.  */
113
114   GElf_Addr offline_next_address;
115
116   GElf_Addr segment_align;      /* Smallest granularity of segments.  */
117
118   /* Binary search table in three parallel malloc'd arrays.  */
119   size_t lookup_elts;           /* Elements in use.  */
120   size_t lookup_alloc;          /* Elements allococated.  */
121   GElf_Addr *lookup_addr;       /* Start address of segment.  */
122   Dwfl_Module **lookup_module;  /* Module associated with segment, or null.  */
123   int *lookup_segndx;           /* User segment index, or -1.  */
124
125   /* Cache from last dwfl_report_segment call.  */
126   const void *lookup_tail_ident;
127   GElf_Off lookup_tail_vaddr;
128   GElf_Off lookup_tail_offset;
129   int lookup_tail_ndx;
130 };
131
132 #define OFFLINE_REDZONE         0x10000
133
134 struct dwfl_file
135 {
136   char *name;
137   int fd;
138   bool valid;                   /* The build ID note has been matched.  */
139   bool relocated;               /* Partial relocation of all sections done.  */
140
141   Elf *elf;
142   GElf_Addr bias;               /* Actual load address - p_vaddr.  */
143 };
144
145 struct Dwfl_Module
146 {
147   Dwfl *dwfl;
148   struct Dwfl_Module *next;     /* Link on Dwfl.modulelist.  */
149
150   void *userdata;
151
152   char *name;                   /* Iterator name for this module.  */
153   GElf_Addr low_addr, high_addr;
154
155   struct dwfl_file main, debug;
156   Ebl *ebl;
157   GElf_Half e_type;             /* GElf_Ehdr.e_type cache.  */
158   Dwfl_Error elferr;            /* Previous failure to open main file.  */
159
160   struct dwfl_relocation *reloc_info; /* Relocatable sections.  */
161
162   struct dwfl_file *symfile;    /* Either main or debug.  */
163   Elf_Data *symdata;            /* Data in the ELF symbol table section.  */
164   size_t syments;               /* sh_size / sh_entsize of that section.  */
165   Elf_Data *symstrdata;         /* Data for its string table.  */
166   Elf_Data *symxndxdata;        /* Data in the extended section index table. */
167
168   Dwarf *dw;                    /* libdw handle for its debugging info.  */
169
170   Dwfl_Error symerr;            /* Previous failure to load symbols.  */
171   Dwfl_Error dwerr;             /* Previous failure to load DWARF.  */
172
173   /* Known CU's in this module.  */
174   struct dwfl_cu *first_cu, **cu;
175
176   void *lazy_cu_root;           /* Table indexed by Dwarf_Off of CU.  */
177
178   struct dwfl_arange *aranges;  /* Mapping of addresses in module to CUs.  */
179
180   void *build_id_bits;          /* malloc'd copy of build ID bits.  */
181   GElf_Addr build_id_vaddr;     /* Address where they reside, 0 if unknown.  */
182   int build_id_len;             /* -1 for prior failure, 0 if unset.  */
183
184   unsigned int ncu;
185   unsigned int lazycu;          /* Possible users, deleted when none left.  */
186   unsigned int naranges;
187
188   Dwarf_CFI *dwarf_cfi;         /* Cached DWARF CFI for this module.  */
189   Dwarf_CFI *eh_cfi;            /* Cached EH CFI for this module.  */
190
191   int segment;                  /* Index of first segment table entry.  */
192   bool gc;                      /* Mark/sweep flag.  */
193 };
194
195
196
197 /* Information cached about each CU in Dwfl_Module.dw.  */
198 struct dwfl_cu
199 {
200   /* This caches libdw information about the CU.  It's also the
201      address passed back to users, so we take advantage of the
202      fact that it's placed first to cast back.  */
203   Dwarf_Die die;
204
205   Dwfl_Module *mod;             /* Pointer back to containing module.  */
206
207   struct dwfl_cu *next;         /* CU immediately following in the file.  */
208
209   struct Dwfl_Lines *lines;
210 };
211
212 struct Dwfl_Lines
213 {
214   struct dwfl_cu *cu;
215
216   /* This is what the opaque Dwfl_Line * pointers we pass to users are.
217      We need to recover pointers to our struct dwfl_cu and a record in
218      libdw's Dwarf_Line table.  To minimize the memory used in addition
219      to libdw's Dwarf_Lines buffer, we just point to our own index in
220      this table, and have one pointer back to the CU.  The indices here
221      match those in libdw's Dwarf_CU.lines->info table.  */
222   struct Dwfl_Line
223   {
224     unsigned int idx;           /* My index in the dwfl_cu.lines table.  */
225   } idx[0];
226 };
227
228 static inline struct dwfl_cu *
229 dwfl_linecu_inline (const Dwfl_Line *line)
230 {
231   const struct Dwfl_Lines *lines = ((const void *) line
232                                     - offsetof (struct Dwfl_Lines,
233                                                 idx[line->idx]));
234   return lines->cu;
235 }
236 #define dwfl_linecu dwfl_linecu_inline
237
238 /* This describes a contiguous address range that lies in a single CU.
239    We condense runs of Dwarf_Arange entries for the same CU into this.  */
240 struct dwfl_arange
241 {
242   struct dwfl_cu *cu;
243   size_t arange;                /* Index in Dwarf_Aranges.  */
244 };
245
246
247
248 extern void __libdwfl_module_free (Dwfl_Module *mod) internal_function;
249
250 /* Find the main ELF file, update MOD->elferr and/or MOD->main.elf.  */
251 extern void __libdwfl_getelf (Dwfl_Module *mod) internal_function;
252
253 /* Process relocations in debugging sections in an ET_REL file.
254    FILE must be opened with ELF_C_READ_MMAP_PRIVATE or ELF_C_READ,
255    to make it possible to relocate the data in place (or ELF_C_RDWR or
256    ELF_C_RDWR_MMAP if you intend to modify the Elf file on disk).  After
257    this, dwarf_begin_elf on FILE will read the relocated data.
258
259    When DEBUG is false, apply partial relocation to all sections.  */
260 extern Dwfl_Error __libdwfl_relocate (Dwfl_Module *mod, Elf *file, bool debug)
261   internal_function;
262
263 /* Process (simple) relocations in arbitrary section TSCN of an ET_REL file.
264    RELOCSCN is SHT_REL or SHT_RELA and TSCN is its sh_info target section.  */
265 extern Dwfl_Error __libdwfl_relocate_section (Dwfl_Module *mod, Elf *relocated,
266                                               Elf_Scn *relocscn, Elf_Scn *tscn,
267                                               bool partial)
268   internal_function;
269
270 /* Adjust *VALUE from section-relative to absolute.
271    MOD->dwfl->callbacks->section_address is called to determine the actual
272    address of a loaded section.  */
273 extern Dwfl_Error __libdwfl_relocate_value (Dwfl_Module *mod, Elf *elf,
274                                             size_t *shstrndx_cache,
275                                             Elf32_Word shndx,
276                                             GElf_Addr *value)
277      internal_function;
278
279
280 /* Ensure that MOD->ebl is set up.  */
281 extern Dwfl_Error __libdwfl_module_getebl (Dwfl_Module *mod) internal_function;
282
283 /* Install a new Dwarf_CFI in *SLOT (MOD->eh_cfi or MOD->dwarf_cfi).  */
284 extern Dwarf_CFI *__libdwfl_set_cfi (Dwfl_Module *mod, Dwarf_CFI **slot,
285                                      Dwarf_CFI *cfi)
286   internal_function;
287
288 /* Iterate through all the CU's in the module.  Start by passing a null
289    LASTCU, and then pass the last *CU returned.  Success return with null
290    *CU no more CUs.  */
291 extern Dwfl_Error __libdwfl_nextcu (Dwfl_Module *mod, struct dwfl_cu *lastcu,
292                                     struct dwfl_cu **cu) internal_function;
293
294 /* Find the CU by address.  */
295 extern Dwfl_Error __libdwfl_addrcu (Dwfl_Module *mod, Dwarf_Addr addr,
296                                     struct dwfl_cu **cu) internal_function;
297
298 /* Ensure that CU->lines (and CU->cu->lines) is set up.  */
299 extern Dwfl_Error __libdwfl_cu_getsrclines (struct dwfl_cu *cu)
300   internal_function;
301
302 /* Look in ELF for an NT_GNU_BUILD_ID note.  If SET is true, store it
303    in MOD and return its length.  If SET is false, instead compare it
304    to that stored in MOD and return 2 if they match, 1 if they do not.
305    Returns -1 for errors, 0 if no note is found.  */
306 extern int __libdwfl_find_build_id (Dwfl_Module *mod, bool set, Elf *elf)
307   internal_function;
308
309 /* Open a main or debuginfo file by its build ID, returns the fd.  */
310 extern int __libdwfl_open_by_build_id (Dwfl_Module *mod, bool debug,
311                                        char **file_name) internal_function;
312
313 extern uint32_t __libdwfl_crc32 (uint32_t crc, unsigned char *buf, size_t len)
314   attribute_hidden;
315 extern int __libdwfl_crc32_file (int fd, uint32_t *resp) attribute_hidden;
316
317
318 /* Meat of dwfl_report_elf, given elf_begin just called.
319    Consumes ELF on success, not on failure.  */
320 extern Dwfl_Module *__libdwfl_report_elf (Dwfl *dwfl, const char *name,
321                                           const char *file_name, int fd,
322                                           Elf *elf, GElf_Addr base, bool sanity)
323   internal_function;
324
325 /* Meat of dwfl_report_offline.  */
326 extern Dwfl_Module *__libdwfl_report_offline (Dwfl *dwfl, const char *name,
327                                               const char *file_name,
328                                               int fd, bool closefd,
329                                               int (*predicate) (const char *,
330                                                                 const char *))
331   internal_function;
332
333 /* Decompression wrappers: decompress whole file into memory.  */
334 extern Dwfl_Error __libdw_gunzip  (int fd, off64_t start_offset,
335                                    void *mapped, size_t mapped_size,
336                                    void **whole, size_t *whole_size)
337   internal_function;
338 extern Dwfl_Error __libdw_bunzip2 (int fd, off64_t start_offset,
339                                    void *mapped, size_t mapped_size,
340                                    void **whole, size_t *whole_size)
341   internal_function;
342 extern Dwfl_Error __libdw_unlzma (int fd, off64_t start_offset,
343                                   void *mapped, size_t mapped_size,
344                                   void **whole, size_t *whole_size)
345   internal_function;
346
347 /* Skip the image header before a file image: updates *START_OFFSET.  */
348 extern Dwfl_Error __libdw_image_header (int fd, off64_t *start_offset,
349                                         void *mapped, size_t mapped_size)
350   internal_function;
351
352 /* Open Elf handle on *FDP.  This handles decompression and checks
353    elf_kind.  Succeed only for ELF_K_ELF, or also ELF_K_AR if ARCHIVE_OK.
354    Returns DWFL_E_NOERROR and sets *ELFP on success, resets *FDP to -1 if
355    it's no longer used.  Resets *FDP on failure too iff CLOSE_ON_FAIL.  */
356 extern Dwfl_Error __libdw_open_file (int *fdp, Elf **elfp,
357                                      bool close_on_fail, bool archive_ok)
358   internal_function;
359
360 /* These are working nicely for --core, but are not ready to be
361    exported interfaces quite yet.  */
362
363 /* Type of callback function ...
364  */
365 typedef bool Dwfl_Memory_Callback (Dwfl *dwfl, int segndx,
366                                    void **buffer, size_t *buffer_available,
367                                    GElf_Addr vaddr, size_t minread, void *arg);
368
369 /* Type of callback function ...
370  */
371 typedef bool Dwfl_Module_Callback (Dwfl_Module *mod, void **userdata,
372                                    const char *name, Dwarf_Addr base,
373                                    void **buffer, size_t *buffer_available,
374                                    GElf_Off cost, GElf_Off worthwhile,
375                                    GElf_Off whole, GElf_Off contiguous,
376                                    void *arg, Elf **elfp);
377
378 /* ...
379  */
380 extern int dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
381                                        Dwfl_Memory_Callback *memory_callback,
382                                        void *memory_callback_arg,
383                                        Dwfl_Module_Callback *read_eagerly,
384                                        void *read_eagerly_arg);
385
386 /* Report a module for entry in the dynamic linker's struct link_map list.
387    For each link_map entry, if an existing module resides at its address,
388    this just modifies that module's name and suggested file name.  If
389    no such module exists, this calls dwfl_report_elf on the l_name string.
390
391    If AUXV is not null, it points to AUXV_SIZE bytes of auxiliary vector
392    data as contained in an NT_AUXV note or read from a /proc/pid/auxv
393    file.  When this is available, it guides the search.  If AUXV is null
394    or the memory it points to is not accessible, then this search can
395    only find where to begin if the correct executable file was
396    previously reported and preloaded as with dwfl_report_elf.
397
398    Returns the number of modules found, or -1 for errors.  */
399 extern int dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size,
400                                  Dwfl_Memory_Callback *memory_callback,
401                                  void *memory_callback_arg);
402
403 /* Examine an ET_CORE file and report modules based on its contents.  */
404 extern int dwfl_core_file_report (Dwfl *dwfl, Elf *elf, const GElf_Ehdr *ehdr);
405
406
407
408 /* Avoid PLT entries.  */
409 INTDECL (dwfl_begin)
410 INTDECL (dwfl_errmsg)
411 INTDECL (dwfl_addrmodule)
412 INTDECL (dwfl_addrsegment)
413 INTDECL (dwfl_addrdwarf)
414 INTDECL (dwfl_addrdie)
415 INTDECL (dwfl_core_file_report)
416 INTDECL (dwfl_getmodules)
417 INTDECL (dwfl_module_addrdie)
418 INTDECL (dwfl_module_address_section)
419 INTDECL (dwfl_module_addrsym)
420 INTDECL (dwfl_module_build_id)
421 INTDECL (dwfl_module_getdwarf)
422 INTDECL (dwfl_module_getelf)
423 INTDECL (dwfl_module_getsym)
424 INTDECL (dwfl_module_getsymtab)
425 INTDECL (dwfl_module_getsrc)
426 INTDECL (dwfl_module_report_build_id)
427 INTDECL (dwfl_report_elf)
428 INTDECL (dwfl_report_begin)
429 INTDECL (dwfl_report_begin_add)
430 INTDECL (dwfl_report_module)
431 INTDECL (dwfl_report_segment)
432 INTDECL (dwfl_report_offline)
433 INTDECL (dwfl_report_end)
434 INTDECL (dwfl_build_id_find_elf)
435 INTDECL (dwfl_build_id_find_debuginfo)
436 INTDECL (dwfl_standard_find_debuginfo)
437 INTDECL (dwfl_link_map_report)
438 INTDECL (dwfl_linux_kernel_find_elf)
439 INTDECL (dwfl_linux_kernel_module_section_address)
440 INTDECL (dwfl_linux_proc_report)
441 INTDECL (dwfl_linux_proc_maps_report)
442 INTDECL (dwfl_linux_proc_find_elf)
443 INTDECL (dwfl_linux_kernel_report_kernel)
444 INTDECL (dwfl_linux_kernel_report_modules)
445 INTDECL (dwfl_linux_kernel_report_offline)
446 INTDECL (dwfl_offline_section_address)
447 INTDECL (dwfl_module_relocate_address)
448 INTDECL (dwfl_module_dwarf_cfi)
449 INTDECL (dwfl_module_eh_cfi)
450
451 /* Leading arguments standard to callbacks passed a Dwfl_Module.  */
452 #define MODCB_ARGS(mod) (mod), &(mod)->userdata, (mod)->name, (mod)->low_addr
453 #define CBFAIL          (errno ? DWFL_E (ERRNO, errno) : DWFL_E_CB);
454
455
456 /* The default used by dwfl_standard_find_debuginfo.  */
457 #define DEFAULT_DEBUGINFO_PATH ":.debug:/usr/lib/debug"
458
459
460 #endif  /* libdwflP.h */