summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWez Furlong <wez@netevil.org>2011-04-03 16:00:01 -0400
committerWez Furlong <wez@netevil.org>2011-04-03 16:00:01 -0400
commite9f8c2cd7be8f75fb1d6d9bdb7f3f418d5068e04 (patch)
tree98ef134b0997b71bc30b176d2752dab7eb3b2c1c
parentee2b74dbc88c21f3e6c53d6d4f09a69b271755e4 (diff)
downloadctf-e9f8c2cd7be8f75fb1d6d9bdb7f3f418d5068e04.tar.gz
pull in the FreeBSD libdwarf, so that we can compile without an external
dependency.
-rw-r--r--Makefile.am19
-rw-r--r--common/list.c1
-rw-r--r--common/utils.c5
-rw-r--r--configure.ac7
-rw-r--r--libctf/ctf_impl.h21
-rw-r--r--libdwarf/_libdwarf.h164
-rw-r--r--libdwarf/dwarf.h478
-rw-r--r--libdwarf/dwarf_abbrev.c70
-rw-r--r--libdwarf/dwarf_attr.c90
-rw-r--r--libdwarf/dwarf_attrval.c267
-rw-r--r--libdwarf/dwarf_cu.c68
-rw-r--r--libdwarf/dwarf_dealloc.c41
-rw-r--r--libdwarf/dwarf_die.c190
-rw-r--r--libdwarf/dwarf_dump.c892
-rw-r--r--libdwarf/dwarf_errmsg.c75
-rw-r--r--libdwarf/dwarf_errno.c38
-rw-r--r--libdwarf/dwarf_finish.c97
-rw-r--r--libdwarf/dwarf_form.c47
-rw-r--r--libdwarf/dwarf_init.c746
-rw-r--r--libdwarf/dwarf_loc.c612
-rw-r--r--libdwarf/libdwarf.h162
-rw-r--r--libdwarf/queue.h636
-rw-r--r--pctf/ctf_api.h1
23 files changed, 4711 insertions, 16 deletions
diff --git a/Makefile.am b/Makefile.am
index e3c0bdd..f7f7a50 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2,7 +2,7 @@ AUTOMAKE_OPTIONS = subdir-objects
bin_PROGRAMS = ctfconvert ctfmerge ctfdump
CFLAGS += -I$(top_srcdir)
lib_LTLIBRARIES = libpctf.la
-noinst_LTLIBRARIES = libpctfcommon.la libcvt.la
+noinst_LTLIBRARIES = libpctfcommon.la libcvt.la libdwarf.la
man1_MANS = man/ctfconvert.1 man/ctfmerge.1 man/ctfdump.1
include_HEADERS = pctf/libctf.h pctf/ctf_api.h pctf/ctf.h
@@ -49,8 +49,23 @@ libcvt_la_SOURCES = \
cvt/traverse.c \
cvt/util.c
+libdwarf_la_SOURCES = \
+ libdwarf/dwarf_abbrev.c \
+ libdwarf/dwarf_attr.c \
+ libdwarf/dwarf_attrval.c \
+ libdwarf/dwarf_cu.c \
+ libdwarf/dwarf_dealloc.c \
+ libdwarf/dwarf_die.c \
+ libdwarf/dwarf_dump.c \
+ libdwarf/dwarf_errmsg.c \
+ libdwarf/dwarf_errno.c \
+ libdwarf/dwarf_finish.c \
+ libdwarf/dwarf_form.c \
+ libdwarf/dwarf_init.c \
+ libdwarf/dwarf_loc.c
+
ctfconvert_SOURCES = cvt/ctfconvert.c
-ctfconvert_LDADD = libcvt.la libpctfcommon.la libpctf.la -ldwarf
+ctfconvert_LDADD = libcvt.la libpctfcommon.la libpctf.la libdwarf.la
ctfmerge_SOURCES = cvt/ctfmerge.c
ctfmerge_LDADD = libcvt.la libpctfcommon.la libpctf.la
diff --git a/common/list.c b/common/list.c
index d5c796f..cc3b110 100644
--- a/common/list.c
+++ b/common/list.c
@@ -30,6 +30,7 @@
* Routines for manipulating linked lists
*/
+#include "libctf/ctf_impl.h"
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
diff --git a/common/utils.c b/common/utils.c
index 49dc25e..f3443aa 100644
--- a/common/utils.c
+++ b/common/utils.c
@@ -46,6 +46,11 @@ getpname(void)
p = getexecname();
#elif HAVE_GETPROGNAME
p = getprogname();
+#elif defined(__linux__)
+ {
+ extern char *program_invocation_short_name;
+ p = program_invocation_short_name;
+ }
#else
# error dont know how to find my executable name
#endif
diff --git a/configure.ac b/configure.ac
index 82ca2b1..0712796 100644
--- a/configure.ac
+++ b/configure.ac
@@ -23,12 +23,6 @@ getprogname \
AC_CHECK_LIB(z, uncompress)
AC_CHECK_LIB(elf, gelf_getshdr)
-AC_CHECK_LIB(dwarf, dwarf_elf_init, [
- AC_MSG_RESULT([you got dwarves])
-],[
- AC_ERROR([Need libdwarf for ctfconvert to operate])
-])
-
AC_CHECK_LIB(pthread, pthread_create)
AC_CHECK_HEADERS([ \
@@ -48,6 +42,7 @@ strings.h \
sys/elf.h \
sys/errno.h \
sys/mman.h \
+sys/param.h \
sys/stat.h \
sys/sysmacros.h \
unistd.h \
diff --git a/libctf/ctf_impl.h b/libctf/ctf_impl.h
index f0f0d55..d7f0075 100644
--- a/libctf/ctf_impl.h
+++ b/libctf/ctf_impl.h
@@ -41,7 +41,7 @@
#if HAVE_SYS_ERRNO_H
# include <sys/errno.h>
#endif
-#if HAVE_SYS_SYSMACROS_H
+#ifdef sun
# include <sys/sysmacros.h>
#else
# include "pctf/sysmacros.h"
@@ -93,19 +93,26 @@
#if HAVE_SYS_ELF_H
# include <sys/elf.h>
#endif
-#if HAVE_LIBDWARF_H
-# include <libdwarf.h>
-#endif
#if HAVE_LIBGEN_H
# include <libgen.h>
#endif
-#if HAVE_DWARF_H
-# include <dwarf.h>
-#endif
+#include "libdwarf/dwarf.h"
+#include "libdwarf/libdwarf.h"
#if HAVE_STDINT_H
# include <stdint.h>
#endif
#include <assert.h>
+#if HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+#include <signal.h>
+
+#ifndef NBBY
+# define NBBY 8
+#endif
+#ifndef __unused
+# define __unused
+#endif
#ifdef __cplusplus
extern "C" {
diff --git a/libdwarf/_libdwarf.h b/libdwarf/_libdwarf.h
new file mode 100644
index 0000000..0f55e49
--- /dev/null
+++ b/libdwarf/_libdwarf.h
@@ -0,0 +1,164 @@
+/*-
+ * 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: src/lib/libdwarf/_libdwarf.h,v 1.1.4.1.6.1 2010/12/21 17:09:25 kensmith Exp $
+ */
+
+#ifndef __LIBDWARF_H_
+#define __LIBDWARF_H_
+
+#include "libctf/ctf_impl.h"
+#include "libdwarf/queue.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/libdwarf/dwarf.h b/libdwarf/dwarf.h
new file mode 100644
index 0000000..40e1229
--- /dev/null
+++ b/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: src/lib/libdwarf/dwarf.h,v 1.1.4.1.6.1 2010/12/21 17:09:25 kensmith Exp $
+ */
+
+#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/libdwarf/dwarf_abbrev.c b/libdwarf/dwarf_abbrev.c
new file mode 100644
index 0000000..b3c863e
--- /dev/null
+++ b/libdwarf/dwarf_abbrev.c
@@ -0,0 +1,70 @@
+/*-
+ * 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: src/lib/libdwarf/dwarf_abbrev.c,v 1.1.4.1.6.1 2010/12/21 17:09:25 kensmith Exp $
+ */
+
+#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/libdwarf/dwarf_attr.c b/libdwarf/dwarf_attr.c
new file mode 100644
index 0000000..600af2d
--- /dev/null
+++ b/libdwarf/dwarf_attr.c
@@ -0,0 +1,90 @@
+/*-
+ * 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: src/lib/libdwarf/dwarf_attr.c,v 1.1.4.1.6.1 2010/12/21 17:09:25 kensmith Exp $
+ */
+
+#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/libdwarf/dwarf_attrval.c b/libdwarf/dwarf_attrval.c
new file mode 100644
index 0000000..a8689ae
--- /dev/null
+++ b/libdwarf/dwarf_attrval.c
@@ -0,0 +1,267 @@
+/*-
+ * 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: src/lib/libdwarf/dwarf_attrval.c,v 1.1.4.1.6.1 2010/12/21 17:09:25 kensmith Exp $
+ */
+
+#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/libdwarf/dwarf_cu.c b/libdwarf/dwarf_cu.c
new file mode 100644
index 0000000..04b9557
--- /dev/null
+++ b/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: src/lib/libdwarf/dwarf_cu.c,v 1.1.4.1.6.1 2010/12/21 17:09:25 kensmith Exp $
+ */
+
+#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/libdwarf/dwarf_dealloc.c b/libdwarf/dwarf_dealloc.c
new file mode 100644
index 0000000..0ccb7e7
--- /dev/null
+++ b/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: src/lib/libdwarf/dwarf_dealloc.c,v 1.1.4.1.6.1 2010/12/21 17:09:25 kensmith Exp $
+ */
+
+#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/libdwarf/dwarf_die.c b/libdwarf/dwarf_die.c
new file mode 100644
index 0000000..d0b4f62
--- /dev/null
+++ b/libdwarf/dwarf_die.c
@@ -0,0 +1,190 @@
+/*-
+ * 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: src/lib/libdwarf/dwarf_die.c,v 1.1.4.1.6.1 2010/12/21 17:09:25 kensmith Exp $
+ */
+
+#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/libdwarf/dwarf_dump.c b/libdwarf/dwarf_dump.c
new file mode 100644
index 0000000..a6683a2
--- /dev/null
+++ b/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: src/lib/libdwarf/dwarf_dump.c,v 1.1.4.1.6.1 2010/12/21 17:09:25 kensmith Exp $
+ */
+
+#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";
+#ifdef SHT_AMD64_UNWIND
+ case SHT_AMD64_UNWIND:
+ return "AMD64 unwind";
+#endif
+ 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/libdwarf/dwarf_errmsg.c b/libdwarf/dwarf_errmsg.c
new file mode 100644
index 0000000..29b7b34
--- /dev/null
+++ b/libdwarf/dwarf_errmsg.c
@@ -0,0 +1,75 @@
+/*-
+ * 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: src/lib/libdwarf/dwarf_errmsg.c,v 1.1.4.1.6.1 2010/12/21 17:09:25 kensmith Exp $
+ */
+
+#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/libdwarf/dwarf_errno.c b/libdwarf/dwarf_errno.c
new file mode 100644
index 0000000..e50c387
--- /dev/null
+++ b/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: src/lib/libdwarf/dwarf_errno.c,v 1.1.4.1.6.1 2010/12/21 17:09:25 kensmith Exp $
+ */
+
+#include "_libdwarf.h"
+
+int
+dwarf_errno(Dwarf_Error *err)
+{
+ if (err == NULL)
+ return -1;
+
+ return (err->err_error);
+}
diff --git a/libdwarf/dwarf_finish.c b/libdwarf/dwarf_finish.c
new file mode 100644
index 0000000..f3f8687
--- /dev/null
+++ b/libdwarf/dwarf_finish.c
@@ -0,0 +1,97 @@
+/*-
+ * 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: src/lib/libdwarf/dwarf_finish.c,v 1.1.4.1.6.1 2010/12/21 17:09:25 kensmith Exp $
+ */
+
+#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/libdwarf/dwarf_form.c b/libdwarf/dwarf_form.c
new file mode 100644
index 0000000..64b97b1
--- /dev/null
+++ b/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: src/lib/libdwarf/dwarf_form.c,v 1.1.4.1.6.1 2010/12/21 17:09:25 kensmith Exp $
+ */
+
+#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/libdwarf/dwarf_init.c b/libdwarf/dwarf_init.c
new file mode 100644
index 0000000..9128a76
--- /dev/null
+++ b/libdwarf/dwarf_init.c
@@ -0,0 +1,746 @@
+/*-
+ * 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: src/lib/libdwarf/dwarf_init.c,v 1.1.4.1.6.1 2010/12/21 17:09:25 kensmith Exp $
+ */
+
+#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/libdwarf/dwarf_loc.c b/libdwarf/dwarf_loc.c
new file mode 100644
index 0000000..19b9e77
--- /dev/null
+++ b/libdwarf/dwarf_loc.c
@@ -0,0 +1,612 @@
+/*-
+ * 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: src/lib/libdwarf/dwarf_loc.c,v 1.2.2.1.6.1 2010/12/21 17:09:25 kensmith Exp $
+ */
+
+#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_uleb128(&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_uleb128(&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/libdwarf/libdwarf.h b/libdwarf/libdwarf.h
new file mode 100644
index 0000000..d3b6905
--- /dev/null
+++ b/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: src/lib/libdwarf/libdwarf.h,v 1.1.4.1.6.1 2010/12/21 17:09:25 kensmith Exp $
+ */
+
+#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_ */
diff --git a/libdwarf/queue.h b/libdwarf/queue.h
new file mode 100644
index 0000000..1fdfea3
--- /dev/null
+++ b/libdwarf/queue.h
@@ -0,0 +1,636 @@
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. 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.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)queue.h 8.5 (Berkeley) 8/20/94
+ * $FreeBSD: src/sys/sys/queue.h,v 1.72.2.3.2.1 2010/12/21 17:09:25 kensmith Exp $
+ */
+
+#ifndef _SYS_QUEUE_H_
+#define _SYS_QUEUE_H_
+
+#include <sys/cdefs.h>
+
+/*
+ * This file defines four types of data structures: singly-linked lists,
+ * singly-linked tail queues, lists and tail queues.
+ *
+ * A singly-linked list is headed by a single forward pointer. The elements
+ * are singly linked for minimum space and pointer manipulation overhead at
+ * the expense of O(n) removal for arbitrary elements. New elements can be
+ * added to the list after an existing element or at the head of the list.
+ * Elements being removed from the head of the list should use the explicit
+ * macro for this purpose for optimum efficiency. A singly-linked list may
+ * only be traversed in the forward direction. Singly-linked lists are ideal
+ * for applications with large datasets and few or no removals or for
+ * implementing a LIFO queue.
+ *
+ * A singly-linked tail queue is headed by a pair of pointers, one to the
+ * head of the list and the other to the tail of the list. The elements are
+ * singly linked for minimum space and pointer manipulation overhead at the
+ * expense of O(n) removal for arbitrary elements. New elements can be added
+ * to the list after an existing element, at the head of the list, or at the
+ * end of the list. Elements being removed from the head of the tail queue
+ * should use the explicit macro for this purpose for optimum efficiency.
+ * A singly-linked tail queue may only be traversed in the forward direction.
+ * Singly-linked tail queues are ideal for applications with large datasets
+ * and few or no removals or for implementing a FIFO queue.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ *
+ *
+ * SLIST LIST STAILQ TAILQ
+ * _HEAD + + + +
+ * _HEAD_INITIALIZER + + + +
+ * _ENTRY + + + +
+ * _INIT + + + +
+ * _EMPTY + + + +
+ * _FIRST + + + +
+ * _NEXT + + + +
+ * _PREV - - - +
+ * _LAST - - + +
+ * _FOREACH + + + +
+ * _FOREACH_SAFE + + + +
+ * _FOREACH_REVERSE - - - +
+ * _FOREACH_REVERSE_SAFE - - - +
+ * _INSERT_HEAD + + + +
+ * _INSERT_BEFORE - + - +
+ * _INSERT_AFTER + + + +
+ * _INSERT_TAIL - - + +
+ * _CONCAT - - + +
+ * _REMOVE_AFTER + - + -
+ * _REMOVE_HEAD + - + -
+ * _REMOVE + + + +
+ *
+ */
+#ifdef QUEUE_MACRO_DEBUG
+/* Store the last 2 places the queue element or head was altered */
+struct qm_trace {
+ char * lastfile;
+ int lastline;
+ char * prevfile;
+ int prevline;
+};
+
+#define TRACEBUF struct qm_trace trace;
+#define TRASHIT(x) do {(x) = (void *)-1;} while (0)
+#define QMD_SAVELINK(name, link) void **name = (void *)&(link)
+
+#define QMD_TRACE_HEAD(head) do { \
+ (head)->trace.prevline = (head)->trace.lastline; \
+ (head)->trace.prevfile = (head)->trace.lastfile; \
+ (head)->trace.lastline = __LINE__; \
+ (head)->trace.lastfile = __FILE__; \
+} while (0)
+
+#define QMD_TRACE_ELEM(elem) do { \
+ (elem)->trace.prevline = (elem)->trace.lastline; \
+ (elem)->trace.prevfile = (elem)->trace.lastfile; \
+ (elem)->trace.lastline = __LINE__; \
+ (elem)->trace.lastfile = __FILE__; \
+} while (0)
+
+#else
+#define QMD_TRACE_ELEM(elem)
+#define QMD_TRACE_HEAD(head)
+#define QMD_SAVELINK(name, link)
+#define TRACEBUF
+#define TRASHIT(x)
+#endif /* QUEUE_MACRO_DEBUG */
+
+/*
+ * Singly-linked List declarations.
+ */
+#define SLIST_HEAD(name, type) \
+struct name { \
+ struct type *slh_first; /* first element */ \
+}
+
+#define SLIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define SLIST_ENTRY(type) \
+struct { \
+ struct type *sle_next; /* next element */ \
+}
+
+/*
+ * Singly-linked List functions.
+ */
+#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
+
+#define SLIST_FIRST(head) ((head)->slh_first)
+
+#define SLIST_FOREACH(var, head, field) \
+ for ((var) = SLIST_FIRST((head)); \
+ (var); \
+ (var) = SLIST_NEXT((var), field))
+
+#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = SLIST_FIRST((head)); \
+ (var) && ((tvar) = SLIST_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
+ for ((varp) = &SLIST_FIRST((head)); \
+ ((var) = *(varp)) != NULL; \
+ (varp) = &SLIST_NEXT((var), field))
+
+#define SLIST_INIT(head) do { \
+ SLIST_FIRST((head)) = NULL; \
+} while (0)
+
+#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
+ SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
+ SLIST_NEXT((slistelm), field) = (elm); \
+} while (0)
+
+#define SLIST_INSERT_HEAD(head, elm, field) do { \
+ SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
+ SLIST_FIRST((head)) = (elm); \
+} while (0)
+
+#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
+
+#define SLIST_REMOVE(head, elm, type, field) do { \
+ QMD_SAVELINK(oldnext, (elm)->field.sle_next); \
+ if (SLIST_FIRST((head)) == (elm)) { \
+ SLIST_REMOVE_HEAD((head), field); \
+ } \
+ else { \
+ struct type *curelm = SLIST_FIRST((head)); \
+ while (SLIST_NEXT(curelm, field) != (elm)) \
+ curelm = SLIST_NEXT(curelm, field); \
+ SLIST_REMOVE_AFTER(curelm, field); \
+ } \
+ TRASHIT(*oldnext); \
+} while (0)
+
+#define SLIST_REMOVE_AFTER(elm, field) do { \
+ SLIST_NEXT(elm, field) = \
+ SLIST_NEXT(SLIST_NEXT(elm, field), field); \
+} while (0)
+
+#define SLIST_REMOVE_HEAD(head, field) do { \
+ SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
+} while (0)
+
+#define SLIST_SWAP(head1, head2, type) do { \
+ struct type *swap_first = SLIST_FIRST(head1); \
+ SLIST_FIRST(head1) = SLIST_FIRST(head2); \
+ SLIST_FIRST(head2) = swap_first; \
+} while (0)
+
+/*
+ * Singly-linked Tail queue declarations.
+ */
+#define STAILQ_HEAD(name, type) \
+struct name { \
+ struct type *stqh_first;/* first element */ \
+ struct type **stqh_last;/* addr of last next element */ \
+}
+
+#define STAILQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).stqh_first }
+
+#define STAILQ_ENTRY(type) \
+struct { \
+ struct type *stqe_next; /* next element */ \
+}
+
+/*
+ * Singly-linked Tail queue functions.
+ */
+#define STAILQ_CONCAT(head1, head2) do { \
+ if (!STAILQ_EMPTY((head2))) { \
+ *(head1)->stqh_last = (head2)->stqh_first; \
+ (head1)->stqh_last = (head2)->stqh_last; \
+ STAILQ_INIT((head2)); \
+ } \
+} while (0)
+
+#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
+
+#define STAILQ_FIRST(head) ((head)->stqh_first)
+
+#define STAILQ_FOREACH(var, head, field) \
+ for((var) = STAILQ_FIRST((head)); \
+ (var); \
+ (var) = STAILQ_NEXT((var), field))
+
+
+#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = STAILQ_FIRST((head)); \
+ (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#define STAILQ_INIT(head) do { \
+ STAILQ_FIRST((head)) = NULL; \
+ (head)->stqh_last = &STAILQ_FIRST((head)); \
+} while (0)
+
+#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
+ if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
+ STAILQ_NEXT((tqelm), field) = (elm); \
+} while (0)
+
+#define STAILQ_INSERT_HEAD(head, elm, field) do { \
+ if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
+ STAILQ_FIRST((head)) = (elm); \
+} while (0)
+
+#define STAILQ_INSERT_TAIL(head, elm, field) do { \
+ STAILQ_NEXT((elm), field) = NULL; \
+ *(head)->stqh_last = (elm); \
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
+} while (0)
+
+#define STAILQ_LAST(head, type, field) \
+ (STAILQ_EMPTY((head)) ? \
+ NULL : \
+ ((struct type *)(void *) \
+ ((char *)((head)->stqh_last) - __offsetof(struct type, field))))
+
+#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
+
+#define STAILQ_REMOVE(head, elm, type, field) do { \
+ QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \
+ if (STAILQ_FIRST((head)) == (elm)) { \
+ STAILQ_REMOVE_HEAD((head), field); \
+ } \
+ else { \
+ struct type *curelm = STAILQ_FIRST((head)); \
+ while (STAILQ_NEXT(curelm, field) != (elm)) \
+ curelm = STAILQ_NEXT(curelm, field); \
+ STAILQ_REMOVE_AFTER(head, curelm, field); \
+ } \
+ TRASHIT(*oldnext); \
+} while (0)
+
+#define STAILQ_REMOVE_HEAD(head, field) do { \
+ if ((STAILQ_FIRST((head)) = \
+ STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
+ (head)->stqh_last = &STAILQ_FIRST((head)); \
+} while (0)
+
+#define STAILQ_REMOVE_AFTER(head, elm, field) do { \
+ if ((STAILQ_NEXT(elm, field) = \
+ STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
+} while (0)
+
+#define STAILQ_SWAP(head1, head2, type) do { \
+ struct type *swap_first = STAILQ_FIRST(head1); \
+ struct type **swap_last = (head1)->stqh_last; \
+ STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \
+ (head1)->stqh_last = (head2)->stqh_last; \
+ STAILQ_FIRST(head2) = swap_first; \
+ (head2)->stqh_last = swap_last; \
+ if (STAILQ_EMPTY(head1)) \
+ (head1)->stqh_last = &STAILQ_FIRST(head1); \
+ if (STAILQ_EMPTY(head2)) \
+ (head2)->stqh_last = &STAILQ_FIRST(head2); \
+} while (0)
+
+
+/*
+ * List declarations.
+ */
+#define LIST_HEAD(name, type) \
+struct name { \
+ struct type *lh_first; /* first element */ \
+}
+
+#define LIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define LIST_ENTRY(type) \
+struct { \
+ struct type *le_next; /* next element */ \
+ struct type **le_prev; /* address of previous next element */ \
+}
+
+/*
+ * List functions.
+ */
+
+#if (defined(_KERNEL) && defined(INVARIANTS))
+#define QMD_LIST_CHECK_HEAD(head, field) do { \
+ if (LIST_FIRST((head)) != NULL && \
+ LIST_FIRST((head))->field.le_prev != \
+ &LIST_FIRST((head))) \
+ panic("Bad list head %p first->prev != head", (head)); \
+} while (0)
+
+#define QMD_LIST_CHECK_NEXT(elm, field) do { \
+ if (LIST_NEXT((elm), field) != NULL && \
+ LIST_NEXT((elm), field)->field.le_prev != \
+ &((elm)->field.le_next)) \
+ panic("Bad link elm %p next->prev != elm", (elm)); \
+} while (0)
+
+#define QMD_LIST_CHECK_PREV(elm, field) do { \
+ if (*(elm)->field.le_prev != (elm)) \
+ panic("Bad link elm %p prev->next != elm", (elm)); \
+} while (0)
+#else
+#define QMD_LIST_CHECK_HEAD(head, field)
+#define QMD_LIST_CHECK_NEXT(elm, field)
+#define QMD_LIST_CHECK_PREV(elm, field)
+#endif /* (_KERNEL && INVARIANTS) */
+
+#define LIST_EMPTY(head) ((head)->lh_first == NULL)
+
+#define LIST_FIRST(head) ((head)->lh_first)
+
+#define LIST_FOREACH(var, head, field) \
+ for ((var) = LIST_FIRST((head)); \
+ (var); \
+ (var) = LIST_NEXT((var), field))
+
+#define LIST_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = LIST_FIRST((head)); \
+ (var) && ((tvar) = LIST_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#define LIST_INIT(head) do { \
+ LIST_FIRST((head)) = NULL; \
+} while (0)
+
+#define LIST_INSERT_AFTER(listelm, elm, field) do { \
+ QMD_LIST_CHECK_NEXT(listelm, field); \
+ if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
+ LIST_NEXT((listelm), field)->field.le_prev = \
+ &LIST_NEXT((elm), field); \
+ LIST_NEXT((listelm), field) = (elm); \
+ (elm)->field.le_prev = &LIST_NEXT((listelm), field); \
+} while (0)
+
+#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
+ QMD_LIST_CHECK_PREV(listelm, field); \
+ (elm)->field.le_prev = (listelm)->field.le_prev; \
+ LIST_NEXT((elm), field) = (listelm); \
+ *(listelm)->field.le_prev = (elm); \
+ (listelm)->field.le_prev = &LIST_NEXT((elm), field); \
+} while (0)
+
+#define LIST_INSERT_HEAD(head, elm, field) do { \
+ QMD_LIST_CHECK_HEAD((head), field); \
+ if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
+ LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
+ LIST_FIRST((head)) = (elm); \
+ (elm)->field.le_prev = &LIST_FIRST((head)); \
+} while (0)
+
+#define LIST_NEXT(elm, field) ((elm)->field.le_next)
+
+#define LIST_REMOVE(elm, field) do { \
+ QMD_SAVELINK(oldnext, (elm)->field.le_next); \
+ QMD_SAVELINK(oldprev, (elm)->field.le_prev); \
+ QMD_LIST_CHECK_NEXT(elm, field); \
+ QMD_LIST_CHECK_PREV(elm, field); \
+ if (LIST_NEXT((elm), field) != NULL) \
+ LIST_NEXT((elm), field)->field.le_prev = \
+ (elm)->field.le_prev; \
+ *(elm)->field.le_prev = LIST_NEXT((elm), field); \
+ TRASHIT(*oldnext); \
+ TRASHIT(*oldprev); \
+} while (0)
+
+#define LIST_SWAP(head1, head2, type, field) do { \
+ struct type *swap_tmp = LIST_FIRST((head1)); \
+ LIST_FIRST((head1)) = LIST_FIRST((head2)); \
+ LIST_FIRST((head2)) = swap_tmp; \
+ if ((swap_tmp = LIST_FIRST((head1))) != NULL) \
+ swap_tmp->field.le_prev = &LIST_FIRST((head1)); \
+ if ((swap_tmp = LIST_FIRST((head2))) != NULL) \
+ swap_tmp->field.le_prev = &LIST_FIRST((head2)); \
+} while (0)
+
+/*
+ * Tail queue declarations.
+ */
+#define TAILQ_HEAD(name, type) \
+struct name { \
+ struct type *tqh_first; /* first element */ \
+ struct type **tqh_last; /* addr of last next element */ \
+ TRACEBUF \
+}
+
+#define TAILQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).tqh_first }
+
+#define TAILQ_ENTRY(type) \
+struct { \
+ struct type *tqe_next; /* next element */ \
+ struct type **tqe_prev; /* address of previous next element */ \
+ TRACEBUF \
+}
+
+/*
+ * Tail queue functions.
+ */
+#if (defined(_KERNEL) && defined(INVARIANTS))
+#define QMD_TAILQ_CHECK_HEAD(head, field) do { \
+ if (!TAILQ_EMPTY(head) && \
+ TAILQ_FIRST((head))->field.tqe_prev != \
+ &TAILQ_FIRST((head))) \
+ panic("Bad tailq head %p first->prev != head", (head)); \
+} while (0)
+
+#define QMD_TAILQ_CHECK_TAIL(head, field) do { \
+ if (*(head)->tqh_last != NULL) \
+ panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \
+} while (0)
+
+#define QMD_TAILQ_CHECK_NEXT(elm, field) do { \
+ if (TAILQ_NEXT((elm), field) != NULL && \
+ TAILQ_NEXT((elm), field)->field.tqe_prev != \
+ &((elm)->field.tqe_next)) \
+ panic("Bad link elm %p next->prev != elm", (elm)); \
+} while (0)
+
+#define QMD_TAILQ_CHECK_PREV(elm, field) do { \
+ if (*(elm)->field.tqe_prev != (elm)) \
+ panic("Bad link elm %p prev->next != elm", (elm)); \
+} while (0)
+#else
+#define QMD_TAILQ_CHECK_HEAD(head, field)
+#define QMD_TAILQ_CHECK_TAIL(head, headname)
+#define QMD_TAILQ_CHECK_NEXT(elm, field)
+#define QMD_TAILQ_CHECK_PREV(elm, field)
+#endif /* (_KERNEL && INVARIANTS) */
+
+#define TAILQ_CONCAT(head1, head2, field) do { \
+ if (!TAILQ_EMPTY(head2)) { \
+ *(head1)->tqh_last = (head2)->tqh_first; \
+ (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
+ (head1)->tqh_last = (head2)->tqh_last; \
+ TAILQ_INIT((head2)); \
+ QMD_TRACE_HEAD(head1); \
+ QMD_TRACE_HEAD(head2); \
+ } \
+} while (0)
+
+#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
+
+#define TAILQ_FIRST(head) ((head)->tqh_first)
+
+#define TAILQ_FOREACH(var, head, field) \
+ for ((var) = TAILQ_FIRST((head)); \
+ (var); \
+ (var) = TAILQ_NEXT((var), field))
+
+#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = TAILQ_FIRST((head)); \
+ (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
+ for ((var) = TAILQ_LAST((head), headname); \
+ (var); \
+ (var) = TAILQ_PREV((var), headname, field))
+
+#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
+ for ((var) = TAILQ_LAST((head), headname); \
+ (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
+ (var) = (tvar))
+
+#define TAILQ_INIT(head) do { \
+ TAILQ_FIRST((head)) = NULL; \
+ (head)->tqh_last = &TAILQ_FIRST((head)); \
+ QMD_TRACE_HEAD(head); \
+} while (0)
+
+#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ QMD_TAILQ_CHECK_NEXT(listelm, field); \
+ if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
+ TAILQ_NEXT((elm), field)->field.tqe_prev = \
+ &TAILQ_NEXT((elm), field); \
+ else { \
+ (head)->tqh_last = &TAILQ_NEXT((elm), field); \
+ QMD_TRACE_HEAD(head); \
+ } \
+ TAILQ_NEXT((listelm), field) = (elm); \
+ (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
+ QMD_TRACE_ELEM(&(elm)->field); \
+ QMD_TRACE_ELEM(&listelm->field); \
+} while (0)
+
+#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
+ QMD_TAILQ_CHECK_PREV(listelm, field); \
+ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
+ TAILQ_NEXT((elm), field) = (listelm); \
+ *(listelm)->field.tqe_prev = (elm); \
+ (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
+ QMD_TRACE_ELEM(&(elm)->field); \
+ QMD_TRACE_ELEM(&listelm->field); \
+} while (0)
+
+#define TAILQ_INSERT_HEAD(head, elm, field) do { \
+ QMD_TAILQ_CHECK_HEAD(head, field); \
+ if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
+ TAILQ_FIRST((head))->field.tqe_prev = \
+ &TAILQ_NEXT((elm), field); \
+ else \
+ (head)->tqh_last = &TAILQ_NEXT((elm), field); \
+ TAILQ_FIRST((head)) = (elm); \
+ (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
+ QMD_TRACE_HEAD(head); \
+ QMD_TRACE_ELEM(&(elm)->field); \
+} while (0)
+
+#define TAILQ_INSERT_TAIL(head, elm, field) do { \
+ QMD_TAILQ_CHECK_TAIL(head, field); \
+ TAILQ_NEXT((elm), field) = NULL; \
+ (elm)->field.tqe_prev = (head)->tqh_last; \
+ *(head)->tqh_last = (elm); \
+ (head)->tqh_last = &TAILQ_NEXT((elm), field); \
+ QMD_TRACE_HEAD(head); \
+ QMD_TRACE_ELEM(&(elm)->field); \
+} while (0)
+
+#define TAILQ_LAST(head, headname) \
+ (*(((struct headname *)((head)->tqh_last))->tqh_last))
+
+#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+
+#define TAILQ_PREV(elm, headname, field) \
+ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+
+#define TAILQ_REMOVE(head, elm, field) do { \
+ QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \
+ QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \
+ QMD_TAILQ_CHECK_NEXT(elm, field); \
+ QMD_TAILQ_CHECK_PREV(elm, field); \
+ if ((TAILQ_NEXT((elm), field)) != NULL) \
+ TAILQ_NEXT((elm), field)->field.tqe_prev = \
+ (elm)->field.tqe_prev; \
+ else { \
+ (head)->tqh_last = (elm)->field.tqe_prev; \
+ QMD_TRACE_HEAD(head); \
+ } \
+ *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
+ TRASHIT(*oldnext); \
+ TRASHIT(*oldprev); \
+ QMD_TRACE_ELEM(&(elm)->field); \
+} while (0)
+
+#define TAILQ_SWAP(head1, head2, type, field) do { \
+ struct type *swap_first = (head1)->tqh_first; \
+ struct type **swap_last = (head1)->tqh_last; \
+ (head1)->tqh_first = (head2)->tqh_first; \
+ (head1)->tqh_last = (head2)->tqh_last; \
+ (head2)->tqh_first = swap_first; \
+ (head2)->tqh_last = swap_last; \
+ if ((swap_first = (head1)->tqh_first) != NULL) \
+ swap_first->field.tqe_prev = &(head1)->tqh_first; \
+ else \
+ (head1)->tqh_last = &(head1)->tqh_first; \
+ if ((swap_first = (head2)->tqh_first) != NULL) \
+ swap_first->field.tqe_prev = &(head2)->tqh_first; \
+ else \
+ (head2)->tqh_last = &(head2)->tqh_first; \
+} while (0)
+
+#endif /* !_SYS_QUEUE_H_ */
diff --git a/pctf/ctf_api.h b/pctf/ctf_api.h
index a26a39e..9a7b91e 100644
--- a/pctf/ctf_api.h
+++ b/pctf/ctf_api.h
@@ -43,7 +43,6 @@
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/types.h>
-#include <sys/elf.h>
#include <pctf/ctf.h>
#ifdef __cplusplus