libdwP.h revision 3c84db3b4b610bf636c4363abb6d3dac5ae020f9
1/* Internal definitions for libdwarf.
2   Copyright (C) 2002-2009 Red Hat, Inc.
3   This file is part of Red Hat elfutils.
4   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
5
6   Red Hat elfutils is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by the
8   Free Software Foundation; version 2 of the License.
9
10   Red Hat elfutils is distributed in the hope that it will be useful, but
11   WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   General Public License for more details.
14
15   You should have received a copy of the GNU General Public License along
16   with Red Hat elfutils; if not, write to the Free Software Foundation,
17   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
18
19   In addition, as a special exception, Red Hat, Inc. gives You the
20   additional right to link the code of Red Hat elfutils with code licensed
21   under any Open Source Initiative certified open source license
22   (http://www.opensource.org/licenses/index.php) which requires the
23   distribution of source code with any binary distribution and to
24   distribute linked combinations of the two.  Non-GPL Code permitted under
25   this exception must only link to the code of Red Hat elfutils through
26   those well defined interfaces identified in the file named EXCEPTION
27   found in the source code files (the "Approved Interfaces").  The files
28   of Non-GPL Code may instantiate templates or use macros or inline
29   functions from the Approved Interfaces without causing the resulting
30   work to be covered by the GNU General Public License.  Only Red Hat,
31   Inc. may make changes or additions to the list of Approved Interfaces.
32   Red Hat's grant of this exception is conditioned upon your not adding
33   any new exceptions.  If you wish to add a new Approved Interface or
34   exception, please contact Red Hat.  You must obey the GNU General Public
35   License in all respects for all of the Red Hat elfutils code and other
36   code used in conjunction with Red Hat elfutils except the Non-GPL Code
37   covered by this exception.  If you modify this file, you may extend this
38   exception to your version of the file, but you are not obligated to do
39   so.  If you do not wish to provide this exception without modification,
40   you must delete this exception statement from your version and license
41   this file solely under the GPL without exception.
42
43   Red Hat elfutils is an included package of the Open Invention Network.
44   An included package of the Open Invention Network is a package for which
45   Open Invention Network licensees cross-license their patents.  No patent
46   license is granted, either expressly or impliedly, by designation as an
47   included package.  Should you wish to participate in the Open Invention
48   Network licensing program, please visit www.openinventionnetwork.com
49   <http://www.openinventionnetwork.com>.  */
50
51#ifndef _LIBDWP_H
52#define _LIBDWP_H 1
53
54#include <libintl.h>
55#include <stdbool.h>
56
57#include <libdw.h>
58
59
60/* gettext helper macros.  */
61#define _(Str) dgettext ("elfutils", Str)
62
63
64/* Version of the DWARF specification we support.  */
65#define DWARF_VERSION 3
66
67/* Version of the CIE format.  */
68#define CIE_VERSION 1
69
70
71/* Known location expressions already decoded.  */
72struct loc_s
73{
74  void *addr;
75  Dwarf_Op *loc;
76  size_t nloc;
77};
78
79/* Valid indeces for the section data.  */
80enum
81  {
82    IDX_debug_info = 0,
83    IDX_debug_abbrev,
84    IDX_debug_aranges,
85    IDX_debug_line,
86    IDX_debug_frame,
87    IDX_debug_loc,
88    IDX_debug_pubnames,
89    IDX_debug_str,
90    IDX_debug_funcnames,
91    IDX_debug_typenames,
92    IDX_debug_varnames,
93    IDX_debug_weaknames,
94    IDX_debug_macinfo,
95    IDX_debug_ranges,
96    IDX_last
97  };
98
99
100/* Error values.  */
101enum
102{
103  DWARF_E_NOERROR = 0,
104  DWARF_E_UNKNOWN_ERROR,
105  DWARF_E_INVALID_ACCESS,
106  DWARF_E_NO_REGFILE,
107  DWARF_E_IO_ERROR,
108  DWARF_E_INVALID_ELF,
109  DWARF_E_NO_DWARF,
110  DWARF_E_NOELF,
111  DWARF_E_GETEHDR_ERROR,
112  DWARF_E_NOMEM,
113  DWARF_E_UNIMPL,
114  DWARF_E_INVALID_CMD,
115  DWARF_E_INVALID_VERSION,
116  DWARF_E_INVALID_FILE,
117  DWARF_E_NO_ENTRY,
118  DWARF_E_INVALID_DWARF,
119  DWARF_E_NO_STRING,
120  DWARF_E_NO_ADDR,
121  DWARF_E_NO_CONSTANT,
122  DWARF_E_NO_REFERENCE,
123  DWARF_E_INVALID_REFERENCE,
124  DWARF_E_NO_DEBUG_LINE,
125  DWARF_E_INVALID_DEBUG_LINE,
126  DWARF_E_TOO_BIG,
127  DWARF_E_VERSION,
128  DWARF_E_INVALID_DIR_IDX,
129  DWARF_E_ADDR_OUTOFRANGE,
130  DWARF_E_NO_LOCLIST,
131  DWARF_E_NO_BLOCK,
132  DWARF_E_INVALID_LINE_IDX,
133  DWARF_E_INVALID_ARANGE_IDX,
134  DWARF_E_NO_MATCH,
135  DWARF_E_NO_FLAG,
136  DWARF_E_INVALID_OFFSET,
137  DWARF_E_NO_DEBUG_RANGES,
138  DWARF_E_INVALID_CFI,
139};
140
141
142/* This is the structure representing the debugging state.  */
143struct Dwarf
144{
145  /* The underlying ELF file.  */
146  Elf *elf;
147
148  /* The section data.  */
149  Elf_Data *sectiondata[IDX_last];
150
151  /* True if the file has a byte order different from the host.  */
152  bool other_byte_order;
153
154  /* If true, we allocated the ELF descriptor ourselves.  */
155  bool free_elf;
156
157  /* Information for traversing the .debug_pubnames section.  This is
158     an array and separately allocated with malloc.  */
159  struct pubnames_s
160  {
161    Dwarf_Off cu_offset;
162    Dwarf_Off set_start;
163    unsigned int cu_header_size;
164    int address_len;
165  } *pubnames_sets;
166  size_t pubnames_nsets;
167
168  /* Search tree for the CUs.  */
169  void *cu_tree;
170  Dwarf_Off next_cu_offset;
171
172  /* Address ranges.  */
173  Dwarf_Aranges *aranges;
174
175  /* Cached info from the CFI section.  */
176  struct Dwarf_CFI_s *cfi;
177
178  /* Internal memory handling.  This is basically a simplified
179     reimplementation of obstacks.  Unfortunately the standard obstack
180     implementation is not usable in libraries.  */
181  struct libdw_memblock
182  {
183    size_t size;
184    size_t remaining;
185    struct libdw_memblock *prev;
186    char mem[0];
187  } *mem_tail;
188
189  /* Default size of allocated memory blocks.  */
190  size_t mem_default_size;
191
192  /* Registered OOM handler.  */
193  Dwarf_OOM oom_handler;
194};
195
196
197/* Abbreviation representation.  */
198struct Dwarf_Abbrev
199{
200  Dwarf_Off offset;
201  unsigned char *attrp;
202  unsigned int attrcnt;
203  unsigned int code;
204  unsigned int tag;
205  bool has_children;
206};
207
208#include "dwarf_abbrev_hash.h"
209
210
211/* Files in line information records.  */
212struct Dwarf_Files_s
213  {
214    struct Dwarf_CU *cu;
215    unsigned int ndirs;
216    unsigned int nfiles;
217    struct Dwarf_Fileinfo_s
218    {
219      char *name;
220      Dwarf_Word mtime;
221      Dwarf_Word length;
222    } info[0];
223    /* nfiles of those, followed by char *[ndirs].  */
224  };
225typedef struct Dwarf_Fileinfo_s Dwarf_Fileinfo;
226
227
228/* Representation of a row in the line table.  */
229
230struct Dwarf_Line_s
231{
232  Dwarf_Files *files;
233
234  Dwarf_Addr addr;
235  unsigned int file;
236  int line;
237  unsigned short int column;
238  unsigned int is_stmt:1;
239  unsigned int basic_block:1;
240  unsigned int end_sequence:1;
241  unsigned int prologue_end:1;
242  unsigned int epilogue_begin:1;
243};
244
245struct Dwarf_Lines_s
246{
247  size_t nlines;
248  struct Dwarf_Line_s info[0];
249};
250
251/* Representation of address ranges.  */
252struct Dwarf_Aranges_s
253{
254  Dwarf *dbg;
255  size_t naranges;
256
257  struct Dwarf_Arange_s
258  {
259    Dwarf_Addr addr;
260    Dwarf_Word length;
261    Dwarf_Off offset;
262  } info[0];
263};
264
265
266/* CU representation.  */
267struct Dwarf_CU
268{
269  Dwarf *dbg;
270  Dwarf_Off start;
271  Dwarf_Off end;
272  uint8_t address_size;
273  uint8_t offset_size;
274  uint16_t version;
275
276  /* Hash table for the abbreviations.  */
277  Dwarf_Abbrev_Hash abbrev_hash;
278  /* Offset of the first abbreviation.  */
279  size_t orig_abbrev_offset;
280  /* Offset past last read abbreviation.  */
281  size_t last_abbrev_offset;
282
283  /* The srcline information.  */
284  Dwarf_Lines *lines;
285
286  /* The source file information.  */
287  Dwarf_Files *files;
288
289  /* Known location lists.  */
290  void *locs;
291};
292
293/* Compute the offset of a CU's first DIE from its offset.  This
294   is either:
295        LEN       VER     OFFSET    ADDR
296      4-bytes + 2-bytes + 4-bytes + 1-byte  for 32-bit dwarf
297     12-bytes + 2-bytes + 8-bytes + 1-byte  for 64-bit dwarf
298
299   Note the trick in the computation.  If the offset_size is 4
300   the '- 4' term changes the '3 *' into a '2 *'.  If the
301   offset_size is 8 it accounts for the 4-byte escape value
302   used at the start of the length.  */
303#define DIE_OFFSET_FROM_CU_OFFSET(cu_offset, offset_size) \
304  ((cu_offset) + 3 * (offset_size) - 4 + 3)
305
306#define CUDIE(fromcu) \
307  ((Dwarf_Die)								      \
308   {									      \
309     .cu = (fromcu),							      \
310     .addr = ((char *) (fromcu)->dbg->sectiondata[IDX_debug_info]->d_buf      \
311	      + (fromcu)->start + 3 * (fromcu)->offset_size - 4 + 3),	      \
312   })
313
314
315/* Macro information.  */
316struct Dwarf_Macro_s
317{
318  unsigned int opcode;
319  Dwarf_Word param1;
320  union
321  {
322    Dwarf_Word u;
323    const char *s;
324  } param2;
325};
326
327
328/* We have to include the file at this point because the inline
329   functions access internals of the Dwarf structure.  */
330#include "memory-access.h"
331
332
333/* Set error value.  */
334extern void __libdw_seterrno (int value) internal_function;
335
336
337/* Memory handling, the easy parts.  This macro does not do any locking.  */
338#define libdw_alloc(dbg, type, tsize, cnt) \
339  ({ struct libdw_memblock *_tail = (dbg)->mem_tail;			      \
340     size_t _required = (tsize) * (cnt);				      \
341     type *_result = (type *) (_tail->mem + (_tail->size - _tail->remaining));\
342     size_t _padding = ((__alignof (type)				      \
343			 - ((uintptr_t) _result & (__alignof (type) - 1)))    \
344			& (__alignof (type) - 1));			      \
345     if (unlikely (_tail->remaining < _required + _padding))		      \
346       _result = (type *) __libdw_allocate (dbg, _required, __alignof (type));\
347     else								      \
348       {								      \
349	 _required += _padding;						      \
350	 _result = (type *) ((char *) _result + _padding);		      \
351	 _tail->remaining -= _required;					      \
352       }								      \
353     _result; })
354
355#define libdw_typed_alloc(dbg, type) \
356  libdw_alloc (dbg, type, sizeof (type), 1)
357
358/* Callback to allocate more.  */
359extern void *__libdw_allocate (Dwarf *dbg, size_t minsize, size_t align)
360     __attribute__ ((__malloc__)) __nonnull_attribute__ (1);
361
362/* Default OOM handler.  */
363extern void __libdw_oom (void) __attribute ((noreturn, visibility ("hidden")));
364
365/* Find CU for given offset.  */
366extern struct Dwarf_CU *__libdw_findcu (Dwarf *dbg, Dwarf_Off offset)
367     __nonnull_attribute__ (1) internal_function;
368
369/* Return tag of given DIE.  */
370extern Dwarf_Abbrev *__libdw_findabbrev (struct Dwarf_CU *cu,
371					 unsigned int code)
372     __nonnull_attribute__ (1) internal_function;
373
374/* Get abbreviation at given offset.  */
375extern Dwarf_Abbrev *__libdw_getabbrev (Dwarf *dbg, struct Dwarf_CU *cu,
376					Dwarf_Off offset, size_t *lengthp,
377					Dwarf_Abbrev *result)
378     __nonnull_attribute__ (1) internal_function;
379
380/* Helper functions for form handling.  */
381extern size_t __libdw_form_val_len (Dwarf *dbg, struct Dwarf_CU *cu,
382				    unsigned int form,
383				    const unsigned char *valp)
384     __nonnull_attribute__ (1, 2, 4) internal_function;
385
386/* Helper function for DW_FORM_ref* handling.  */
387extern int __libdw_formref (Dwarf_Attribute *attr, Dwarf_Off *return_offset)
388     __nonnull_attribute__ (1, 2) internal_function;
389
390
391/* Helper function to locate attribute.  */
392extern unsigned char *__libdw_find_attr (Dwarf_Die *die,
393					 unsigned int search_name,
394					 unsigned int *codep,
395					 unsigned int *formp)
396     __nonnull_attribute__ (1) internal_function;
397
398/* Helper function to access integer attribute.  */
399extern int __libdw_attr_intval (Dwarf_Die *die, int *valp, int attval)
400     __nonnull_attribute__ (1, 2) internal_function;
401
402/* Helper function to walk scopes.  */
403struct Dwarf_Die_Chain
404{
405  Dwarf_Die die;
406  struct Dwarf_Die_Chain *parent;
407  bool prune;			/* The PREVISIT function can set this.  */
408};
409extern int __libdw_visit_scopes (unsigned int depth,
410				 struct Dwarf_Die_Chain *root,
411				 int (*previsit) (unsigned int depth,
412						  struct Dwarf_Die_Chain *,
413						  void *arg),
414				 int (*postvisit) (unsigned int depth,
415						   struct Dwarf_Die_Chain *,
416						   void *arg),
417				 void *arg)
418  __nonnull_attribute__ (2, 3) internal_function;
419
420/* Parse a DWARF Dwarf_Block into an array of Dwarf_Op's,
421   and cache the result (via tsearch).  */
422extern int __libdw_intern_expression (Dwarf *dbg,
423				      bool other_byte_order,
424				      unsigned int address_size,
425				      void **cache, const Dwarf_Block *block,
426				      Dwarf_Op **llbuf, size_t *listlen,
427				      int sec_index)
428  __nonnull_attribute__ (4, 5, 6, 7) internal_function;
429
430
431/* Return error code of last failing function call.  This value is kept
432   separately for each thread.  */
433extern int __dwarf_errno_internal (void);
434
435
436/* Reader hooks.  */
437
438/* Relocation hooks return -1 on error (in that case the error code
439   must already have been set), 0 if there is no relocation and 1 if a
440   relocation was present.*/
441
442static inline int
443__libdw_relocate_address (Dwarf *dbg __attribute__ ((unused)),
444			  int sec_index __attribute__ ((unused)),
445			  const void *addr __attribute__ ((unused)),
446			  int width __attribute__ ((unused)),
447			  Dwarf_Addr *val __attribute__ ((unused)))
448{
449  return 0;
450}
451
452static inline int
453__libdw_relocate_offset (Dwarf *dbg __attribute__ ((unused)),
454			 int sec_index __attribute__ ((unused)),
455			 const void *addr __attribute__ ((unused)),
456			 int width __attribute__ ((unused)),
457			 Dwarf_Off *val __attribute__ ((unused)))
458{
459  return 0;
460}
461
462static inline Elf_Data *
463__libdw_checked_get_data (Dwarf *dbg, int sec_index)
464{
465  Elf_Data *data = dbg->sectiondata[sec_index];
466  if (unlikely (data == NULL)
467      || unlikely (data->d_buf == NULL))
468    {
469      __libdw_seterrno (DWARF_E_INVALID_DWARF);
470      return NULL;
471    }
472  return data;
473}
474
475static inline int
476__libdw_offset_in_section (Dwarf *dbg, int sec_index,
477			   Dwarf_Off offset, size_t size)
478{
479  Elf_Data *data = __libdw_checked_get_data (dbg, sec_index);
480  if (data == NULL)
481    return -1;
482  if (unlikely (offset > data->d_size)
483      || unlikely (data->d_size - offset < size))
484    {
485      __libdw_seterrno (DWARF_E_INVALID_OFFSET);
486      return -1;
487    }
488
489  return 0;
490}
491
492static inline bool
493__libdw_in_section (Dwarf *dbg, int sec_index,
494		    const void *addr, size_t size)
495{
496  Elf_Data *data = __libdw_checked_get_data (dbg, sec_index);
497  if (data == NULL)
498    return false;
499  if (unlikely (addr < data->d_buf)
500      || unlikely (data->d_size - (addr - data->d_buf) < size))
501    {
502      __libdw_seterrno (DWARF_E_INVALID_OFFSET);
503      return false;
504    }
505
506  return true;
507}
508
509#define READ_AND_RELOCATE(RELOC_HOOK, VAL)				\
510  ({									\
511    if (!__libdw_in_section (dbg, sec_index, addr, width))		\
512      return -1;							\
513									\
514    const unsigned char *orig_addr = addr;				\
515    if (width == 4)							\
516      VAL = read_4ubyte_unaligned_inc (dbg, addr);			\
517    else								\
518      VAL = read_8ubyte_unaligned_inc (dbg, addr);			\
519									\
520    int status = RELOC_HOOK (dbg, sec_index, orig_addr, width, &VAL);	\
521    if (status < 0)							\
522      return status;							\
523    status > 0;								\
524   })
525
526static inline int
527__libdw_read_address_inc (Dwarf *dbg,
528			  int sec_index, const unsigned char **addrp,
529			  int width, Dwarf_Addr *ret)
530{
531  const unsigned char *addr = *addrp;
532  READ_AND_RELOCATE (__libdw_relocate_address, (*ret));
533  *addrp = addr;
534  return 0;
535}
536
537static inline int
538__libdw_read_address (Dwarf *dbg,
539		      int sec_index, const unsigned char *addr,
540		      int width, Dwarf_Addr *ret)
541{
542  READ_AND_RELOCATE (__libdw_relocate_address, (*ret));
543  return 0;
544}
545
546static inline int
547__libdw_read_offset_inc (Dwarf *dbg,
548			 int sec_index, const unsigned char **addrp,
549			 int width, Dwarf_Off *ret, int sec_ret,
550			 size_t size)
551{
552  const unsigned char *addr = *addrp;
553  READ_AND_RELOCATE (__libdw_relocate_offset, (*ret));
554  *addrp = addr;
555  return __libdw_offset_in_section (dbg, sec_ret, *ret, size);
556}
557
558static inline int
559__libdw_read_offset (Dwarf *dbg,
560		     int sec_index, const unsigned char *addr,
561		     int width, Dwarf_Off *ret, int sec_ret,
562		     size_t size)
563{
564  READ_AND_RELOCATE (__libdw_relocate_offset, (*ret));
565  return __libdw_offset_in_section (dbg, sec_ret, *ret, size);
566}
567
568/* Read up begin/end pair and increment read pointer.
569    - If it's normal range record, set up *BEGINP and *ENDP and return 0.
570    - If it's base address selection record, set up *BASEP and return 1.
571    - If it's end of rangelist, don't set anything and return 2
572    - If an error occurs, don't set anything and return <0.  */
573int __libdw_read_begin_end_pair_inc (Dwarf *dbg, int sec_index,
574				     unsigned char **addr, int width,
575				     Dwarf_Addr *beginp, Dwarf_Addr *endp,
576				     Dwarf_Addr *basep)
577  internal_function;
578
579unsigned char * __libdw_formptr (Dwarf_Attribute *attr, int sec_index,
580				 int err_nodata, unsigned char **endpp,
581				 Dwarf_Off *offsetp)
582  internal_function;
583
584
585
586/* Aliases to avoid PLTs.  */
587INTDECL (dwarf_attr)
588INTDECL (dwarf_attr_integrate)
589INTDECL (dwarf_begin_elf)
590INTDECL (dwarf_child)
591INTDECL (dwarf_dieoffset)
592INTDECL (dwarf_diename)
593INTDECL (dwarf_end)
594INTDECL (dwarf_entrypc)
595INTDECL (dwarf_errmsg)
596INTDECL (dwarf_formaddr)
597INTDECL (dwarf_formblock)
598INTDECL (dwarf_formref_die)
599INTDECL (dwarf_formsdata)
600INTDECL (dwarf_formstring)
601INTDECL (dwarf_formudata)
602INTDECL (dwarf_getarange_addr)
603INTDECL (dwarf_getarangeinfo)
604INTDECL (dwarf_getaranges)
605INTDECL (dwarf_getsrcfiles)
606INTDECL (dwarf_getsrclines)
607INTDECL (dwarf_hasattr)
608INTDECL (dwarf_haschildren)
609INTDECL (dwarf_haspc)
610INTDECL (dwarf_highpc)
611INTDECL (dwarf_lowpc)
612INTDECL (dwarf_nextcu)
613INTDECL (dwarf_offdie)
614INTDECL (dwarf_ranges)
615INTDECL (dwarf_siblingof)
616INTDECL (dwarf_tag)
617
618#endif	/* libdwP.h */
619