libdwfl: Enhance address_sync calculation to handle more prelink permutations.
[platform/upstream/elfutils.git] / libdwfl / libdwflP.h
1 /* Internal definitions for libdwfl.
2    Copyright (C) 2005-2011 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   DWFL_ERROR (WRONG_ID_ELF, N_("ELF file does not match build ID"))
98
99 #define DWFL_ERROR(name, text) DWFL_E_##name,
100 typedef enum { DWFL_ERRORS DWFL_E_NUM } Dwfl_Error;
101 #undef  DWFL_ERROR
102
103 #define OTHER_ERROR(name)       ((unsigned int) DWFL_E_##name << 16)
104 #define DWFL_E(name, errno)     (OTHER_ERROR (name) | (errno))
105
106 extern int __libdwfl_canon_error (Dwfl_Error) internal_function;
107 extern void __libdwfl_seterrno (Dwfl_Error) internal_function;
108
109 struct Dwfl
110 {
111   const Dwfl_Callbacks *callbacks;
112
113   Dwfl_Module *modulelist;    /* List in order used by full traversals.  */
114
115   GElf_Addr offline_next_address;
116
117   GElf_Addr segment_align;      /* Smallest granularity of segments.  */
118
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.  */
125
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;
130   int lookup_tail_ndx;
131 };
132
133 #define OFFLINE_REDZONE         0x10000
134
135 struct dwfl_file
136 {
137   char *name;
138   int fd;
139   bool valid;                   /* The build ID note has been matched.  */
140   bool relocated;               /* Partial relocation of all sections done.  */
141
142   Elf *elf;
143
144   /* This is the lowest p_vaddr in this ELF file, aligned to p_align.
145      For a file without phdrs, this is zero.  */
146   GElf_Addr vaddr;
147
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;
151 };
152
153 struct Dwfl_Module
154 {
155   Dwfl *dwfl;
156   struct Dwfl_Module *next;     /* Link on Dwfl.modulelist.  */
157
158   void *userdata;
159
160   char *name;                   /* Iterator name for this module.  */
161   GElf_Addr low_addr, high_addr;
162
163   struct dwfl_file main, debug;
164   GElf_Addr main_bias;
165   Ebl *ebl;
166   GElf_Half e_type;             /* GElf_Ehdr.e_type cache.  */
167   Dwfl_Error elferr;            /* Previous failure to open main file.  */
168
169   struct dwfl_relocation *reloc_info; /* Relocatable sections.  */
170
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. */
176
177   Dwarf *dw;                    /* libdw handle for its debugging info.  */
178
179   Dwfl_Error symerr;            /* Previous failure to load symbols.  */
180   Dwfl_Error dwerr;             /* Previous failure to load DWARF.  */
181
182   /* Known CU's in this module.  */
183   struct dwfl_cu *first_cu, **cu;
184
185   void *lazy_cu_root;           /* Table indexed by Dwarf_Off of CU.  */
186
187   struct dwfl_arange *aranges;  /* Mapping of addresses in module to CUs.  */
188
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.  */
192
193   unsigned int ncu;
194   unsigned int lazycu;          /* Possible users, deleted when none left.  */
195   unsigned int naranges;
196
197   Dwarf_CFI *dwarf_cfi;         /* Cached DWARF CFI for this module.  */
198   Dwarf_CFI *eh_cfi;            /* Cached EH CFI for this module.  */
199
200   int segment;                  /* Index of first segment table entry.  */
201   bool gc;                      /* Mark/sweep flag.  */
202 };
203
204
205
206 /* Information cached about each CU in Dwfl_Module.dw.  */
207 struct dwfl_cu
208 {
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.  */
212   Dwarf_Die die;
213
214   Dwfl_Module *mod;             /* Pointer back to containing module.  */
215
216   struct dwfl_cu *next;         /* CU immediately following in the file.  */
217
218   struct Dwfl_Lines *lines;
219 };
220
221 struct Dwfl_Lines
222 {
223   struct dwfl_cu *cu;
224
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.  */
231   struct Dwfl_Line
232   {
233     unsigned int idx;           /* My index in the dwfl_cu.lines table.  */
234   } idx[0];
235 };
236
237 static inline struct dwfl_cu *
238 dwfl_linecu_inline (const Dwfl_Line *line)
239 {
240   const struct Dwfl_Lines *lines = ((const void *) line
241                                     - offsetof (struct Dwfl_Lines,
242                                                 idx[line->idx]));
243   return lines->cu;
244 }
245 #define dwfl_linecu dwfl_linecu_inline
246
247 static inline GElf_Addr
248 dwfl_adjusted_address (Dwfl_Module *mod, GElf_Addr addr)
249 {
250   return addr + mod->main_bias;
251 }
252
253 static inline GElf_Addr
254 dwfl_deadjust_address (Dwfl_Module *mod, GElf_Addr addr)
255 {
256   return addr - mod->main_bias;
257 }
258
259 static inline Dwarf_Addr
260 dwfl_adjusted_dwarf_addr (Dwfl_Module *mod, Dwarf_Addr addr)
261 {
262   return dwfl_adjusted_address (mod, (addr
263                                       - mod->debug.address_sync
264                                       + mod->main.address_sync));
265 }
266
267 static inline Dwarf_Addr
268 dwfl_deadjust_dwarf_addr (Dwfl_Module *mod, Dwarf_Addr addr)
269 {
270   return (dwfl_deadjust_address (mod, addr)
271           - mod->main.address_sync
272           + mod->debug.address_sync);
273 }
274
275 static inline GElf_Addr
276 dwfl_adjusted_st_value (Dwfl_Module *mod, GElf_Addr addr)
277 {
278   if (mod->symfile == &mod->main)
279     return dwfl_adjusted_address (mod, addr);
280   return dwfl_adjusted_dwarf_addr (mod, addr);
281 }
282
283 static inline GElf_Addr
284 dwfl_deadjust_st_value (Dwfl_Module *mod, GElf_Addr addr)
285 {
286   if (mod->symfile == &mod->main)
287     return dwfl_deadjust_address (mod, addr);
288   return dwfl_deadjust_dwarf_addr (mod, addr);
289 }
290
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.  */
293 struct dwfl_arange
294 {
295   struct dwfl_cu *cu;
296   size_t arange;                /* Index in Dwarf_Aranges.  */
297 };
298
299
300
301 extern void __libdwfl_module_free (Dwfl_Module *mod) internal_function;
302
303 /* Find the main ELF file, update MOD->elferr and/or MOD->main.elf.  */
304 extern void __libdwfl_getelf (Dwfl_Module *mod) internal_function;
305
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.
311
312    When DEBUG is false, apply partial relocation to all sections.  */
313 extern Dwfl_Error __libdwfl_relocate (Dwfl_Module *mod, Elf *file, bool debug)
314   internal_function;
315
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,
320                                               bool partial)
321   internal_function;
322
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,
328                                             Elf32_Word shndx,
329                                             GElf_Addr *value)
330      internal_function;
331
332
333 /* Ensure that MOD->ebl is set up.  */
334 extern Dwfl_Error __libdwfl_module_getebl (Dwfl_Module *mod) internal_function;
335
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,
338                                      Dwarf_CFI *cfi)
339   internal_function;
340
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
343    *CU no more CUs.  */
344 extern Dwfl_Error __libdwfl_nextcu (Dwfl_Module *mod, struct dwfl_cu *lastcu,
345                                     struct dwfl_cu **cu) internal_function;
346
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;
350
351 /* Ensure that CU->lines (and CU->cu->lines) is set up.  */
352 extern Dwfl_Error __libdwfl_cu_getsrclines (struct dwfl_cu *cu)
353   internal_function;
354
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)
360   internal_function;
361
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;
365
366 extern uint32_t __libdwfl_crc32 (uint32_t crc, unsigned char *buf, size_t len)
367   attribute_hidden;
368 extern int __libdwfl_crc32_file (int fd, uint32_t *resp) attribute_hidden;
369
370
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)
376   internal_function;
377
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 *,
383                                                                 const char *))
384   internal_function;
385
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)
390   internal_function;
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)
394   internal_function;
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)
398   internal_function;
399
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)
403   internal_function;
404
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)
411   internal_function;
412
413 /* These are working nicely for --core, but are not ready to be
414    exported interfaces quite yet.  */
415
416 /* Type of callback function ...
417  */
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);
421
422 /* Type of callback function ...
423  */
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);
430
431 /* ...
432  */
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);
438
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.
443
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.
450
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);
455
456
457 /* Avoid PLT entries.  */
458 INTDECL (dwfl_begin)
459 INTDECL (dwfl_errmsg)
460 INTDECL (dwfl_errno)
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)
500
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);
504
505
506 /* The default used by dwfl_standard_find_debuginfo.  */
507 #define DEFAULT_DEBUGINFO_PATH ":.debug:/usr/lib/debug"
508
509
510 #endif  /* libdwflP.h */