blob: 0633853966d44fca6aeb7d4661e60390390f7c66 [file] [log] [blame]
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001/* Internal definitions for libdwarf.
Mark Wielaarddf85bf92014-05-01 14:48:27 +02002 Copyright (C) 2002-2011, 2013, 2014 Red Hat, Inc.
Mark Wielaardde2ed972012-06-05 17:15:16 +02003 This file is part of elfutils.
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004 Written by Ulrich Drepper <drepper@redhat.com>, 2002.
5
Mark Wielaardde2ed972012-06-05 17:15:16 +02006 This file is free software; you can redistribute it and/or modify
7 it under the terms of either
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00008
Mark Wielaardde2ed972012-06-05 17:15:16 +02009 * the GNU Lesser General Public License as published by the Free
10 Software Foundation; either version 3 of the License, or (at
11 your option) any later version
12
13 or
14
15 * the GNU General Public License as published by the Free
16 Software Foundation; either version 2 of the License, or (at
17 your option) any later version
18
19 or both in parallel, as here.
20
21 elfutils is distributed in the hope that it will be useful, but
Ulrich Drepper361df7d2006-04-04 21:38:57 +000022 WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 General Public License for more details.
25
Mark Wielaardde2ed972012-06-05 17:15:16 +020026 You should have received copies of the GNU General Public License and
27 the GNU Lesser General Public License along with this program. If
28 not, see <http://www.gnu.org/licenses/>. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000029
30#ifndef _LIBDWP_H
31#define _LIBDWP_H 1
32
33#include <libintl.h>
34#include <stdbool.h>
35
36#include <libdw.h>
Josh Stonec0d2a0b2013-12-09 13:52:10 -080037#include <dwarf.h>
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000038
39
40/* gettext helper macros. */
41#define _(Str) dgettext ("elfutils", Str)
42
43
Roland McGrath6724c902005-10-28 07:07:19 +000044/* Known location expressions already decoded. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000045struct loc_s
46{
47 void *addr;
Roland McGrath6724c902005-10-28 07:07:19 +000048 Dwarf_Op *loc;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000049 size_t nloc;
50};
51
Roland McGrathf0371042009-09-10 12:39:09 -070052/* Known DW_OP_implicit_value blocks already decoded.
53 This overlaps struct loc_s exactly, but only the
54 first member really has to match. */
55struct loc_block_s
56{
57 void *addr;
58 unsigned char *data;
59 size_t length;
60};
61
Petr Machatafb90bf32014-10-17 02:47:03 +020062/* Already decoded .debug_line units. */
63struct files_lines_s
64{
65 Dwarf_Off debug_line_offset;
66 Dwarf_Files *files;
67 Dwarf_Lines *lines;
68};
69
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000070/* Valid indeces for the section data. */
71enum
72 {
73 IDX_debug_info = 0,
Roland McGrath827d4d12010-06-01 20:17:36 -070074 IDX_debug_types,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000075 IDX_debug_abbrev,
76 IDX_debug_aranges,
77 IDX_debug_line,
78 IDX_debug_frame,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000079 IDX_debug_loc,
80 IDX_debug_pubnames,
81 IDX_debug_str,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000082 IDX_debug_macinfo,
Mark Wielaarda0172d72012-06-25 17:18:53 +020083 IDX_debug_macro,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000084 IDX_debug_ranges,
Florian Weimerefa72a02014-04-15 14:04:19 +020085 IDX_gnu_debugaltlink,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000086 IDX_last
87 };
88
89
90/* Error values. */
91enum
92{
93 DWARF_E_NOERROR = 0,
94 DWARF_E_UNKNOWN_ERROR,
95 DWARF_E_INVALID_ACCESS,
96 DWARF_E_NO_REGFILE,
97 DWARF_E_IO_ERROR,
98 DWARF_E_INVALID_ELF,
99 DWARF_E_NO_DWARF,
100 DWARF_E_NOELF,
101 DWARF_E_GETEHDR_ERROR,
102 DWARF_E_NOMEM,
103 DWARF_E_UNIMPL,
104 DWARF_E_INVALID_CMD,
105 DWARF_E_INVALID_VERSION,
106 DWARF_E_INVALID_FILE,
107 DWARF_E_NO_ENTRY,
108 DWARF_E_INVALID_DWARF,
109 DWARF_E_NO_STRING,
110 DWARF_E_NO_ADDR,
111 DWARF_E_NO_CONSTANT,
112 DWARF_E_NO_REFERENCE,
113 DWARF_E_INVALID_REFERENCE,
114 DWARF_E_NO_DEBUG_LINE,
115 DWARF_E_INVALID_DEBUG_LINE,
116 DWARF_E_TOO_BIG,
117 DWARF_E_VERSION,
118 DWARF_E_INVALID_DIR_IDX,
119 DWARF_E_ADDR_OUTOFRANGE,
120 DWARF_E_NO_LOCLIST,
121 DWARF_E_NO_BLOCK,
122 DWARF_E_INVALID_LINE_IDX,
123 DWARF_E_INVALID_ARANGE_IDX,
124 DWARF_E_NO_MATCH,
125 DWARF_E_NO_FLAG,
126 DWARF_E_INVALID_OFFSET,
127 DWARF_E_NO_DEBUG_RANGES,
Roland McGrath3c84db32009-06-24 17:41:40 -0700128 DWARF_E_INVALID_CFI,
Petr Machatafb90bf32014-10-17 02:47:03 +0200129 DWARF_E_NO_ALT_DEBUGLINK,
130 DWARF_E_INVALID_OPCODE,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000131};
132
133
Roland McGrath3e0f7d12010-06-15 23:10:35 -0700134#include "dwarf_sig8_hash.h"
135
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000136/* This is the structure representing the debugging state. */
137struct Dwarf
138{
139 /* The underlying ELF file. */
140 Elf *elf;
141
Mark Wielaard775375e2012-06-22 12:02:45 +0200142 /* dwz alternate DWARF file. */
143 Dwarf *alt_dwarf;
144
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000145 /* The section data. */
146 Elf_Data *sectiondata[IDX_last];
147
Roland McGrath725aad52011-02-23 19:52:46 -0800148#if USE_ZLIB
149 /* The 1 << N bit is set if sectiondata[N] is malloc'd decompressed data. */
150 unsigned int sectiondata_gzip_mask:IDX_last;
151#endif
152
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000153 /* True if the file has a byte order different from the host. */
154 bool other_byte_order;
155
156 /* If true, we allocated the ELF descriptor ourselves. */
157 bool free_elf;
158
159 /* Information for traversing the .debug_pubnames section. This is
160 an array and separately allocated with malloc. */
161 struct pubnames_s
162 {
163 Dwarf_Off cu_offset;
164 Dwarf_Off set_start;
165 unsigned int cu_header_size;
166 int address_len;
167 } *pubnames_sets;
168 size_t pubnames_nsets;
169
170 /* Search tree for the CUs. */
171 void *cu_tree;
172 Dwarf_Off next_cu_offset;
173
Roland McGrath2b1f0952010-06-20 17:55:50 -0700174 /* Search tree and sig8 hash table for .debug_types type units. */
175 void *tu_tree;
Roland McGrath3e0f7d12010-06-15 23:10:35 -0700176 Dwarf_Off next_tu_offset;
Roland McGrath2b1f0952010-06-20 17:55:50 -0700177 Dwarf_Sig8_Hash sig8_hash;
Roland McGrath3e0f7d12010-06-15 23:10:35 -0700178
Petr Machatafb90bf32014-10-17 02:47:03 +0200179 /* Search tree for .debug_macro operator tables. */
180 void *macro_ops;
181
182 /* Search tree for decoded .debug_line units. */
183 void *files_lines;
184
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000185 /* Address ranges. */
186 Dwarf_Aranges *aranges;
187
Roland McGrath3c84db32009-06-24 17:41:40 -0700188 /* Cached info from the CFI section. */
189 struct Dwarf_CFI_s *cfi;
190
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000191 /* Internal memory handling. This is basically a simplified
192 reimplementation of obstacks. Unfortunately the standard obstack
193 implementation is not usable in libraries. */
194 struct libdw_memblock
195 {
196 size_t size;
197 size_t remaining;
198 struct libdw_memblock *prev;
199 char mem[0];
200 } *mem_tail;
201
202 /* Default size of allocated memory blocks. */
203 size_t mem_default_size;
204
205 /* Registered OOM handler. */
206 Dwarf_OOM oom_handler;
207};
208
209
210/* Abbreviation representation. */
211struct Dwarf_Abbrev
212{
Roland McGrath1f6d2012008-12-31 00:21:04 -0800213 Dwarf_Off offset;
214 unsigned char *attrp;
215 unsigned int attrcnt;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000216 unsigned int code;
217 unsigned int tag;
Roland McGrath1f6d2012008-12-31 00:21:04 -0800218 bool has_children;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000219};
220
221#include "dwarf_abbrev_hash.h"
222
223
224/* Files in line information records. */
225struct Dwarf_Files_s
226 {
Roland McGrath43da9892007-04-16 23:13:37 +0000227 unsigned int ndirs;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000228 unsigned int nfiles;
229 struct Dwarf_Fileinfo_s
230 {
231 char *name;
232 Dwarf_Word mtime;
233 Dwarf_Word length;
234 } info[0];
Roland McGrath43da9892007-04-16 23:13:37 +0000235 /* nfiles of those, followed by char *[ndirs]. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000236 };
237typedef struct Dwarf_Fileinfo_s Dwarf_Fileinfo;
238
239
240/* Representation of a row in the line table. */
Roland McGrath03288f02009-01-28 22:00:54 -0800241
242struct Dwarf_Line_s
243{
Roland McGrath6e1f4652009-07-08 14:48:34 -0700244 Dwarf_Files *files;
245
Roland McGrath03288f02009-01-28 22:00:54 -0800246 Dwarf_Addr addr;
247 unsigned int file;
248 int line;
249 unsigned short int column;
250 unsigned int is_stmt:1;
251 unsigned int basic_block:1;
252 unsigned int end_sequence:1;
253 unsigned int prologue_end:1;
254 unsigned int epilogue_begin:1;
Roland McGrathc70cf4e2010-06-18 17:01:05 -0700255 /* The remaining bit fields are not flags, but hold values presumed to be
256 small. All the flags and other bit fields should add up to 48 bits
257 to give the whole struct a nice round size. */
258 unsigned int op_index:8;
259 unsigned int isa:8;
260 unsigned int discriminator:24;
Roland McGrath03288f02009-01-28 22:00:54 -0800261};
262
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000263struct Dwarf_Lines_s
Roland McGrath03288f02009-01-28 22:00:54 -0800264{
265 size_t nlines;
266 struct Dwarf_Line_s info[0];
267};
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000268
269/* Representation of address ranges. */
270struct Dwarf_Aranges_s
271{
272 Dwarf *dbg;
273 size_t naranges;
274
275 struct Dwarf_Arange_s
276 {
277 Dwarf_Addr addr;
278 Dwarf_Word length;
279 Dwarf_Off offset;
280 } info[0];
281};
282
283
284/* CU representation. */
285struct Dwarf_CU
286{
287 Dwarf *dbg;
288 Dwarf_Off start;
289 Dwarf_Off end;
290 uint8_t address_size;
291 uint8_t offset_size;
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000292 uint16_t version;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000293
Roland McGrath3e0f7d12010-06-15 23:10:35 -0700294 /* Zero if this is a normal CU. Nonzero if it is a type unit. */
295 size_t type_offset;
296 uint64_t type_sig8;
297
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000298 /* Hash table for the abbreviations. */
299 Dwarf_Abbrev_Hash abbrev_hash;
300 /* Offset of the first abbreviation. */
301 size_t orig_abbrev_offset;
302 /* Offset past last read abbreviation. */
303 size_t last_abbrev_offset;
304
305 /* The srcline information. */
306 Dwarf_Lines *lines;
307
308 /* The source file information. */
309 Dwarf_Files *files;
310
311 /* Known location lists. */
312 void *locs;
313};
314
Ulrich Drepper35f08c42008-01-18 19:59:08 +0000315/* Compute the offset of a CU's first DIE from its offset. This
316 is either:
317 LEN VER OFFSET ADDR
318 4-bytes + 2-bytes + 4-bytes + 1-byte for 32-bit dwarf
319 12-bytes + 2-bytes + 8-bytes + 1-byte for 64-bit dwarf
Roland McGrath3e0f7d12010-06-15 23:10:35 -0700320 or in .debug_types, SIGNATURE TYPE-OFFSET
321 4-bytes + 2-bytes + 4-bytes + 1-byte + 8-bytes + 4-bytes for 32-bit
322 12-bytes + 2-bytes + 8-bytes + 1-byte + 8-bytes + 8-bytes for 64-bit
Ulrich Dreppera969d8e2008-01-22 06:15:00 +0000323
Ulrich Drepper35f08c42008-01-18 19:59:08 +0000324 Note the trick in the computation. If the offset_size is 4
325 the '- 4' term changes the '3 *' into a '2 *'. If the
326 offset_size is 8 it accounts for the 4-byte escape value
327 used at the start of the length. */
Roland McGrath3e0f7d12010-06-15 23:10:35 -0700328#define DIE_OFFSET_FROM_CU_OFFSET(cu_offset, offset_size, type_unit) \
329 ((type_unit) ? ((cu_offset) + 4 * (offset_size) - 4 + 3 + 8) \
330 : ((cu_offset) + 3 * (offset_size) - 4 + 3))
Ulrich Drepper35f08c42008-01-18 19:59:08 +0000331
Roland McGrath3e0f7d12010-06-15 23:10:35 -0700332#define CUDIE(fromcu) \
Roland McGrath6724c902005-10-28 07:07:19 +0000333 ((Dwarf_Die) \
334 { \
335 .cu = (fromcu), \
Roland McGrath5cc030d2010-06-20 17:25:35 -0700336 .addr = ((char *) cu_data (fromcu)->d_buf \
Roland McGrath3e0f7d12010-06-15 23:10:35 -0700337 + DIE_OFFSET_FROM_CU_OFFSET ((fromcu)->start, \
338 (fromcu)->offset_size, \
339 (fromcu)->type_offset != 0)) \
340 }) \
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000341
342
Petr Machatafb90bf32014-10-17 02:47:03 +0200343/* Prototype of a single .debug_macro operator. */
344typedef struct
345{
346 Dwarf_Word nforms;
347 unsigned char const *forms;
348} Dwarf_Macro_Op_Proto;
349
350/* Prototype table. */
351typedef struct
352{
353 /* Offset of .debug_macro section. */
354 Dwarf_Off offset;
355
356 /* Offset of associated .debug_line section. */
357 Dwarf_Off line_offset;
358
359 /* The source file information. */
360 Dwarf_Files *files;
361
362 /* If this macro unit was opened through dwarf_getmacros or
363 dwarf_getmacros_die, this caches value of DW_AT_comp_dir, if
364 present. */
365 const char *comp_dir;
366
367 /* Header length. */
368 Dwarf_Half header_len;
369
370 uint16_t version;
371 bool is_64bit;
372 uint8_t sec_index; /* IDX_debug_macro or IDX_debug_macinfo. */
373
374 /* Shows where in TABLE each opcode is defined. Since opcode 0 is
375 never used, it stores index of opcode X in X-1'th element. The
376 value of 0xff means not stored at all. */
377 unsigned char opcodes[255];
378
379 /* Individual opcode prototypes. */
380 Dwarf_Macro_Op_Proto table[];
381} Dwarf_Macro_Op_Table;
382
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000383struct Dwarf_Macro_s
384{
Petr Machatafb90bf32014-10-17 02:47:03 +0200385 Dwarf_Macro_Op_Table *table;
386 Dwarf_Attribute *attributes;
387 uint8_t opcode;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000388};
389
Petr Machatafb90bf32014-10-17 02:47:03 +0200390static inline Dwarf_Word
391libdw_macro_nforms (Dwarf_Macro *macro)
392{
393 return macro->table->table[macro->table->opcodes[macro->opcode - 1]].nforms;
394}
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000395
396/* We have to include the file at this point because the inline
397 functions access internals of the Dwarf structure. */
398#include "memory-access.h"
399
400
401/* Set error value. */
402extern void __libdw_seterrno (int value) internal_function;
403
404
405/* Memory handling, the easy parts. This macro does not do any locking. */
Ulrich Drepperdb1d5432006-10-10 15:34:34 +0000406#define libdw_alloc(dbg, type, tsize, cnt) \
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000407 ({ struct libdw_memblock *_tail = (dbg)->mem_tail; \
408 size_t _required = (tsize) * (cnt); \
409 type *_result = (type *) (_tail->mem + (_tail->size - _tail->remaining));\
410 size_t _padding = ((__alignof (type) \
411 - ((uintptr_t) _result & (__alignof (type) - 1))) \
412 & (__alignof (type) - 1)); \
413 if (unlikely (_tail->remaining < _required + _padding)) \
Roland McGrathc373d852006-10-10 00:25:21 +0000414 _result = (type *) __libdw_allocate (dbg, _required, __alignof (type));\
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000415 else \
416 { \
417 _required += _padding; \
418 _result = (type *) ((char *) _result + _padding); \
Roland McGrathc373d852006-10-10 00:25:21 +0000419 _tail->remaining -= _required; \
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000420 } \
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000421 _result; })
422
423#define libdw_typed_alloc(dbg, type) \
424 libdw_alloc (dbg, type, sizeof (type), 1)
425
426/* Callback to allocate more. */
Roland McGrathc373d852006-10-10 00:25:21 +0000427extern void *__libdw_allocate (Dwarf *dbg, size_t minsize, size_t align)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000428 __attribute__ ((__malloc__)) __nonnull_attribute__ (1);
429
430/* Default OOM handler. */
431extern void __libdw_oom (void) __attribute ((noreturn, visibility ("hidden")));
432
Roland McGrath725aad52011-02-23 19:52:46 -0800433#if USE_ZLIB
434extern void __libdw_free_zdata (Dwarf *dwarf) internal_function;
435#else
436# define __libdw_free_zdata(dwarf) ((void) (dwarf))
437#endif
438
Roland McGrath3e0f7d12010-06-15 23:10:35 -0700439/* Allocate the internal data for a unit not seen before. */
440extern struct Dwarf_CU *__libdw_intern_next_unit (Dwarf *dbg, bool debug_types)
441 __nonnull_attribute__ (1) internal_function;
442
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000443/* Find CU for given offset. */
Roland McGrath2b1f0952010-06-20 17:55:50 -0700444extern struct Dwarf_CU *__libdw_findcu (Dwarf *dbg, Dwarf_Off offset, bool tu)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000445 __nonnull_attribute__ (1) internal_function;
446
Josh Stoneb849f812014-12-10 18:28:04 -0800447/* Get abbreviation with given code. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000448extern Dwarf_Abbrev *__libdw_findabbrev (struct Dwarf_CU *cu,
449 unsigned int code)
450 __nonnull_attribute__ (1) internal_function;
451
452/* Get abbreviation at given offset. */
453extern Dwarf_Abbrev *__libdw_getabbrev (Dwarf *dbg, struct Dwarf_CU *cu,
454 Dwarf_Off offset, size_t *lengthp,
455 Dwarf_Abbrev *result)
456 __nonnull_attribute__ (1) internal_function;
457
Josh Stoneb849f812014-12-10 18:28:04 -0800458/* Get abbreviation of given DIE, and optionally set *READP to the DIE memory
459 just past the abbreviation code. */
460static inline Dwarf_Abbrev *
461__nonnull_attribute__ (1)
462__libdw_dieabbrev (Dwarf_Die *die, const unsigned char **readp)
463{
464 /* Do we need to get the abbreviation, or need to read after the code? */
465 if (die->abbrev == NULL || readp != NULL)
466 {
467 /* Get the abbreviation code. */
468 unsigned int code;
469 const unsigned char *addr = die->addr;
470 get_uleb128 (code, addr);
471 if (readp != NULL)
472 *readp = addr;
473
474 /* Find the abbreviation. */
475 if (die->abbrev == NULL)
476 die->abbrev = __libdw_findabbrev (die->cu, code);
477 }
478 return die->abbrev;
479}
480
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000481/* Helper functions for form handling. */
Josh Stonec0d2a0b2013-12-09 13:52:10 -0800482extern size_t __libdw_form_val_compute_len (Dwarf *dbg, struct Dwarf_CU *cu,
483 unsigned int form,
Mark Wielaardcb73b5a2014-12-04 21:43:44 +0100484 const unsigned char *valp,
485 const unsigned char *endp)
486 __nonnull_attribute__ (1, 2, 4, 5) internal_function;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000487
Josh Stonec0d2a0b2013-12-09 13:52:10 -0800488/* Find the length of a form attribute. */
489static inline size_t
Mark Wielaardcb73b5a2014-12-04 21:43:44 +0100490__nonnull_attribute__ (1, 2, 4, 5)
Josh Stonec0d2a0b2013-12-09 13:52:10 -0800491__libdw_form_val_len (Dwarf *dbg, struct Dwarf_CU *cu,
Mark Wielaardcb73b5a2014-12-04 21:43:44 +0100492 unsigned int form, const unsigned char *valp,
493 const unsigned char *endp)
Josh Stonec0d2a0b2013-12-09 13:52:10 -0800494{
495 /* Small lookup table of forms with fixed lengths. Absent indexes are
496 initialized 0, so any truly desired 0 is set to 0x80 and masked. */
497 static const uint8_t form_lengths[] =
498 {
499 [DW_FORM_flag_present] = 0x80,
500 [DW_FORM_data1] = 1, [DW_FORM_ref1] = 1, [DW_FORM_flag] = 1,
501 [DW_FORM_data2] = 2, [DW_FORM_ref2] = 2,
502 [DW_FORM_data4] = 4, [DW_FORM_ref4] = 4,
503 [DW_FORM_data8] = 8, [DW_FORM_ref8] = 8, [DW_FORM_ref_sig8] = 8,
504 };
505
506 /* Return immediately for forms with fixed lengths. */
507 if (form < sizeof form_lengths / sizeof form_lengths[0])
508 {
509 uint8_t len = form_lengths[form];
510 if (len != 0)
Mark Wielaardcb73b5a2014-12-04 21:43:44 +0100511 {
512 len &= 0x7f; /* Mask to allow 0x80 -> 0. */
513 if (unlikely (len > (size_t) (endp - valp)))
514 {
515 __libdw_seterrno (DWARF_E_INVALID_DWARF);
516 return -1;
517 }
518 return len;
519 }
Josh Stonec0d2a0b2013-12-09 13:52:10 -0800520 }
521
522 /* Other forms require some computation. */
Mark Wielaardcb73b5a2014-12-04 21:43:44 +0100523 return __libdw_form_val_compute_len (dbg, cu, form, valp, endp);
Josh Stonec0d2a0b2013-12-09 13:52:10 -0800524}
525
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000526/* Helper function for DW_FORM_ref* handling. */
527extern int __libdw_formref (Dwarf_Attribute *attr, Dwarf_Off *return_offset)
528 __nonnull_attribute__ (1, 2) internal_function;
529
530
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000531/* Helper function to locate attribute. */
532extern unsigned char *__libdw_find_attr (Dwarf_Die *die,
533 unsigned int search_name,
534 unsigned int *codep,
535 unsigned int *formp)
536 __nonnull_attribute__ (1) internal_function;
537
538/* Helper function to access integer attribute. */
Roland McGrath6724c902005-10-28 07:07:19 +0000539extern int __libdw_attr_intval (Dwarf_Die *die, int *valp, int attval)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000540 __nonnull_attribute__ (1, 2) internal_function;
541
Roland McGrath1ecb6062005-08-15 09:53:04 +0000542/* Helper function to walk scopes. */
Roland McGrath71e15a02005-08-27 10:33:26 +0000543struct Dwarf_Die_Chain
544{
545 Dwarf_Die die;
546 struct Dwarf_Die_Chain *parent;
547 bool prune; /* The PREVISIT function can set this. */
548};
549extern int __libdw_visit_scopes (unsigned int depth,
550 struct Dwarf_Die_Chain *root,
551 int (*previsit) (unsigned int depth,
552 struct Dwarf_Die_Chain *,
553 void *arg),
554 int (*postvisit) (unsigned int depth,
555 struct Dwarf_Die_Chain *,
556 void *arg),
Roland McGrath1ecb6062005-08-15 09:53:04 +0000557 void *arg)
558 __nonnull_attribute__ (2, 3) internal_function;
559
Roland McGrath3c84db32009-06-24 17:41:40 -0700560/* Parse a DWARF Dwarf_Block into an array of Dwarf_Op's,
561 and cache the result (via tsearch). */
562extern int __libdw_intern_expression (Dwarf *dbg,
563 bool other_byte_order,
564 unsigned int address_size,
Roland McGrath688f7fc2010-05-08 03:22:59 -0700565 unsigned int ref_size,
Roland McGrath3c84db32009-06-24 17:41:40 -0700566 void **cache, const Dwarf_Block *block,
Roland McGrath0ab97832010-04-26 11:50:27 -0700567 bool cfap, bool valuep,
Roland McGrath3c84db32009-06-24 17:41:40 -0700568 Dwarf_Op **llbuf, size_t *listlen,
569 int sec_index)
Roland McGrath688f7fc2010-05-08 03:22:59 -0700570 __nonnull_attribute__ (5, 6, 9, 10) internal_function;
Roland McGrath3c84db32009-06-24 17:41:40 -0700571
Roland McGrath932585d2010-05-08 04:01:14 -0700572extern Dwarf_Die *__libdw_offdie (Dwarf *dbg, Dwarf_Off offset,
573 Dwarf_Die *result, bool debug_types)
574 internal_function;
575
Roland McGrath3c84db32009-06-24 17:41:40 -0700576
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000577/* Return error code of last failing function call. This value is kept
578 separately for each thread. */
579extern int __dwarf_errno_internal (void);
580
581
Ulrich Drepper99d23722009-06-14 20:19:45 -0700582/* Reader hooks. */
583
584/* Relocation hooks return -1 on error (in that case the error code
585 must already have been set), 0 if there is no relocation and 1 if a
586 relocation was present.*/
587
588static inline int
589__libdw_relocate_address (Dwarf *dbg __attribute__ ((unused)),
590 int sec_index __attribute__ ((unused)),
591 const void *addr __attribute__ ((unused)),
592 int width __attribute__ ((unused)),
593 Dwarf_Addr *val __attribute__ ((unused)))
594{
595 return 0;
596}
597
598static inline int
599__libdw_relocate_offset (Dwarf *dbg __attribute__ ((unused)),
600 int sec_index __attribute__ ((unused)),
601 const void *addr __attribute__ ((unused)),
602 int width __attribute__ ((unused)),
603 Dwarf_Off *val __attribute__ ((unused)))
604{
605 return 0;
606}
607
608static inline Elf_Data *
609__libdw_checked_get_data (Dwarf *dbg, int sec_index)
610{
611 Elf_Data *data = dbg->sectiondata[sec_index];
612 if (unlikely (data == NULL)
613 || unlikely (data->d_buf == NULL))
614 {
615 __libdw_seterrno (DWARF_E_INVALID_DWARF);
616 return NULL;
617 }
618 return data;
619}
620
621static inline int
622__libdw_offset_in_section (Dwarf *dbg, int sec_index,
623 Dwarf_Off offset, size_t size)
624{
625 Elf_Data *data = __libdw_checked_get_data (dbg, sec_index);
626 if (data == NULL)
627 return -1;
628 if (unlikely (offset > data->d_size)
629 || unlikely (data->d_size - offset < size))
630 {
631 __libdw_seterrno (DWARF_E_INVALID_OFFSET);
632 return -1;
633 }
634
635 return 0;
636}
637
638static inline bool
639__libdw_in_section (Dwarf *dbg, int sec_index,
640 const void *addr, size_t size)
641{
642 Elf_Data *data = __libdw_checked_get_data (dbg, sec_index);
643 if (data == NULL)
644 return false;
645 if (unlikely (addr < data->d_buf)
646 || unlikely (data->d_size - (addr - data->d_buf) < size))
647 {
648 __libdw_seterrno (DWARF_E_INVALID_OFFSET);
649 return false;
650 }
651
652 return true;
653}
654
655#define READ_AND_RELOCATE(RELOC_HOOK, VAL) \
656 ({ \
657 if (!__libdw_in_section (dbg, sec_index, addr, width)) \
658 return -1; \
659 \
660 const unsigned char *orig_addr = addr; \
661 if (width == 4) \
662 VAL = read_4ubyte_unaligned_inc (dbg, addr); \
663 else \
664 VAL = read_8ubyte_unaligned_inc (dbg, addr); \
665 \
666 int status = RELOC_HOOK (dbg, sec_index, orig_addr, width, &VAL); \
667 if (status < 0) \
668 return status; \
669 status > 0; \
670 })
671
672static inline int
673__libdw_read_address_inc (Dwarf *dbg,
Roland McGrath05c4e042009-06-18 13:56:02 -0700674 int sec_index, const unsigned char **addrp,
Ulrich Drepper99d23722009-06-14 20:19:45 -0700675 int width, Dwarf_Addr *ret)
676{
Roland McGrath05c4e042009-06-18 13:56:02 -0700677 const unsigned char *addr = *addrp;
Ulrich Drepper99d23722009-06-14 20:19:45 -0700678 READ_AND_RELOCATE (__libdw_relocate_address, (*ret));
679 *addrp = addr;
680 return 0;
681}
682
683static inline int
684__libdw_read_address (Dwarf *dbg,
685 int sec_index, const unsigned char *addr,
686 int width, Dwarf_Addr *ret)
687{
688 READ_AND_RELOCATE (__libdw_relocate_address, (*ret));
689 return 0;
690}
691
692static inline int
693__libdw_read_offset_inc (Dwarf *dbg,
Roland McGrath05c4e042009-06-18 13:56:02 -0700694 int sec_index, const unsigned char **addrp,
Ulrich Drepper99d23722009-06-14 20:19:45 -0700695 int width, Dwarf_Off *ret, int sec_ret,
696 size_t size)
697{
Roland McGrath05c4e042009-06-18 13:56:02 -0700698 const unsigned char *addr = *addrp;
Ulrich Drepper99d23722009-06-14 20:19:45 -0700699 READ_AND_RELOCATE (__libdw_relocate_offset, (*ret));
700 *addrp = addr;
701 return __libdw_offset_in_section (dbg, sec_ret, *ret, size);
702}
703
704static inline int
Mark Wielaard775375e2012-06-22 12:02:45 +0200705__libdw_read_offset (Dwarf *dbg, Dwarf *dbg_ret,
Ulrich Drepper99d23722009-06-14 20:19:45 -0700706 int sec_index, const unsigned char *addr,
707 int width, Dwarf_Off *ret, int sec_ret,
708 size_t size)
709{
710 READ_AND_RELOCATE (__libdw_relocate_offset, (*ret));
Mark Wielaard775375e2012-06-22 12:02:45 +0200711 return __libdw_offset_in_section (dbg_ret, sec_ret, *ret, size);
Ulrich Drepper99d23722009-06-14 20:19:45 -0700712}
713
Roland McGrath3e0f7d12010-06-15 23:10:35 -0700714static inline size_t
715cu_sec_idx (struct Dwarf_CU *cu)
716{
717 return cu->type_offset == 0 ? IDX_debug_info : IDX_debug_types;
718}
719
720static inline Elf_Data *
721cu_data (struct Dwarf_CU *cu)
722{
723 return cu->dbg->sectiondata[cu_sec_idx (cu)];
724}
725
Ulrich Drepper99d23722009-06-14 20:19:45 -0700726/* Read up begin/end pair and increment read pointer.
727 - If it's normal range record, set up *BEGINP and *ENDP and return 0.
728 - If it's base address selection record, set up *BASEP and return 1.
729 - If it's end of rangelist, don't set anything and return 2
730 - If an error occurs, don't set anything and return <0. */
731int __libdw_read_begin_end_pair_inc (Dwarf *dbg, int sec_index,
732 unsigned char **addr, int width,
733 Dwarf_Addr *beginp, Dwarf_Addr *endp,
734 Dwarf_Addr *basep)
735 internal_function;
736
737unsigned char * __libdw_formptr (Dwarf_Attribute *attr, int sec_index,
738 int err_nodata, unsigned char **endpp,
739 Dwarf_Off *offsetp)
740 internal_function;
741
Mark Wielaard3951f2e2013-12-09 16:33:26 +0100742/* Fills in the given attribute to point at an empty location expression. */
743void __libdw_empty_loc_attr (Dwarf_Attribute *attr, struct Dwarf_CU *cu)
744 internal_function;
745
Petr Machatafb90bf32014-10-17 02:47:03 +0200746/* Load .debug_line unit at DEBUG_LINE_OFFSET. COMP_DIR is a value of
747 DW_AT_comp_dir or NULL if that attribute is not available. Caches
748 the loaded unit and optionally set *LINESP and/or *FILESP (if not
749 NULL) with loaded information. Returns 0 for success or a negative
750 value for failure. */
751int __libdw_getsrclines (Dwarf *dbg, Dwarf_Off debug_line_offset,
752 const char *comp_dir, unsigned address_size,
753 Dwarf_Lines **linesp, Dwarf_Files **filesp)
754 internal_function
755 __nonnull_attribute__ (1);
756
757/* Load and return value of DW_AT_comp_dir from CUDIE. */
758const char *__libdw_getcompdir (Dwarf_Die *cudie);
759
Ulrich Drepper99d23722009-06-14 20:19:45 -0700760
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000761/* Aliases to avoid PLTs. */
Roland McGrathebc5c882010-01-05 22:53:31 -0800762INTDECL (dwarf_aggregate_size)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000763INTDECL (dwarf_attr)
764INTDECL (dwarf_attr_integrate)
Mark Wielaard775375e2012-06-22 12:02:45 +0200765INTDECL (dwarf_begin)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000766INTDECL (dwarf_begin_elf)
767INTDECL (dwarf_child)
768INTDECL (dwarf_dieoffset)
Roland McGrath71e15a02005-08-27 10:33:26 +0000769INTDECL (dwarf_diename)
Roland McGrath4959bf82005-08-09 10:31:08 +0000770INTDECL (dwarf_end)
Roland McGrath07d4f2f2005-10-28 06:56:24 +0000771INTDECL (dwarf_entrypc)
Roland McGrath4959bf82005-08-09 10:31:08 +0000772INTDECL (dwarf_errmsg)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000773INTDECL (dwarf_formaddr)
774INTDECL (dwarf_formblock)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000775INTDECL (dwarf_formref_die)
776INTDECL (dwarf_formsdata)
777INTDECL (dwarf_formstring)
778INTDECL (dwarf_formudata)
Florian Weimer35e2a762014-04-15 14:31:55 +0200779INTDECL (dwarf_getalt)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000780INTDECL (dwarf_getarange_addr)
781INTDECL (dwarf_getarangeinfo)
782INTDECL (dwarf_getaranges)
Mark Wielaardb2535b62013-08-30 23:55:12 +0200783INTDECL (dwarf_getlocation_die)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000784INTDECL (dwarf_getsrcfiles)
785INTDECL (dwarf_getsrclines)
786INTDECL (dwarf_hasattr)
787INTDECL (dwarf_haschildren)
788INTDECL (dwarf_haspc)
789INTDECL (dwarf_highpc)
790INTDECL (dwarf_lowpc)
791INTDECL (dwarf_nextcu)
Roland McGrath3e0f7d12010-06-15 23:10:35 -0700792INTDECL (dwarf_next_unit)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000793INTDECL (dwarf_offdie)
Mark Wielaard3a36e8a2014-10-06 22:00:16 +0200794INTDECL (dwarf_peel_type)
Roland McGrath07d4f2f2005-10-28 06:56:24 +0000795INTDECL (dwarf_ranges)
Florian Weimer35e2a762014-04-15 14:31:55 +0200796INTDECL (dwarf_setalt)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000797INTDECL (dwarf_siblingof)
Roland McGrathebc5c882010-01-05 22:53:31 -0800798INTDECL (dwarf_srclang)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000799INTDECL (dwarf_tag)
800
801#endif /* libdwP.h */