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