diff options
author | jb <jb@FreeBSD.org> | 2008-05-22 02:14:23 +0000 |
---|---|---|
committer | jb <jb@FreeBSD.org> | 2008-05-22 02:14:23 +0000 |
commit | 6bb9fac44691095d77c0fe90a650a6e10efad674 (patch) | |
tree | e3765f4585c6589b116b3afadce01322d61764ac /lib/libdwarf | |
parent | ec1dde64a242f2a00001a19b01713bd34b4420ec (diff) | |
download | FreeBSD-src-6bb9fac44691095d77c0fe90a650a6e10efad674.zip FreeBSD-src-6bb9fac44691095d77c0fe90a650a6e10efad674.tar.gz |
Add a BSD licensed DWARF library for use by the DTrace clients.
The API for this library is deliberately different to the GPL'd
libdwarf to avoid licensing problems.
Diffstat (limited to 'lib/libdwarf')
-rw-r--r-- | lib/libdwarf/Makefile | 30 | ||||
-rw-r--r-- | lib/libdwarf/_libdwarf.h | 168 | ||||
-rw-r--r-- | lib/libdwarf/dwarf.h | 478 | ||||
-rw-r--r-- | lib/libdwarf/dwarf_abbrev.c | 71 | ||||
-rw-r--r-- | lib/libdwarf/dwarf_attr.c | 92 | ||||
-rw-r--r-- | lib/libdwarf/dwarf_attrval.c | 270 | ||||
-rw-r--r-- | lib/libdwarf/dwarf_cu.c | 68 | ||||
-rw-r--r-- | lib/libdwarf/dwarf_dealloc.c | 41 | ||||
-rw-r--r-- | lib/libdwarf/dwarf_die.c | 191 | ||||
-rw-r--r-- | lib/libdwarf/dwarf_dump.c | 892 | ||||
-rw-r--r-- | lib/libdwarf/dwarf_errmsg.c | 76 | ||||
-rw-r--r-- | lib/libdwarf/dwarf_errno.c | 38 | ||||
-rw-r--r-- | lib/libdwarf/dwarf_finish.c | 98 | ||||
-rw-r--r-- | lib/libdwarf/dwarf_form.c | 47 | ||||
-rw-r--r-- | lib/libdwarf/dwarf_init.c | 748 | ||||
-rw-r--r-- | lib/libdwarf/dwarf_loc.c | 613 | ||||
-rw-r--r-- | lib/libdwarf/libdwarf.h | 162 |
17 files changed, 4083 insertions, 0 deletions
diff --git a/lib/libdwarf/Makefile b/lib/libdwarf/Makefile new file mode 100644 index 0000000..0acc6aa --- /dev/null +++ b/lib/libdwarf/Makefile @@ -0,0 +1,30 @@ +# $FreeBSD$ + +LIB= dwarf + +SRCS= \ + dwarf_abbrev.c \ + dwarf_attr.c \ + dwarf_attrval.c \ + dwarf_cu.c \ + dwarf_dealloc.c \ + dwarf_die.c \ + dwarf_dump.c \ + dwarf_errmsg.c \ + dwarf_errno.c \ + dwarf_finish.c \ + dwarf_form.c \ + dwarf_init.c \ + dwarf_loc.c + +INCS= dwarf.h libdwarf.h + +CFLAGS+= -I. -I${.CURDIR} + +SHLIB_MAJOR= 1 + +WARNS?= 6 + +WITHOUT_MAN= yes + +.include <bsd.lib.mk> diff --git a/lib/libdwarf/_libdwarf.h b/lib/libdwarf/_libdwarf.h new file mode 100644 index 0000000..697b034 --- /dev/null +++ b/lib/libdwarf/_libdwarf.h @@ -0,0 +1,168 @@ +/*- + * Copyright (c) 2007 John Birrell (jb@freebsd.org) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef __LIBDWARF_H_ +#define __LIBDWARF_H_ + +#include <sys/param.h> +#include <sys/queue.h> +#include <stdio.h> +#include <gelf.h> +#include "dwarf.h" +#include "libdwarf.h" + +#define DWARF_debug_abbrev 0 +#define DWARF_debug_aranges 1 +#define DWARF_debug_frame 2 +#define DWARF_debug_info 3 +#define DWARF_debug_line 4 +#define DWARF_debug_pubnames 5 +#define DWARF_eh_frame 6 +#define DWARF_debug_macinfo 7 +#define DWARF_debug_str 8 +#define DWARF_debug_loc 9 +#define DWARF_debug_pubtypes 10 +#define DWARF_debug_ranges 11 +#define DWARF_debug_static_func 12 +#define DWARF_debug_static_vars 13 +#define DWARF_debug_types 14 +#define DWARF_debug_weaknames 15 +#define DWARF_symtab 16 +#define DWARF_strtab 17 +#define DWARF_DEBUG_SNAMES 18 + +#define DWARF_DIE_HASH_SIZE 8191 + +#define DWARF_SET_ERROR(_e, _err) do { \ + _e->err_error = _err; \ + _e->elf_error = 0; \ + _e->err_func = __func__; \ + _e->err_line = __LINE__; \ + _e->err_msg[0] = '\0'; \ + } while (0) + +#define DWARF_SET_ELF_ERROR(_e, _err) do { \ + _e->err_error = DWARF_E_ELF; \ + _e->elf_error = _err; \ + _e->err_func = __func__; \ + _e->err_line = __LINE__; \ + _e->err_msg[0] = '\0'; \ + } while (0) + +struct _Dwarf_AttrValue { + uint64_t av_attrib; /* DW_AT_ */ + uint64_t av_form; /* DW_FORM_ */ + union { + uint64_t u64; + int64_t s64; + const char *s; + uint8_t *u8p; + } u[2]; /* Value. */ + STAILQ_ENTRY(_Dwarf_AttrValue) + av_next; /* Next attribute value. */ +}; + +struct _Dwarf_Die { + int die_level; /* Parent-child level. */ + uint64_t die_offset; /* DIE offset in section. */ + uint64_t die_abnum; /* Abbrev number. */ + Dwarf_Abbrev die_a; /* Abbrev pointer. */ + Dwarf_CU die_cu; /* Compilation unit pointer. */ + const char *die_name; /* Ptr to the name string. */ + STAILQ_HEAD(, _Dwarf_AttrValue) + die_attrval; /* List of attribute values. */ + STAILQ_ENTRY(_Dwarf_Die) + die_next; /* Next die in list. */ + STAILQ_ENTRY(_Dwarf_Die) + die_hash; /* Next die in hash table. */ +}; + +struct _Dwarf_Attribute { + uint64_t at_attrib; /* DW_AT_ */ + uint64_t at_form; /* DW_FORM_ */ + STAILQ_ENTRY(_Dwarf_Attribute) + at_next; /* Next attribute. */ +}; + +struct _Dwarf_Abbrev { + uint64_t a_entry; /* Abbrev entry. */ + uint64_t a_tag; /* Tag: DW_TAG_ */ + uint8_t a_children; /* DW_CHILDREN_no or DW_CHILDREN_yes */ + STAILQ_HEAD(, _Dwarf_Attribute) + a_attrib; /* List of attributes. */ + STAILQ_ENTRY(_Dwarf_Abbrev) + a_next; /* Next abbrev. */ +}; + +struct _Dwarf_CU { + uint64_t cu_offset; /* Offset to the this compilation unit. */ + uint32_t cu_length; /* Length of CU data. */ + uint32_t cu_header_length; + /* Length of the CU header. */ + uint16_t cu_version; /* DWARF version. */ + uint64_t cu_abbrev_offset; + /* Offset into .debug_abbrev. */ + uint8_t cu_pointer_size; + /* Number of bytes in pointer. */ + uint64_t cu_next_offset; + /* Offset to the next compilation unit. */ + STAILQ_HEAD(, _Dwarf_Abbrev) + cu_abbrev; /* List of abbrevs. */ + STAILQ_HEAD(, _Dwarf_Die) + cu_die; /* List of dies. */ + STAILQ_HEAD(, _Dwarf_Die) + cu_die_hash[DWARF_DIE_HASH_SIZE]; + /* Hash of dies. */ + STAILQ_ENTRY(_Dwarf_CU) + cu_next; /* Next compilation unit. */ +}; + +typedef struct _Dwarf_section { + Elf_Scn *s_scn; /* Section pointer. */ + GElf_Shdr s_shdr; /* Copy of the section header. */ + char *s_sname; /* Ptr to the section name. */ + uint32_t s_shnum; /* Section number. */ + Elf_Data *s_data; /* Section data. */ +} Dwarf_section; + +struct _Dwarf_Debug { + Elf *dbg_elf; /* Ptr to the ELF handle. */ + GElf_Ehdr dbg_ehdr; /* Copy of the ELF header. */ + int dbg_elf_close; /* True if elf_end() required. */ + int dbg_mode; /* Access mode. */ + size_t dbg_stnum; /* Section header string table section number. */ + int dbg_offsize; /* DWARF offset size. */ + Dwarf_section dbg_s[DWARF_DEBUG_SNAMES]; + /* Array of section information. */ + STAILQ_HEAD(, _Dwarf_CU) + dbg_cu; /* List of compilation units. */ + Dwarf_CU dbg_cu_current; + /* Ptr to the current compilation unit. */ +}; + +#endif /* !__LIBDWARF_H_ */ diff --git a/lib/libdwarf/dwarf.h b/lib/libdwarf/dwarf.h new file mode 100644 index 0000000..ecbafcf --- /dev/null +++ b/lib/libdwarf/dwarf.h @@ -0,0 +1,478 @@ +/*- + * Copyright (c) 2007 John Birrell (jb@freebsd.org) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *notice, this list of conditions and the following disclaimer in the + *documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _DWARF_H_ +#define _DWARF_H_ + +#define DW_TAG_array_type 0x01 +#define DW_TAG_class_type 0x02 +#define DW_TAG_entry_point 0x03 +#define DW_TAG_enumeration_type 0x04 +#define DW_TAG_formal_parameter 0x05 +#define DW_TAG_imported_declaration 0x08 +#define DW_TAG_label 0x0a +#define DW_TAG_lexical_block 0x0b +#define DW_TAG_member 0x0d +#define DW_TAG_pointer_type 0x0f +#define DW_TAG_reference_type 0x10 +#define DW_TAG_compile_unit 0x11 +#define DW_TAG_string_type 0x12 +#define DW_TAG_structure_type 0x13 +#define DW_TAG_subroutine_type 0x15 +#define DW_TAG_typedef 0x16 +#define DW_TAG_union_type 0x17 +#define DW_TAG_unspecified_parameters 0x18 +#define DW_TAG_variant 0x19 +#define DW_TAG_common_block 0x1a +#define DW_TAG_common_inclusion 0x1b +#define DW_TAG_inheritance 0x1c +#define DW_TAG_inlined_subroutine 0x1d +#define DW_TAG_module 0x1e +#define DW_TAG_ptr_to_member_type 0x1f +#define DW_TAG_set_type 0x20 +#define DW_TAG_subrange_type 0x21 +#define DW_TAG_with_stmt 0x22 +#define DW_TAG_access_declaration 0x23 +#define DW_TAG_base_type 0x24 +#define DW_TAG_catch_block 0x25 +#define DW_TAG_const_type 0x26 +#define DW_TAG_constant 0x27 +#define DW_TAG_enumerator 0x28 +#define DW_TAG_friend 0x2a +#define DW_TAG_namelist 0x2b +#define DW_TAG_namelist_item 0x2c +#define DW_TAG_packed_type 0x2d +#define DW_TAG_subprogram 0x2e +#define DW_TAG_template_type_parameter 0x2f +#define DW_TAG_template_type_param 0x2f +#define DW_TAG_template_value_parameter 0x30 +#define DW_TAG_template_value_param 0x30 +#define DW_TAG_thrown_type 0x31 +#define DW_TAG_try_block 0x32 +#define DW_TAG_variant_part 0x33 +#define DW_TAG_variable 0x34 +#define DW_TAG_volatile_type 0x35 +#define DW_TAG_dwarf_procedure 0x36 +#define DW_TAG_restrict_type 0x37 +#define DW_TAG_interface_type 0x38 +#define DW_TAG_namespace 0x39 +#define DW_TAG_imported_module 0x3a +#define DW_TAG_unspecified_type 0x3b +#define DW_TAG_partial_unit 0x3c +#define DW_TAG_imported_unit 0x3d +#define DW_TAG_condition 0x3f +#define DW_TAG_shared_type 0x40 + +#define DW_TAG_lo_user 0x4080 + +#define DW_TAG_hi_user 0xffff + +#define DW_CHILDREN_no 0x00 +#define DW_CHILDREN_yes 0x01 + +#define DW_AT_sibling 0x01 +#define DW_AT_location 0x02 +#define DW_AT_name 0x03 +#define DW_AT_ordering 0x09 +#define DW_AT_subscr_data 0x0a +#define DW_AT_byte_size 0x0b +#define DW_AT_bit_offset 0x0c +#define DW_AT_bit_size 0x0d +#define DW_AT_element_list 0x0f +#define DW_AT_stmt_list 0x10 +#define DW_AT_low_pc 0x11 +#define DW_AT_high_pc 0x12 +#define DW_AT_language 0x13 +#define DW_AT_member 0x14 +#define DW_AT_discr 0x15 +#define DW_AT_discr_value 0x16 +#define DW_AT_visibility 0x17 +#define DW_AT_import 0x18 +#define DW_AT_string_length 0x19 +#define DW_AT_common_reference 0x1a +#define DW_AT_comp_dir 0x1b +#define DW_AT_const_value 0x1c +#define DW_AT_containing_type 0x1d +#define DW_AT_default_value 0x1e +#define DW_AT_inline 0x20 +#define DW_AT_is_optional 0x21 +#define DW_AT_lower_bound 0x22 +#define DW_AT_producer 0x25 +#define DW_AT_prototyped 0x27 +#define DW_AT_return_addr 0x2a +#define DW_AT_start_scope 0x2c +#define DW_AT_bit_stride 0x2e +#define DW_AT_stride_size 0x2e +#define DW_AT_upper_bound 0x2f +#define DW_AT_abstract_origin 0x31 +#define DW_AT_accessibility 0x32 +#define DW_AT_address_class 0x33 +#define DW_AT_artificial 0x34 +#define DW_AT_base_types 0x35 +#define DW_AT_calling_convention 0x36 +#define DW_AT_count 0x37 +#define DW_AT_data_member_location 0x38 +#define DW_AT_decl_column 0x39 +#define DW_AT_decl_file 0x3a +#define DW_AT_decl_line 0x3b +#define DW_AT_declaration 0x3c +#define DW_AT_discr_list 0x3d +#define DW_AT_encoding 0x3e +#define DW_AT_external 0x3f +#define DW_AT_frame_base 0x40 +#define DW_AT_friend 0x41 +#define DW_AT_identifier_case 0x42 +#define DW_AT_macro_info 0x43 +#define DW_AT_namelist_item 0x44 +#define DW_AT_priority 0x45 +#define DW_AT_segment 0x46 +#define DW_AT_specification 0x47 +#define DW_AT_static_link 0x48 +#define DW_AT_type 0x49 +#define DW_AT_use_location 0x4a +#define DW_AT_variable_parameter 0x4b +#define DW_AT_virtuality 0x4c +#define DW_AT_vtable_elem_location 0x4d + +#define DW_AT_lo_user 0x2000 + +#define DW_AT_hi_user 0x3fff + +#define DW_FORM_addr 0x01 +#define DW_FORM_block2 0x03 +#define DW_FORM_block4 0x04 +#define DW_FORM_data2 0x05 +#define DW_FORM_data4 0x06 +#define DW_FORM_data8 0x07 +#define DW_FORM_string 0x08 +#define DW_FORM_block 0x09 +#define DW_FORM_block1 0x0a +#define DW_FORM_data1 0x0b +#define DW_FORM_flag 0x0c +#define DW_FORM_sdata 0x0d +#define DW_FORM_strp 0x0e +#define DW_FORM_udata 0x0f +#define DW_FORM_ref_addr 0x10 +#define DW_FORM_ref1 0x11 +#define DW_FORM_ref2 0x12 +#define DW_FORM_ref4 0x13 +#define DW_FORM_ref8 0x14 +#define DW_FORM_ref_udata 0x15 +#define DW_FORM_indirect 0x16 + +#define DW_OP_addr 0x03 +#define DW_OP_deref 0x06 +#define DW_OP_const1u 0x08 +#define DW_OP_const1s 0x09 +#define DW_OP_const2u 0x0a +#define DW_OP_const2s 0x0b +#define DW_OP_const4u 0x0c +#define DW_OP_const4s 0x0d +#define DW_OP_const8u 0x0e +#define DW_OP_const8s 0x0f +#define DW_OP_constu 0x10 +#define DW_OP_consts 0x11 +#define DW_OP_dup 0x12 +#define DW_OP_drop 0x13 +#define DW_OP_over 0x14 +#define DW_OP_pick 0x15 +#define DW_OP_swap 0x16 +#define DW_OP_rot 0x17 +#define DW_OP_xderef 0x18 +#define DW_OP_abs 0x19 +#define DW_OP_and 0x1a +#define DW_OP_div 0x1b +#define DW_OP_minus 0x1c +#define DW_OP_mod 0x1d +#define DW_OP_mul 0x1e +#define DW_OP_neg 0x1f +#define DW_OP_not 0x20 +#define DW_OP_or 0x21 +#define DW_OP_plus 0x22 +#define DW_OP_plus_uconst 0x23 +#define DW_OP_shl 0x24 +#define DW_OP_shr 0x25 +#define DW_OP_shra 0x26 +#define DW_OP_xor 0x27 +#define DW_OP_bra 0x28 +#define DW_OP_eq 0x29 +#define DW_OP_ge 0x2a +#define DW_OP_gt 0x2b +#define DW_OP_le 0x2c +#define DW_OP_lt 0x2d +#define DW_OP_ne 0x2e +#define DW_OP_skip 0x2f +#define DW_OP_lit0 0x30 +#define DW_OP_lit1 0x31 +#define DW_OP_lit2 0x32 +#define DW_OP_lit3 0x33 +#define DW_OP_lit4 0x34 +#define DW_OP_lit5 0x35 +#define DW_OP_lit6 0x36 +#define DW_OP_lit7 0x37 +#define DW_OP_lit8 0x38 +#define DW_OP_lit9 0x39 +#define DW_OP_lit10 0x3a +#define DW_OP_lit11 0x3b +#define DW_OP_lit12 0x3c +#define DW_OP_lit13 0x3d +#define DW_OP_lit14 0x3e +#define DW_OP_lit15 0x3f +#define DW_OP_lit16 0x40 +#define DW_OP_lit17 0x41 +#define DW_OP_lit18 0x42 +#define DW_OP_lit19 0x43 +#define DW_OP_lit20 0x44 +#define DW_OP_lit21 0x45 +#define DW_OP_lit22 0x46 +#define DW_OP_lit23 0x47 +#define DW_OP_lit24 0x48 +#define DW_OP_lit25 0x49 +#define DW_OP_lit26 0x4a +#define DW_OP_lit27 0x4b +#define DW_OP_lit28 0x4c +#define DW_OP_lit29 0x4d +#define DW_OP_lit30 0x4e +#define DW_OP_lit31 0x4f +#define DW_OP_reg0 0x50 +#define DW_OP_reg1 0x51 +#define DW_OP_reg2 0x52 +#define DW_OP_reg3 0x53 +#define DW_OP_reg4 0x54 +#define DW_OP_reg5 0x55 +#define DW_OP_reg6 0x56 +#define DW_OP_reg7 0x57 +#define DW_OP_reg8 0x58 +#define DW_OP_reg9 0x59 +#define DW_OP_reg10 0x5a +#define DW_OP_reg11 0x5b +#define DW_OP_reg12 0x5c +#define DW_OP_reg13 0x5d +#define DW_OP_reg14 0x5e +#define DW_OP_reg15 0x5f +#define DW_OP_reg16 0x60 +#define DW_OP_reg17 0x61 +#define DW_OP_reg18 0x62 +#define DW_OP_reg19 0x63 +#define DW_OP_reg20 0x64 +#define DW_OP_reg21 0x65 +#define DW_OP_reg22 0x66 +#define DW_OP_reg23 0x67 +#define DW_OP_reg24 0x68 +#define DW_OP_reg25 0x69 +#define DW_OP_reg26 0x6a +#define DW_OP_reg27 0x6b +#define DW_OP_reg28 0x6c +#define DW_OP_reg29 0x6d +#define DW_OP_reg30 0x6e +#define DW_OP_reg31 0x6f +#define DW_OP_breg0 0x70 +#define DW_OP_breg1 0x71 +#define DW_OP_breg2 0x72 +#define DW_OP_breg3 0x73 +#define DW_OP_breg4 0x74 +#define DW_OP_breg5 0x75 +#define DW_OP_breg6 0x76 +#define DW_OP_breg7 0x77 +#define DW_OP_breg8 0x78 +#define DW_OP_breg9 0x79 +#define DW_OP_breg10 0x7a +#define DW_OP_breg11 0x7b +#define DW_OP_breg12 0x7c +#define DW_OP_breg13 0x7d +#define DW_OP_breg14 0x7e +#define DW_OP_breg15 0x7f +#define DW_OP_breg16 0x80 +#define DW_OP_breg17 0x81 +#define DW_OP_breg18 0x82 +#define DW_OP_breg19 0x83 +#define DW_OP_breg20 0x84 +#define DW_OP_breg21 0x85 +#define DW_OP_breg22 0x86 +#define DW_OP_breg23 0x87 +#define DW_OP_breg24 0x88 +#define DW_OP_breg25 0x89 +#define DW_OP_breg26 0x8a +#define DW_OP_breg27 0x8b +#define DW_OP_breg28 0x8c +#define DW_OP_breg29 0x8d +#define DW_OP_breg30 0x8e +#define DW_OP_breg31 0x8f +#define DW_OP_regx 0x90 +#define DW_OP_fbreg 0x91 +#define DW_OP_bregx 0x92 +#define DW_OP_piece 0x93 +#define DW_OP_deref_size 0x94 +#define DW_OP_xderef_size 0x95 +#define DW_OP_nop 0x96 + +#define DW_OP_lo_user 0xe0 + +#define DW_OP_hi_user 0xff + +#define DW_ATE_address 0x1 +#define DW_ATE_boolean 0x2 +#define DW_ATE_complex_float 0x3 +#define DW_ATE_float 0x4 +#define DW_ATE_signed 0x5 +#define DW_ATE_signed_char 0x6 +#define DW_ATE_unsigned 0x7 +#define DW_ATE_unsigned_char 0x8 +#define DW_ATE_imaginary_float 0x9 +#define DW_ATE_packed_decimal 0xa +#define DW_ATE_numeric_string 0xb +#define DW_ATE_edited 0xc +#define DW_ATE_signed_fixed 0xd +#define DW_ATE_unsigned_fixed 0xe +#define DW_ATE_decimal_float 0xf + +#define DW_ATE_lo_user 0x80 + +#define DW_ATE_hi_user 0xff + +#define DW_ACCESS_public 0x01 +#define DW_ACCESS_protected 0x02 +#define DW_ACCESS_private 0x03 + +#define DW_VIS_local 0x01 +#define DW_VIS_exported 0x02 +#define DW_VIS_qualified 0x03 + +#define DW_VIRTUALITY_none 0x00 +#define DW_VIRTUALITY_virtual 0x01 +#define DW_VIRTUALITY_pure_virtual 0x02 + +#define DW_LANG_C89 0x0001 +#define DW_LANG_C 0x0002 +#define DW_LANG_Ada83 0x0003 +#define DW_LANG_C_plus_plus 0x0004 +#define DW_LANG_Cobol74 0x0005 +#define DW_LANG_Cobol85 0x0006 +#define DW_LANG_Fortran77 0x0007 +#define DW_LANG_Fortran90 0x0008 +#define DW_LANG_Pascal83 0x0009 +#define DW_LANG_Modula2 0x000a +#define DW_LANG_Java 0x000b +#define DW_LANG_C99 0x000c +#define DW_LANG_Ada95 0x000d +#define DW_LANG_Fortran95 0x000e +#define DW_LANG_PLI 0x000f +#define DW_LANG_ObjC 0x0010 +#define DW_LANG_ObjC_plus_plus 0x0011 +#define DW_LANG_UPC 0x0012 +#define DW_LANG_D 0x0013 + +#define DW_LANG_lo_user 0x8000 + +#define DW_LANG_hi_user 0xffff + +#define DW_ID_case_sensitive 0x00 +#define DW_ID_up_case 0x01 +#define DW_ID_down_case 0x02 +#define DW_ID_case_insensitive 0x03 + +#define DW_CC_normal 0x01 +#define DW_CC_program 0x02 +#define DW_CC_nocall 0x03 + +#define DW_CC_lo_user 0x40 + +#define DW_CC_hi_user 0xff + +#define DW_INL_not_inlined 0x00 +#define DW_INL_inlined 0x01 +#define DW_INL_declared_not_inlined 0x02 +#define DW_INL_declared_inlined 0x03 + +#define DW_ORD_row_major 0x00 +#define DW_ORD_col_major 0x01 + +#define DW_DSC_label 0x00 +#define DW_DSC_range 0x01 + +#define DW_LNS_copy 0x01 +#define DW_LNS_advance_pc 0x02 +#define DW_LNS_advance_line 0x03 +#define DW_LNS_set_file 0x04 +#define DW_LNS_set_column 0x05 +#define DW_LNS_negate_stmt 0x06 +#define DW_LNS_set_basic_block 0x07 +#define DW_LNS_const_add_pc 0x08 +#define DW_LNS_fixed_advance_pc 0x09 +#define DW_LNS_set_prologue_end 0x0a +#define DW_LNS_set_epilogue_begin 0x0b +#define DW_LNS_set_isa 0x0c + +#define DW_LNE_end_sequence 0x01 +#define DW_LNE_set_address 0x02 +#define DW_LNE_define_file 0x03 + +#define DW_LNE_lo_user 0x80 + +#define DW_LNE_hi_user 0xff + +#define DW_MACINFO_define 0x01 +#define DW_MACINFO_undef 0x02 +#define DW_MACINFO_start_file 0x03 +#define DW_MACINFO_end_file 0x04 +#define DW_MACINFO_vendor_ext 0xff + +#define DW_CFA_advance_loc 0x40 +#define DW_CFA_offset 0x80 +#define DW_CFA_restore 0xc0 +#define DW_CFA_extended 0 + +#define DW_CFA_nop 0x00 +#define DW_CFA_set_loc 0x01 +#define DW_CFA_advance_loc1 0x02 +#define DW_CFA_advance_loc2 0x03 +#define DW_CFA_advance_loc4 0x04 +#define DW_CFA_offset_extended 0x05 +#define DW_CFA_restore_extended 0x06 +#define DW_CFA_undefined 0x07 +#define DW_CFA_same_value 0x08 +#define DW_CFA_register 0x09 +#define DW_CFA_remember_state 0x0a +#define DW_CFA_restore_state 0x0b +#define DW_CFA_def_cfa 0x0c +#define DW_CFA_def_cfa_register 0x0d +#define DW_CFA_def_cfa_offset 0x0e +#define DW_CFA_def_cfa_expression 0x0f +#define DW_CFA_expression 0x10 +#define DW_CFA_cfa_offset_extended_sf 0x11 +#define DW_CFA_def_cfa_sf 0x12 +#define DW_CFA_def_cfa_offset_sf 0x13 +#define DW_CFA_val_offset 0x14 +#define DW_CFA_val_offset_sf 0x15 +#define DW_CFA_val_expression 0x16 + +#define DW_CFA_lo_user 0x1c + +#define DW_CFA_high_user 0x3f + +#endif /* !_DWARF_H_ */ diff --git a/lib/libdwarf/dwarf_abbrev.c b/lib/libdwarf/dwarf_abbrev.c new file mode 100644 index 0000000..aae575c --- /dev/null +++ b/lib/libdwarf/dwarf_abbrev.c @@ -0,0 +1,71 @@ +/*- + * Copyright (c) 2007 John Birrell (jb@freebsd.org) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <stdlib.h> +#include "_libdwarf.h" + +int +dwarf_abbrev_add(Dwarf_CU cu, uint64_t entry, uint64_t tag, uint8_t children, Dwarf_Abbrev *ap, Dwarf_Error *error) +{ + Dwarf_Abbrev a; + int ret = DWARF_E_NONE; + + if ((a = malloc(sizeof(struct _Dwarf_Abbrev))) == NULL) { + DWARF_SET_ERROR(error, DWARF_E_MEMORY); + return DWARF_E_MEMORY; + } + + /* Initialise the abbrev structure. */ + a->a_entry = entry; + a->a_tag = tag; + a->a_children = children; + + /* Initialise the list of attributes. */ + STAILQ_INIT(&a->a_attrib); + + /* Add the abbrev to the list in the compilation unit. */ + STAILQ_INSERT_TAIL(&cu->cu_abbrev, a, a_next); + + if (ap != NULL) + *ap = a; + + return ret; +} + +Dwarf_Abbrev +dwarf_abbrev_find(Dwarf_CU cu, uint64_t entry) +{ + Dwarf_Abbrev a = NULL; + + STAILQ_FOREACH(a, &cu->cu_abbrev, a_next) { + if (a->a_entry == entry) + break; + } + + return a; +} diff --git a/lib/libdwarf/dwarf_attr.c b/lib/libdwarf/dwarf_attr.c new file mode 100644 index 0000000..3c9d4c8 --- /dev/null +++ b/lib/libdwarf/dwarf_attr.c @@ -0,0 +1,92 @@ +/*- + * Copyright (c) 2007 John Birrell (jb@freebsd.org) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <stdlib.h> +#include <string.h> +#include "_libdwarf.h" + +int +dwarf_attr(Dwarf_Die die, Dwarf_Half attr, Dwarf_Attribute *atp, Dwarf_Error *err) +{ + Dwarf_Attribute at; + Dwarf_Abbrev a; + int ret = DWARF_E_NONE; + + if (err == NULL) + return DWARF_E_ERROR; + + if (die == NULL || atp == NULL || (a = die->die_a) == NULL) { + DWARF_SET_ERROR(err, DWARF_E_ARGUMENT); + return DWARF_E_ARGUMENT; + } + + STAILQ_FOREACH(at, &a->a_attrib, at_next) + if (at->at_attrib == attr) + break; + + *atp = at; + + if (at == NULL) { + DWARF_SET_ERROR(err, DWARF_E_NO_ENTRY); + ret = DWARF_E_NO_ENTRY; + } + + return ret; +} + +int +dwarf_attr_add(Dwarf_Abbrev a, uint64_t attr, uint64_t form, Dwarf_Attribute *atp, Dwarf_Error *error) +{ + Dwarf_Attribute at; + int ret = DWARF_E_NONE; + + if (error == NULL) + return DWARF_E_ERROR; + + if (a == NULL) { + DWARF_SET_ERROR(error, DWARF_E_ARGUMENT); + return DWARF_E_ARGUMENT; + } + + if ((at = malloc(sizeof(struct _Dwarf_Attribute))) == NULL) { + DWARF_SET_ERROR(error, DWARF_E_MEMORY); + return DWARF_E_MEMORY; + } + + /* Initialise the attribute structure. */ + at->at_attrib = attr; + at->at_form = form; + + /* Add the attribute to the list in the abbrev. */ + STAILQ_INSERT_TAIL(&a->a_attrib, at, at_next); + + if (atp != NULL) + *atp = at; + + return ret; +} diff --git a/lib/libdwarf/dwarf_attrval.c b/lib/libdwarf/dwarf_attrval.c new file mode 100644 index 0000000..db07ee7 --- /dev/null +++ b/lib/libdwarf/dwarf_attrval.c @@ -0,0 +1,270 @@ +/*- + * Copyright (c) 2007 John Birrell (jb@freebsd.org) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include "_libdwarf.h" + +Dwarf_AttrValue +dwarf_attrval_find(Dwarf_Die die, Dwarf_Half attr) +{ + Dwarf_AttrValue av; + + STAILQ_FOREACH(av, &die->die_attrval, av_next) { + if (av->av_attrib == attr) + break; + } + + return av; +} + +int +dwarf_attrval_add(Dwarf_Die die, Dwarf_AttrValue avref, Dwarf_AttrValue *avp, Dwarf_Error *error) +{ + Dwarf_AttrValue av; + int ret = DWARF_E_NONE; + + if ((av = malloc(sizeof(struct _Dwarf_AttrValue))) == NULL) { + DWARF_SET_ERROR(error, DWARF_E_MEMORY); + return DWARF_E_MEMORY; + } + + memcpy(av, avref, sizeof(struct _Dwarf_AttrValue)); + + /* Add the attribute value to the list in the die. */ + STAILQ_INSERT_TAIL(&die->die_attrval, av, av_next); + + /* Save a pointer to the attribute name if this is one. */ + if (av->av_attrib == DW_AT_name) + switch (av->av_form) { + case DW_FORM_strp: + die->die_name = av->u[1].s; + break; + case DW_FORM_string: + die->die_name = av->u[0].s; + break; + default: + break; + } + + if (avp != NULL) + *avp = av; + + return ret; +} + +int +dwarf_attrval_flag(Dwarf_Die die, uint64_t attr, Dwarf_Bool *valp, Dwarf_Error *err) +{ + Dwarf_AttrValue av; + int ret = DWARF_E_NONE; + + if (err == NULL) + return DWARF_E_ERROR; + + if (die == NULL || valp == NULL) { + DWARF_SET_ERROR(err, DWARF_E_ARGUMENT); + return DWARF_E_ARGUMENT; + } + + *valp = 0; + + if ((av = dwarf_attrval_find(die, attr)) == NULL) { + DWARF_SET_ERROR(err, DWARF_E_NO_ENTRY); + ret = DWARF_E_NO_ENTRY; + } else { + switch (av->av_form) { + case DW_FORM_flag: + *valp = (Dwarf_Bool) av->u[0].u64; + break; + default: + printf("%s(%d): av->av_form '%s' (0x%lx) not handled\n", + __func__,__LINE__,get_form_desc(av->av_form), + (u_long) av->av_form); + DWARF_SET_ERROR(err, DWARF_E_BAD_FORM); + ret = DWARF_E_BAD_FORM; + } + } + + return ret; +} + +int +dwarf_attrval_string(Dwarf_Die die, uint64_t attr, const char **strp, Dwarf_Error *err) +{ + Dwarf_AttrValue av; + int ret = DWARF_E_NONE; + + if (err == NULL) + return DWARF_E_ERROR; + + if (die == NULL || strp == NULL) { + DWARF_SET_ERROR(err, DWARF_E_ARGUMENT); + return DWARF_E_ARGUMENT; + } + + *strp = NULL; + + if (attr == DW_AT_name) + *strp = die->die_name; + else if ((av = dwarf_attrval_find(die, attr)) == NULL) { + DWARF_SET_ERROR(err, DWARF_E_NO_ENTRY); + ret = DWARF_E_NO_ENTRY; + } else { + switch (av->av_form) { + case DW_FORM_strp: + *strp = av->u[1].s; + break; + case DW_FORM_string: + *strp = av->u[0].s; + break; + default: + printf("%s(%d): av->av_form '%s' (0x%lx) not handled\n", + __func__,__LINE__,get_form_desc(av->av_form), + (u_long) av->av_form); + DWARF_SET_ERROR(err, DWARF_E_BAD_FORM); + ret = DWARF_E_BAD_FORM; + } + } + + return ret; +} + +int +dwarf_attrval_signed(Dwarf_Die die, uint64_t attr, Dwarf_Signed *valp, Dwarf_Error *err) +{ + Dwarf_AttrValue av; + int ret = DWARF_E_NONE; + + if (err == NULL) + return DWARF_E_ERROR; + + if (die == NULL || valp == NULL) { + DWARF_SET_ERROR(err, DWARF_E_ARGUMENT); + return DWARF_E_ARGUMENT; + } + + *valp = 0; + + if ((av = dwarf_attrval_find(die, attr)) == NULL) { + DWARF_SET_ERROR(err, DWARF_E_NO_ENTRY); + ret = DWARF_E_NO_ENTRY; + } else { + switch (av->av_form) { + case DW_FORM_data1: + case DW_FORM_sdata: + *valp = av->u[0].s64; + break; + default: + printf("%s(%d): av->av_form '%s' (0x%lx) not handled\n", + __func__,__LINE__,get_form_desc(av->av_form), + (u_long) av->av_form); + DWARF_SET_ERROR(err, DWARF_E_BAD_FORM); + ret = DWARF_E_BAD_FORM; + } + } + + return ret; +} + +int +dwarf_attrval_unsigned(Dwarf_Die die, uint64_t attr, Dwarf_Unsigned *valp, Dwarf_Error *err) +{ + Dwarf_AttrValue av; + int ret = DWARF_E_NONE; + + if (err == NULL) + return DWARF_E_ERROR; + + if (die == NULL || valp == NULL) { + DWARF_SET_ERROR(err, DWARF_E_ARGUMENT); + return DWARF_E_ARGUMENT; + } + + *valp = 0; + + if ((av = dwarf_attrval_find(die, attr)) == NULL && attr != DW_AT_type) { + DWARF_SET_ERROR(err, DWARF_E_NO_ENTRY); + ret = DWARF_E_NO_ENTRY; + } else if (av == NULL && (av = dwarf_attrval_find(die, + DW_AT_abstract_origin)) != NULL) { + Dwarf_Die die1; + Dwarf_Unsigned val; + + switch (av->av_form) { + case DW_FORM_data1: + case DW_FORM_data2: + case DW_FORM_data4: + case DW_FORM_data8: + case DW_FORM_ref1: + case DW_FORM_ref2: + case DW_FORM_ref4: + case DW_FORM_ref8: + case DW_FORM_ref_udata: + val = av->u[0].u64; + + if ((die1 = dwarf_die_find(die, val)) == NULL || + (av = dwarf_attrval_find(die1, attr)) == NULL) { + DWARF_SET_ERROR(err, DWARF_E_NO_ENTRY); + ret = DWARF_E_NO_ENTRY; + } + break; + default: + printf("%s(%d): av->av_form '%s' (0x%lx) not handled\n", + __func__,__LINE__,get_form_desc(av->av_form), + (u_long) av->av_form); + DWARF_SET_ERROR(err, DWARF_E_BAD_FORM); + ret = DWARF_E_BAD_FORM; + } + } + + if (ret == DWARF_E_NONE) { + switch (av->av_form) { + case DW_FORM_data1: + case DW_FORM_data2: + case DW_FORM_data4: + case DW_FORM_data8: + case DW_FORM_ref1: + case DW_FORM_ref2: + case DW_FORM_ref4: + case DW_FORM_ref8: + case DW_FORM_ref_udata: + *valp = av->u[0].u64; + break; + default: + printf("%s(%d): av->av_form '%s' (0x%lx) not handled\n", + __func__,__LINE__,get_form_desc(av->av_form), + (u_long) av->av_form); + DWARF_SET_ERROR(err, DWARF_E_BAD_FORM); + ret = DWARF_E_BAD_FORM; + } + } + + return ret; +} diff --git a/lib/libdwarf/dwarf_cu.c b/lib/libdwarf/dwarf_cu.c new file mode 100644 index 0000000..325ffdc --- /dev/null +++ b/lib/libdwarf/dwarf_cu.c @@ -0,0 +1,68 @@ +/*- + * Copyright (c) 2007 John Birrell (jb@freebsd.org) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include "_libdwarf.h" + +int +dwarf_next_cu_header(Dwarf_Debug dbg, Dwarf_Unsigned *cu_header_length, + Dwarf_Half *cu_version, Dwarf_Unsigned *cu_abbrev_offset, + Dwarf_Half *cu_pointer_size, Dwarf_Unsigned *cu_next_offset, Dwarf_Error *error) +{ + Dwarf_CU next; + + if (error == NULL) + return DWARF_E_ERROR; + + if (dbg == NULL || cu_header_length == NULL || cu_version == NULL || + cu_abbrev_offset == NULL || cu_pointer_size == NULL || + cu_next_offset == NULL) { + DWARF_SET_ERROR(error, DWARF_E_ARGUMENT); + return DWARF_E_ERROR; + } + + if (dbg->dbg_cu_current == NULL) + dbg->dbg_cu_current = STAILQ_FIRST(&dbg->dbg_cu); + else if ((next = STAILQ_NEXT(dbg->dbg_cu_current, cu_next)) == NULL) { + DWARF_SET_ERROR(error, DWARF_E_NO_ENTRY); + return DWARF_E_NO_ENTRY; + } else + dbg->dbg_cu_current = next; + + if (dbg->dbg_cu_current == NULL) { + DWARF_SET_ERROR(error, DWARF_E_NO_ENTRY); + return DWARF_E_NO_ENTRY; + } + + *cu_header_length = dbg->dbg_cu_current->cu_header_length; + *cu_version = dbg->dbg_cu_current->cu_version; + *cu_abbrev_offset = dbg->dbg_cu_current->cu_abbrev_offset; + *cu_pointer_size = dbg->dbg_cu_current->cu_pointer_size; + *cu_next_offset = dbg->dbg_cu_current->cu_next_offset; + + return DWARF_E_NONE; +} diff --git a/lib/libdwarf/dwarf_dealloc.c b/lib/libdwarf/dwarf_dealloc.c new file mode 100644 index 0000000..dd910a0 --- /dev/null +++ b/lib/libdwarf/dwarf_dealloc.c @@ -0,0 +1,41 @@ +/*- + * Copyright (c) 2007 John Birrell (jb@freebsd.org) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include "_libdwarf.h" + +void +dwarf_dealloc(Dwarf_Debug dbg __unused, Dwarf_Ptr p __unused, Dwarf_Unsigned alloc_type __unused) +{ + /* + * This libdwarf implementation doesn't use this style + * of memory allocation. It doesn't copy things to return + * them to the client, so the client doesn't need to + * remember to free them. + */ + return; +} diff --git a/lib/libdwarf/dwarf_die.c b/lib/libdwarf/dwarf_die.c new file mode 100644 index 0000000..143e708 --- /dev/null +++ b/lib/libdwarf/dwarf_die.c @@ -0,0 +1,191 @@ +/*- + * Copyright (c) 2007 John Birrell (jb@freebsd.org) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <stdlib.h> +#include "_libdwarf.h" + +static const char *anon_name = "__anon__"; + +int +dwarf_die_add(Dwarf_CU cu, int level, uint64_t offset, uint64_t abnum, Dwarf_Abbrev a, Dwarf_Die *diep, Dwarf_Error *err) +{ + Dwarf_Die die; + uint64_t key; + int ret = DWARF_E_NONE; + + if (err == NULL) + return DWARF_E_ERROR; + + if (cu == NULL || a == NULL) { + DWARF_SET_ERROR(err, DWARF_E_ARGUMENT); + return DWARF_E_ARGUMENT; + } + + if ((die = malloc(sizeof(struct _Dwarf_Die))) == NULL) { + DWARF_SET_ERROR(err, DWARF_E_MEMORY); + return DWARF_E_MEMORY; + } + + /* Initialise the abbrev structure. */ + die->die_level = level; + die->die_offset = offset; + die->die_abnum = abnum; + die->die_a = a; + die->die_cu = cu; + die->die_name = anon_name; + + /* Initialise the list of attribute values. */ + STAILQ_INIT(&die->die_attrval); + + /* Add the die to the list in the compilation unit. */ + STAILQ_INSERT_TAIL(&cu->cu_die, die, die_next); + + /* Add the die to the hash table in the compilation unit. */ + key = offset % DWARF_DIE_HASH_SIZE; + STAILQ_INSERT_TAIL(&cu->cu_die_hash[key], die, die_hash); + + if (diep != NULL) + *diep = die; + + return ret; +} + +int +dwarf_dieoffset(Dwarf_Die die, Dwarf_Off *ret_offset, Dwarf_Error *err __unused) +{ + *ret_offset = die->die_offset; + + return DWARF_E_NONE; +} + +int +dwarf_child(Dwarf_Die die, Dwarf_Die *ret_die, Dwarf_Error *err) +{ + Dwarf_Die next; + int ret = DWARF_E_NONE; + + if (err == NULL) + return DWARF_E_ERROR; + + if (die == NULL || ret_die == NULL) { + DWARF_SET_ERROR(err, DWARF_E_ARGUMENT); + return DWARF_E_ARGUMENT; + } + + if ((next = STAILQ_NEXT(die, die_next)) == NULL || + next->die_level != die->die_level + 1) { + *ret_die = NULL; + DWARF_SET_ERROR(err, DWARF_E_NO_ENTRY); + ret = DWARF_E_NO_ENTRY; + } else + *ret_die = next; + + return ret; +} + +int +dwarf_tag(Dwarf_Die die, Dwarf_Half *tag, Dwarf_Error *err) +{ + Dwarf_Abbrev a; + + if (err == NULL) + return DWARF_E_ERROR; + + if (die == NULL || tag == NULL || (a = die->die_a) == NULL) { + DWARF_SET_ERROR(err, DWARF_E_ARGUMENT); + return DWARF_E_ARGUMENT; + } + + *tag = a->a_tag; + + return DWARF_E_NONE; +} + +int +dwarf_siblingof(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Die *caller_ret_die, Dwarf_Error *err) +{ + Dwarf_Die next; + Dwarf_CU cu; + int ret = DWARF_E_NONE; + + if (err == NULL) + return DWARF_E_ERROR; + + if (dbg == NULL || caller_ret_die == NULL) { + DWARF_SET_ERROR(err, DWARF_E_ARGUMENT); + return DWARF_E_ARGUMENT; + } + + if ((cu = dbg->dbg_cu_current) == NULL) { + DWARF_SET_ERROR(err, DWARF_E_CU_CURRENT); + return DWARF_E_CU_CURRENT; + } + + if (die == NULL) { + *caller_ret_die = STAILQ_FIRST(&cu->cu_die); + + if (*caller_ret_die == NULL) { + DWARF_SET_ERROR(err, DWARF_E_NO_ENTRY); + ret = DWARF_E_NO_ENTRY; + } + } else { + next = die; + while ((next = STAILQ_NEXT(next, die_next)) != NULL) { + if (next->die_level < die->die_level) { + next = NULL; + break; + } + if (next->die_level == die->die_level) { + *caller_ret_die = next; + break; + } + } + + if (next == NULL) { + *caller_ret_die = NULL; + DWARF_SET_ERROR(err, DWARF_E_NO_ENTRY); + ret = DWARF_E_NO_ENTRY; + } + } + + return ret; +} + +Dwarf_Die +dwarf_die_find(Dwarf_Die die, Dwarf_Unsigned off) +{ + Dwarf_CU cu = die->die_cu; + Dwarf_Die die1; + + STAILQ_FOREACH(die1, &cu->cu_die, die_next) { + if (die1->die_offset == off) + return (die1); + } + + return (NULL); +} diff --git a/lib/libdwarf/dwarf_dump.c b/lib/libdwarf/dwarf_dump.c new file mode 100644 index 0000000..e92fee0d --- /dev/null +++ b/lib/libdwarf/dwarf_dump.c @@ -0,0 +1,892 @@ +/*- + * Copyright (c) 2007 John Birrell (jb@freebsd.org) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <stdlib.h> +#include <string.h> +#include "_libdwarf.h" + +const char * +get_sht_desc(uint32_t sh_type) +{ + switch (sh_type) { + case SHT_NULL: + return "inactive"; + case SHT_PROGBITS: + return "program defined information"; + case SHT_SYMTAB: + return "symbol table section"; + case SHT_STRTAB: + return "string table section"; + case SHT_RELA: + return "relocation section with addends"; + case SHT_HASH: + return "symbol hash table section"; + case SHT_DYNAMIC: + return "dynamic section"; + case SHT_NOTE: + return "note section"; + case SHT_NOBITS: + return "no space section"; + case SHT_REL: + return "relocation section - no addends"; + case SHT_SHLIB: + return "reserved - purpose unknown"; + case SHT_DYNSYM: + return "dynamic symbol table section"; + case SHT_INIT_ARRAY: + return "Initialization function pointers."; + case SHT_FINI_ARRAY: + return "Termination function pointers."; + case SHT_PREINIT_ARRAY: + return "Pre-initialization function ptrs."; + case SHT_GROUP: + return "Section group."; + case SHT_SYMTAB_SHNDX: + return "Section indexes (see SHN_XINDEX)."; + case SHT_GNU_verdef: + return "Symbol versions provided"; + case SHT_GNU_verneed: + return "Symbol versions required"; + case SHT_GNU_versym: + return "Symbol version table"; + case SHT_AMD64_UNWIND: + return "AMD64 unwind"; + default: + return "Unknown"; + } +} + +const char * +get_attr_desc(uint32_t attr) +{ + switch (attr) { + case DW_AT_abstract_origin: + return "DW_AT_abstract_origin"; + case DW_AT_accessibility: + return "DW_AT_accessibility"; + case DW_AT_address_class: + return "DW_AT_address_class"; + case DW_AT_artificial: + return "DW_AT_artificial"; + case DW_AT_base_types: + return "DW_AT_base_types"; + case DW_AT_bit_offset: + return "DW_AT_bit_offset"; + case DW_AT_bit_size: + return "DW_AT_bit_size"; + case DW_AT_byte_size: + return "DW_AT_byte_size"; + case DW_AT_calling_convention: + return "DW_AT_calling_convention"; + case DW_AT_common_reference: + return "DW_AT_common_reference"; + case DW_AT_comp_dir: + return "DW_AT_comp_dir"; + case DW_AT_const_value: + return "DW_AT_const_value"; + case DW_AT_containing_type: + return "DW_AT_containing_type"; + case DW_AT_count: + return "DW_AT_count"; + case DW_AT_data_member_location: + return "DW_AT_data_member_location"; + case DW_AT_decl_column: + return "DW_AT_decl_column"; + case DW_AT_decl_file: + return "DW_AT_decl_file"; + case DW_AT_decl_line: + return "DW_AT_decl_line"; + case DW_AT_declaration: + return "DW_AT_declaration"; + case DW_AT_default_value: + return "DW_AT_default_value"; + case DW_AT_discr: + return "DW_AT_discr"; + case DW_AT_discr_list: + return "DW_AT_discr_list"; + case DW_AT_discr_value: + return "DW_AT_discr_value"; + case DW_AT_element_list: + return "DW_AT_element_list"; + case DW_AT_encoding: + return "DW_AT_encoding"; + case DW_AT_external: + return "DW_AT_external"; + case DW_AT_frame_base: + return "DW_AT_frame_base"; + case DW_AT_friend: + return "DW_AT_friend"; + case DW_AT_high_pc: + return "DW_AT_high_pc"; + case DW_AT_identifier_case: + return "DW_AT_identifier_case"; + case DW_AT_import: + return "DW_AT_import"; + case DW_AT_inline: + return "DW_AT_inline"; + case DW_AT_is_optional: + return "DW_AT_is_optional"; + case DW_AT_language: + return "DW_AT_language"; + case DW_AT_location: + return "DW_AT_location"; + case DW_AT_low_pc: + return "DW_AT_low_pc"; + case DW_AT_lower_bound: + return "DW_AT_lower_bound"; + case DW_AT_macro_info: + return "DW_AT_macro_info"; + case DW_AT_member: + return "DW_AT_member"; + case DW_AT_name: + return "DW_AT_name"; + case DW_AT_namelist_item: + return "DW_AT_namelist_item"; + case DW_AT_ordering: + return "DW_AT_ordering"; + case DW_AT_priority: + return "DW_AT_priority"; + case DW_AT_producer: + return "DW_AT_producer"; + case DW_AT_prototyped: + return "DW_AT_prototyped"; + case DW_AT_return_addr: + return "DW_AT_return_addr"; + case DW_AT_segment: + return "DW_AT_segment"; + case DW_AT_sibling: + return "DW_AT_sibling"; + case DW_AT_specification: + return "DW_AT_specification"; + case DW_AT_start_scope: + return "DW_AT_start_scope"; + case DW_AT_static_link: + return "DW_AT_static_link"; + case DW_AT_stmt_list: + return "DW_AT_stmt_list"; + case DW_AT_stride_size: + return "DW_AT_stride_size"; + case DW_AT_string_length: + return "DW_AT_string_length"; + case DW_AT_subscr_data: + return "DW_AT_subscr_data"; + case DW_AT_type: + return "DW_AT_type"; + case DW_AT_upper_bound: + return "DW_AT_upper_bound"; + case DW_AT_use_location: + return "DW_AT_use_location"; + case DW_AT_variable_parameter: + return "DW_AT_variable_parameter"; + case DW_AT_virtuality: + return "DW_AT_virtuality"; + case DW_AT_visibility: + return "DW_AT_visibility"; + case DW_AT_vtable_elem_location: + return "DW_AT_vtable_elem_location"; + default: + break; + } + + return "Unknown attribute"; +} + +const char * +get_form_desc(uint32_t form) +{ + switch (form) { + case DW_FORM_addr: + return "DW_FORM_addr"; + case DW_FORM_block: + return "DW_FORM_block"; + case DW_FORM_block1: + return "DW_FORM_block1"; + case DW_FORM_block2: + return "DW_FORM_block2"; + case DW_FORM_block4: + return "DW_FORM_block4"; + case DW_FORM_data1: + return "DW_FORM_data1"; + case DW_FORM_data2: + return "DW_FORM_data2"; + case DW_FORM_data4: + return "DW_FORM_data4"; + case DW_FORM_data8: + return "DW_FORM_data8"; + case DW_FORM_flag: + return "DW_FORM_flag"; + case DW_FORM_indirect: + return "DW_FORM_indirect"; + case DW_FORM_ref1: + return "DW_FORM_ref1"; + case DW_FORM_ref2: + return "DW_FORM_ref2"; + case DW_FORM_ref4: + return "DW_FORM_ref4"; + case DW_FORM_ref8: + return "DW_FORM_ref8"; + case DW_FORM_ref_addr: + return "DW_FORM_ref_addr"; + case DW_FORM_ref_udata: + return "DW_FORM_ref_udata"; + case DW_FORM_sdata: + return "DW_FORM_sdata"; + case DW_FORM_string: + return "DW_FORM_string"; + case DW_FORM_strp: + return "DW_FORM_strp"; + case DW_FORM_udata: + return "DW_FORM_udata"; + default: + break; + } + + return "Unknown attribute"; +} + +const char * +get_tag_desc(uint32_t tag) +{ + switch (tag) { + case DW_TAG_access_declaration: + return "DW_TAG_access_declaration"; + case DW_TAG_array_type: + return "DW_TAG_array_type"; + case DW_TAG_base_type: + return "DW_TAG_base_type"; + case DW_TAG_catch_block: + return "DW_TAG_catch_block"; + case DW_TAG_class_type: + return "DW_TAG_class_type"; + case DW_TAG_common_block: + return "DW_TAG_common_block"; + case DW_TAG_common_inclusion: + return "DW_TAG_common_inclusion"; + case DW_TAG_compile_unit: + return "DW_TAG_compile_unit"; + case DW_TAG_condition: + return "DW_TAG_condition"; + case DW_TAG_const_type: + return "DW_TAG_const_type"; + case DW_TAG_constant: + return "DW_TAG_constant"; + case DW_TAG_dwarf_procedure: + return "DW_TAG_dwarf_procedure"; + case DW_TAG_entry_point: + return "DW_TAG_entry_point"; + case DW_TAG_enumeration_type: + return "DW_TAG_enumeration_type"; + case DW_TAG_enumerator: + return "DW_TAG_enumerator"; + case DW_TAG_formal_parameter: + return "DW_TAG_formal_parameter"; + case DW_TAG_friend: + return "DW_TAG_friend"; + case DW_TAG_imported_declaration: + return "DW_TAG_imported_declaration"; + case DW_TAG_imported_module: + return "DW_TAG_imported_module"; + case DW_TAG_imported_unit: + return "DW_TAG_imported_unit"; + case DW_TAG_inheritance: + return "DW_TAG_inheritance"; + case DW_TAG_inlined_subroutine: + return "DW_TAG_inlined_subroutine"; + case DW_TAG_interface_type: + return "DW_TAG_interface_type"; + case DW_TAG_label: + return "DW_TAG_label"; + case DW_TAG_lexical_block: + return "DW_TAG_lexical_block"; + case DW_TAG_member: + return "DW_TAG_member"; + case DW_TAG_module: + return "DW_TAG_module"; + case DW_TAG_namelist: + return "DW_TAG_namelist"; + case DW_TAG_namelist_item: + return "DW_TAG_namelist_item"; + case DW_TAG_namespace: + return "DW_TAG_namespace"; + case DW_TAG_packed_type: + return "DW_TAG_packed_type"; + case DW_TAG_partial_unit: + return "DW_TAG_partial_unit"; + case DW_TAG_pointer_type: + return "DW_TAG_pointer_type"; + case DW_TAG_ptr_to_member_type: + return "DW_TAG_ptr_to_member_type"; + case DW_TAG_reference_type: + return "DW_TAG_reference_type"; + case DW_TAG_restrict_type: + return "DW_TAG_restrict_type"; + case DW_TAG_set_type: + return "DW_TAG_set_type"; + case DW_TAG_shared_type: + return "DW_TAG_shared_type"; + case DW_TAG_string_type: + return "DW_TAG_string_type"; + case DW_TAG_structure_type: + return "DW_TAG_structure_type"; + case DW_TAG_subprogram: + return "DW_TAG_subprogram"; + case DW_TAG_subrange_type: + return "DW_TAG_subrange_type"; + case DW_TAG_subroutine_type: + return "DW_TAG_subroutine_type"; + case DW_TAG_template_type_parameter: + return "DW_TAG_template_type_parameter"; + case DW_TAG_template_value_parameter: + return "DW_TAG_template_value_parameter"; + case DW_TAG_thrown_type: + return "DW_TAG_thrown_type"; + case DW_TAG_try_block: + return "DW_TAG_try_block"; + case DW_TAG_typedef: + return "DW_TAG_typedef"; + case DW_TAG_union_type: + return "DW_TAG_union_type"; + case DW_TAG_unspecified_parameters: + return "DW_TAG_unspecified_parameters"; + case DW_TAG_unspecified_type: + return "DW_TAG_unspecified_type"; + case DW_TAG_variable: + return "DW_TAG_variable"; + case DW_TAG_variant: + return "DW_TAG_variant"; + case DW_TAG_variant_part: + return "DW_TAG_variant_part"; + case DW_TAG_volatile_type: + return "DW_TAG_volatile_type"; + case DW_TAG_with_stmt: + return "DW_TAG_with_stmt"; + default: + break; + } + + return "Unknown tag"; +} + +void +dwarf_dump_abbrev(Dwarf_Debug dbg) +{ + Dwarf_Abbrev a; + Dwarf_Attribute at; + Dwarf_CU cu; + + printf("Contents of the .debug_abbrev section:\n\nEntry Tag\n"); + + STAILQ_FOREACH(cu, &dbg->dbg_cu, cu_next) { + STAILQ_FOREACH(a, &cu->cu_abbrev, a_next) { + printf("%5lu %-30s [%s children]\n", + (u_long) a->a_entry, get_tag_desc(a->a_tag), + (a->a_children == DW_CHILDREN_yes) ? "has" : "no"); + + STAILQ_FOREACH(at, &a->a_attrib, at_next) + printf(" %-30s %s\n", get_attr_desc(at->at_attrib), + get_form_desc(at->at_form)); + } + } +} +#ifdef DOODAD + case DW_AT_inline: + switch (uvalue) + { + case DW_INL_not_inlined: + printf (_("(not inlined)")); + break; + case DW_INL_inlined: + printf (_("(inlined)")); + break; + case DW_INL_declared_not_inlined: + printf (_("(declared as inline but ignored)")); + break; + case DW_INL_declared_inlined: + printf (_("(declared as inline and inlined)")); + break; + default: + printf (_(" (Unknown inline attribute value: %lx)"), uvalue); + break; + } + break; + + case DW_AT_language: + switch (uvalue) + { + case DW_LANG_C: printf ("(non-ANSI C)"); break; + case DW_LANG_C89: printf ("(ANSI C)"); break; + case DW_LANG_C_plus_plus: printf ("(C++)"); break; + case DW_LANG_Fortran77: printf ("(FORTRAN 77)"); break; + case DW_LANG_Fortran90: printf ("(Fortran 90)"); break; + case DW_LANG_Modula2: printf ("(Modula 2)"); break; + case DW_LANG_Pascal83: printf ("(ANSI Pascal)"); break; + case DW_LANG_Ada83: printf ("(Ada)"); break; + case DW_LANG_Cobol74: printf ("(Cobol 74)"); break; + case DW_LANG_Cobol85: printf ("(Cobol 85)"); break; + /* DWARF 2.1 values. */ + case DW_LANG_C99: printf ("(ANSI C99)"); break; + case DW_LANG_Ada95: printf ("(ADA 95)"); break; + case DW_LANG_Fortran95: printf ("(Fortran 95)"); break; + /* MIPS extension. */ + case DW_LANG_Mips_Assembler: printf ("(MIPS assembler)"); break; + /* UPC extension. */ + case DW_LANG_Upc: printf ("(Unified Parallel C)"); break; + default: + printf ("(Unknown: %lx)", uvalue); + break; + } + break; + + case DW_AT_encoding: + switch (uvalue) + { + case DW_ATE_void: printf ("(void)"); break; + case DW_ATE_address: printf ("(machine address)"); break; + case DW_ATE_boolean: printf ("(boolean)"); break; + case DW_ATE_complex_float: printf ("(complex float)"); break; + case DW_ATE_float: printf ("(float)"); break; + case DW_ATE_signed: printf ("(signed)"); break; + case DW_ATE_signed_char: printf ("(signed char)"); break; + case DW_ATE_unsigned: printf ("(unsigned)"); break; + case DW_ATE_unsigned_char: printf ("(unsigned char)"); break; + /* DWARF 2.1 value. */ + case DW_ATE_imaginary_float: printf ("(imaginary float)"); break; + default: + if (uvalue >= DW_ATE_lo_user + && uvalue <= DW_ATE_hi_user) + printf ("(user defined type)"); + else + printf ("(unknown type)"); + break; + } + break; + + case DW_AT_accessibility: + switch (uvalue) + { + case DW_ACCESS_public: printf ("(public)"); break; + case DW_ACCESS_protected: printf ("(protected)"); break; + case DW_ACCESS_private: printf ("(private)"); break; + default: + printf ("(unknown accessibility)"); + break; + } + break; + + case DW_AT_visibility: + switch (uvalue) + { + case DW_VIS_local: printf ("(local)"); break; + case DW_VIS_exported: printf ("(exported)"); break; + case DW_VIS_qualified: printf ("(qualified)"); break; + default: printf ("(unknown visibility)"); break; + } + break; + + case DW_AT_virtuality: + switch (uvalue) + { + case DW_VIRTUALITY_none: printf ("(none)"); break; + case DW_VIRTUALITY_virtual: printf ("(virtual)"); break; + case DW_VIRTUALITY_pure_virtual:printf ("(pure_virtual)"); break; + default: printf ("(unknown virtuality)"); break; + } + break; + + case DW_AT_identifier_case: + switch (uvalue) + { + case DW_ID_case_sensitive: printf ("(case_sensitive)"); break; + case DW_ID_up_case: printf ("(up_case)"); break; + case DW_ID_down_case: printf ("(down_case)"); break; + case DW_ID_case_insensitive: printf ("(case_insensitive)"); break; + default: printf ("(unknown case)"); break; + } + break; + + case DW_AT_calling_convention: + switch (uvalue) + { + case DW_CC_normal: printf ("(normal)"); break; + case DW_CC_program: printf ("(program)"); break; + case DW_CC_nocall: printf ("(nocall)"); break; + default: + if (uvalue >= DW_CC_lo_user + && uvalue <= DW_CC_hi_user) + printf ("(user defined)"); + else + printf ("(unknown convention)"); + } + break; + + case DW_AT_ordering: + switch (uvalue) + { + case -1: printf ("(undefined)"); break; + case 0: printf ("(row major)"); break; + case 1: printf ("(column major)"); break; + } + break; + + case DW_AT_frame_base: + case DW_AT_location: + case DW_AT_data_member_location: + case DW_AT_vtable_elem_location: + case DW_AT_allocated: + case DW_AT_associated: + case DW_AT_data_location: + case DW_AT_stride: + case DW_AT_upper_bound: + case DW_AT_lower_bound: + if (block_start) + { + printf ("("); + decode_location_expression (block_start, pointer_size, uvalue); + printf (")"); + } + else if (form == DW_FORM_data4 || form == DW_FORM_data8) + { + printf ("("); + printf ("location list"); + printf (")"); + } + break; +#endif + +static void +dwarf_dump_av_attr(Dwarf_Die die __unused, Dwarf_AttrValue av) +{ + switch (av->av_attrib) { + case DW_AT_accessibility: + break; + + case DW_AT_calling_convention: + break; + + case DW_AT_encoding: + break; + + case DW_AT_identifier_case: + break; + + case DW_AT_inline: + break; + + case DW_AT_language: + break; + + case DW_AT_ordering: + break; + + case DW_AT_virtuality: + break; + + case DW_AT_visibility: + break; + + case DW_AT_frame_base: + case DW_AT_location: + case DW_AT_data_member_location: + case DW_AT_vtable_elem_location: + case DW_AT_upper_bound: + case DW_AT_lower_bound: + break; + + default: + break; + } +} + +void +dwarf_dump_av(Dwarf_Die die, Dwarf_AttrValue av) +{ + uint64_t i; + + printf(" %-30s : %-16s ", + get_attr_desc(av->av_attrib), + get_form_desc(av->av_form)); + + switch (av->av_form) { + case DW_FORM_addr: + printf("0x%llx", (unsigned long long) av->u[0].u64); + break; + case DW_FORM_block: + case DW_FORM_block1: + case DW_FORM_block2: + case DW_FORM_block4: + printf("%lu byte block:", (u_long) av->u[0].u64); + for (i = 0; i < av->u[0].u64; i++) + printf(" %02x", av->u[1].u8p[i]); + break; + case DW_FORM_data1: + case DW_FORM_data2: + case DW_FORM_data4: + case DW_FORM_data8: + case DW_FORM_flag: + printf("%llu", (unsigned long long) av->u[0].u64); + break; + case DW_FORM_ref1: + case DW_FORM_ref2: + case DW_FORM_ref4: + case DW_FORM_ref8: + case DW_FORM_ref_udata: + printf("<%llx>", (unsigned long long) (av->u[0].u64 + + die->die_cu->cu_offset)); + break; + case DW_FORM_string: + printf("%s", av->u[0].s); + break; + case DW_FORM_strp: + printf("(indirect string, offset 0x%llx): %s", + (unsigned long long) av->u[0].u64, av->u[1].s); + break; + default: + printf("unknown form"); + break; + } + + /* Dump any extra attribute-specific information. */ + dwarf_dump_av_attr(die, av); + + printf("\n"); +} + +void +dwarf_dump_die_at_offset(Dwarf_Debug dbg, Dwarf_Off off) +{ + Dwarf_CU cu; + Dwarf_Die die; + + if (dbg == NULL) + return; + + STAILQ_FOREACH(cu, &dbg->dbg_cu, cu_next) { + STAILQ_FOREACH(die, &cu->cu_die, die_next) { + if ((off_t) die->die_offset == off) { + dwarf_dump_die(die); + return; + } + } + } +} + +void +dwarf_dump_die(Dwarf_Die die) +{ + Dwarf_AttrValue av; + + printf("<%d><%llx>: Abbrev number: %llu (%s)\n", + die->die_level, (unsigned long long) die->die_offset, + (unsigned long long) die->die_abnum, + get_tag_desc(die->die_a->a_tag)); + + STAILQ_FOREACH(av, &die->die_attrval, av_next) + dwarf_dump_av(die, av); +} + +void +dwarf_dump_raw(Dwarf_Debug dbg) +{ + Dwarf_CU cu; + char *p = (char *) dbg; + int i; + + printf("dbg %p\n",dbg); + + if (dbg == NULL) + return; + + for (i = 0; i < (int) sizeof(*dbg); i++) { + if (*p >= 0x20 && *p < 0x7f) { + printf(" %c",*p++ & 0xff); + } else { + printf(" %02x",*p++ & 0xff); + } + } + printf("\n"); + + STAILQ_FOREACH(cu, &dbg->dbg_cu, cu_next) { + p = (char *) cu; + printf("cu %p\n",cu); + for (i = 0; i < (int) sizeof(*cu); i++) { + if (*p >= 0x20 && *p < 0x7f) { + printf(" %c",*p++ & 0xff); + } else { + printf(" %02x",*p++ & 0xff); + } + } + printf("\n"); + } +} + +static void +dwarf_dump_tree_dies(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Error *error) +{ + Dwarf_Die child; + int ret; + + do { + dwarf_dump_die(die); + + if ((ret = dwarf_child(die, &child, error) == DWARF_E_NO_ENTRY)) { + /* No children. */ + } else if (ret != DWARF_E_NONE) { + printf("Error %s\n", dwarf_errmsg(error)); + return; + } else + dwarf_dump_tree_dies(dbg, child, error); + + if (dwarf_siblingof(dbg, die, &die, error) != DWARF_E_NONE) + die = NULL; + + } while (die != NULL); +} + +void +dwarf_dump_tree(Dwarf_Debug dbg) +{ + Dwarf_CU cu; + Dwarf_Die die; + Dwarf_Error error; + Dwarf_Half cu_pointer_size; + Dwarf_Half cu_version; + Dwarf_Unsigned cu_abbrev_offset; + Dwarf_Unsigned cu_header_length; + Dwarf_Unsigned cu_next_offset; + + STAILQ_FOREACH(cu, &dbg->dbg_cu, cu_next) { + printf ("\nCompilation Unit @ offset %llx:\n", + (unsigned long long) cu->cu_offset); + printf (" Length: %lu\n", (u_long) cu->cu_length); + printf (" Version: %hu\n", cu->cu_version); + printf (" Abbrev Offset: %lu\n", (u_long) cu->cu_abbrev_offset); + printf (" Pointer Size: %u\n", (u_int) cu->cu_pointer_size); + + if (dwarf_next_cu_header(dbg, &cu_header_length, + &cu_version, &cu_abbrev_offset, &cu_pointer_size, + &cu_next_offset, &error) != DWARF_E_NONE) { + printf("Error %s\n", dwarf_errmsg(&error)); + return; + } + + if (dwarf_siblingof(dbg, NULL, &die, &error) != DWARF_E_NONE) { + printf("Error %s\n", dwarf_errmsg(&error)); + return; + } + + dwarf_dump_tree_dies(dbg, die, &error); + + } +} + +void +dwarf_dump_info(Dwarf_Debug dbg) +{ + Dwarf_CU cu; + Dwarf_Die die; + + printf("Contents of the .debug_info section:\n"); + + STAILQ_FOREACH(cu, &dbg->dbg_cu, cu_next) { + printf ("\nCompilation Unit @ offset %llx:\n", + (unsigned long long) cu->cu_offset); + printf (" Length: %lu\n", (u_long) cu->cu_length); + printf (" Version: %hu\n", cu->cu_version); + printf (" Abbrev Offset: %lu\n", (u_long) cu->cu_abbrev_offset); + printf (" Pointer Size: %u\n", (u_int) cu->cu_pointer_size); + + STAILQ_FOREACH(die, &cu->cu_die, die_next) + dwarf_dump_die(die); + } +} + + +void +dwarf_dump_shstrtab(Dwarf_Debug dbg) +{ + char *name; + int indx = 0; + + printf("---------------------\nSection header string table contents:\n"); + while ((name = elf_strptr(dbg->dbg_elf, dbg->dbg_stnum, indx)) != NULL) { + printf("%5d '%s'\n",indx,name); + indx += strlen(name) + 1; + } +} + +void +dwarf_dump_strtab(Dwarf_Debug dbg) +{ + char *name; + int indx = 0; + + printf("---------------------\nString table contents:\n"); + while ((name = elf_strptr(dbg->dbg_elf, dbg->dbg_s[DWARF_strtab].s_shnum, indx)) != NULL) { + printf("%5d '%s'\n",indx,name); + indx += strlen(name) + 1; + } +} + +void +dwarf_dump_dbgstr(Dwarf_Debug dbg) +{ + char *name; + int indx = 0; + + printf("---------------------\nDebug string table contents:\n"); + while ((name = elf_strptr(dbg->dbg_elf, dbg->dbg_s[DWARF_debug_str].s_shnum, indx)) != NULL) { + printf("%5d '%s'\n",indx,name); + indx += strlen(name) + 1; + } +} + +void +dwarf_dump_symtab(Dwarf_Debug dbg) +{ + GElf_Sym sym; + char *name; + int indx = 0; + + printf("---------------------\nSymbol table contents:\n"); + while (gelf_getsym(dbg->dbg_s[DWARF_symtab].s_data, indx++, &sym) != NULL) { + if ((name = elf_strptr(dbg->dbg_elf, dbg->dbg_s[DWARF_strtab].s_shnum, sym.st_name)) == NULL) + printf("sym.st_name %u indx %d sym.st_size %lu\n",sym.st_name,indx,(u_long) sym.st_size); + else + printf("'%s' sym.st_name %u indx %d sym.st_size %lu\n",name,sym.st_name,indx,(u_long) sym.st_size); + } +} + +void +dwarf_dump(Dwarf_Debug dbg) +{ + dwarf_dump_strtab(dbg); + dwarf_dump_shstrtab(dbg); + dwarf_dump_dbgstr(dbg); + dwarf_dump_symtab(dbg); + dwarf_dump_info(dbg); +} diff --git a/lib/libdwarf/dwarf_errmsg.c b/lib/libdwarf/dwarf_errmsg.c new file mode 100644 index 0000000..ffc2020 --- /dev/null +++ b/lib/libdwarf/dwarf_errmsg.c @@ -0,0 +1,76 @@ +/*- + * Copyright (c) 2007 John Birrell (jb@freebsd.org) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <stdio.h> +#include "_libdwarf.h" + +const char *_libdwarf_errors[] = { +#define DEFINE_ERROR(N,S) [DWARF_E_##N] = S + DEFINE_ERROR(NONE, "No Error"), + DEFINE_ERROR(ERROR, "An error"), + DEFINE_ERROR(NO_ENTRY, "No entry found"), + DEFINE_ERROR(ARGUMENT, "Invalid argument"), + DEFINE_ERROR(DEBUG_INFO, "Debug info NULL"), + DEFINE_ERROR(MEMORY, "Insufficient memory"), + DEFINE_ERROR(ELF, "ELF error"), + DEFINE_ERROR(INVALID_CU, "Invalid compilation unit data"), + DEFINE_ERROR(CU_VERSION, "Wrong CU version. Only 2 and 3 supported"), + DEFINE_ERROR(MISSING_ABBREV, "Abbrev not found"), + DEFINE_ERROR(NOT_IMPLEMENTED, "Unimplemented code at"), + DEFINE_ERROR(CU_CURRENT, "No current compilation unit"), + DEFINE_ERROR(BAD_FORM, "Wrong form type for attribute value"), + DEFINE_ERROR(INVALID_EXPR, "Invalid DWARF expression"), + DEFINE_ERROR(NUM, "Unknown DWARF error") +#undef DEFINE_ERROR +}; + +const char * +dwarf_errmsg(Dwarf_Error *error) +{ + const char *p; + + if (error == NULL) + return NULL; + + if (error->err_error < 0 || error->err_error >= DWARF_E_NUM) + return _libdwarf_errors[DWARF_E_NUM]; + else if (error->err_error == DWARF_E_NONE) + return _libdwarf_errors[DWARF_E_NONE]; + else + p = _libdwarf_errors[error->err_error]; + + if (error->err_error == DWARF_E_ELF) + snprintf(error->err_msg, sizeof(error->err_msg), + "ELF error : %s [%s(%d)]", elf_errmsg(error->elf_error), + error->err_func, error->err_line); + else + snprintf(error->err_msg, sizeof(error->err_msg), + "%s [%s(%d)]", p, error->err_func, error->err_line); + + return (const char *) error->err_msg; +} diff --git a/lib/libdwarf/dwarf_errno.c b/lib/libdwarf/dwarf_errno.c new file mode 100644 index 0000000..d54ebfa --- /dev/null +++ b/lib/libdwarf/dwarf_errno.c @@ -0,0 +1,38 @@ +/*- + * Copyright (c) 2007 John Birrell (jb@freebsd.org) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include "_libdwarf.h" + +int +dwarf_errno(Dwarf_Error *err) +{ + if (err == NULL) + return -1; + + return (err->err_error); +} diff --git a/lib/libdwarf/dwarf_finish.c b/lib/libdwarf/dwarf_finish.c new file mode 100644 index 0000000..d665ed9 --- /dev/null +++ b/lib/libdwarf/dwarf_finish.c @@ -0,0 +1,98 @@ +/*- + * Copyright (c) 2007 John Birrell (jb@freebsd.org) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <stdlib.h> +#include "_libdwarf.h" + +int +dwarf_finish(Dwarf_Debug *dbgp, Dwarf_Error *error) +{ + Dwarf_Abbrev ab; + Dwarf_Abbrev tab; + Dwarf_Attribute at; + Dwarf_Attribute tat; + Dwarf_AttrValue av; + Dwarf_AttrValue tav; + Dwarf_CU cu; + Dwarf_CU tcu; + Dwarf_Debug dbg; + Dwarf_Die die; + Dwarf_Die tdie; + + if (error == NULL) + /* Can only return a generic error. */ + return DWARF_E_ERROR; + + if (dbgp == NULL) { + DWARF_SET_ERROR(error, DWARF_E_ARGUMENT); + return DWARF_E_ERROR; + } + + if ((dbg = *dbgp) == NULL) + return DWARF_E_NONE; + + /* Free entries in the compilation unit list. */ + STAILQ_FOREACH_SAFE(cu, &dbg->dbg_cu, cu_next, tcu) { + /* Free entries in the die list */ + STAILQ_FOREACH_SAFE(die, &cu->cu_die, die_next, tdie) { + /* Free entries in the attribute value list */ + STAILQ_FOREACH_SAFE(av, &die->die_attrval, av_next, tav) { + STAILQ_REMOVE(&die->die_attrval, av, _Dwarf_AttrValue, av_next); + free(av); + } + + STAILQ_REMOVE(&cu->cu_die, die, _Dwarf_Die, die_next); + free(die); + } + + /* Free entries in the abbrev list */ + STAILQ_FOREACH_SAFE(ab, &cu->cu_abbrev, a_next, tab) { + /* Free entries in the attribute list */ + STAILQ_FOREACH_SAFE(at, &ab->a_attrib, at_next, tat) { + STAILQ_REMOVE(&ab->a_attrib, at, _Dwarf_Attribute, at_next); + free(at); + } + + STAILQ_REMOVE(&cu->cu_abbrev, ab, _Dwarf_Abbrev, a_next); + free(ab); + } + + STAILQ_REMOVE(&dbg->dbg_cu, cu, _Dwarf_CU, cu_next); + free(cu); + } + + if (dbg->dbg_elf_close) + /* Free resources associated with the ELF file. */ + elf_end(dbg->dbg_elf); + + free(dbg); + + *dbgp = NULL; + + return DWARF_E_NONE; +} diff --git a/lib/libdwarf/dwarf_form.c b/lib/libdwarf/dwarf_form.c new file mode 100644 index 0000000..6fdf35e --- /dev/null +++ b/lib/libdwarf/dwarf_form.c @@ -0,0 +1,47 @@ +/*- + * Copyright (c) 2007 John Birrell (jb@freebsd.org) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include "_libdwarf.h" + +int +dwarf_whatform(Dwarf_Attribute at, Dwarf_Half *return_form, Dwarf_Error *err) +{ + int ret = DWARF_E_NONE; + + if (err == NULL) + return DWARF_E_ERROR; + + if (at == NULL || return_form == NULL) { + DWARF_SET_ERROR(err, DWARF_E_ARGUMENT); + return DWARF_E_ARGUMENT; + } + + *return_form = at->at_form; + + return ret; +} diff --git a/lib/libdwarf/dwarf_init.c b/lib/libdwarf/dwarf_init.c new file mode 100644 index 0000000..30b7b0f --- /dev/null +++ b/lib/libdwarf/dwarf_init.c @@ -0,0 +1,748 @@ +/*- + * Copyright (c) 2007 John Birrell (jb@freebsd.org) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <stdlib.h> +#include <string.h> +#include "_libdwarf.h" + +static const char *debug_snames[DWARF_DEBUG_SNAMES] = { + ".debug_abbrev", + ".debug_aranges", + ".debug_frame", + ".debug_info", + ".debug_line", + ".debug_pubnames", + ".eh_frame", + ".debug_macinfo", + ".debug_str", + ".debug_loc", + ".debug_pubtypes", + ".debug_ranges", + ".debug_static_func", + ".debug_static_vars", + ".debug_types", + ".debug_weaknames", + ".symtab", + ".strtab" +}; + +static uint64_t (*dwarf_read) (Elf_Data **, uint64_t *, int); +static void (*dwarf_write) (Elf_Data **, uint64_t *, uint64_t, int); + +static uint64_t +dwarf_read_lsb(Elf_Data **dp, uint64_t *offsetp, int bytes_to_read) +{ + uint64_t ret = 0; + + uint8_t *src = (uint8_t *) (*dp)->d_buf + *offsetp; + + switch (bytes_to_read) { + case 8: + ret |= ((uint64_t) src[4]) << 32 | ((uint64_t) src[5]) << 40; + ret |= ((uint64_t) src[6]) << 48 | ((uint64_t) src[7]) << 56; + case 4: + ret |= ((uint64_t) src[2]) << 16 | ((uint64_t) src[3]) << 24; + case 2: + ret |= ((uint64_t) src[1]) << 8; + case 1: + ret |= src[0]; + break; + default: + return 0; + break; + } + + *offsetp += bytes_to_read; + + return ret; +} + +static uint64_t +dwarf_read_msb(Elf_Data **dp, uint64_t *offsetp, int bytes_to_read) +{ + uint64_t ret = 0; + + uint8_t *src = (uint8_t *) (*dp)->d_buf + *offsetp; + + switch (bytes_to_read) { + case 1: + ret = src[0]; + break; + case 2: + ret = src[1] | ((uint64_t) src[0]) << 8; + break; + case 4: + ret = src[3] | ((uint64_t) src[2]) << 8; + ret |= ((uint64_t) src[1]) << 16 | ((uint64_t) src[0]) << 24; + break; + case 8: + ret = src[7] | ((uint64_t) src[6]) << 8; + ret |= ((uint64_t) src[5]) << 16 | ((uint64_t) src[4]) << 24; + ret |= ((uint64_t) src[3]) << 32 | ((uint64_t) src[2]) << 40; + ret |= ((uint64_t) src[1]) << 48 | ((uint64_t) src[0]) << 56; + break; + default: + return 0; + break; + } + + *offsetp += bytes_to_read; + + return ret; +} + +static void +dwarf_write_lsb(Elf_Data **dp, uint64_t *offsetp, uint64_t value, int bytes_to_write) +{ + uint8_t *dst = (uint8_t *) (*dp)->d_buf + *offsetp; + + switch (bytes_to_write) { + case 8: + dst[7] = (value >> 56) & 0xff; + dst[6] = (value >> 48) & 0xff; + dst[5] = (value >> 40) & 0xff; + dst[4] = (value >> 32) & 0xff; + case 4: + dst[3] = (value >> 24) & 0xff; + dst[2] = (value >> 16) & 0xff; + case 2: + dst[1] = (value >> 8) & 0xff; + case 1: + dst[0] = value & 0xff; + break; + default: + return; + break; + } + + *offsetp += bytes_to_write; +} + +static void +dwarf_write_msb(Elf_Data **dp, uint64_t *offsetp, uint64_t value, int bytes_to_write) +{ + uint8_t *dst = (uint8_t *) (*dp)->d_buf + *offsetp; + + switch (bytes_to_write) { + case 8: + dst[7] = value & 0xff; + dst[6] = (value >> 8) & 0xff; + dst[5] = (value >> 16) & 0xff; + dst[4] = (value >> 24) & 0xff; + value >>= 32; + case 4: + dst[3] = value & 0xff; + dst[2] = (value >> 8) & 0xff; + value >>= 16; + case 2: + dst[1] = value & 0xff; + value >>= 8; + case 1: + dst[0] = value & 0xff; + break; + default: + return; + break; + } + + *offsetp += bytes_to_write; +} + +static int64_t +dwarf_read_sleb128(Elf_Data **dp, uint64_t *offsetp) +{ + int64_t ret = 0; + uint8_t b; + int shift = 0; + + uint8_t *src = (uint8_t *) (*dp)->d_buf + *offsetp; + + do { + b = *src++; + + ret |= ((b & 0x7f) << shift); + + (*offsetp)++; + + shift += 7; + } while ((b & 0x80) != 0); + + if (shift < 32 && (b & 0x40) != 0) + ret |= (-1 << shift); + + return ret; +} + +static uint64_t +dwarf_read_uleb128(Elf_Data **dp, uint64_t *offsetp) +{ + uint64_t ret = 0; + uint8_t b; + int shift = 0; + + uint8_t *src = (uint8_t *) (*dp)->d_buf + *offsetp; + + do { + b = *src++; + + ret |= ((b & 0x7f) << shift); + + (*offsetp)++; + + shift += 7; + } while ((b & 0x80) != 0); + + return ret; +} + +static const char * +dwarf_read_string(Elf_Data **dp, uint64_t *offsetp) +{ + char *ret; + + char *src = (char *) (*dp)->d_buf + *offsetp; + + ret = src; + + while (*src != '\0' && *offsetp < (*dp)->d_size) { + src++; + (*offsetp)++; + } + + if (*src == '\0' && *offsetp < (*dp)->d_size) + (*offsetp)++; + + return ret; +} + +static uint8_t * +dwarf_read_block(Elf_Data **dp, uint64_t *offsetp, uint64_t length) +{ + uint8_t *ret; + + uint8_t *src = (char *) (*dp)->d_buf + *offsetp; + + ret = src; + + (*offsetp) += length; + + return ret; +} + +static int +dwarf_apply_relocations(Dwarf_Debug dbg, Elf_Data *reld, int secindx) +{ + Elf_Data *d; + GElf_Rela rela; + int indx = 0; + int ret = DWARF_E_NONE; + uint64_t offset; + + /* Point to the data to be relocated: */ + d = dbg->dbg_s[secindx].s_data; + + /* Enter a loop to process each relocation addend: */ + while (gelf_getrela(reld, indx++, &rela) != NULL) { + GElf_Sym sym; + Elf64_Xword symindx = ELF64_R_SYM(rela.r_info); + + if (gelf_getsym(dbg->dbg_s[DWARF_symtab].s_data, symindx, &sym) == NULL) { + printf("Couldn't find symbol index %lu for relocation\n",(u_long) symindx); + continue; + } + + offset = rela.r_offset; + + dwarf_write(&d, &offset, rela.r_addend, dbg->dbg_offsize); + } + + return ret; +} + +static int +dwarf_relocate(Dwarf_Debug dbg, Dwarf_Error *error) +{ + Elf_Scn *scn = NULL; + GElf_Shdr shdr; + int i; + int ret = DWARF_E_NONE; + + /* Look for sections which relocate the debug sections. */ + while ((scn = elf_nextscn(dbg->dbg_elf, scn)) != NULL) { + if (gelf_getshdr(scn, &shdr) == NULL) { + DWARF_SET_ELF_ERROR(error, elf_errno()); + return DWARF_E_ELF; + } + + if (shdr.sh_type != SHT_RELA || shdr.sh_size == 0) + continue; + + for (i = 0; i < DWARF_DEBUG_SNAMES; i++) { + if (dbg->dbg_s[i].s_shnum == shdr.sh_info && + dbg->dbg_s[DWARF_symtab].s_shnum == shdr.sh_link) { + Elf_Data *rd; + + /* Get the relocation data. */ + if ((rd = elf_getdata(scn, NULL)) == NULL) { + DWARF_SET_ELF_ERROR(error, elf_errno()); + return DWARF_E_ELF; + } + + /* Apply the relocations. */ + dwarf_apply_relocations(dbg, rd, i); + break; + } + } + } + + return ret; +} + +static int +dwarf_init_attr(Dwarf_Debug dbg, Elf_Data **dp, uint64_t *offsetp, + Dwarf_CU cu, Dwarf_Die die, Dwarf_Attribute at, uint64_t form, + Dwarf_Error *error) +{ + int ret = DWARF_E_NONE; + struct _Dwarf_AttrValue avref; + + memset(&avref, 0, sizeof(avref)); + avref.av_attrib = at->at_attrib; + avref.av_form = at->at_form; + + switch (form) { + case DW_FORM_addr: + avref.u[0].u64 = dwarf_read(dp, offsetp, cu->cu_pointer_size); + break; + case DW_FORM_block: + avref.u[0].u64 = dwarf_read_uleb128(dp, offsetp); + avref.u[1].u8p = dwarf_read_block(dp, offsetp, avref.u[0].u64); + break; + case DW_FORM_block1: + avref.u[0].u64 = dwarf_read(dp, offsetp, 1); + avref.u[1].u8p = dwarf_read_block(dp, offsetp, avref.u[0].u64); + break; + case DW_FORM_block2: + avref.u[0].u64 = dwarf_read(dp, offsetp, 2); + avref.u[1].u8p = dwarf_read_block(dp, offsetp, avref.u[0].u64); + break; + case DW_FORM_block4: + avref.u[0].u64 = dwarf_read(dp, offsetp, 4); + avref.u[1].u8p = dwarf_read_block(dp, offsetp, avref.u[0].u64); + break; + case DW_FORM_data1: + case DW_FORM_flag: + case DW_FORM_ref1: + avref.u[0].u64 = dwarf_read(dp, offsetp, 1); + break; + case DW_FORM_data2: + case DW_FORM_ref2: + avref.u[0].u64 = dwarf_read(dp, offsetp, 2); + break; + case DW_FORM_data4: + case DW_FORM_ref4: + avref.u[0].u64 = dwarf_read(dp, offsetp, 4); + break; + case DW_FORM_data8: + case DW_FORM_ref8: + avref.u[0].u64 = dwarf_read(dp, offsetp, 8); + break; + case DW_FORM_indirect: + form = dwarf_read_uleb128(dp, offsetp); + return dwarf_init_attr(dbg, dp, offsetp, cu, die, at, form, error); + case DW_FORM_ref_addr: + if (cu->cu_version == 2) + avref.u[0].u64 = dwarf_read(dp, offsetp, cu->cu_pointer_size); + else if (cu->cu_version == 3) + avref.u[0].u64 = dwarf_read(dp, offsetp, dbg->dbg_offsize); + break; + case DW_FORM_ref_udata: + case DW_FORM_udata: + avref.u[0].u64 = dwarf_read_uleb128(dp, offsetp); + break; + case DW_FORM_sdata: + avref.u[0].s64 = dwarf_read_sleb128(dp, offsetp); + break; + case DW_FORM_string: + avref.u[0].s = dwarf_read_string(dp, offsetp); + break; + case DW_FORM_strp: + avref.u[0].u64 = dwarf_read(dp, offsetp, dbg->dbg_offsize); + avref.u[1].s = elf_strptr(dbg->dbg_elf, + dbg->dbg_s[DWARF_debug_str].s_shnum, avref.u[0].u64); + break; + default: + DWARF_SET_ERROR(error, DWARF_E_NOT_IMPLEMENTED); + ret = DWARF_E_NOT_IMPLEMENTED; + break; + } + + if (ret == DWARF_E_NONE) + ret = dwarf_attrval_add(die, &avref, NULL, error); + + return ret; +} + +static int +dwarf_init_abbrev(Dwarf_Debug dbg, Dwarf_CU cu, Dwarf_Error *error) +{ + Dwarf_Abbrev a; + Elf_Data *d; + int ret = DWARF_E_NONE; + uint64_t attr; + uint64_t entry; + uint64_t form; + uint64_t offset; + uint64_t tag; + u_int8_t children; + + d = dbg->dbg_s[DWARF_debug_abbrev].s_data; + + offset = cu->cu_abbrev_offset; + + while (offset < d->d_size) { + + entry = dwarf_read_uleb128(&d, &offset); + + /* Check if this is the end of the data: */ + if (entry == 0) + break; + + tag = dwarf_read_uleb128(&d, &offset); + + children = dwarf_read(&d, &offset, 1); + + if ((ret = dwarf_abbrev_add(cu, entry, tag, children, &a, error)) != DWARF_E_NONE) + break; + + do { + attr = dwarf_read_uleb128(&d, &offset); + form = dwarf_read_uleb128(&d, &offset); + + if (attr != 0) + if ((ret = dwarf_attr_add(a, attr, form, NULL, error)) != DWARF_E_NONE) + return ret; + } while (attr != 0); + } + + return ret; +} + +static int +dwarf_init_info(Dwarf_Debug dbg, Dwarf_Error *error) +{ + Dwarf_CU cu; + Elf_Data *d = NULL; + Elf_Scn *scn; + int i; + int level = 0; + int relocated = 0; + int ret = DWARF_E_NONE; + uint64_t length; + uint64_t next_offset; + uint64_t offset = 0; + + scn = dbg->dbg_s[DWARF_debug_info].s_scn; + + d = dbg->dbg_s[DWARF_debug_info].s_data; + + while (offset < d->d_size) { + /* Allocate memory for the first compilation unit. */ + if ((cu = calloc(sizeof(struct _Dwarf_CU), 1)) == NULL) { + DWARF_SET_ERROR(error, DWARF_E_MEMORY); + return DWARF_E_MEMORY; + } + + /* Save the offet to this compilation unit: */ + cu->cu_offset = offset; + + length = dwarf_read(&d, &offset, 4); + if (length == 0xffffffff) { + length = dwarf_read(&d, &offset, 8); + dbg->dbg_offsize = 8; + } else + dbg->dbg_offsize = 4; + + /* + * Check if there is enough ELF data for this CU. + * This assumes that libelf gives us the entire + * section in one Elf_Data object. + */ + if (length > d->d_size - offset) { + free(cu); + DWARF_SET_ERROR(error, DWARF_E_INVALID_CU); + return DWARF_E_INVALID_CU; + } + + /* Relocate the DWARF sections if necessary: */ + if (!relocated) { + if ((ret = dwarf_relocate(dbg, error)) != DWARF_E_NONE) + return ret; + relocated = 1; + } + + /* Compute the offset to the next compilation unit: */ + next_offset = offset + length; + + /* Initialise the compilation unit. */ + cu->cu_length = length; + cu->cu_header_length = (dbg->dbg_offsize == 4) ? 4 : 12; + cu->cu_version = dwarf_read(&d, &offset, 2); + cu->cu_abbrev_offset = dwarf_read(&d, &offset, dbg->dbg_offsize); + cu->cu_pointer_size = dwarf_read(&d, &offset, 1); + cu->cu_next_offset = next_offset; + + /* Initialise the list of abbrevs. */ + STAILQ_INIT(&cu->cu_abbrev); + + /* Initialise the list of dies. */ + STAILQ_INIT(&cu->cu_die); + + /* Initialise the hash table of dies. */ + for (i = 0; i < DWARF_DIE_HASH_SIZE; i++) + STAILQ_INIT(&cu->cu_die_hash[i]); + + /* Add the compilation unit to the list. */ + STAILQ_INSERT_TAIL(&dbg->dbg_cu, cu, cu_next); + + if (cu->cu_version != 2 && cu->cu_version != 3) { + DWARF_SET_ERROR(error, DWARF_E_CU_VERSION); + ret = DWARF_E_CU_VERSION; + break; + } + + /* Parse the .debug_abbrev info for this CU: */ + if ((ret = dwarf_init_abbrev(dbg, cu, error)) != DWARF_E_NONE) + break; + + level = 0; + + while (offset < next_offset && offset < d->d_size) { + Dwarf_Abbrev a; + Dwarf_Attribute at; + Dwarf_Die die; + uint64_t abnum; + uint64_t die_offset = offset;; + + abnum = dwarf_read_uleb128(&d, &offset); + + if (abnum == 0) { + level--; + continue; + } + + if ((a = dwarf_abbrev_find(cu, abnum)) == NULL) { + DWARF_SET_ERROR(error, DWARF_E_MISSING_ABBREV); + return DWARF_E_MISSING_ABBREV; + } + + if ((ret = dwarf_die_add(cu, level, die_offset, + abnum, a, &die, error)) != DWARF_E_NONE) + return ret; + + STAILQ_FOREACH(at, &a->a_attrib, at_next) { + if ((ret = dwarf_init_attr(dbg, &d, &offset, + cu, die, at, at->at_form, error)) != DWARF_E_NONE) + return ret; + } + + if (a->a_children == DW_CHILDREN_yes) + level++; + } + + offset = next_offset; + } + + return ret; +} + +static int +dwarf_elf_read(Dwarf_Debug dbg, Dwarf_Error *error) +{ + GElf_Shdr shdr; + Elf_Scn *scn = NULL; + char *sname; + int i; + int ret = DWARF_E_NONE; + + /* Get a copy of the ELF header. */ + if (gelf_getehdr(dbg->dbg_elf, &dbg->dbg_ehdr) == NULL) { + DWARF_SET_ELF_ERROR(error, elf_errno()); + return DWARF_E_ELF; + } + + /* Check the ELF data format: */ + switch (dbg->dbg_ehdr.e_ident[EI_DATA]) { + case ELFDATA2MSB: + dwarf_read = dwarf_read_msb; + dwarf_write = dwarf_write_msb; + break; + + case ELFDATA2LSB: + case ELFDATANONE: + default: + dwarf_read = dwarf_read_lsb; + dwarf_write = dwarf_write_lsb; + break; + } + + /* Get the section index to the string table. */ + if (elf_getshstrndx(dbg->dbg_elf, &dbg->dbg_stnum) == 0) { + DWARF_SET_ELF_ERROR(error, elf_errno()); + return DWARF_E_ELF; + } + + /* Look for the debug sections. */ + while ((scn = elf_nextscn(dbg->dbg_elf, scn)) != NULL) { + /* Get a copy of the section header: */ + if (gelf_getshdr(scn, &shdr) == NULL) { + DWARF_SET_ELF_ERROR(error, elf_errno()); + return DWARF_E_ELF; + } + + /* Get a pointer to the section name: */ + if ((sname = elf_strptr(dbg->dbg_elf, dbg->dbg_stnum, shdr.sh_name)) == NULL) { + DWARF_SET_ELF_ERROR(error, elf_errno()); + return DWARF_E_ELF; + } + + /* + * Look up the section name to check if it's + * one we need for DWARF. + */ + for (i = 0; i < DWARF_DEBUG_SNAMES; i++) { + if (strcmp(sname, debug_snames[i]) == 0) { + dbg->dbg_s[i].s_sname = sname; + dbg->dbg_s[i].s_shnum = elf_ndxscn(scn); + dbg->dbg_s[i].s_scn = scn; + memcpy(&dbg->dbg_s[i].s_shdr, &shdr, sizeof(shdr)); + if ((dbg->dbg_s[i].s_data = elf_getdata(scn, NULL)) == NULL) { + DWARF_SET_ELF_ERROR(error, elf_errno()); + return DWARF_E_ELF; + } + break; + } + } + } + + /* Check if any of the required sections are missing: */ + if (dbg->dbg_s[DWARF_debug_abbrev].s_scn == NULL || + dbg->dbg_s[DWARF_debug_info].s_scn == NULL) { + /* Missing debug information. */ + DWARF_SET_ERROR(error, DWARF_E_DEBUG_INFO); + return DWARF_E_DEBUG_INFO; + } + + /* Initialise the compilation-units: */ + ret = dwarf_init_info(dbg, error); + + return ret; +} + +int +dwarf_elf_init(Elf *elf, int mode, Dwarf_Debug *ret_dbg, Dwarf_Error *error) +{ + Dwarf_Debug dbg; + int ret = DWARF_E_NONE; + + if (error == NULL) + /* Can only return a generic error. */ + return DWARF_E_ERROR; + + if (elf == NULL || ret_dbg == NULL) { + DWARF_SET_ERROR(error, DWARF_E_ARGUMENT); + ret = DWARF_E_ARGUMENT; + } else if ((dbg = calloc(sizeof(struct _Dwarf_Debug), 1)) == NULL) { + DWARF_SET_ERROR(error, DWARF_E_MEMORY); + ret = DWARF_E_MEMORY; + } else { + dbg->dbg_elf = elf; + dbg->dbg_elf_close = 0; + dbg->dbg_mode = mode; + + STAILQ_INIT(&dbg->dbg_cu); + + *ret_dbg = dbg; + + /* Read the ELF sections. */ + ret = dwarf_elf_read(dbg, error); + } + + return ret; +} + +int +dwarf_init(int fd, int mode, Dwarf_Debug *ret_dbg, Dwarf_Error *error) +{ + Dwarf_Error lerror; + Elf *elf; + Elf_Cmd c; + int ret; + + if (error == NULL) + /* Can only return a generic error. */ + return DWARF_E_ERROR; + + if (fd < 0 || ret_dbg == NULL) { + DWARF_SET_ERROR(error, DWARF_E_ARGUMENT); + return DWARF_E_ERROR; + } + + /* Translate the DWARF mode to ELF mode. */ + switch (mode) { + default: + case DW_DLC_READ: + c = ELF_C_READ; + break; + } + + if (elf_version(EV_CURRENT) == EV_NONE) { + DWARF_SET_ELF_ERROR(error, elf_errno()); + return DWARF_E_ERROR; + } + + if ((elf = elf_begin(fd, c, NULL)) == NULL) { + DWARF_SET_ELF_ERROR(error, elf_errno()); + return DWARF_E_ERROR; + } + + ret = dwarf_elf_init(elf, mode, ret_dbg, error); + + if (*ret_dbg != NULL) + /* Remember to close the ELF file. */ + (*ret_dbg)->dbg_elf_close = 1; + + if (ret != DWARF_E_NONE) { + if (*ret_dbg != NULL) { + dwarf_finish(ret_dbg, &lerror); + } else + elf_end(elf); + } + + return ret; +} diff --git a/lib/libdwarf/dwarf_loc.c b/lib/libdwarf/dwarf_loc.c new file mode 100644 index 0000000..6012142 --- /dev/null +++ b/lib/libdwarf/dwarf_loc.c @@ -0,0 +1,613 @@ +/*- + * Copyright (c) 2007 John Birrell (jb@freebsd.org) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <stdlib.h> +#include "_libdwarf.h" + +static int64_t +dwarf_decode_sleb128(uint8_t **dp) +{ + int64_t ret = 0; + uint8_t b; + int shift = 0; + + uint8_t *src = *dp; + + do { + b = *src++; + + ret |= ((b & 0x7f) << shift); + + shift += 7; + } while ((b & 0x80) != 0); + + if (shift < 32 && (b & 0x40) != 0) + ret |= (-1 << shift); + + *dp = src; + + return ret; +} + +static uint64_t +dwarf_decode_uleb128(uint8_t **dp) +{ + uint64_t ret = 0; + uint8_t b; + int shift = 0; + + uint8_t *src = *dp; + + do { + b = *src++; + + ret |= ((b & 0x7f) << shift); + + shift += 7; + } while ((b & 0x80) != 0); + + *dp = src; + + return ret; +} + +/* + * Given an array of bytes of length 'len' representing a + * DWARF expression, compute the number of operations based + * on there being one byte describing the operation and + * zero or more bytes of operands as defined in the standard + * for each operation type. + */ +int +dwarf_op_num(uint8_t pointer_size, uint8_t *p, int len) +{ + int count = 0; + int64_t sval; + uint64_t uval; + uint8_t *last = p + len; + + /* + * Process each byte. If an error occurs, then the + * count will be set to -1. + */ + while (p < last && count >= 0) { + count++; + + switch (*p++) { + /* Operations with no operands. */ + case DW_OP_deref: + case DW_OP_reg0: + case DW_OP_reg1: + case DW_OP_reg2: + case DW_OP_reg3: + case DW_OP_reg4: + case DW_OP_reg5: + case DW_OP_reg6: + case DW_OP_reg7: + case DW_OP_reg8: + case DW_OP_reg9: + case DW_OP_reg10: + case DW_OP_reg11: + case DW_OP_reg12: + case DW_OP_reg13: + case DW_OP_reg14: + case DW_OP_reg15: + case DW_OP_reg16: + case DW_OP_reg17: + case DW_OP_reg18: + case DW_OP_reg19: + case DW_OP_reg20: + case DW_OP_reg21: + case DW_OP_reg22: + case DW_OP_reg23: + case DW_OP_reg24: + case DW_OP_reg25: + case DW_OP_reg26: + case DW_OP_reg27: + case DW_OP_reg28: + case DW_OP_reg29: + case DW_OP_reg30: + case DW_OP_reg31: + + case DW_OP_lit0: + case DW_OP_lit1: + case DW_OP_lit2: + case DW_OP_lit3: + case DW_OP_lit4: + case DW_OP_lit5: + case DW_OP_lit6: + case DW_OP_lit7: + case DW_OP_lit8: + case DW_OP_lit9: + case DW_OP_lit10: + case DW_OP_lit11: + case DW_OP_lit12: + case DW_OP_lit13: + case DW_OP_lit14: + case DW_OP_lit15: + case DW_OP_lit16: + case DW_OP_lit17: + case DW_OP_lit18: + case DW_OP_lit19: + case DW_OP_lit20: + case DW_OP_lit21: + case DW_OP_lit22: + case DW_OP_lit23: + case DW_OP_lit24: + case DW_OP_lit25: + case DW_OP_lit26: + case DW_OP_lit27: + case DW_OP_lit28: + case DW_OP_lit29: + case DW_OP_lit30: + case DW_OP_lit31: + + case DW_OP_dup: + case DW_OP_drop: + + case DW_OP_over: + + case DW_OP_swap: + case DW_OP_rot: + case DW_OP_xderef: + + case DW_OP_abs: + case DW_OP_and: + case DW_OP_div: + case DW_OP_minus: + case DW_OP_mod: + case DW_OP_mul: + case DW_OP_neg: + case DW_OP_not: + case DW_OP_or: + case DW_OP_plus: + + case DW_OP_shl: + case DW_OP_shr: + case DW_OP_shra: + case DW_OP_xor: + + case DW_OP_eq: + case DW_OP_ge: + case DW_OP_gt: + case DW_OP_le: + case DW_OP_lt: + case DW_OP_ne: + + case DW_OP_nop: + break; + + /* Operations with 1-byte operands. */ + case DW_OP_const1u: + case DW_OP_const1s: + case DW_OP_pick: + case DW_OP_deref_size: + case DW_OP_xderef_size: + p++; + break; + + /* Operations with 2-byte operands. */ + case DW_OP_const2u: + case DW_OP_const2s: + case DW_OP_bra: + case DW_OP_skip: + p += 2; + break; + + /* Operations with 4-byte operands. */ + case DW_OP_const4u: + case DW_OP_const4s: + p += 4; + break; + + /* Operations with 8-byte operands. */ + case DW_OP_const8u: + case DW_OP_const8s: + p += 8; + break; + + /* Operations with an unsigned LEB128 operand. */ + case DW_OP_constu: + case DW_OP_plus_uconst: + case DW_OP_regx: + case DW_OP_piece: + uval = dwarf_decode_sleb128(&p); + break; + + /* Operations with a signed LEB128 operand. */ + case DW_OP_consts: + case DW_OP_breg0: + case DW_OP_breg1: + case DW_OP_breg2: + case DW_OP_breg3: + case DW_OP_breg4: + case DW_OP_breg5: + case DW_OP_breg6: + case DW_OP_breg7: + case DW_OP_breg8: + case DW_OP_breg9: + case DW_OP_breg10: + case DW_OP_breg11: + case DW_OP_breg12: + case DW_OP_breg13: + case DW_OP_breg14: + case DW_OP_breg15: + case DW_OP_breg16: + case DW_OP_breg17: + case DW_OP_breg18: + case DW_OP_breg19: + case DW_OP_breg20: + case DW_OP_breg21: + case DW_OP_breg22: + case DW_OP_breg23: + case DW_OP_breg24: + case DW_OP_breg25: + case DW_OP_breg26: + case DW_OP_breg27: + case DW_OP_breg28: + case DW_OP_breg29: + case DW_OP_breg30: + case DW_OP_breg31: + case DW_OP_fbreg: + sval = dwarf_decode_sleb128(&p); + break; + + /* + * Operations with an unsigned LEB128 operand + * followed by a signed LEB128 operand. + */ + case DW_OP_bregx: + uval = dwarf_decode_uleb128(&p); + sval = dwarf_decode_sleb128(&p); + break; + + /* Target address size operand. */ + case DW_OP_addr: + p += pointer_size; + break; + + /* All other operations cause an error. */ + default: + count = -1; + break; + } + } + + return count; +} + +static int +dwarf_loc_fill(Dwarf_Locdesc *lbuf, uint8_t pointer_size, uint8_t *p, int len) +{ + int count = 0; + int ret = DWARF_E_NONE; + uint64_t operand1; + uint64_t operand2; + uint8_t *last = p + len; + + /* + * Process each byte. If an error occurs, then the + * count will be set to -1. + */ + while (p < last && ret == DWARF_E_NONE) { + operand1 = 0; + operand2 = 0; + + lbuf->ld_s[count].lr_atom = *p; + + switch (*p++) { + /* Operations with no operands. */ + case DW_OP_deref: + case DW_OP_reg0: + case DW_OP_reg1: + case DW_OP_reg2: + case DW_OP_reg3: + case DW_OP_reg4: + case DW_OP_reg5: + case DW_OP_reg6: + case DW_OP_reg7: + case DW_OP_reg8: + case DW_OP_reg9: + case DW_OP_reg10: + case DW_OP_reg11: + case DW_OP_reg12: + case DW_OP_reg13: + case DW_OP_reg14: + case DW_OP_reg15: + case DW_OP_reg16: + case DW_OP_reg17: + case DW_OP_reg18: + case DW_OP_reg19: + case DW_OP_reg20: + case DW_OP_reg21: + case DW_OP_reg22: + case DW_OP_reg23: + case DW_OP_reg24: + case DW_OP_reg25: + case DW_OP_reg26: + case DW_OP_reg27: + case DW_OP_reg28: + case DW_OP_reg29: + case DW_OP_reg30: + case DW_OP_reg31: + + case DW_OP_lit0: + case DW_OP_lit1: + case DW_OP_lit2: + case DW_OP_lit3: + case DW_OP_lit4: + case DW_OP_lit5: + case DW_OP_lit6: + case DW_OP_lit7: + case DW_OP_lit8: + case DW_OP_lit9: + case DW_OP_lit10: + case DW_OP_lit11: + case DW_OP_lit12: + case DW_OP_lit13: + case DW_OP_lit14: + case DW_OP_lit15: + case DW_OP_lit16: + case DW_OP_lit17: + case DW_OP_lit18: + case DW_OP_lit19: + case DW_OP_lit20: + case DW_OP_lit21: + case DW_OP_lit22: + case DW_OP_lit23: + case DW_OP_lit24: + case DW_OP_lit25: + case DW_OP_lit26: + case DW_OP_lit27: + case DW_OP_lit28: + case DW_OP_lit29: + case DW_OP_lit30: + case DW_OP_lit31: + + case DW_OP_dup: + case DW_OP_drop: + + case DW_OP_over: + + case DW_OP_swap: + case DW_OP_rot: + case DW_OP_xderef: + + case DW_OP_abs: + case DW_OP_and: + case DW_OP_div: + case DW_OP_minus: + case DW_OP_mod: + case DW_OP_mul: + case DW_OP_neg: + case DW_OP_not: + case DW_OP_or: + case DW_OP_plus: + + case DW_OP_shl: + case DW_OP_shr: + case DW_OP_shra: + case DW_OP_xor: + + case DW_OP_eq: + case DW_OP_ge: + case DW_OP_gt: + case DW_OP_le: + case DW_OP_lt: + case DW_OP_ne: + + case DW_OP_nop: + break; + + /* Operations with 1-byte operands. */ + case DW_OP_const1u: + case DW_OP_const1s: + case DW_OP_pick: + case DW_OP_deref_size: + case DW_OP_xderef_size: + operand1 = *p++; + break; + + /* Operations with 2-byte operands. */ + case DW_OP_const2u: + case DW_OP_const2s: + case DW_OP_bra: + case DW_OP_skip: + p += 2; + break; + + /* Operations with 4-byte operands. */ + case DW_OP_const4u: + case DW_OP_const4s: + p += 4; + break; + + /* Operations with 8-byte operands. */ + case DW_OP_const8u: + case DW_OP_const8s: + p += 8; + break; + + /* Operations with an unsigned LEB128 operand. */ + case DW_OP_constu: + case DW_OP_plus_uconst: + case DW_OP_regx: + case DW_OP_piece: + operand1 = dwarf_decode_sleb128(&p); + break; + + /* Operations with a signed LEB128 operand. */ + case DW_OP_consts: + case DW_OP_breg0: + case DW_OP_breg1: + case DW_OP_breg2: + case DW_OP_breg3: + case DW_OP_breg4: + case DW_OP_breg5: + case DW_OP_breg6: + case DW_OP_breg7: + case DW_OP_breg8: + case DW_OP_breg9: + case DW_OP_breg10: + case DW_OP_breg11: + case DW_OP_breg12: + case DW_OP_breg13: + case DW_OP_breg14: + case DW_OP_breg15: + case DW_OP_breg16: + case DW_OP_breg17: + case DW_OP_breg18: + case DW_OP_breg19: + case DW_OP_breg20: + case DW_OP_breg21: + case DW_OP_breg22: + case DW_OP_breg23: + case DW_OP_breg24: + case DW_OP_breg25: + case DW_OP_breg26: + case DW_OP_breg27: + case DW_OP_breg28: + case DW_OP_breg29: + case DW_OP_breg30: + case DW_OP_breg31: + case DW_OP_fbreg: + operand1 = dwarf_decode_sleb128(&p); + break; + + /* + * Operations with an unsigned LEB128 operand + * followed by a signed LEB128 operand. + */ + case DW_OP_bregx: + operand1 = dwarf_decode_uleb128(&p); + operand2 = dwarf_decode_sleb128(&p); + break; + + /* Target address size operand. */ + case DW_OP_addr: + p += pointer_size; + break; + + /* All other operations cause an error. */ + default: + break; + } + + lbuf->ld_s[count].lr_number = operand1; + lbuf->ld_s[count].lr_number2 = operand2; + + count++; + } + + return ret; +} + +int +dwarf_locdesc(Dwarf_Die die, uint64_t attr, Dwarf_Locdesc **llbuf, Dwarf_Signed *lenp, Dwarf_Error *err) +{ + Dwarf_AttrValue av; + Dwarf_Locdesc *lbuf; + int num; + int ret = DWARF_E_NONE; + + if (err == NULL) + return DWARF_E_ERROR; + + if (die == NULL || llbuf == NULL || lenp == NULL) { + DWARF_SET_ERROR(err, DWARF_E_ARGUMENT); + return DWARF_E_ARGUMENT; + } + + if ((av = dwarf_attrval_find(die, attr)) == NULL) { + DWARF_SET_ERROR(err, DWARF_E_NO_ENTRY); + ret = DWARF_E_NO_ENTRY; + } else if ((lbuf = calloc(sizeof(Dwarf_Locdesc), 1)) == NULL) { + DWARF_SET_ERROR(err, DWARF_E_MEMORY); + ret = DWARF_E_MEMORY; + } else { + *lenp = 0; + switch (av->av_form) { + case DW_FORM_block: + case DW_FORM_block1: + case DW_FORM_block2: + case DW_FORM_block4: + /* Compute the number of locations: */ + if ((num = dwarf_op_num(die->die_cu->cu_pointer_size, + av->u[1].u8p, av->u[0].u64)) < 0) { + DWARF_SET_ERROR(err, DWARF_E_INVALID_EXPR); + ret = DWARF_E_INVALID_EXPR; + + /* Allocate an array of location structures. */ + } else if ((lbuf->ld_s = + calloc(sizeof(Dwarf_Loc), num)) == NULL) { + DWARF_SET_ERROR(err, DWARF_E_MEMORY); + ret = DWARF_E_MEMORY; + + /* Fill the array of location structures. */ + } else if ((ret = dwarf_loc_fill(lbuf, + die->die_cu->cu_pointer_size, + av->u[1].u8p, av->u[0].u64)) != DWARF_E_NONE) { + free(lbuf->ld_s); + } else + /* Only one descriptor is returned. */ + *lenp = 1; + break; + default: + printf("%s(%d): form %s not handled\n",__func__, + __LINE__,get_form_desc(av->av_form)); + DWARF_SET_ERROR(err, DWARF_E_NOT_IMPLEMENTED); + ret = DWARF_E_ERROR; + } + + if (ret == DWARF_E_NONE) { + *llbuf = lbuf; + } else + free(lbuf); + } + + return ret; +} + +int +dwarf_locdesc_free(Dwarf_Locdesc *lbuf, Dwarf_Error *err) +{ + if (err == NULL) + return DWARF_E_ERROR; + + if (lbuf == NULL) { + DWARF_SET_ERROR(err, DWARF_E_ARGUMENT); + return DWARF_E_ARGUMENT; + } + + if (lbuf->ld_s != NULL) + free(lbuf->ld_s); + + free(lbuf); + + return DWARF_E_NONE; +} diff --git a/lib/libdwarf/libdwarf.h b/lib/libdwarf/libdwarf.h new file mode 100644 index 0000000..6d4930d --- /dev/null +++ b/lib/libdwarf/libdwarf.h @@ -0,0 +1,162 @@ +/*- + * Copyright (c) 2007 John Birrell (jb@freebsd.org) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _LIBDWARF_H_ +#define _LIBDWARF_H_ + +#include <libelf.h> + +typedef int Dwarf_Bool; +typedef off_t Dwarf_Off; +typedef uint64_t Dwarf_Unsigned; +typedef uint16_t Dwarf_Half; +typedef uint8_t Dwarf_Small; +typedef int64_t Dwarf_Signed; +typedef uint64_t Dwarf_Addr; +typedef void *Dwarf_Ptr; + +/* Forward definitions. */ +typedef struct _Dwarf_Abbrev *Dwarf_Abbrev; +typedef struct _Dwarf_Arange *Dwarf_Arange; +typedef struct _Dwarf_Attribute *Dwarf_Attribute; +typedef struct _Dwarf_AttrValue *Dwarf_AttrValue; +typedef struct _Dwarf_CU *Dwarf_CU; +typedef struct _Dwarf_Cie *Dwarf_Cie; +typedef struct _Dwarf_Debug *Dwarf_Debug; +typedef struct _Dwarf_Die *Dwarf_Die; +typedef struct _Dwarf_Fde *Dwarf_Fde; +typedef struct _Dwarf_Func *Dwarf_Func; +typedef struct _Dwarf_Global *Dwarf_Global; +typedef struct _Dwarf_Line *Dwarf_Line; +typedef struct _Dwarf_Type *Dwarf_Type; +typedef struct _Dwarf_Var *Dwarf_Var; +typedef struct _Dwarf_Weak *Dwarf_Weak; + +typedef struct { + Dwarf_Small lr_atom; + Dwarf_Unsigned lr_number; + Dwarf_Unsigned lr_number2; + Dwarf_Unsigned lr_offset; +} Dwarf_Loc; + +typedef struct { + Dwarf_Addr ld_lopc; + Dwarf_Addr ld_hipc; + Dwarf_Half ld_cents; + Dwarf_Loc *ld_s; +} Dwarf_Locdesc; + +/* + * Error numbers which are specific to this implementation. + */ +enum { + DWARF_E_NONE, /* No error. */ + DWARF_E_ERROR, /* An error! */ + DWARF_E_NO_ENTRY, /* No entry. */ + DWARF_E_ARGUMENT, /* Invalid argument. */ + DWARF_E_DEBUG_INFO, /* Debug info NULL. */ + DWARF_E_MEMORY, /* Insufficient memory. */ + DWARF_E_ELF, /* ELF error. */ + DWARF_E_INVALID_CU, /* Invalid compilation unit data. */ + DWARF_E_CU_VERSION, /* Wrong CU version. */ + DWARF_E_MISSING_ABBREV, /* Abbrev not found. */ + DWARF_E_NOT_IMPLEMENTED, /* Not implemented. */ + DWARF_E_CU_CURRENT, /* No current compilation unit. */ + DWARF_E_BAD_FORM, /* Wrong form type for attribute value. */ + DWARF_E_INVALID_EXPR, /* Invalid DWARF expression. */ + DWARF_E_NUM /* Max error number. */ +}; + +typedef struct _Dwarf_Error { + int err_error; /* DWARF error. */ + int elf_error; /* ELF error. */ + const char *err_func; /* Function name where error occurred. */ + int err_line; /* Line number where error occurred. */ + char err_msg[1024]; /* Formatted error message. */ +} Dwarf_Error; + +/* + * Return values which have to be compatible with other + * implementations of libdwarf. + */ +#define DW_DLV_NO_ENTRY DWARF_E_NO_ENTRY +#define DW_DLV_OK DWARF_E_NONE +#define DW_DLE_DEBUG_INFO_NULL DWARF_E_DEBUG_INFO + +#define DW_DLC_READ 0 /* read only access */ + +/* Function prototype definitions. */ +__BEGIN_DECLS +Dwarf_Abbrev dwarf_abbrev_find(Dwarf_CU, uint64_t); +Dwarf_AttrValue dwarf_attrval_find(Dwarf_Die, Dwarf_Half); +Dwarf_Die dwarf_die_find(Dwarf_Die, Dwarf_Unsigned); +const char *dwarf_errmsg(Dwarf_Error *); +const char *get_sht_desc(uint32_t); +const char *get_attr_desc(uint32_t); +const char *get_form_desc(uint32_t); +const char *get_tag_desc(uint32_t); +int dwarf_abbrev_add(Dwarf_CU, uint64_t, uint64_t, uint8_t, Dwarf_Abbrev *, Dwarf_Error *); +int dwarf_attr(Dwarf_Die, Dwarf_Half, Dwarf_Attribute *, Dwarf_Error *); +int dwarf_attr_add(Dwarf_Abbrev, uint64_t, uint64_t, Dwarf_Attribute *, Dwarf_Error *); +int dwarf_attrval(Dwarf_Die, Dwarf_Half, Dwarf_AttrValue *, Dwarf_Error *); +int dwarf_attrval_add(Dwarf_Die, Dwarf_AttrValue, Dwarf_AttrValue *, Dwarf_Error *); +int dwarf_attrval_flag(Dwarf_Die, uint64_t, Dwarf_Bool *, Dwarf_Error *); +int dwarf_attrval_signed(Dwarf_Die, uint64_t, Dwarf_Signed *, Dwarf_Error *); +int dwarf_attrval_string(Dwarf_Die, uint64_t, const char **, Dwarf_Error *); +int dwarf_attrval_unsigned(Dwarf_Die, uint64_t, Dwarf_Unsigned *, Dwarf_Error *); +int dwarf_child(Dwarf_Die, Dwarf_Die *, Dwarf_Error *); +int dwarf_die_add(Dwarf_CU, int, uint64_t, uint64_t, Dwarf_Abbrev, Dwarf_Die *, Dwarf_Error *); +int dwarf_dieoffset(Dwarf_Die, Dwarf_Off *, Dwarf_Error *); +int dwarf_elf_init(Elf *, int, Dwarf_Debug *, Dwarf_Error *); +int dwarf_errno(Dwarf_Error *); +int dwarf_finish(Dwarf_Debug *, Dwarf_Error *); +int dwarf_locdesc(Dwarf_Die, uint64_t, Dwarf_Locdesc **, Dwarf_Signed *, Dwarf_Error *); +int dwarf_locdesc_free(Dwarf_Locdesc *, Dwarf_Error *); +int dwarf_init(int, int, Dwarf_Debug *, Dwarf_Error *); +int dwarf_next_cu_header(Dwarf_Debug, Dwarf_Unsigned *, Dwarf_Half *, + Dwarf_Unsigned *, Dwarf_Half *, Dwarf_Unsigned *, Dwarf_Error *); +int dwarf_op_num(uint8_t, uint8_t *, int); +int dwarf_siblingof(Dwarf_Debug, Dwarf_Die, Dwarf_Die *, Dwarf_Error *); +int dwarf_tag(Dwarf_Die, Dwarf_Half *, Dwarf_Error *); +int dwarf_whatform(Dwarf_Attribute, Dwarf_Half *, Dwarf_Error *); +void dwarf_dealloc(Dwarf_Debug, Dwarf_Ptr, Dwarf_Unsigned); +void dwarf_dump(Dwarf_Debug); +void dwarf_dump_abbrev(Dwarf_Debug); +void dwarf_dump_av(Dwarf_Die, Dwarf_AttrValue); +void dwarf_dump_dbgstr(Dwarf_Debug); +void dwarf_dump_die(Dwarf_Die); +void dwarf_dump_die_at_offset(Dwarf_Debug, Dwarf_Off); +void dwarf_dump_info(Dwarf_Debug); +void dwarf_dump_shstrtab(Dwarf_Debug); +void dwarf_dump_strtab(Dwarf_Debug); +void dwarf_dump_symtab(Dwarf_Debug); +void dwarf_dump_raw(Dwarf_Debug); +void dwarf_dump_tree(Dwarf_Debug); +__END_DECLS + +#endif /* !_LIBDWARF_H_ */ |