Adjust for monotone.
diff --git a/libdwarf/.cvsignore b/libdwarf/.cvsignore
new file mode 100644
index 0000000..70845e0
--- /dev/null
+++ b/libdwarf/.cvsignore
@@ -0,0 +1 @@
+Makefile.in
diff --git a/libdwarf/AVAILABLE b/libdwarf/AVAILABLE
new file mode 100644
index 0000000..642dd27
--- /dev/null
+++ b/libdwarf/AVAILABLE
@@ -0,0 +1,136 @@
+Data Types:
+
+  Dwarf_Bool
+  Dwarf_Off
+  Dwarf_Unsigned
+  Dwarf_Half
+  Dwarf_Small
+  Dwarf_Signed
+  Dwarf_Addr
+  Dwarf_Ptr
+  Dwarf_Handler
+
+  Dwarf_Debug
+  Dwarf_Die
+  Dwarf_Line
+  Dwarf_Global
+  Dwarf_Loc
+  Dwarf_Locdesc
+  Dwarf_Block
+  Dwarf_Error
+  Dwarf_Attribute
+  Dwarf_Fde
+  Dwarf_Cie
+  Dwarf_Arange
+
+ NOT!!!:
+
+  Dwarf_Frame_Op
+  Dwarf_Macro_Details
+
+  Dwarf_Weak
+  Dwarf_Func
+  Dwarf_Type
+  Dwarf_Var
+  Dwarf_Abbrev
+
+Functions:
+
+  dwarf_init()
+  dwarf_elf_init()
+  dwarf_get_elf()
+  dwarf_finish()
+  dwarf_next_cu_header()
+  dwarf_siblingof()
+  dwarf_child()
+  dwarf_offdie()
+  dwarf_tag()
+  dwarf_dieoffset()
+  dwarf_die_CU_offset()
+  dwarf_diename()
+  dwarf_attrlist()
+  dwarf_srclang()
+  dwarf_arrayorder()
+  dwarf_hasform()
+  dwarf_whatattr()
+  dwarf_formref()
+  dwarf_global_formref()
+  dwarf_formaddr()
+  dwarf_formflag()
+  dwarf_hasattr()
+  dwarf_attr()
+  dwarf_lowpc()
+  dwarf_highpc()
+  dwarf_bytesize()
+  dwarf_bitsize()
+  dwarf_bitoffset()
+  dwarf_formudata()
+  dwarf_formblock()
+  dwarf_formstring()
+  dwarf_loclist()
+  dwarf_srclines()
+  dwarf_srcfiles()
+  dwarf_linebeginstatement()
+  dwarf_lineendsequence()
+  dwarf_lineno()
+  dwarf_lineaddr()
+  dwarf_lineoff()
+  dwarf_linesrc()
+  dwarf_lineblock()
+  dwarf_get_globals()
+  dwarf_globname()
+  dwarf_global_die_offset()
+  dwarf_global_cu_offset()
+  dwarf_global_name_offsets()
+  dwarf_find_macro_value_start()
+  dwarf_get_fde_list_eh()
+  dwarf_get_fde_range()
+  dwarf_get_cie_of_fde()
+  dwarf_get_cie_info()
+  dwarf_get_fde_instr_bytes()
+  dwarf_get_fde_n()
+  dwarf_get_fde_at_pc()
+  dwarf_get_str()
+  dwarf_get_aranges()
+  dwarf_get_cu_die_offset()
+  dwarf_get_loclist_entry()
+  dwarf_get_abbrev()
+  dwarf_get_abbrev_tag()
+  dwarf_get_abbrev_code()
+  dwarf_get_abbrev_children_flag()
+  dwarf_get_abbrev_entry()
+  dwarf_get_arange_info()
+  dwarf_get_address_size()
+  dwarf_errno()
+  dwarf_errmsg()
+  dwarf_seterrhand()
+  dwarf_seterrarg()
+  dwarf_dealloc()
+
+ NOT!!!:
+
+  dwarf_get_weaks()
+  dwarf_weakname()
+  dwarf_weak_die_offset()
+  dwarf_weak_cu_offset()
+  dwarf_weak_name_offsets()
+  dwarf_get_funcs()
+  dwarf_funcname()
+  dwarf_func_die_offset()
+  dwarf_func_cu_offset()
+  dwarf_func_name_offsets()
+  dwarf_get_types()
+  dwarf_typename()
+  dwarf_type_die_offset()
+  dwarf_type_cu_offset()
+  dwarf_type_name_offsets()
+  dwarf_get_vars()
+  dwarf_varname()
+  dwarf_var_die_offset()
+  dwarf_var_cu_offset()
+  dwarf_var_name_offsets()
+  dwarf_get_fde_list()
+  dwarf_get_fde_for_die()
+  dwarf_get_fde_info_for_reg()		<<-------
+  dwarf_get_fde_info_for_all_regs()
+  dwarf_expand_frame_instructions()	<<-------
diff --git a/libdwarf/ChangeLog b/libdwarf/ChangeLog
new file mode 100644
index 0000000..c46ffcb
--- /dev/null
+++ b/libdwarf/ChangeLog
@@ -0,0 +1,3 @@
+2003-08-11  Ulrich Drepper  <drepper@redhat.com>
+
+        * Moved to CVS archive.
diff --git a/libdwarf/Makefile.am b/libdwarf/Makefile.am
new file mode 100644
index 0000000..8af7a67
--- /dev/null
+++ b/libdwarf/Makefile.am
@@ -0,0 +1,103 @@
+## Process this file with automake to create Makefile.in -*-Makefile-*-
+## Configure input file for elfutils.
+##
+## Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
+##
+## This program is Open Source software; you can redistribute it and/or
+## modify it under the terms of the Open Software License version 1.0 as
+## published by the Open Source Initiative.
+##
+## You should have received a copy of the Open Software License along
+## with this program; if not, you may obtain a copy of the Open Software
+## License version 1.0 from http://www.opensource.org/licenses/osl.php or
+## by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+## 3001 King Ranch Road, Ukiah, CA 95482.
+##
+DEFS = -D_GNU_SOURCE -DHAVE_CONFIG_H -DDWARF_DEBUG
+AM_CFLAGS = -Wall -Werror
+INCLUDES = -I. -I$(srcdir) -I$(srcdir)/../libelf -I.. -I$(srcdir)/../lib
+VERSION = 1
+
+lib_LIBRARIES = libdwarf.a
+noinst_LIBRARIES = libdwarf_pic.a
+noinst_PROGRAMS = $(noinst_LIBRARIES:_pic.a=.so)
+include_HEADERS = dwarf.h
+euincludedir = ${includedir}/elfutils
+euinclude_HEADERS = libdwarf.h
+
+libdwarf_a_SOURCES = dwarf_init.c dwarf_elf_init.c dwarf_get_elf.c \
+		     dwarf_finish.c \
+		     dwarf_next_cu_header.c dwarf_siblingof.c dwarf_child.c \
+		     dwarf_offdie.c \
+		     dwarf_tag.c dwarf_dieoffset.c dwarf_die_CU_offset.c \
+		     dwarf_diename.c dwarf_attrlist.c dwarf_hasattr.c \
+		     dwarf_attr.c dwarf_lowpc.c dwarf_highpc.c \
+		     dwarf_getconstant.c \
+		     dwarf_bytesize.c dwarf_bitsize.c dwarf_bitoffset.c \
+		     dwarf_srclang.c dwarf_whatattr.c dwarf_arrayorder.c \
+		     dwarf_hasform.c dwarf_whatform.c dwarf_formref.c \
+		     dwarf_global_formref.c dwarf_formaddr.c \
+		     dwarf_formstring.c dwarf_loclist.c \
+		     dwarf_formflag.c dwarf_formudata.c dwarf_formsdata.c \
+		     dwarf_formblock.c \
+		     dwarf_srclines.c dwarf_srcfiles.c \
+		     dwarf_linebeginstatement.c dwarf_lineendsequence.c \
+		     dwarf_lineno.c dwarf_lineaddr.c dwarf_lineoff.c \
+		     dwarf_linesrc.c dwarf_lineblock.c \
+		     dwarf_lineprologueend.c dwarf_lineepiloguebegin.c \
+		     dwarf_get_globals.c dwarf_globname.c \
+		     dwarf_global_die_offset.c dwarf_global_cu_offset.c \
+		     dwarf_global_name_offsets.c \
+		     dwarf_error.c dwarf_errno.c dwarf_errmsg.c \
+		     dwarf_abbrev_hash.c dwarf_getabbrev.c dwarf_form.c \
+		     dwarf_find_macro_value_start.c dwarf_get_str.c \
+		     dwarf_get_aranges.c dwarf_get_arange.c \
+		     dwarf_get_cu_die_offset.c dwarf_get_arange_info.c \
+		     dwarf_get_fde_list_eh.c dwarf_get_cie_of_fde.c \
+		     dwarf_get_cie_info.c dwarf_get_fde_instr_bytes.c \
+		     dwarf_get_fde_range.c dwarf_get_fde_n.c \
+		     dwarf_get_fde_at_pc.c  \
+		     dwarf_get_loclist_entry.c \
+		     dwarf_get_abbrev.c dwarf_get_abbrev_tag.c \
+		     dwarf_get_abbrev_code.c dwarf_get_abbrev_children_flag.c\
+		     dwarf_get_abbrev_entry.c \
+		     dwarf_get_address_size.c \
+		     dwarf_seterrhand.c dwarf_seterrarg.c \
+		     dwarf_dealloc.c
+
+libdwarf_pic_a_SOURCES =
+am_libdwarf_pic_a_OBJECTS = $(libdwarf_a_SOURCES:.c=.os)
+
+libdwarf_so_SOURCES =
+libdwarf.so: libdwarf_pic.a libdwarf.map
+	$(CC) -shared -o $@ -Wl,--whole-archive,$<,--no-whole-archive \
+	      -Wl,--version-script,$(srcdir)/libdwarf.map,--no-undefined \
+	      -Wl,--soname,$@.$(VERSION),-z,defs \
+	      ../libelf/libelf.so
+	ln -fs $@ $@.$(VERSION)
+
+
+%.os: %.c %.o
+	if $(COMPILE) -c -o $@ -fpic -DPIC -DSHARED -MT $@ -MD -MP \
+	  -MF "$(DEPDIR)/$*.Tpo" `test -f '$<' || echo '$(srcdir)/'`$<; \
+	then cat "$(DEPDIR)/$*.Tpo" >> "$(DEPDIR)/$*.Po"; \
+	     rm -f "$(DEPDIR)/$*.Tpo"; \
+	else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
+	fi
+
+install: install-am libdwarf.so
+	$(mkinstalldirs) $(DESTDIR)$(libdir)
+	$(INSTALL_PROGRAM) libdwarf.so $(DESTDIR)$(libdir)/libdwarf-$(PACKAGE_VERSION).so
+	ln -fs libdwarf-$(PACKAGE_VERSION).so $(DESTDIR)$(libdir)/libdwarf.so.$(VERSION)
+	ln -fs libdwarf.so.$(VERSION) $(DESTDIR)$(libdir)/libdwarf.so
+
+uninstall: uninstall-am
+	rm -f $(DESTDIR)$(libdir)/libdwarf-$(PACKAGE_VERSION).so
+	rm -f $(DESTDIR)$(libdir)/libdwarf.so.$(VERSION)
+	rm -f $(DESTDIR)$(libdir)/libdwarf.so
+	rmdir --ignore-fail-on-non-empty $(DESTDIR)$(includedir)/elfutils
+
+noinst_HEADERS = libdwarfP.h memory-access.h dwarf_abbrev_hash.h
+EXTRA_DIST = AVAILABLE libdwarf.map
+
+CLEANFILES = $(am_libdwarf_pic_a_OBJECTS)
diff --git a/libdwarf/dwarf.h b/libdwarf/dwarf.h
new file mode 100644
index 0000000..81bdcc4
--- /dev/null
+++ b/libdwarf/dwarf.h
@@ -0,0 +1,549 @@
+/* This file defines standard DWARF types, structures, and macros.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifndef _DWARF_H
+#define	_DWARF_H 1
+
+/* DWARF tags.  */
+enum
+  {
+    DW_TAG_array_type = 0x01,
+    DW_TAG_class_type = 0x02,
+    DW_TAG_entry_point = 0x03,
+    DW_TAG_enumeration_type = 0x04,
+    DW_TAG_formal_parameter = 0x05,
+    DW_TAG_imported_declaration = 0x08,
+    DW_TAG_label = 0x0a,
+    DW_TAG_lexical_block = 0x0b,
+    DW_TAG_member = 0x0d,
+    DW_TAG_pointer_type = 0x0f,
+    DW_TAG_reference_type = 0x10,
+    DW_TAG_compile_unit = 0x11,
+    DW_TAG_string_type = 0x12,
+    DW_TAG_structure_type = 0x13,
+    DW_TAG_subroutine_type = 0x15,
+    DW_TAG_typedef = 0x16,
+    DW_TAG_union_type = 0x17,
+    DW_TAG_unspecified_parameters = 0x18,
+    DW_TAG_variant = 0x19,
+    DW_TAG_common_block = 0x1a,
+    DW_TAG_common_inclusion = 0x1b,
+    DW_TAG_inheritance = 0x1c,
+    DW_TAG_inlined_subroutine = 0x1d,
+    DW_TAG_module = 0x1e,
+    DW_TAG_ptr_to_member_type = 0x1f,
+    DW_TAG_set_type = 0x20,
+    DW_TAG_subrange_type = 0x21,
+    DW_TAG_with_stmt = 0x22,
+    DW_TAG_access_declaration = 0x23,
+    DW_TAG_base_type = 0x24,
+    DW_TAG_catch_block = 0x25,
+    DW_TAG_const_type = 0x26,
+    DW_TAG_constant = 0x27,
+    DW_TAG_enumerator = 0x28,
+    DW_TAG_file_type = 0x29,
+    DW_TAG_friend = 0x2a,
+    DW_TAG_namelist = 0x2b,
+    DW_TAG_namelist_item = 0x2c,
+    DW_TAG_packed_type = 0x2d,
+    DW_TAG_subprogram = 0x2e,
+    DW_TAG_template_type_param = 0x2f,
+    DW_TAG_template_value_param = 0x30,
+    DW_TAG_thrown_type = 0x31,
+    DW_TAG_try_block = 0x32,
+    DW_TAG_variant_part = 0x33,
+    DW_TAG_variable = 0x34,
+    DW_TAG_volatile_type = 0x35,
+    DW_TAG_lo_user = 0x4080,
+    DW_TAG_MIPS_loop = 0x4081,
+    DW_TAG_format_label = 0x4101,
+    DW_TAG_function_template = 0x4102,
+    DW_TAG_class_template = 0x4103,
+    DW_TAG_hi_user = 0xffff
+  };
+
+
+/* Children determination encodings.  */
+enum
+  {
+    DW_CHILDREN_no = 0,
+    DW_CHILDREN_yes = 1
+  };
+
+
+/* DWARF attributes encodings.  */
+enum
+  {
+    DW_AT_sibling = 0x01,
+    DW_AT_location = 0x02,
+    DW_AT_name = 0x03,
+    DW_AT_ordering = 0x09,
+    DW_AT_subscr_data = 0x0a,
+    DW_AT_byte_size = 0x0b,
+    DW_AT_bit_offset = 0x0c,
+    DW_AT_bit_size = 0x0d,
+    DW_AT_element_list = 0x0f,
+    DW_AT_stmt_list = 0x10,
+    DW_AT_low_pc = 0x11,
+    DW_AT_high_pc = 0x12,
+    DW_AT_language = 0x13,
+    DW_AT_member = 0x14,
+    DW_AT_discr = 0x15,
+    DW_AT_discr_value = 0x16,
+    DW_AT_visibility = 0x17,
+    DW_AT_import = 0x18,
+    DW_AT_string_length = 0x19,
+    DW_AT_common_reference = 0x1a,
+    DW_AT_comp_dir = 0x1b,
+    DW_AT_const_value = 0x1c,
+    DW_AT_containing_type = 0x1d,
+    DW_AT_default_value = 0x1e,
+    DW_AT_inline = 0x20,
+    DW_AT_is_optional = 0x21,
+    DW_AT_lower_bound = 0x22,
+    DW_AT_producer = 0x25,
+    DW_AT_prototyped = 0x27,
+    DW_AT_return_addr = 0x2a,
+    DW_AT_start_scope = 0x2c,
+    DW_AT_stride_size = 0x2e,
+    DW_AT_upper_bound = 0x2f,
+    DW_AT_abstract_origin = 0x31,
+    DW_AT_accessibility = 0x32,
+    DW_AT_address_class = 0x33,
+    DW_AT_artificial = 0x34,
+    DW_AT_base_types = 0x35,
+    DW_AT_calling_convention = 0x36,
+    DW_AT_count = 0x37,
+    DW_AT_data_member_location = 0x38,
+    DW_AT_decl_column = 0x39,
+    DW_AT_decl_file = 0x3a,
+    DW_AT_decl_line = 0x3b,
+    DW_AT_declaration = 0x3c,
+    DW_AT_discr_list = 0x3d,
+    DW_AT_encoding = 0x3e,
+    DW_AT_external = 0x3f,
+    DW_AT_frame_base = 0x40,
+    DW_AT_friend = 0x41,
+    DW_AT_identifier_case = 0x42,
+    DW_AT_macro_info = 0x43,
+    DW_AT_namelist_items = 0x44,
+    DW_AT_priority = 0x45,
+    DW_AT_segment = 0x46,
+    DW_AT_specification = 0x47,
+    DW_AT_static_link = 0x48,
+    DW_AT_type = 0x49,
+    DW_AT_use_location = 0x4a,
+    DW_AT_variable_parameter = 0x4b,
+    DW_AT_virtuality = 0x4c,
+    DW_AT_vtable_elem_location = 0x4d,
+    DW_AT_lo_user = 0x2000,
+    DW_AT_MIPS_fde = 0x2001,
+    DW_AT_MIPS_loop_begin = 0x2002,
+    DW_AT_MIPS_tail_loop_begin = 0x2003,
+    DW_AT_MIPS_epilog_begin = 0x2004,
+    DW_AT_MIPS_loop_unroll_factor = 0x2005,
+    DW_AT_MIPS_software_pipeline_depth = 0x2006,
+    DW_AT_MIPS_linkage_name = 0x2007,
+    DW_AT_MIPS_stride = 0x2008,
+    DW_AT_MIPS_abstract_name = 0x2009,
+    DW_AT_MIPS_clone_origin = 0x200a,
+    DW_AT_MIPS_has_inlines = 0x200b,
+    DW_AT_MIPS_stride_byte = 0x200c,
+    DW_AT_MIPS_stride_elem = 0x200d,
+    DW_AT_MIPS_ptr_dopetype = 0x200e,
+    DW_AT_MIPS_allocatable_dopetype = 0x200f,
+    DW_AT_MIPS_assumed_shape_dopetype = 0x2010,
+    DW_AT_MIPS_assumed_size = 0x2011,
+    DW_AT_sf_names = 0x2101,
+    DW_AT_src_info = 0x2102,
+    DW_AT_mac_info = 0x2103,
+    DW_AT_src_coords = 0x2104,
+    DW_AT_body_begin = 0x2105,
+    DW_AT_body_end = 0x2106,
+    DW_AT_hi_user = 0x3fff
+  };
+
+
+/* DWARF form encodings.  */
+enum
+  {
+    DW_FORM_addr = 0x01,
+    DW_FORM_block2 = 0x03,
+    DW_FORM_block4 = 0x04,
+    DW_FORM_data2 = 0x05,
+    DW_FORM_data4 = 0x06,
+    DW_FORM_data8 = 0x07,
+    DW_FORM_string = 0x08,
+    DW_FORM_block = 0x09,
+    DW_FORM_block1 = 0x0a,
+    DW_FORM_data1 = 0x0b,
+    DW_FORM_flag = 0x0c,
+    DW_FORM_sdata = 0x0d,
+    DW_FORM_strp = 0x0e,
+    DW_FORM_udata = 0x0f,
+    DW_FORM_ref_addr = 0x10,
+    DW_FORM_ref1 = 0x11,
+    DW_FORM_ref2 = 0x12,
+    DW_FORM_ref4 = 0x13,
+    DW_FORM_ref8 = 0x14,
+    DW_FORM_ref_udata = 0x15,
+    DW_FORM_indirect = 0x16
+  };
+
+
+/* DWARF location operation encodings.  */
+enum
+  {
+    DW_OP_addr = 0x03,		/* Constant address.  */
+    DW_OP_deref = 0x06,
+    DW_OP_const1u = 0x08,	/* Unsigned 1-byte constant.  */
+    DW_OP_const1s = 0x09,	/* Signed 1-byte constant.  */
+    DW_OP_const2u = 0x0a,	/* Unsigned 2-byte constant.  */
+    DW_OP_const2s = 0x0b,	/* Signed 2-byte constant.  */
+    DW_OP_const4u = 0x0c,	/* Unsigned 4-byte constant.  */
+    DW_OP_const4s = 0x0d,	/* Signed 4-byte constant.  */
+    DW_OP_const8u = 0x0e,	/* Unsigned 8-byte constant.  */
+    DW_OP_const8s = 0x0f,	/* Signed 8-byte constant.  */
+    DW_OP_constu = 0x10,	/* Unsigned LEB128 constant.  */
+    DW_OP_consts = 0x11,	/* Signed LEB128 constant.  */
+    DW_OP_dup = 0x12,
+    DW_OP_drop = 0x13,
+    DW_OP_over = 0x14,
+    DW_OP_pick = 0x15,		/* 1-byte stack index.  */
+    DW_OP_swap = 0x16,
+    DW_OP_rot = 0x17,
+    DW_OP_xderef = 0x18,
+    DW_OP_abs = 0x19,
+    DW_OP_and = 0x1a,
+    DW_OP_div = 0x1b,
+    DW_OP_minus = 0x1c,
+    DW_OP_mod = 0x1d,
+    DW_OP_mul = 0x1e,
+    DW_OP_neg = 0x1f,
+    DW_OP_not = 0x20,
+    DW_OP_or = 0x21,
+    DW_OP_plus = 0x22,
+    DW_OP_plus_uconst = 0x23,	/* Unsigned LEB128 addend.  */
+    DW_OP_shl = 0x24,
+    DW_OP_shr = 0x25,
+    DW_OP_shra = 0x26,
+    DW_OP_xor = 0x27,
+    DW_OP_bra = 0x28,		/* Signed 2-byte constant.  */
+    DW_OP_eq = 0x29,
+    DW_OP_ge = 0x2a,
+    DW_OP_gt = 0x2b,
+    DW_OP_le = 0x2c,
+    DW_OP_lt = 0x2d,
+    DW_OP_ne = 0x2e,
+    DW_OP_skip = 0x2f,		/* Signed 2-byte constant.  */
+    DW_OP_lit0 = 0x30,		/* Literal 0.  */
+    DW_OP_lit1 = 0x31,		/* Literal 1.  */
+    DW_OP_lit2 = 0x32,		/* Literal 2.  */
+    DW_OP_lit3 = 0x33,		/* Literal 3.  */
+    DW_OP_lit4 = 0x34,		/* Literal 4.  */
+    DW_OP_lit5 = 0x35,		/* Literal 5.  */
+    DW_OP_lit6 = 0x36,		/* Literal 6.  */
+    DW_OP_lit7 = 0x37,		/* Literal 7.  */
+    DW_OP_lit8 = 0x38,		/* Literal 8.  */
+    DW_OP_lit9 = 0x39,		/* Literal 9.  */
+    DW_OP_lit10 = 0x3a,		/* Literal 10.  */
+    DW_OP_lit11 = 0x3b,		/* Literal 11.  */
+    DW_OP_lit12 = 0x3c,		/* Literal 12.  */
+    DW_OP_lit13 = 0x3d,		/* Literal 13.  */
+    DW_OP_lit14 = 0x3e,		/* Literal 14.  */
+    DW_OP_lit15 = 0x3f,		/* Literal 15.  */
+    DW_OP_lit16 = 0x40,		/* Literal 16.  */
+    DW_OP_lit17 = 0x41,		/* Literal 17.  */
+    DW_OP_lit18 = 0x42,		/* Literal 18.  */
+    DW_OP_lit19 = 0x43,		/* Literal 19.  */
+    DW_OP_lit20 = 0x44,		/* Literal 20.  */
+    DW_OP_lit21 = 0x45,		/* Literal 21.  */
+    DW_OP_lit22 = 0x46,		/* Literal 22.  */
+    DW_OP_lit23 = 0x47,		/* Literal 23.  */
+    DW_OP_lit24 = 0x48,		/* Literal 24.  */
+    DW_OP_lit25 = 0x49,		/* Literal 25.  */
+    DW_OP_lit26 = 0x4a,		/* Literal 26.  */
+    DW_OP_lit27 = 0x4b,		/* Literal 27.  */
+    DW_OP_lit28 = 0x4c,		/* Literal 28.  */
+    DW_OP_lit29 = 0x4d,		/* Literal 29.  */
+    DW_OP_lit30 = 0x4e,		/* Literal 30.  */
+    DW_OP_lit31 = 0x4f,		/* Literal 31.  */
+    DW_OP_reg0 = 0x50,		/* Register 0.  */
+    DW_OP_reg1 = 0x51,		/* Register 1.  */
+    DW_OP_reg2 = 0x52,		/* Register 2.  */
+    DW_OP_reg3 = 0x53,		/* Register 3.  */
+    DW_OP_reg4 = 0x54,		/* Register 4.  */
+    DW_OP_reg5 = 0x55,		/* Register 5.  */
+    DW_OP_reg6 = 0x56,		/* Register 6.  */
+    DW_OP_reg7 = 0x57,		/* Register 7.  */
+    DW_OP_reg8 = 0x58,		/* Register 8.  */
+    DW_OP_reg9 = 0x59,		/* Register 9.  */
+    DW_OP_reg10 = 0x5a,		/* Register 10.  */
+    DW_OP_reg11 = 0x5b,		/* Register 11.  */
+    DW_OP_reg12 = 0x5c,		/* Register 12.  */
+    DW_OP_reg13 = 0x5d,		/* Register 13.  */
+    DW_OP_reg14 = 0x5e,		/* Register 14.  */
+    DW_OP_reg15 = 0x5f,		/* Register 15.  */
+    DW_OP_reg16 = 0x60,		/* Register 16.  */
+    DW_OP_reg17 = 0x61,		/* Register 17.  */
+    DW_OP_reg18 = 0x62,		/* Register 18.  */
+    DW_OP_reg19 = 0x63,		/* Register 19.  */
+    DW_OP_reg20 = 0x64,		/* Register 20.  */
+    DW_OP_reg21 = 0x65,		/* Register 21.  */
+    DW_OP_reg22 = 0x66,		/* Register 22.  */
+    DW_OP_reg23 = 0x67,		/* Register 24.  */
+    DW_OP_reg24 = 0x68,		/* Register 24.  */
+    DW_OP_reg25 = 0x69,		/* Register 25.  */
+    DW_OP_reg26 = 0x6a,		/* Register 26.  */
+    DW_OP_reg27 = 0x6b,		/* Register 27.  */
+    DW_OP_reg28 = 0x6c,		/* Register 28.  */
+    DW_OP_reg29 = 0x6d,		/* Register 29.  */
+    DW_OP_reg30 = 0x6e,		/* Register 30.  */
+    DW_OP_reg31 = 0x6f,		/* Register 31.  */
+    DW_OP_breg0 = 0x70,		/* Base register 0.  */
+    DW_OP_breg1 = 0x71,		/* Base register 1.  */
+    DW_OP_breg2 = 0x72,		/* Base register 2.  */
+    DW_OP_breg3 = 0x73,		/* Base register 3.  */
+    DW_OP_breg4 = 0x74,		/* Base register 4.  */
+    DW_OP_breg5 = 0x75,		/* Base register 5.  */
+    DW_OP_breg6 = 0x76,		/* Base register 6.  */
+    DW_OP_breg7 = 0x77,		/* Base register 7.  */
+    DW_OP_breg8 = 0x78,		/* Base register 8.  */
+    DW_OP_breg9 = 0x79,		/* Base register 9.  */
+    DW_OP_breg10 = 0x7a,	/* Base register 10.  */
+    DW_OP_breg11 = 0x7b,	/* Base register 11.  */
+    DW_OP_breg12 = 0x7c,	/* Base register 12.  */
+    DW_OP_breg13 = 0x7d,	/* Base register 13.  */
+    DW_OP_breg14 = 0x7e,	/* Base register 14.  */
+    DW_OP_breg15 = 0x7f,	/* Base register 15.  */
+    DW_OP_breg16 = 0x80,	/* Base register 16.  */
+    DW_OP_breg17 = 0x81,	/* Base register 17.  */
+    DW_OP_breg18 = 0x82,	/* Base register 18.  */
+    DW_OP_breg19 = 0x83,	/* Base register 19.  */
+    DW_OP_breg20 = 0x84,	/* Base register 20.  */
+    DW_OP_breg21 = 0x85,	/* Base register 21.  */
+    DW_OP_breg22 = 0x86,	/* Base register 22.  */
+    DW_OP_breg23 = 0x87,	/* Base register 23.  */
+    DW_OP_breg24 = 0x88,	/* Base register 24.  */
+    DW_OP_breg25 = 0x89,	/* Base register 25.  */
+    DW_OP_breg26 = 0x8a,	/* Base register 26.  */
+    DW_OP_breg27 = 0x8b,	/* Base register 27.  */
+    DW_OP_breg28 = 0x8c,	/* Base register 28.  */
+    DW_OP_breg29 = 0x8d,	/* Base register 29.  */
+    DW_OP_breg30 = 0x8e,	/* Base register 30.  */
+    DW_OP_breg31 = 0x8f,	/* Base register 31.  */
+    DW_OP_regx = 0x90,		/* Unsigned LEB128 register.  */
+    DW_OP_fbreg = 0x91,		/* Signed LEB128 register.  */
+    DW_OP_bregx = 0x92,		/* ULEB128 register followed by SLEB128 off. */
+    DW_OP_piece = 0x93,		/* ULEB128 size of piece addressed. */
+    DW_OP_deref_size = 0x94,	/* 1-byte size of data retrieved.  */
+    DW_OP_xderef_size = 0x95,	/* 1-byte size of data retrieved.  */
+    DW_OP_nop = 0x96,
+    DW_OP_push_object_address = 0x97,
+    DW_OP_call2 = 0x98,
+    DW_OP_call4 = 0x99,
+    DW_OP_call_ref = 0x9a,
+
+    DW_OP_lo_user = 0xe0,	/* Implementation-defined range start.  */
+    DW_OP_hi_user = 0xff	/* Implementation-defined range end.  */
+  };
+
+
+/* DWARF base type encodings.  */
+enum
+  {
+    DW_ATE_void = 0x0,
+    DW_ATE_address = 0x1,
+    DW_ATE_boolean = 0x2,
+    DW_ATE_complex_float = 0x3,
+    DW_ATE_float = 0x4,
+    DW_ATE_signed = 0x5,
+    DW_ATE_signed_char = 0x6,
+    DW_ATE_unsigned = 0x7,
+    DW_ATE_unsigned_char = 0x8,
+
+    DW_ATE_lo_user = 0x80,
+    DW_ATE_hi_user = 0xff
+  };
+
+
+/* DWARF accessibility encodings.  */
+enum
+  {
+    DW_ACCESS_public = 1,
+    DW_ACCESS_protected = 2,
+    DW_ACCESS_private = 3
+  };
+
+
+/* DWARF visibility encodings.  */
+enum
+  {
+    DW_VIS_local = 1,
+    DW_VIS_exported = 2,
+    DW_VIS_qualified = 3
+  };
+
+
+/* DWARF virtuality encodings.  */
+enum
+  {
+    DW_VIRTUALITY_none = 0,
+    DW_VIRTUALITY_virtual = 1,
+    DW_VIRTUALITY_pure_virtual = 2
+  };
+
+
+/* DWARF language encodings.  */
+enum
+  {
+    DW_LANG_C89 = 0x0001,
+    DW_LANG_C = 0x0002,
+    DW_LANG_Ada83 = 0x0003,
+    DW_LANG_C_plus_plus	= 0x0004,
+    DW_LANG_Cobol74 = 0x0005,
+    DW_LANG_Cobol85 = 0x0006,
+    DW_LANG_Fortran77 = 0x0007,
+    DW_LANG_Fortran90 = 0x0008,
+    DW_LANG_Pascal83 = 0x0009,
+    DW_LANG_Modula2 = 0x000a,
+    DW_LANG_Java = 0x000b,
+    DW_LANG_C99 = 0x000c,
+    DW_LANG_Ada95 = 0x000d,
+    DW_LANG_Fortran95 = 0x000e,
+    DW_LANG_PL1 = 0x000f,
+    DW_LANG_lo_user = 0x8000,
+    DW_LANG_Mips_Assembler = 0x8001,
+    DW_LANG_hi_user = 0xffff
+  };
+
+
+/* DWARF identifier case encodings.  */
+enum
+  {
+    DW_ID_case_sensitive = 0,
+    DW_ID_up_case = 1,
+    DW_ID_down_case = 2,
+    DW_ID_case_insensitive = 3
+  };
+
+
+/* DWARF calling conventions encodings.  */
+enum
+  {
+    DW_CC_normal = 0x1,
+    DW_CC_program = 0x2,
+    DW_CC_nocall = 0x3,
+    DW_CC_lo_user = 0x40,
+    DW_CC_hi_user = 0xff
+  };
+
+
+/* DWARF inline encodings.  */
+enum
+  {
+    DW_INL_not_inlined = 0,
+    DW_INL_inlined = 1,
+    DW_INL_declared_not_inlined = 2,
+    DW_INL_declared_inlined = 3
+  };
+
+
+/* DWARF ordering encodings.  */
+enum
+  {
+    DW_ORD_row_major = 0,
+    DW_ORD_col_major = 1
+  };
+
+
+/* DWARF discriminant descriptor encodings.  */
+enum
+  {
+    DW_DSC_label = 0,
+    DW_DSC_range = 1
+  };
+
+
+/* DWARF standard opcode encodings.  */
+enum
+  {
+    DW_LNS_copy = 1,
+    DW_LNS_advance_pc = 2,
+    DW_LNS_advance_line = 3,
+    DW_LNS_set_file = 4,
+    DW_LNS_set_column = 5,
+    DW_LNS_negate_stmt = 6,
+    DW_LNS_set_basic_block = 7,
+    DW_LNS_const_add_pc = 8,
+    DW_LNS_fixed_advance_pc = 9,
+    DW_LNS_set_prologue_end = 10,
+    DW_LNS_set_epilog_begin = 11
+  };
+
+
+/* DWARF extended opcide encodings.  */
+enum
+  {
+    DW_LNE_end_sequence = 1,
+    DW_LNE_set_address = 2,
+    DW_LNE_define_file = 3
+  };
+
+
+/* DWARF macinfo type encodings.  */
+enum
+  {
+    DW_MACINFO_define = 1,
+    DW_MACINFO_undef = 2,
+    DW_MACINFO_start_file = 3,
+    DW_MACINFO_end_file = 4,
+    DW_MACINFO_vendor_ext = 255
+  };
+
+
+/* DWARF call frame instruction encodings.  */
+enum
+  {
+    DW_CFA_advance_loc = 0x40,
+    DW_CFA_offset = 0x80,
+    DW_CFA_restore = 0xc0,
+    DW_CFA_extended = 0,
+
+    DW_CFA_nop = 0x00,
+    DW_CFA_set_loc = 0x01,
+    DW_CFA_advance_loc1 = 0x02,
+    DW_CFA_advance_loc2 = 0x03,
+    DW_CFA_advance_loc4 = 0x04,
+    DW_CFA_offset_extended = 0x05,
+    DW_CFA_restore_extended = 0x06,
+    DW_CFA_undefined = 0x07,
+    DW_CFA_same_value = 0x08,
+    DW_CFA_register = 0x09,
+    DW_CFA_remember_state = 0x0a,
+    DW_CFA_restore_state = 0x0b,
+    DW_CFA_def_cfa = 0x0c,
+    DW_CFA_def_cfa_register = 0x0d,
+    DW_CFA_def_cfa_offset = 0x0e,
+    DW_CFA_low_user = 0x1c,
+    DW_CFA_MIPS_advance_loc8 = 0x1d,
+    DW_CFA_GNU_window_save = 0x2d,
+    DW_CFA_GNU_args_size = 0x2e,
+    DW_CFA_high_user = 0x3f
+  };
+
+
+/* DWARF XXX.  */
+#define DW_ADDR_none	0
+
+#endif	/* dwarf.h */
diff --git a/libdwarf/dwarf_abbrev_hash.c b/libdwarf/dwarf_abbrev_hash.c
new file mode 100644
index 0000000..a196449
--- /dev/null
+++ b/libdwarf/dwarf_abbrev_hash.c
@@ -0,0 +1,29 @@
+/* Implementation of hash table for DWARF .debug_abbrev section content.
+   Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define NO_UNDEF
+#include "libdwarfP.h"
+
+#define next_prime __libdwarf_next_prime
+extern size_t next_prime (size_t) attribute_hidden;
+
+#include <dynamicsizehash.c>
+
+#undef next_prime
+#define next_prime attribute_hidden __libdwarf_next_prime
+#include "../lib/next_prime.c"
diff --git a/libdwarf/dwarf_abbrev_hash.h b/libdwarf/dwarf_abbrev_hash.h
new file mode 100644
index 0000000..45c2346
--- /dev/null
+++ b/libdwarf/dwarf_abbrev_hash.h
@@ -0,0 +1,24 @@
+/* Hash table for DWARF .debug_abbrev section content.
+   Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifndef _DWARF_ABBREV_HASH_H
+#define _DWARF_ABBREV_HASH_H	1
+
+#define NAME Dwarf_Abbrev_Hash
+#define TYPE Dwarf_Abbrev
+#define COMPARE(a, b) (0)
+
+#include <dynamicsizehash.h>
+
+#endif	/* dwarf_abbrev_hash.h */
diff --git a/libdwarf/dwarf_arrayorder.c b/libdwarf/dwarf_arrayorder.c
new file mode 100644
index 0000000..88f3080
--- /dev/null
+++ b/libdwarf/dwarf_arrayorder.c
@@ -0,0 +1,31 @@
+/* Return array ordering information associated with die.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_arrayorder (die, return_order, error)
+     Dwarf_Die die;
+     Dwarf_Unsigned *return_order;
+     Dwarf_Error *error;
+{
+  return __libdwarf_getconstant (die, DW_AT_ordering, return_order, error);
+}
diff --git a/libdwarf/dwarf_attr.c b/libdwarf/dwarf_attr.c
new file mode 100644
index 0000000..f1b20f4
--- /dev/null
+++ b/libdwarf/dwarf_attr.c
@@ -0,0 +1,113 @@
+/* Return die attribute with specified of given type.
+   Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_attr (die, attr, return_attr, error)
+     Dwarf_Die die;
+     Dwarf_Half attr;
+     Dwarf_Attribute *return_attr;
+     Dwarf_Error *error;
+{
+  Dwarf_Debug dbg = die->cu->dbg;
+  Dwarf_Small *die_addr;
+  Dwarf_Word u128;
+  Dwarf_Abbrev abbrev;
+  Dwarf_Small *attrp;
+
+  /* Address of the given die.  */
+  die_addr = die->addr;
+
+  /* Get abbrev code.  */
+  get_uleb128 (u128, die_addr);
+  /*  And get the abbreviation itself.  */
+  abbrev = __libdwarf_get_abbrev (dbg, die->cu, u128, error);
+  if (abbrev == NULL)
+    return DW_DLV_ERROR;
+
+  /* This is where the attributes start.  */
+  attrp = abbrev->attrp;
+
+  /* Search the name attribute.  */
+  while (1)
+    {
+      Dwarf_Word attr_name;
+      Dwarf_Word attr_form;
+
+      /* Are we still in bounds?  */
+      if (unlikely (attrp
+		    >= ((Dwarf_Small *) dbg->sections[IDX_debug_abbrev].addr
+			+ dbg->sections[IDX_debug_abbrev].size)))
+	{
+	  __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+	  return DW_DLV_ERROR;
+	}
+
+      /* Get attribute name and form.
+
+	 XXX We don't check whether this reads beyond the end of the
+	 section.  */
+      get_uleb128 (attr_name, attrp);
+      get_uleb128 (attr_form, attrp);
+
+      /* We can stop if we found the attribute with value zero.  */
+      if (attr_name == 0 && attr_form == 0)
+	break;
+
+      /* Is this the name attribute?  */
+      if (attr_name == attr)
+	{
+	  Dwarf_Attribute new_attr;
+
+	  new_attr =
+	    (Dwarf_Attribute) malloc (sizeof (struct Dwarf_Attribute_s));
+	  if (new_attr == NULL)
+	    {
+	      __libdwarf_error (dbg, error, DW_E_NOMEM);
+	      return DW_DLV_ERROR;
+	    }
+
+	  new_attr->code = attr_name;
+	  new_attr->form = attr_form;
+	  new_attr->valp = die_addr;
+	  new_attr->cu = die->cu;
+
+	  *return_attr = new_attr;
+	  return DW_DLV_OK;
+	}
+
+      /* Skip over the rest of this attribute (if there is any).  */
+      if (attr_form != 0)
+	{
+	  size_t len;
+
+	  if (__libdwarf_form_val_len (dbg, die->cu, attr_form, die_addr, &len,
+				       error) != DW_DLV_OK)
+	    return DW_DLV_ERROR;
+
+	  die_addr += len;
+	}
+    }
+
+  /* No such attribute present.  */
+  return DW_DLV_NO_ENTRY;
+}
diff --git a/libdwarf/dwarf_attrlist.c b/libdwarf/dwarf_attrlist.c
new file mode 100644
index 0000000..bef5a11
--- /dev/null
+++ b/libdwarf/dwarf_attrlist.c
@@ -0,0 +1,182 @@
+/* Return attribute list for die.
+   Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include <libdwarfP.h>
+
+
+struct attrlist
+{
+  struct attrlist *next;
+  Dwarf_Attribute attr;
+};
+
+
+int
+dwarf_attrlist (die, attrbuf, attrcount, error)
+     Dwarf_Die die;
+     Dwarf_Attribute **attrbuf;
+     Dwarf_Signed *attrcount;
+     Dwarf_Error *error;
+{
+  Dwarf_Debug dbg = die->cu->dbg;
+  Dwarf_Small *die_addr;
+  Dwarf_Word u128;
+  Dwarf_Abbrev abbrev;
+  Dwarf_Small *attrp;
+  struct attrlist *alist;
+  int nattr;
+  Dwarf_Attribute *result;
+
+  /* Address of the given die.  */
+  die_addr = die->addr;
+
+  /* Get abbrev code.  */
+  get_uleb128 (u128, die_addr);
+  /*  And get the abbreviation itself.  */
+  abbrev = __libdwarf_get_abbrev (dbg, die->cu, u128, error);
+  if (abbrev == NULL)
+    return DW_DLV_ERROR;
+
+  /* This is where the attributes start.  */
+  attrp = abbrev->attrp;
+
+  /* Initialize the list.  We create one because we don't know yet how
+     many attributes there will be.  */
+  alist = NULL;
+  nattr = 0;
+
+  /* Go over the list of attributes.  */
+  while (1)
+    {
+      Dwarf_Word attr_name;
+      Dwarf_Word attr_form;
+      Dwarf_Attribute new_attr;
+      struct attrlist *new_alist;
+
+      /* Are we still in bounds?  */
+      if (unlikely (attrp
+		    >= ((Dwarf_Small *) dbg->sections[IDX_debug_abbrev].addr
+			+ dbg->sections[IDX_debug_abbrev].size)))
+	{
+	  while (alist != NULL)
+	    {
+	      free (alist->attr);
+	      alist = alist->next;
+	    }
+
+	  __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+	  return DW_DLV_ERROR;
+	}
+
+      /* Get attribute name and form.
+
+	 XXX We don't check whether this reads beyond the end of the
+	 section.  */
+      get_uleb128 (attr_name, attrp);
+      get_uleb128 (attr_form, attrp);
+
+      /* We can stop if we found the attribute with value zero.  */
+      if (attr_name == 0 && attr_form == 0)
+	break;
+
+      /* Allocate the attribute data structure.  */
+      new_attr = (Dwarf_Attribute) malloc (sizeof (struct Dwarf_Attribute_s));
+      if (new_attr == NULL)
+	{
+	  while (alist != NULL)
+	    {
+	      free (alist->attr);
+	      alist = alist->next;
+	    }
+
+	  __libdwarf_error (dbg, error, DW_E_NOMEM);
+	  return DW_DLV_ERROR;
+	}
+
+      /* Fill in the values.  */
+      new_attr->code = attr_name;
+      new_attr->form = attr_form;
+      new_attr->valp = die_addr;
+      new_attr->cu = die->cu;
+
+      /* Enqueue.  */
+      new_alist = (struct attrlist *) alloca (sizeof (struct attrlist));
+      new_alist->attr = new_attr;
+      new_alist->next = alist;
+      alist = new_alist;
+      ++nattr;
+
+      /* Skip over the rest of this attribute (if there is any).  */
+      if (attr_form != 0)
+	{
+	  size_t len;
+
+	  if (unlikely (__libdwarf_form_val_len (dbg, die->cu, attr_form,
+						 die_addr, &len, error)
+			!= DW_DLV_OK))
+	    {
+	      while (alist != NULL)
+		{
+		  free (alist->attr);
+		  alist = alist->next;
+		}
+
+	      return DW_DLV_ERROR;
+	    }
+
+	  die_addr += len;
+	}
+    }
+
+  if (nattr == 0)
+    {
+      *attrcount = 0;
+      *attrbuf = NULL;
+      return DW_DLV_NO_ENTRY;
+    }
+
+  /* Allocate the array for the result.  */
+  result = (Dwarf_Attribute *) malloc (nattr * sizeof (Dwarf_Attribute));
+  if (result == NULL)
+    {
+      while (alist != NULL)
+	{
+	  free (alist->attr);
+	  alist = alist->next;
+	}
+
+      __libdwarf_error (dbg, error, DW_E_NOMEM);
+      return DW_DLV_ERROR;
+    }
+
+  /* Store the number of attributes and the result pointer.  */
+  *attrcount = nattr;
+  *attrbuf = result;
+
+  /* Put the attribute entries in the array (in the right order).  */
+  do
+    {
+      result[--nattr] = alist->attr;
+      alist = alist->next;
+    }
+  while (nattr > 0);
+
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_bitoffset.c b/libdwarf/dwarf_bitoffset.c
new file mode 100644
index 0000000..bfc9165
--- /dev/null
+++ b/libdwarf/dwarf_bitoffset.c
@@ -0,0 +1,31 @@
+/* Return bit offset value associated with die.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_bitoffset (die, return_size, error)
+     Dwarf_Die die;
+     Dwarf_Unsigned *return_size;
+     Dwarf_Error *error;
+{
+  return __libdwarf_getconstant (die, DW_AT_bit_offset, return_size, error);
+}
diff --git a/libdwarf/dwarf_bitsize.c b/libdwarf/dwarf_bitsize.c
new file mode 100644
index 0000000..007975c
--- /dev/null
+++ b/libdwarf/dwarf_bitsize.c
@@ -0,0 +1,31 @@
+/* Return bit size value associated with die.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_bitsize (die, return_size, error)
+     Dwarf_Die die;
+     Dwarf_Unsigned *return_size;
+     Dwarf_Error *error;
+{
+  return __libdwarf_getconstant (die, DW_AT_bit_size, return_size, error);
+}
diff --git a/libdwarf/dwarf_bytesize.c b/libdwarf/dwarf_bytesize.c
new file mode 100644
index 0000000..68d728a
--- /dev/null
+++ b/libdwarf/dwarf_bytesize.c
@@ -0,0 +1,31 @@
+/* Return byte size value associated with die.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_bytesize (die, return_size, error)
+     Dwarf_Die die;
+     Dwarf_Unsigned *return_size;
+     Dwarf_Error *error;
+{
+  return __libdwarf_getconstant (die, DW_AT_byte_size, return_size, error);
+}
diff --git a/libdwarf/dwarf_child.c b/libdwarf/dwarf_child.c
new file mode 100644
index 0000000..ee9c833
--- /dev/null
+++ b/libdwarf/dwarf_child.c
@@ -0,0 +1,123 @@
+/* Return child of die.
+   Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_child (die, return_kid, error)
+     Dwarf_Die die;
+     Dwarf_Die *return_kid;
+     Dwarf_Error *error;
+{
+  Dwarf_Debug dbg = die->cu->dbg;
+  Dwarf_Abbrev abbrev;
+  Dwarf_Small *attrp;
+  Dwarf_Small *die_addr;
+  Dwarf_Word u128;
+  Dwarf_Die new_die;
+
+  if (! die->abbrev->has_children)
+    return DW_DLV_NO_ENTRY;
+
+  /* Address of the given die.  */
+  die_addr = die->addr;
+
+  /* Get abbrev code.  */
+  get_uleb128 (u128, die_addr);
+  /*  And get the abbreviation itself.  */
+  abbrev = __libdwarf_get_abbrev (dbg, die->cu, u128, error);
+  if (abbrev == NULL)
+    return DW_DLV_ERROR;
+
+  /* This is where the attributes start.  */
+  attrp = abbrev->attrp;
+
+  /* Skip over the attributes of the given die.  */
+  while (1)
+    {
+      Dwarf_Word attr_name;
+      Dwarf_Word attr_form;
+
+      /* Are we still in bounds?  */
+      if (unlikely (attrp
+		    >= ((Dwarf_Small *)dbg->sections[IDX_debug_abbrev].addr
+			+ dbg->sections[IDX_debug_abbrev].size)))
+	{
+	  __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+	  return DW_DLV_ERROR;
+	}
+
+      /* Get attribute name and form.
+
+	 XXX We don't check whether this reads beyond the end of the
+	 section.  */
+      get_uleb128 (attr_name, attrp);
+      get_uleb128 (attr_form, attrp);
+
+      /* We can stop if we found the attribute with value zero.  */
+      if (attr_name == 0 && attr_form == 0)
+	break;
+
+      /* Skip over the rest of this attribute (if there is any).  */
+      if (attr_form != 0)
+	{
+	  size_t len;
+
+	  if (unlikely (__libdwarf_form_val_len (dbg, die->cu, attr_form,
+						 die_addr, &len, error)
+			!= DW_DLV_OK))
+	    return DW_DLV_ERROR;
+
+	  die_addr += len;
+	}
+    }
+
+  /* Allocate the die structure for the result.  */
+  new_die = (Dwarf_Die) malloc (sizeof (struct Dwarf_Die_s));
+  if (new_die == NULL)
+    {
+      __libdwarf_error (dbg, error, DW_E_NOMEM);
+      return DW_DLV_ERROR;
+    }
+#ifdef DWARF_DEBUG
+  new_die->memtag = DW_DLA_DIE;
+#endif
+
+  /* Remember the address.  */
+  new_die->addr = die_addr;
+
+  /* And the compile unit.  */
+  new_die->cu = die->cu;
+
+  /* 7.5.2  Debugging Information Entry
+
+     Each debugging information entry begins with an unsigned LEB128
+     number containing the abbreviation code for the entry.  */
+  get_uleb128 (u128, die_addr);
+
+  /* Find the abbreviation.  */
+  new_die->abbrev = __libdwarf_get_abbrev (dbg, die->cu, u128, error);
+  if (new_die->abbrev == NULL)
+    return DW_DLV_ERROR;
+
+  *return_kid = new_die;
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_dealloc.c b/libdwarf/dwarf_dealloc.c
new file mode 100644
index 0000000..365303b
--- /dev/null
+++ b/libdwarf/dwarf_dealloc.c
@@ -0,0 +1,32 @@
+/* Deallocate memory.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include <libdwarfP.h>
+
+
+void
+dwarf_dealloc (dbg, space, alloc_type)
+     Dwarf_Debug dbg;
+     Dwarf_Ptr space;
+     Dwarf_Unsigned alloc_type;
+{
+  /* XXX For now we don't do anything fancy.  */
+  free (space);
+}
diff --git a/libdwarf/dwarf_die_CU_offset.c b/libdwarf/dwarf_die_CU_offset.c
new file mode 100644
index 0000000..2d80fd5
--- /dev/null
+++ b/libdwarf/dwarf_die_CU_offset.c
@@ -0,0 +1,33 @@
+/* Return offset of die in compile unit data.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_die_CU_offset (die, return_offset, error)
+     Dwarf_Die die;
+     Dwarf_Off *return_offset;
+     Dwarf_Error *error;
+{
+  *return_offset =
+    (die->addr
+     - (Dwarf_Small *) die->cu->dbg->sections[IDX_debug_info].addr
+     - die->cu->offset);
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_diename.c b/libdwarf/dwarf_diename.c
new file mode 100644
index 0000000..2dfcd57
--- /dev/null
+++ b/libdwarf/dwarf_diename.c
@@ -0,0 +1,139 @@
+/* Return string in name attribute of die.
+   Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include <string.h>
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_diename (die, return_name, error)
+     Dwarf_Die die;
+     char **return_name;
+     Dwarf_Error *error;
+{
+  Dwarf_Debug dbg = die->cu->dbg;
+  Dwarf_Small *die_addr;
+  Dwarf_Word u128;
+  Dwarf_Abbrev abbrev;
+  Dwarf_Small *attrp;
+
+  /* Address of the given die.  */
+  die_addr = die->addr;
+
+  /* Get abbrev code.  */
+  get_uleb128 (u128, die_addr);
+  /*  And get the abbreviation itself.  */
+  abbrev = __libdwarf_get_abbrev (dbg, die->cu, u128, error);
+  if (abbrev == NULL)
+    return DW_DLV_ERROR;
+
+  /* This is where the attributes start.  */
+  attrp = abbrev->attrp;
+
+  /* Search the name attribute.  */
+  while (1)
+    {
+      Dwarf_Word attr_name;
+      Dwarf_Word attr_form;
+
+      /* Are we still in bounds?  */
+      if (unlikely (attrp
+		    >= ((Dwarf_Small *)dbg->sections[IDX_debug_abbrev].addr
+			+ dbg->sections[IDX_debug_abbrev].size)))
+	{
+	  __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+	  return DW_DLV_ERROR;
+	}
+
+      /* Get attribute name and form.
+
+	 XXX We don't check whether this reads beyond the end of the
+	 section.  */
+      get_uleb128 (attr_name, attrp);
+      get_uleb128 (attr_form, attrp);
+
+      /* We can stop if we found the attribute with value zero.  */
+      if (attr_name == 0 && attr_form == 0)
+	break;
+
+      /* Is this the name attribute?  */
+      if (attr_name == DW_AT_name)
+	{
+	  char *str;
+
+	  /* We found it.  Duplicate the string and return.  There are
+             two possible forms: DW_FORM_string and DW_FORM_strp.  */
+	  if (attr_form == DW_FORM_string)
+	    {
+	      str = (char *) die_addr;
+	    }
+	  else if (likely (attr_form == DW_FORM_strp))
+	    {
+	      Dwarf_Unsigned off;
+	      Dwarf_Signed len;
+
+	      if (die->cu->offset_size == 4)
+		off = read_4ubyte_unaligned (dbg, die_addr);
+	      else
+		off = read_8ubyte_unaligned (dbg, die_addr);
+
+	      /* This is an offset in the .debug_str section.  Make sure
+		 it's within range.  */
+	      if (unlikely (dwarf_get_str (dbg, off, &str, &len, error)
+			    != DW_DLV_OK))
+		{
+		  __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+		  return DW_DLV_ERROR;
+		}
+	    }
+	  else
+	    {
+	      __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+	      return DW_DLV_ERROR;
+	    }
+
+	  str = strdup (str);
+	  if (str == NULL)
+	    {
+	      __libdwarf_error (dbg, error, DW_E_NOMEM);
+	      return DW_DLV_ERROR;
+	    }
+
+	  *return_name = str;
+	  return DW_DLV_OK;
+	}
+
+      /* Skip over the rest of this attribute (if there is any).  */
+      if (attr_form != 0)
+	{
+	  size_t len;
+
+	  if (unlikely (__libdwarf_form_val_len (dbg, die->cu, attr_form,
+						 die_addr, &len, error)
+			!= DW_DLV_OK))
+	    return DW_DLV_ERROR;
+
+	  die_addr += len;
+	}
+    }
+
+  /* No name attribute present.  */
+  return DW_DLV_NO_ENTRY;
+}
diff --git a/libdwarf/dwarf_dieoffset.c b/libdwarf/dwarf_dieoffset.c
new file mode 100644
index 0000000..2886f9f
--- /dev/null
+++ b/libdwarf/dwarf_dieoffset.c
@@ -0,0 +1,31 @@
+/* Return offset of die in .debug_info section.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_dieoffset (die, return_offset, error)
+     Dwarf_Die die;
+     Dwarf_Off *return_offset;
+     Dwarf_Error *error;
+{
+  *return_offset =
+    (die->addr - (Dwarf_Small *) die->cu->dbg->sections[IDX_debug_info].addr);
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_elf_init.c b/libdwarf/dwarf_elf_init.c
new file mode 100644
index 0000000..d69d747
--- /dev/null
+++ b/libdwarf/dwarf_elf_init.c
@@ -0,0 +1,197 @@
+/* Create descriptor from ELF handle for processing file.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <endian.h>
+#include <gelf.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libdwarfP.h>
+
+
+/* Section names.  */
+static const char dwarf_scnnames[IDX_last][17] =
+{
+  [IDX_debug_info] = ".debug_info",
+  [IDX_debug_abbrev] = ".debug_abbrev",
+  [IDX_debug_aranges] = ".debug_aranges",
+  [IDX_debug_line] = ".debug_line",
+  [IDX_debug_frame] = ".debug_frame",
+  [IDX_eh_frame] = ".eh_frame",
+  [IDX_debug_loc] = ".debug_loc",
+  [IDX_debug_pubnames] = ".debug_pubnames",
+  [IDX_debug_str] = ".debug_str",
+  [IDX_debug_funcnames] = ".debug_funcnames",
+  [IDX_debug_typenames] = ".debug_typenames",
+  [IDX_debug_varnames] = ".debug_varnames",
+  [IDX_debug_weaknames] = ".debug_weaknames",
+  [IDX_debug_macinfo] = ".debug_macinfo"
+};
+#define ndwarf_scnnames (sizeof (dwarf_scnnames) / sizeof (dwarf_scnnames[0]))
+
+
+int
+dwarf_elf_init (elf, access, errhand, errarg, dbg, error)
+     Elf *elf;
+     Dwarf_Unsigned access;
+     Dwarf_Handler errhand;
+     Dwarf_Ptr errarg;
+     Dwarf_Debug *dbg;
+     Dwarf_Error *error;
+{
+  int result = DW_DLV_ERROR;
+  Dwarf_Debug newdbg;
+  GElf_Ehdr ehdr_mem;
+  GElf_Ehdr *ehdr;
+  Elf_Scn *scn;
+
+  /* XXX For now nothing but read-only support is available.  */
+  if (access != DW_DLC_READ)
+    abort ();
+
+  /* Get the ELF header of the file.  We need various pieces of
+     information from it.  */
+  ehdr = gelf_getehdr (elf, &ehdr_mem);
+  if (ehdr == NULL)
+    {
+      struct Dwarf_Debug_s tmpdbg;
+
+      tmpdbg.dbg_errhand = errhand;
+      tmpdbg.dbg_errarg = errarg;
+
+      if (elf_kind (elf) != ELF_K_ELF)
+	__libdwarf_error (&tmpdbg, error, DW_E_NOELF);
+      else
+	__libdwarf_error (&tmpdbg, error, DW_E_GETEHDR_ERROR);
+
+      return result;
+    }
+
+  /* Allocate and fill the result data structure.  */
+  newdbg = (Dwarf_Debug) calloc (1, sizeof (struct Dwarf_Debug_s));
+  if (newdbg == NULL)
+    {
+      struct Dwarf_Debug_s tmpdbg;
+
+      tmpdbg.dbg_errhand = errhand;
+      tmpdbg.dbg_errarg = errarg;
+
+      __libdwarf_error (&tmpdbg, error, DW_E_NOMEM);
+    }
+  else
+    {
+      /* We have been able to allocate the memory for the debug handle.  */
+      newdbg->dbg_errhand = errhand;
+      newdbg->dbg_errarg = errarg;
+      newdbg->elf = elf;
+      if ((BYTE_ORDER == LITTLE_ENDIAN
+	   && ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
+	  || (BYTE_ORDER == BIG_ENDIAN
+	      && ehdr->e_ident[EI_DATA] == ELFDATA2LSB))
+	newdbg->other_byte_order = 1;
+      newdbg->access = access;
+#ifdef DWARF_DEBUG
+      newdbg->memtag = DW_DLA_DEBUG;
+#endif
+
+      /* All done.  */
+      *dbg = newdbg;
+      result = DW_DLV_OK;
+
+      /* Find out whether the file actually has the necessary DWARF
+         sections.  */
+      scn = NULL;
+      while ((scn = elf_nextscn (elf, scn)) != NULL)
+	{
+	  GElf_Shdr shdr_mem;
+	  GElf_Shdr *shdr;
+	  const char *scnname;
+	  size_t cnt;
+	  Elf_Data *data;
+
+	  /* Get the section header data.  */
+	  shdr = gelf_getshdr (scn, &shdr_mem);
+	  if (shdr == NULL)
+	    /* This should never happen.  If it does something is
+	       wrong in the libelf library.  */
+	    abort ();
+
+	  /* We recognize the DWARF section by their names.  This is
+	     not very safe and stable but the best we can do.  */
+	  scnname = elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name);
+	  if (scnname == NULL)
+	    {
+	      /* The section name must be valid.  Otherwise is the ELF file
+		 invalid.  */
+	      __libdwarf_error (newdbg, error, DW_E_INVALID_ELF);
+	      break;
+	    }
+
+	  /* Recognize the various sections.  Most names start with
+             .debug_.  */
+	  for (cnt = 0; cnt < ndwarf_scnnames; ++cnt)
+	    if (strcmp (scnname, dwarf_scnnames[cnt]) == 0)
+	      break;
+
+	  if (cnt < ndwarf_scnnames)
+	    {
+	      /* Found it.  Remember where the data is.  */
+	      assert (cnt < IDX_last);
+	      if (unlikely (newdbg->sections[cnt].addr != NULL))
+		{
+		  /* A section appears twice.  That's bad.  */
+		  __libdwarf_error (newdbg, error, DW_E_INVALID_DWARF);
+		  break;
+		}
+
+	      /* Get the section data.  */
+	      data = elf_getdata (scn, NULL);
+	      if (data != NULL && data->d_size != 0)
+		{
+		  /* Yep, there is actually data available.  */
+		  newdbg->sections[cnt].addr = data->d_buf;
+		  newdbg->sections[cnt].size = data->d_size;
+		}
+	    }
+	}
+
+      if (scn == NULL)
+	{
+	  /* We looked at all the sections.  Now determine whether all
+	     the sections with debugging information we need are there.
+
+	     XXX Which sections are absolutely necessary?  Add tests
+	     if necessary.  For now we require only .debug_info.  Hopefully
+	     this is correct.  */
+	  if (newdbg->sections[IDX_debug_info].addr == NULL)
+	    {
+	      __libdwarf_error (newdbg, error, DW_E_NO_DWARF);
+	      result = DW_DLV_NO_ENTRY;
+	    }
+	  else
+	    result = DW_DLV_OK;
+	}
+
+      if (result != DW_DLV_OK)
+	/* Something went wrong.  */
+	free (newdbg);
+    }
+
+  return result;
+}
diff --git a/libdwarf/dwarf_errmsg.c b/libdwarf/dwarf_errmsg.c
new file mode 100644
index 0000000..1d19f41
--- /dev/null
+++ b/libdwarf/dwarf_errmsg.c
@@ -0,0 +1,67 @@
+/* Return error message.
+   Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libdwarfP.h>
+
+
+/* Map error values to strings.  */
+/* XXX This table should avoid string pointers.  Fixing it can wait
+   until the code is stable.  */
+static const char *msgs[] =
+{
+  [DW_E_NOERROR] = N_("no error"),
+  [DW_E_INVALID_ACCESS] = N_("invalid access mode"),
+  [DW_E_NO_REGFILE] = N_("no regular file"),
+  [DW_E_IO_ERROR] = N_("I/O error"),
+  [DW_E_NOMEM] = N_("out of memory"),
+  [DW_E_NOELF] = N_("file is not an ELF file"),
+  [DW_E_GETEHDR_ERROR] = N_("getehdr call failed"),
+  [DW_E_INVALID_ELF] = N_("invalid ELF file"),
+  [DW_E_INVALID_DWARF] = N_("invalid DWARF debugging information"),
+  [DW_E_NO_DWARF] = N_("no DWARF debugging information available"),
+  [DW_E_NO_CU] = N_("no compilation unit"),
+  [DW_E_1ST_NO_CU] = N_("first die is no compile unit die"),
+  [DW_E_INVALID_OFFSET] = N_("invalid offset"),
+  [DW_E_INVALID_REFERENCE] = N_("invalid reference form"),
+  [DW_E_NO_REFERENCE] = N_("no reference form"),
+  [DW_E_NO_ADDR] = N_("no address form"),
+  [DW_E_NO_FLAG] = N_("no flag form"),
+  [DW_E_NO_CONSTANT] = N_("no constant form"),
+  [DW_E_NO_BLOCK] = N_("no block form"),
+  [DW_E_NO_STRING] = N_("no string form"),
+  [DW_E_WRONG_ATTR] = N_("wrong attribute code"),
+  [DW_E_NO_DATA] = N_("no data form"),
+  [DW_E_NO_DEBUG_LINE] = N_(".debug_line section missing"),
+  [DW_E_VERSION_ERROR] = N_("version mismatch"),
+  [DW_E_INVALID_DIR_IDX] = N_("invalid directory index"),
+  [DW_E_INVALID_ADDR] = N_("invalid address"),
+  [DW_E_NO_ABBR] = N_("no valid abbreviation"),
+};
+#define nmsgs (sizeof (msgs) / sizeof (msgs[0]))
+
+
+const char *
+dwarf_errmsg (Dwarf_Error error)
+{
+  const char *retval = N_("unknown error");
+
+  if (error->de_error < nmsgs)
+    retval = msgs[error->de_error];
+
+  return _(retval);
+}
diff --git a/libdwarf/dwarf_errno.c b/libdwarf/dwarf_errno.c
new file mode 100644
index 0000000..4d659e0
--- /dev/null
+++ b/libdwarf/dwarf_errno.c
@@ -0,0 +1,26 @@
+/* Return error value.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libdwarfP.h>
+
+
+Dwarf_Unsigned
+dwarf_errno (Dwarf_Error error)
+{
+  return error->de_error;
+}
diff --git a/libdwarf/dwarf_error.c b/libdwarf/dwarf_error.c
new file mode 100644
index 0000000..16c0c45
--- /dev/null
+++ b/libdwarf/dwarf_error.c
@@ -0,0 +1,52 @@
+/* Handle error.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include <libdwarfP.h>
+#include <system.h>
+
+
+void
+internal_function
+__libdwarf_error (Dwarf_Debug dbg, Dwarf_Error *error, int errval)
+{
+  /* Allocate memory for the error structure given to the user.  */
+  Dwarf_Error errmem = (Dwarf_Error) malloc (sizeof (*error));
+  /* We cannot report an error if we cannot allocate memory.  */
+  if (errmem == NULL)
+    return;
+
+  errmem->de_error = errval;
+
+  /* DBG must never be NULL.  */
+  assert (dbg != NULL);
+
+  if (error != NULL)
+    /* If the user provides an ERROR parameter we have to use it.  */
+    *error = errmem;
+  else if (likely (dbg->dbg_errhand != NULL))
+    /* Use the handler the user provided if possible.  */
+    dbg->dbg_errhand (error, dbg->dbg_errarg);
+  else
+    {
+      assert (! "error and dbg->dbg_errhand == NULL");
+      abort ();
+    }
+}
diff --git a/libdwarf/dwarf_find_macro_value_start.c b/libdwarf/dwarf_find_macro_value_start.c
new file mode 100644
index 0000000..fdaaf72
--- /dev/null
+++ b/libdwarf/dwarf_find_macro_value_start.c
@@ -0,0 +1,45 @@
+/* Find start of macro value.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libdwarf.h>
+
+
+char *
+dwarf_find_macro_value_start (macro_string)
+     char *macro_string;
+{
+  int with_paren = 0;
+
+  while (*macro_string != '\0')
+    {
+      if (*macro_string == '(')
+	with_paren = 1;
+      else if (*macro_string == ')')
+	/* After the closing parenthesis there must be a space.  */
+	return macro_string + 2;
+      else if (*macro_string == ' ' && ! with_paren)
+	/* Not a function like macro and we found the space terminating
+	   the name.  */
+	return macro_string + 1;
+
+      ++macro_string;
+    }
+
+  /* The macro has no value.  Return a pointer to the NUL byte.  */
+  return macro_string;
+}
diff --git a/libdwarf/dwarf_finish.c b/libdwarf/dwarf_finish.c
new file mode 100644
index 0000000..f689e79
--- /dev/null
+++ b/libdwarf/dwarf_finish.c
@@ -0,0 +1,40 @@
+/* Free resources allocated for debug handle.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_finish (dbg, error)
+     Dwarf_Debug dbg;
+     Dwarf_Error *error;
+{
+  if (dbg == NULL)
+    return DW_DLV_ERROR;
+
+#ifdef DWARF_DEBUG
+  if (dbg->memtag != DW_DLA_DEBUG)
+    return DW_DLV_ERROR;
+#endif
+
+  free (dbg);
+
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_form.c b/libdwarf/dwarf_form.c
new file mode 100644
index 0000000..9adf3ed
--- /dev/null
+++ b/libdwarf/dwarf_form.c
@@ -0,0 +1,107 @@
+/* Helper functions for form handling.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include <string.h>
+
+#include <libdwarfP.h>
+
+
+int
+internal_function
+__libdwarf_form_val_len (Dwarf_Debug dbg, Dwarf_CU_Info cu, Dwarf_Word form,
+			 Dwarf_Small *valp, size_t *len, Dwarf_Error *error)
+{
+  Dwarf_Small *saved;
+  Dwarf_Word u128;
+
+  switch (form)
+    {
+    case DW_FORM_addr:
+    case DW_FORM_strp:
+    case DW_FORM_ref_addr:
+      *len = cu->address_size;
+      break;
+
+    case DW_FORM_block1:
+      *len = *valp + 1;
+      break;
+
+    case DW_FORM_block2:
+      *len = read_2ubyte_unaligned (dbg, valp) + 2;
+      break;
+
+    case DW_FORM_block4:
+      *len = read_4ubyte_unaligned (dbg, valp) + 4;
+      break;
+
+    case DW_FORM_block:
+      saved = valp;
+      get_uleb128 (u128, valp);
+      *len = u128 + (valp - saved);
+      break;
+
+    case DW_FORM_ref1:
+    case DW_FORM_data1:
+    case DW_FORM_flag:
+      *len = 1;
+      break;
+
+    case DW_FORM_data2:
+    case DW_FORM_ref2:
+      *len = 2;
+      break;
+
+    case DW_FORM_data4:
+    case DW_FORM_ref4:
+      *len = 4;
+      break;
+
+    case DW_FORM_data8:
+    case DW_FORM_ref8:
+      *len = 8;
+      break;
+
+    case DW_FORM_string:
+      *len = strlen ((char *) valp) + 1;
+      break;
+
+    case DW_FORM_sdata:
+    case DW_FORM_udata:
+    case DW_FORM_ref_udata:
+      saved = valp;
+      get_uleb128 (u128, valp);
+      *len = valp - saved;
+      break;
+
+    case DW_FORM_indirect:
+      saved = valp;
+      get_uleb128 (u128, valp);
+      if (__libdwarf_form_val_len (dbg, cu, u128, valp, len, error)
+	  != DW_DLV_OK)
+	return DW_DLV_ERROR;
+      *len += valp - saved;
+      break;
+
+    default:
+      __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+      return DW_DLV_ERROR;
+    }
+
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_formaddr.c b/libdwarf/dwarf_formaddr.c
new file mode 100644
index 0000000..148508f
--- /dev/null
+++ b/libdwarf/dwarf_formaddr.c
@@ -0,0 +1,42 @@
+/* Return address represented by attribute.
+   Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_formaddr (attr, return_addr, error)
+     Dwarf_Attribute attr;
+     Dwarf_Addr *return_addr;
+     Dwarf_Error *error;
+{
+  if (unlikely (attr->form != DW_FORM_addr))
+    {
+      __libdwarf_error (attr->cu->dbg, error, DW_E_NO_ADDR);
+      return DW_DLV_ERROR;
+    }
+
+  if (attr->cu->address_size == 4)
+    *return_addr = read_4ubyte_unaligned (attr->cu->dbg, attr->valp);
+  else
+    *return_addr = read_8ubyte_unaligned (attr->cu->dbg, attr->valp);
+
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_formblock.c b/libdwarf/dwarf_formblock.c
new file mode 100644
index 0000000..44606ed
--- /dev/null
+++ b/libdwarf/dwarf_formblock.c
@@ -0,0 +1,76 @@
+/* Return block of uninterpreted data represented by attribute.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include <stdlib.h>
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_formblock (attr, return_block, error)
+     Dwarf_Attribute attr;
+     Dwarf_Block **return_block;
+     Dwarf_Error *error;
+{
+  Dwarf_Small *attrp = attr->valp;
+  Dwarf_Unsigned len;
+  Dwarf_Ptr *data;
+  Dwarf_Block *result;
+
+  switch (attr->form)
+    {
+    case DW_FORM_block1:
+      len = *attrp;
+      data = (Dwarf_Ptr) (attrp + 1);
+      break;
+
+    case DW_FORM_block2:
+      len = read_2ubyte_unaligned (attr->cu->dbg, attrp);
+      data = (Dwarf_Ptr) (attrp + 2);
+      break;
+
+    case DW_FORM_block4:
+      len = read_4ubyte_unaligned (attr->cu->dbg, attrp);
+      data = (Dwarf_Ptr) (attrp + 2);
+      break;
+
+    case DW_FORM_block:
+      get_uleb128 (len, attrp);
+      data = (Dwarf_Ptr) attrp;
+      break;
+
+    default:
+      __libdwarf_error (attr->cu->dbg, error, DW_E_NO_BLOCK);
+      return DW_DLV_ERROR;
+    }
+
+  /* Allocate memory for the result.  */
+  result = (Dwarf_Block *) malloc (sizeof (Dwarf_Block));
+  if (result == NULL)
+    {
+      __libdwarf_error (attr->cu->dbg, error, DW_E_NOMEM);
+      return DW_DLV_ERROR;
+    }
+
+  result->bl_len = len;
+  result->bl_data = data;
+
+  *return_block = result;
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_formflag.c b/libdwarf/dwarf_formflag.c
new file mode 100644
index 0000000..32a98fd
--- /dev/null
+++ b/libdwarf/dwarf_formflag.c
@@ -0,0 +1,39 @@
+/* Return flag represented by attribute.
+   Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_formflag (attr, return_bool, error)
+     Dwarf_Attribute attr;
+     Dwarf_Bool *return_bool;
+     Dwarf_Error *error;
+{
+  if (unlikely (attr->form != DW_FORM_flag))
+    {
+      __libdwarf_error (attr->cu->dbg, error, DW_E_NO_FLAG);
+      return DW_DLV_ERROR;
+    }
+
+  *return_bool = attr->valp != 0;
+
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_formref.c b/libdwarf/dwarf_formref.c
new file mode 100644
index 0000000..4ae353a
--- /dev/null
+++ b/libdwarf/dwarf_formref.c
@@ -0,0 +1,67 @@
+/* Return compile-unit relative offset of reference associated with form.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_formref (attr, return_offset, error)
+     Dwarf_Attribute attr;
+     Dwarf_Off *return_offset;
+     Dwarf_Error *error;
+{
+  switch (attr->form)
+    {
+    case DW_FORM_ref1:
+      *return_offset = *attr->valp;
+      break;
+
+    case DW_FORM_ref2:
+      *return_offset = read_2ubyte_unaligned (attr->cu->dbg, attr->valp);
+      break;
+
+    case DW_FORM_ref4:
+      *return_offset = read_4ubyte_unaligned (attr->cu->dbg, attr->valp);
+      break;
+
+    case DW_FORM_ref8:
+      *return_offset = read_8ubyte_unaligned (attr->cu->dbg, attr->valp);
+      break;
+
+    case DW_FORM_ref_udata:
+      {
+	Dwarf_Off off;
+	Dwarf_Small *attrp = attr->valp;
+	get_uleb128 (off, attrp);
+	*return_offset = off;
+      }
+      break;
+
+    case DW_FORM_ref_addr:
+      __libdwarf_error (attr->cu->dbg, error, DW_E_INVALID_REFERENCE);
+      return DW_DLV_ERROR;
+
+    default:
+      __libdwarf_error (attr->cu->dbg, error, DW_E_NO_REFERENCE);
+      return DW_DLV_ERROR;
+    }
+
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_formsdata.c b/libdwarf/dwarf_formsdata.c
new file mode 100644
index 0000000..8024e76
--- /dev/null
+++ b/libdwarf/dwarf_formsdata.c
@@ -0,0 +1,72 @@
+/* Return signed constant represented by attribute.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_formsdata (attr, return_sval, error)
+     Dwarf_Attribute attr;
+     Dwarf_Signed *return_sval;
+     Dwarf_Error *error;
+{
+  Dwarf_Signed u128;
+
+  switch (attr->form)
+    {
+    case DW_FORM_data1:
+      *return_sval = *attr->valp;
+      break;
+
+    case DW_FORM_data2:
+      *return_sval = read_2ubyte_unaligned (attr->cu->dbg, attr->valp);
+      break;
+
+    case DW_FORM_data4:
+      *return_sval = read_4ubyte_unaligned (attr->cu->dbg, attr->valp);
+      break;
+
+    case DW_FORM_data8:
+      *return_sval = read_8ubyte_unaligned (attr->cu->dbg, attr->valp);
+      break;
+
+    case DW_FORM_sdata:
+      {
+	Dwarf_Small *attrp = attr->valp;
+	get_sleb128 (u128, attrp);
+	*return_sval = u128;
+      }
+      break;
+
+    case DW_FORM_udata:
+      {
+	Dwarf_Small *attrp = attr->valp;
+	get_uleb128 (u128, attrp);
+	*return_sval = u128;
+      }
+      break;
+
+    default:
+      __libdwarf_error (attr->cu->dbg, error, DW_E_NO_CONSTANT);
+      return DW_DLV_ERROR;
+    }
+
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_formstring.c b/libdwarf/dwarf_formstring.c
new file mode 100644
index 0000000..205a946
--- /dev/null
+++ b/libdwarf/dwarf_formstring.c
@@ -0,0 +1,51 @@
+/* Return string represented by attribute.
+   Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include <string.h>
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_formstring (attr, return_string, error)
+     Dwarf_Attribute attr;
+     char **return_string;
+     Dwarf_Error *error;
+{
+  char *result;
+
+  if (attr->form == DW_FORM_string)
+    result = (char *) attr->valp;
+  else if (likely (attr->form == DW_FORM_strp))
+    {
+      Dwarf_Unsigned offset;
+
+      offset = read_4ubyte_unaligned (attr->cu->dbg, attr->valp);
+
+      result = (char *) attr->cu->dbg->sections[IDX_debug_str].addr + offset;
+    }
+  else
+    {
+      __libdwarf_error (attr->cu->dbg, error, DW_E_NO_STRING);
+      return DW_DLV_ERROR;
+    }
+
+  *return_string = result;
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_formudata.c b/libdwarf/dwarf_formudata.c
new file mode 100644
index 0000000..35e133c
--- /dev/null
+++ b/libdwarf/dwarf_formudata.c
@@ -0,0 +1,72 @@
+/* Return unsigned constant represented by attribute.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_formudata (attr, return_uval, error)
+     Dwarf_Attribute attr;
+     Dwarf_Unsigned *return_uval;
+     Dwarf_Error *error;
+{
+  Dwarf_Unsigned u128;
+
+  switch (attr->form)
+    {
+    case DW_FORM_data1:
+      *return_uval = *attr->valp;
+      break;
+
+    case DW_FORM_data2:
+      *return_uval = read_2ubyte_unaligned (attr->cu->dbg, attr->valp);
+      break;
+
+    case DW_FORM_data4:
+      *return_uval = read_4ubyte_unaligned (attr->cu->dbg, attr->valp);
+      break;
+
+    case DW_FORM_data8:
+      *return_uval = read_8ubyte_unaligned (attr->cu->dbg, attr->valp);
+      break;
+
+    case DW_FORM_sdata:
+      {
+	Dwarf_Small *attrp = attr->valp;
+	get_sleb128 (u128, attrp);
+	*return_uval = u128;
+      }
+      break;
+
+    case DW_FORM_udata:
+      {
+	Dwarf_Small *attrp = attr->valp;
+	get_uleb128 (u128, attrp);
+	*return_uval = u128;
+      }
+      break;
+
+    default:
+      __libdwarf_error (attr->cu->dbg, error, DW_E_NO_CONSTANT);
+      return DW_DLV_ERROR;
+    }
+
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_get_abbrev.c b/libdwarf/dwarf_get_abbrev.c
new file mode 100644
index 0000000..0295f9b
--- /dev/null
+++ b/libdwarf/dwarf_get_abbrev.c
@@ -0,0 +1,111 @@
+/* Get abbreviation record.
+   Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include <stdlib.h>
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_get_abbrev (dbg, offset, return_abbrev, length, attr_count, error)
+     Dwarf_Debug dbg;
+     Dwarf_Unsigned offset;
+     Dwarf_Abbrev *return_abbrev;
+     Dwarf_Unsigned *length;
+     Dwarf_Unsigned *attr_count;
+     Dwarf_Error *error;
+{
+  Dwarf_Abbrev ent;
+  Dwarf_Small *abbrevp;
+  Dwarf_Small *start_abbrevp;
+
+  /* Address in memory.  */
+  abbrevp = (Dwarf_Small *) dbg->sections[IDX_debug_abbrev].addr + offset;
+
+  /* Remember where we started.  */
+  start_abbrevp = abbrevp;
+
+  if (*abbrevp != '\0')
+    {
+      /* 7.5.3 Abbreviations Tables
+
+	 [...] Each declaration begins with an unsigned LEB128 number
+	 representing the abbreviation code itself.  [...]  The
+	 abbreviation code is followed by another unsigned LEB128
+	 number that encodes the entry's tag.  [...]
+
+	 [...] Following the tag encoding is a 1-byte value that
+	 determines whether a debugging information entry using this
+	 abbreviation has child entries or not. [...]
+
+	 [...] Finally, the child encoding is followed by a series of
+	 attribute specifications. Each attribute specification
+	 consists of two parts. The first part is an unsigned LEB128
+	 number representing the attribute's name. The second part is
+	 an unsigned LEB128 number representing the attribute s form.  */
+      Dwarf_Word abbrev_code;
+      Dwarf_Word abbrev_tag;
+      Dwarf_Word attr_name;
+      Dwarf_Word attr_form;
+      Dwarf_Unsigned attrcnt;
+
+      /* XXX We have no tests for crossing the section boundary here.
+	 We should compare with dbg->sections[IDX_debug_abbrev].size.  */
+      get_uleb128 (abbrev_code, abbrevp);
+      get_uleb128 (abbrev_tag, abbrevp);
+
+      /* Get memory for the result.  */
+      ent = (Dwarf_Abbrev) malloc (sizeof (struct Dwarf_Abbrev_s));
+      if (ent == NULL)
+	{
+	  __libdwarf_error (dbg, error, DW_E_NOMEM);
+	  return DW_DLV_ERROR;
+	}
+
+      ent->code = abbrev_code;
+      ent->tag = abbrev_tag;
+      ent->has_children = *abbrevp++ == DW_CHILDREN_yes;
+      ent->attrp = abbrevp;
+      ent->offset = offset;
+
+      /* Skip over all the attributes.  */
+      attrcnt = 0;
+      do
+	{
+	  get_uleb128 (attr_name, abbrevp);
+	  get_uleb128 (attr_form, abbrevp);
+	}
+      while (attr_name != 0 && attr_form != 0 && ++attrcnt);
+
+      /* Number of attributes.  */
+      *attr_count = ent->attrcnt = attrcnt;
+
+      /* Store the actual abbreviation record.  */
+      *return_abbrev = ent;
+    }
+  else
+    /* Read over the NUL byte.  */
+    ++abbrevp;
+
+  /* Length of the entry.  */
+  *length = abbrevp - start_abbrevp;
+
+  /* If we come here we haven't found anything.  */
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_get_abbrev_children_flag.c b/libdwarf/dwarf_get_abbrev_children_flag.c
new file mode 100644
index 0000000..079c85a
--- /dev/null
+++ b/libdwarf/dwarf_get_abbrev_children_flag.c
@@ -0,0 +1,29 @@
+/* Get children flag of abbreviation record.
+   Copyright (C) 2001, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwarfP.h"
+
+
+int dwarf_get_abbrev_children_flag (abbrev, return_flag, error)
+     Dwarf_Abbrev abbrev;
+     Dwarf_Signed *return_flag;
+     Dwarf_Error *error;
+{
+  *return_flag = abbrev->has_children;
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_get_abbrev_code.c b/libdwarf/dwarf_get_abbrev_code.c
new file mode 100644
index 0000000..08ecb43
--- /dev/null
+++ b/libdwarf/dwarf_get_abbrev_code.c
@@ -0,0 +1,29 @@
+/* Get code of abbreviation record.
+   Copyright (C) 2001, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwarfP.h"
+
+
+int dwarf_get_abbrev_code (abbrev, return_code, error)
+     Dwarf_Abbrev abbrev;
+     Dwarf_Unsigned *return_code;
+     Dwarf_Error *error;
+{
+  *return_code = abbrev->code;
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_get_abbrev_entry.c b/libdwarf/dwarf_get_abbrev_entry.c
new file mode 100644
index 0000000..4deccd0
--- /dev/null
+++ b/libdwarf/dwarf_get_abbrev_entry.c
@@ -0,0 +1,63 @@
+/* Get attribute from abbreviation record.
+   Copyright (C) 2001, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include <stdlib.h>
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_get_abbrev_entry (abbrev, idx, attr_num, form, offset, error)
+     Dwarf_Abbrev abbrev;
+     Dwarf_Signed idx;
+     Dwarf_Half *attr_num;
+     Dwarf_Signed *form;
+     Dwarf_Off *offset;
+     Dwarf_Error *error;
+{
+  Dwarf_Small *attrp;
+  Dwarf_Small *start_attrp;
+  Dwarf_Word attr_name;
+  Dwarf_Word attr_form;
+
+  if (idx < 0)
+    return DW_DLV_NO_ENTRY;
+
+  /* Address in memory.  */
+  attrp = abbrev->attrp;
+
+  /* Read the attributes, skip over the ones we don't want.  */
+  do
+    {
+      start_attrp = attrp;
+
+      get_uleb128 (attr_name, attrp);
+      get_uleb128 (attr_form, attrp);
+
+      if (attr_name == 0 || attr_form == 0)
+	return DW_DLV_NO_ENTRY;
+    }
+  while (idx-- > 0);
+
+  *attr_num = attr_name;
+  *form = attr_form;
+  *offset = (start_attrp - abbrev->attrp) + abbrev->offset;
+
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_get_abbrev_tag.c b/libdwarf/dwarf_get_abbrev_tag.c
new file mode 100644
index 0000000..b3f9fd1
--- /dev/null
+++ b/libdwarf/dwarf_get_abbrev_tag.c
@@ -0,0 +1,29 @@
+/* Get tag of abbreviation record.
+   Copyright (C) 2001, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwarfP.h"
+
+
+int dwarf_get_abbrev_tag (abbrev, return_tag, error)
+     Dwarf_Abbrev abbrev;
+     Dwarf_Half *return_tag;
+     Dwarf_Error *error;
+{
+  *return_tag = abbrev->tag;
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_get_address_size.c b/libdwarf/dwarf_get_address_size.c
new file mode 100644
index 0000000..fe5234c
--- /dev/null
+++ b/libdwarf/dwarf_get_address_size.c
@@ -0,0 +1,30 @@
+/* Return address size.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_get_address_size (dbg, addr_size, error)
+     Dwarf_Debug dbg;
+     Dwarf_Half *addr_size;
+     Dwarf_Error *error;
+{
+  *addr_size = elf_getident (dbg->elf, NULL)[EI_CLASS] == ELFCLASS64 ? 8 : 4;
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_get_arange.c b/libdwarf/dwarf_get_arange.c
new file mode 100644
index 0000000..02df19d
--- /dev/null
+++ b/libdwarf/dwarf_get_arange.c
@@ -0,0 +1,41 @@
+/* Find matching range for address.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_get_arange (aranges, arange_count, address, return_arange, error)
+     Dwarf_Arange *aranges;
+     Dwarf_Unsigned arange_count;
+     Dwarf_Addr address;
+     Dwarf_Arange *return_arange;
+     Dwarf_Error *error;
+{
+  Dwarf_Unsigned cnt;
+
+  for (cnt = 0; cnt < arange_count; ++cnt)
+    if (aranges[cnt]->address <= address
+	&& address < aranges[cnt]->address + aranges[cnt]->length)
+      {
+	*return_arange = aranges[cnt];
+	return DW_DLV_OK;
+      }
+
+  return DW_DLV_NO_ENTRY;
+}
diff --git a/libdwarf/dwarf_get_arange_info.c b/libdwarf/dwarf_get_arange_info.c
new file mode 100644
index 0000000..4d37e08
--- /dev/null
+++ b/libdwarf/dwarf_get_arange_info.c
@@ -0,0 +1,48 @@
+/* Return start, length, and CU DIE offset of range.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_get_arange_info (arange, start, length, cu_die_offset, error)
+     Dwarf_Arange arange;
+     Dwarf_Addr *start;
+     Dwarf_Unsigned *length;
+     Dwarf_Off *cu_die_offset;
+     Dwarf_Error *error;
+{
+  Dwarf_Small *cu_header;
+  unsigned int offset_size;
+
+  *start = arange->address;
+  *length = arange->length;
+
+  /* Determine the size of the CU header.  */
+  cu_header =
+    ((Dwarf_Small *) arange->info->dbg->sections[IDX_debug_info].addr
+     + arange->info->offset);
+  if (read_4ubyte_unaligned_noncvt (cu_header) == 0xffffffff)
+    offset_size = 8;
+  else
+    offset_size = 4;
+
+  *cu_die_offset = arange->info->offset + 3 * offset_size - 4 + 3;
+
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_get_aranges.c b/libdwarf/dwarf_get_aranges.c
new file mode 100644
index 0000000..b8cabb0
--- /dev/null
+++ b/libdwarf/dwarf_get_aranges.c
@@ -0,0 +1,186 @@
+/* Return list address ranges.
+   Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include <libdwarfP.h>
+
+
+struct arangelist
+{
+  Dwarf_Arange arange;
+  struct arangelist *next;
+};
+
+
+int
+dwarf_get_aranges (dbg, aranges, return_count, error)
+     Dwarf_Debug dbg;
+     Dwarf_Arange **aranges;
+     Dwarf_Signed *return_count;
+     Dwarf_Error *error;
+{
+  Dwarf_Small *readp;
+  Dwarf_Small *readendp;
+  struct arangelist *arangelist = NULL;
+  unsigned int narangelist = 0;
+
+  if (dbg->sections[IDX_debug_aranges].addr == NULL)
+    return DW_DLV_NO_ENTRY;
+
+  readp = (Dwarf_Small *) dbg->sections[IDX_debug_aranges].addr;
+  readendp = readp + dbg->sections[IDX_debug_aranges].size;
+
+  while (readp < readendp)
+    {
+      Dwarf_Small *hdrstart = readp;
+      Dwarf_Unsigned length;
+      unsigned int length_bytes;
+      unsigned int version;
+      Dwarf_Unsigned offset;
+      unsigned int address_size;
+      unsigned int segment_size;
+      Dwarf_Arange_Info arange_info;
+
+      /* Each entry starts with a header:
+
+	 1. A 4-byte or 12-byte length containing the length of the
+	 set of entries for this compilation unit, not including the
+	 length field itself. [...]
+
+	 2. A 2-byte version identifier containing the value 2 for
+	 DWARF Version 2.1.
+
+	 3. A 4-byte or 8-byte offset into the .debug_info section. [...]
+
+	 4. A 1-byte unsigned integer containing the size in bytes of
+	 an address (or the offset portion of an address for segmented
+	 addressing) on the target system.
+
+	 5. A 1-byte unsigned integer containing the size in bytes of
+	 a segment descriptor on the target system.  */
+      length = read_4ubyte_unaligned (dbg, readp);
+      readp += 4;
+      length_bytes = 4;
+      if (length == 0xffffffff)
+	{
+	  length = read_8ubyte_unaligned (dbg, readp);
+	  readp += 8;
+	  length_bytes = 8;
+	}
+
+      version = read_2ubyte_unaligned (dbg, readp);
+      readp += 2;
+      if (version != 2)
+	{
+	  __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+	  return DW_DLV_ERROR;
+	}
+
+      if (length_bytes == 4)
+	offset = read_4ubyte_unaligned (dbg, readp);
+      else
+	offset = read_8ubyte_unaligned (dbg, readp);
+      readp += length_bytes;
+
+      address_size = *readp++;
+      segment_size = *readp++;
+
+      /* Round the address to the next multiple of 2*address_size.  */
+      readp += ((2 * address_size - ((readp - hdrstart) % (2 * address_size)))
+		% (2 * address_size));
+
+      arange_info =
+	(Dwarf_Arange_Info) malloc (sizeof (struct Dwarf_Arange_s));
+      if (arange_info == NULL)
+	{
+	  __libdwarf_error (dbg, error, DW_E_NOMEM);
+	  return DW_DLV_ERROR;
+	}
+
+      arange_info->dbg = dbg;
+      arange_info->offset = offset;
+
+      while (1)
+	{
+	  Dwarf_Unsigned range_address;
+	  Dwarf_Unsigned range_length;
+	  struct arangelist *new_arange;
+
+	  if (address_size == 4)
+	    {
+	      range_address = read_4ubyte_unaligned (dbg, readp);
+	      readp += 4;
+	      range_length = read_4ubyte_unaligned (dbg, readp);
+	      readp += 4;
+	    }
+	  else if (likely (address_size == 8))
+	    {
+	      range_address = read_8ubyte_unaligned (dbg, readp);
+	      readp += 8;
+	      range_length = read_8ubyte_unaligned (dbg, readp);
+	      readp += 8;
+	    }
+	  else
+	    abort ();
+
+	  /* Two zero values mark the end.  */
+	  if (range_address == 0 && range_length == 0)
+	    break;
+
+	  new_arange =
+	    (struct arangelist *) alloca (sizeof (struct arangelist));
+	  new_arange->arange =
+	    (Dwarf_Arange) malloc (sizeof (struct Dwarf_Arange_s));
+	  if (new_arange->arange == NULL)
+	    {
+	      __libdwarf_error (dbg, error, DW_E_NOMEM);
+	      return DW_DLV_ERROR;
+	    }
+
+	  new_arange->arange->address = range_address;
+	  new_arange->arange->length = range_length;
+	  new_arange->arange->info = arange_info;
+
+	  new_arange->next = arangelist;
+	  arangelist = new_arange;
+	  ++narangelist;
+	}
+    }
+
+  if (narangelist == 0)
+    return DW_DLV_NO_ENTRY;
+
+  /* Allocate the array for the result.  */
+  *return_count = narangelist;
+  *aranges = (Dwarf_Arange *) malloc (narangelist
+				      * sizeof (struct Dwarf_Arange_s));
+  if (*aranges == NULL)
+    {
+      __libdwarf_error (dbg, error, DW_E_NOMEM);
+      return DW_DLV_ERROR;
+    }
+
+  while (narangelist-- > 0)
+    {
+      (*aranges)[narangelist] = arangelist->arange;
+      arangelist = arangelist->next;
+    }
+
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_get_cie_info.c b/libdwarf/dwarf_get_cie_info.c
new file mode 100644
index 0000000..029d9c9
--- /dev/null
+++ b/libdwarf/dwarf_get_cie_info.c
@@ -0,0 +1,53 @@
+/* Get information about CIE.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_get_cie_info (cie, bytes_in_cie, version, augmenter,
+		    code_alignment_factor, data_alignment_factor,
+		    return_address_register, initial_instructions,
+		    initial_instructions_length, error)
+     Dwarf_Cie cie;
+     Dwarf_Unsigned *bytes_in_cie;
+     Dwarf_Small *version;
+     char **augmenter;
+     Dwarf_Unsigned *code_alignment_factor;
+     Dwarf_Signed *data_alignment_factor;
+     Dwarf_Half *return_address_register;
+     Dwarf_Ptr *initial_instructions;
+     Dwarf_Unsigned *initial_instructions_length;
+     Dwarf_Error *error;
+{
+  *bytes_in_cie = cie->length;
+
+  *version = CIE_VERSION;
+
+  *augmenter = cie->augmentation;
+
+  *code_alignment_factor = cie->code_alignment_factor;
+  *data_alignment_factor = cie->data_alignment_factor;
+
+  *return_address_register = cie->return_address_register;
+
+  *initial_instructions = cie->initial_instructions;
+  *initial_instructions_length = cie->initial_instructions_length;
+
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_get_cie_of_fde.c b/libdwarf/dwarf_get_cie_of_fde.c
new file mode 100644
index 0000000..49718e9
--- /dev/null
+++ b/libdwarf/dwarf_get_cie_of_fde.c
@@ -0,0 +1,30 @@
+/* Get CIE of FDE.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_get_cie_of_fde (fde, return_cie, error)
+     Dwarf_Fde fde;
+     Dwarf_Cie *return_cie;
+     Dwarf_Error *error;
+{
+  *return_cie = fde->cie;
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_get_cu_die_offset.c b/libdwarf/dwarf_get_cu_die_offset.c
new file mode 100644
index 0000000..a358d5c
--- /dev/null
+++ b/libdwarf/dwarf_get_cu_die_offset.c
@@ -0,0 +1,43 @@
+/* Return offset of compile unit DIE containing the range.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_get_cu_die_offset (arange, return_offset, error)
+     Dwarf_Arange arange;
+     Dwarf_Off *return_offset;
+     Dwarf_Error *error;
+{
+  Dwarf_Small *cu_header;
+  unsigned int offset_size;
+
+  /* Determine the size of the CU header.  */
+  cu_header =
+    ((Dwarf_Small *) arange->info->dbg->sections[IDX_debug_info].addr
+     + arange->info->offset);
+  if (read_4ubyte_unaligned_noncvt (cu_header) == 0xffffffff)
+    offset_size = 8;
+  else
+    offset_size = 4;
+
+  *return_offset = arange->info->offset + 3 * offset_size - 4 + 3;
+
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_get_elf.c b/libdwarf/dwarf_get_elf.c
new file mode 100644
index 0000000..9313e95
--- /dev/null
+++ b/libdwarf/dwarf_get_elf.c
@@ -0,0 +1,33 @@
+/* Return ELF handle.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_get_elf_init (dbg, elf, error)
+     Dwarf_Debug dbg;
+     Elf **elf;
+     Dwarf_Error *error;
+{
+  if (dbg == NULL)
+    return DW_DLV_ERROR;
+
+  *elf = dbg->elf;
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_get_fde_at_pc.c b/libdwarf/dwarf_get_fde_at_pc.c
new file mode 100644
index 0000000..fee2efd
--- /dev/null
+++ b/libdwarf/dwarf_get_fde_at_pc.c
@@ -0,0 +1,57 @@
+/* Find FDE for given address.
+   Copyright (C) 2001, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwarfP.h"
+
+
+int
+dwarf_get_fde_at_pc (fde_data, pc_of_interest, returned_fde, lopc, hipc, error)
+     Dwarf_Fde *fde_data;
+     Dwarf_Addr pc_of_interest;
+     Dwarf_Fde *returned_fde;
+     Dwarf_Addr *lopc;
+     Dwarf_Addr *hipc;
+     Dwarf_Error *error;
+{
+  Dwarf_Debug dbg = fde_data[0]->cie->dbg;
+  int low = 0;
+  int high = dbg->fde_cnt - 1;
+
+  /* Since the FDEs are sorted by their addresses and since there can
+     potentially be many FDEs we better use binary search.  */
+  while (low <= high)
+    {
+      int curidx = (low + high) / 2;
+      Dwarf_Fde cur = fde_data[curidx];
+
+      if (pc_of_interest < cur->initial_location)
+	high = curidx - 1;
+      else if (likely (cur->initial_location + cur->address_range
+		       <= pc_of_interest))
+	low = curidx + 1;
+      else
+	{
+	  *returned_fde = cur;
+	  *lopc = cur->initial_location;
+	  *hipc = cur->initial_location + cur->address_range - 1;
+	  return DW_DLV_OK;
+	}
+    }
+
+  return DW_DLV_NO_ENTRY;
+}
diff --git a/libdwarf/dwarf_get_fde_instr_bytes.c b/libdwarf/dwarf_get_fde_instr_bytes.c
new file mode 100644
index 0000000..74a5388
--- /dev/null
+++ b/libdwarf/dwarf_get_fde_instr_bytes.c
@@ -0,0 +1,33 @@
+/* Get frame construction instructions of FDE.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_get_fde_instr_bytes (fde, outinstrs, outlen, error)
+     Dwarf_Fde fde;
+     Dwarf_Ptr *outinstrs;
+     Dwarf_Unsigned *outlen;
+     Dwarf_Error *error;
+{
+  *outinstrs = fde->instructions;
+  *outlen = fde->instructions_length;
+
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_get_fde_list_eh.c b/libdwarf/dwarf_get_fde_list_eh.c
new file mode 100644
index 0000000..bcda71b
--- /dev/null
+++ b/libdwarf/dwarf_get_fde_list_eh.c
@@ -0,0 +1,363 @@
+/* Get frame descriptions.  GCC version using .eh_frame.
+   Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <libdwarfP.h>
+
+
+struct cielist
+{
+  Dwarf_Cie cie;
+  struct cielist *next;
+};
+
+
+struct fdelist
+{
+  Dwarf_Fde fde;
+  Dwarf_Small *cie_id_ptr;
+  struct fdelist *next;
+};
+
+
+int
+dwarf_get_fde_list_eh (dbg, cie_data, cie_element_count, fde_data,
+		       fde_element_count, error)
+     Dwarf_Debug dbg;
+     Dwarf_Cie **cie_data;
+     Dwarf_Signed *cie_element_count;
+     Dwarf_Fde **fde_data;
+     Dwarf_Signed *fde_element_count;
+     Dwarf_Error *error;
+{
+  Dwarf_Small *readp;
+  Dwarf_Small *readendp;
+  struct cielist *cielist = NULL;
+  struct cielist *copy_cielist;
+  unsigned int ncielist = 0;
+  struct fdelist *fdelist = NULL;
+  unsigned int nfdelist = 0;
+
+  if (dbg->sections[IDX_eh_frame].addr == NULL)
+    return DW_DLV_NO_ENTRY;
+
+  readp = (Dwarf_Small *) dbg->sections[IDX_eh_frame].addr;
+  readendp = readp + dbg->sections[IDX_eh_frame].size;
+
+  while (readp < readendp)
+    {
+      /* Each CIE contains the following:
+
+	 1. CIE_length (initial length)
+
+	 A constant that gives the number of bytes of the CIE
+	 structure, not including the length field, itself [...].
+
+	 2. CIE_id
+
+	 A constant that is used to distinguish CIEs from FDEs.
+
+	 3. version (ubyte) [...]
+
+	 4. augmentation (array of ubyte)
+
+	 A null-terminated string that identifies the augmentation to
+	 this CIE or to the FDEs that use it.
+
+	 5. code_alignment_factor (unsigned LEB128)
+
+	 A constant that is factored out of all advance location
+	 instructions (see below).
+
+	 6. data_alignment_factor (signed LEB128)
+
+	 A constant that is factored out of all offset instructions
+	 [...].
+
+	 7. return_address_register (ubyte)
+
+	 A constant that indicates which column in the rule table
+	 represents the return address of the function.
+
+	 8. initial_instructions (array of ubyte) [...] */
+      Dwarf_Small *fde_cie_start;
+      Dwarf_Small *readstartp;
+      Dwarf_Small *cie_id_ptr;
+      Dwarf_Unsigned length;
+      unsigned int address_size;
+      Dwarf_Unsigned start_offset;
+      Dwarf_Unsigned cie_id;
+
+      /* Remember where this entry started.  */
+      fde_cie_start = readp;
+      start_offset = (readp
+		      - (Dwarf_Small *) dbg->sections[IDX_eh_frame].addr);
+
+      length = read_4ubyte_unaligned (dbg, readp);
+      address_size = 4;
+      readp += 4;
+      if (length == 0xffffffff)
+	{
+	  length = read_8ubyte_unaligned (dbg, readp);
+	  readp += 8;
+	  address_size = 8;
+	}
+      readstartp = readp;
+
+      /* Requirement from the DWARF specification.  */
+      if (unlikely (length % address_size != 0))
+	{
+	  /* XXX Free resources.  */
+	  __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+	  return DW_DLV_ERROR;
+	}
+
+      /* No more entries.  */
+      if (length == 0)
+	break;
+
+      cie_id_ptr = readp;
+      if (address_size == 4)
+	{
+	  cie_id = read_4sbyte_unaligned (dbg, readp);
+	  readp += 4;
+	}
+      else
+	{
+	  cie_id = read_8sbyte_unaligned (dbg, readp);
+	  readp += 8;
+	}
+
+      /* Now we can distinguish between CIEs and FDEs.  gcc uses 0 to
+	 signal the record is a CIE.  */
+      if (cie_id == 0)
+	{
+	  char *augmentation;
+	  Dwarf_Unsigned code_alignment_factor;
+	  Dwarf_Signed data_alignment_factor;
+	  Dwarf_Small *initial_instructions;
+	  Dwarf_Small return_address_register;
+	  struct cielist *new_cie;
+
+	  if (unlikely (*readp++ != CIE_VERSION))
+	    {
+	      __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+	      return DW_DLV_ERROR;
+	    }
+
+	  augmentation = (char *) readp;
+	  readp += strlen (augmentation) + 1;
+
+	  if (strcmp (augmentation, "") == 0)
+	    {
+	      get_uleb128 (code_alignment_factor, readp);
+	      get_sleb128 (data_alignment_factor, readp);
+	      return_address_register = *readp++;
+	      initial_instructions = readp;
+	    }
+	  else if (strcmp (augmentation, "eh") == 0)
+	    {
+	      /* GCC exception handling.  It has an extra field next
+		 which is the address of a exception table.  We ignore
+		 this value since it's only used at runtime by the
+		 exception handling.  */
+	      readp += address_size;
+
+	      /* Now the standard fields.  */
+	      get_uleb128 (code_alignment_factor, readp);
+	      get_sleb128 (data_alignment_factor, readp);
+	      return_address_register = *readp++;
+	      initial_instructions = readp;
+	    }
+	  else
+	    {
+	      /* We don't know this augmentation.  Skip the rest.  The
+		 specification says that nothing after the augmentation
+		 string is usable.  */
+	      code_alignment_factor = 0;
+	      data_alignment_factor = 0;
+	      return_address_register = 0;
+	      initial_instructions = NULL;
+	    }
+
+	  /* Go to the next record.  */
+	  readp = readstartp + length;
+
+	  /* Create the new CIE record.  */
+	  new_cie = (struct cielist *) alloca (sizeof (struct cielist));
+	  new_cie->cie = (Dwarf_Cie) malloc (sizeof (struct Dwarf_Cie_s));
+	  if (new_cie->cie == NULL)
+	    {
+	      __libdwarf_error (dbg, error, DW_E_NOMEM);
+	      return DW_DLV_ERROR;
+	    }
+
+	  new_cie->cie->dbg = dbg;
+	  new_cie->cie->length = length;
+	  new_cie->cie->augmentation = augmentation;
+	  new_cie->cie->code_alignment_factor = code_alignment_factor;
+	  new_cie->cie->data_alignment_factor = data_alignment_factor;
+	  new_cie->cie->return_address_register = return_address_register;
+	  new_cie->cie->initial_instructions = initial_instructions;
+	  new_cie->cie->initial_instructions_length =
+	    readp - initial_instructions;
+
+	  new_cie->cie->offset = start_offset;
+	  new_cie->cie->index = ncielist;
+	  new_cie->next = cielist;
+	  cielist = new_cie;
+	  ++ncielist;
+	}
+      else
+	{
+	  Dwarf_Addr initial_location;
+	  Dwarf_Unsigned address_range;
+	  Dwarf_Small *instructions;
+	  struct fdelist *new_fde;
+	  struct cielist *cie;
+
+	  if (address_size == 4)
+	    {
+	      initial_location = read_4ubyte_unaligned (dbg, readp);
+	      readp += 4;
+	      address_range = read_4ubyte_unaligned (dbg, readp);
+	      readp += 4;
+	    }
+	  else
+	    {
+	      initial_location = read_8ubyte_unaligned (dbg, readp);
+	      readp += 8;
+	      address_range = read_8ubyte_unaligned (dbg, readp);
+	      readp += 8;
+	    }
+
+	  instructions = readp;
+
+	  /* Go to the next record.  */
+	  readp = readstartp + length;
+
+	  /* Create the new FDE record.  */
+	  new_fde = (struct fdelist *) alloca (sizeof (struct fdelist));
+	  new_fde->fde = (Dwarf_Fde) malloc (sizeof (struct Dwarf_Fde_s));
+	  if (new_fde->fde == NULL)
+	    {
+	      __libdwarf_error (dbg, error, DW_E_NOMEM);
+	      return DW_DLV_ERROR;
+	    }
+
+	  new_fde->fde->initial_location = initial_location;
+	  new_fde->fde->address_range = address_range;
+	  new_fde->fde->instructions = instructions;
+	  new_fde->fde->instructions_length = readp - instructions;
+	  new_fde->fde->fde_bytes = fde_cie_start;
+	  new_fde->fde->fde_byte_length = readstartp + length - fde_cie_start;
+	  new_fde->fde->cie = NULL;
+	  new_fde->cie_id_ptr = cie_id_ptr;
+
+	  for (cie = cielist; cie != NULL; cie = cie->next)
+	    /* This test takes the non-standard way of using the CIE ID
+	       in the GNU .eh_frame sectio into account.  Instead of being
+	       a direct offset in the section it is a offset from the
+	       location of the FDE'S CIE ID value itself to the CIE entry.  */
+	    if (cie->cie->offset
+		== (size_t) (cie_id_ptr - cie_id
+			     - (Dwarf_Small *) dbg->sections[IDX_eh_frame].addr))
+	      {
+		new_fde->fde->cie = cie->cie;
+		break;
+	      }
+
+	  new_fde->fde->offset = cie_id;
+	  new_fde->next = fdelist;
+	  fdelist = new_fde;
+	  ++nfdelist;
+	}
+    }
+
+  /* There must always be at least one CIE.  */
+  if (unlikely (ncielist == 0))
+    {
+      __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+      return DW_DLV_ERROR;
+    }
+
+  /* Create the lists.  */
+  *cie_data = (Dwarf_Cie *) malloc (ncielist * sizeof (struct Dwarf_Cie_s));
+  if (nfdelist > 0)
+    *fde_data = (Dwarf_Fde *) malloc (nfdelist * sizeof (struct Dwarf_Fde_s));
+  else
+    *fde_data = NULL;
+  if ((nfdelist > 0 && *fde_data == NULL) || *cie_data == NULL)
+    {
+      __libdwarf_error (dbg, error, DW_E_NOMEM);
+      return DW_DLV_ERROR;
+    }
+
+  /* Remember the counts.  */
+  dbg->fde_cnt = nfdelist;
+  dbg->cie_cnt = ncielist;
+
+  /* Add all the CIEs.  */
+  copy_cielist = cielist;
+  *cie_element_count = ncielist;
+  while (ncielist-- > 0)
+    {
+      (*cie_data)[ncielist] = cielist->cie;
+      cielist = cielist->next;
+    }
+
+  /* Add all the FDEs.  */
+  *fde_element_count = nfdelist;
+  while (nfdelist-- > 0)
+    {
+      (*fde_data)[nfdelist] = fdelist->fde;
+
+      if (fdelist->fde->cie == NULL)
+	{
+	  /* We have not yet found the CIE.  Search now that we know
+             about all of them.  */
+	  cielist = copy_cielist;
+	  do
+	    {
+	      if (cielist->cie->offset
+		  == (size_t) (fdelist->cie_id_ptr - fdelist->fde->offset
+			       - (Dwarf_Small *) dbg->sections[IDX_eh_frame].addr))
+		{
+		  fdelist->fde->cie = cielist->cie;
+		  break;
+		}
+	      cielist = cielist->next;
+	    }
+	  while (cielist != NULL);
+
+	  if (cielist == NULL)
+	    {
+	      /* There is no matching CIE.  This is bad.  */
+	      /* XXX Free everything.  */
+	      __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+	      return DW_DLV_ERROR;
+	    }
+	}
+
+      fdelist = fdelist->next;
+    }
+
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_get_fde_n.c b/libdwarf/dwarf_get_fde_n.c
new file mode 100644
index 0000000..5531dea
--- /dev/null
+++ b/libdwarf/dwarf_get_fde_n.c
@@ -0,0 +1,36 @@
+/* Get nth frame descriptions.
+   Copyright (C) 2001, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwarfP.h"
+
+
+int
+dwarf_get_fde_n (fde_data, fde_index, returned_fde, error)
+     Dwarf_Fde *fde_data;
+     Dwarf_Unsigned fde_index;
+     Dwarf_Fde *returned_fde;
+     Dwarf_Error *error;
+{
+  Dwarf_Debug dbg = fde_data[0]->cie->dbg;
+
+  if (fde_index >= dbg->fde_cnt)
+    return DW_DLV_NO_ENTRY;
+
+  *returned_fde = fde_data[fde_index];
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_get_fde_range.c b/libdwarf/dwarf_get_fde_range.c
new file mode 100644
index 0000000..f704914
--- /dev/null
+++ b/libdwarf/dwarf_get_fde_range.c
@@ -0,0 +1,44 @@
+/* Get information about the function range.
+   Copyright (C) 2001, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwarfP.h"
+
+
+int
+dwarf_get_fde_range (fde, low_pc, func_length, fde_bytes, fde_byte_length,
+		     cie_offset, cie_index, fde_offset, error)
+     Dwarf_Fde fde;
+     Dwarf_Addr *low_pc;
+     Dwarf_Unsigned *func_length;
+     Dwarf_Ptr *fde_bytes;
+     Dwarf_Unsigned *fde_byte_length;
+     Dwarf_Off *cie_offset;
+     Dwarf_Signed *cie_index;
+     Dwarf_Off *fde_offset;
+     Dwarf_Error *error;
+{
+  *low_pc = fde->initial_location;
+  *func_length = fde->address_range;
+  *fde_bytes = fde->fde_bytes;
+  *fde_byte_length = fde->fde_byte_length;
+  *cie_offset = fde->cie->offset;
+  *cie_index = fde->cie->index;
+  *fde_offset = fde->offset;
+
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_get_globals.c b/libdwarf/dwarf_get_globals.c
new file mode 100644
index 0000000..01b48ae
--- /dev/null
+++ b/libdwarf/dwarf_get_globals.c
@@ -0,0 +1,176 @@
+/* Return list of global definitions.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <libdwarfP.h>
+
+
+struct globallist
+{
+  Dwarf_Global global;
+  struct globallist *next;
+};
+
+
+/* Read the whole given section.  */
+int
+dwarf_get_globals (dbg, globals, return_count, error)
+     Dwarf_Debug dbg;
+     Dwarf_Global **globals;
+     Dwarf_Signed *return_count;
+     Dwarf_Error *error;
+{
+  Dwarf_Small *readp;
+  Dwarf_Small *readendp;
+  struct globallist *globallist = NULL;
+  unsigned int ngloballist = 0;
+
+  if (dbg->sections[IDX_debug_pubnames].addr == NULL)
+    return DW_DLV_NO_ENTRY;
+
+  readp = (Dwarf_Small *) dbg->sections[IDX_debug_pubnames].addr;
+  readendp = readp + dbg->sections[IDX_debug_pubnames].size;
+
+  while (readp < readendp)
+    {
+      Dwarf_Unsigned length;
+      Dwarf_Unsigned info_length;
+      unsigned int length_bytes;
+      unsigned int version;
+      Dwarf_Unsigned offset;
+      Dwarf_Global_Info global_info;
+
+      /* Each entry starts with a header:
+
+ 	 1. A 4-byte or 12-byte length of the set of entries for this
+ 	 compilation unit, not including the length field itself. [...]
+
+	 2. A 2-byte version identifier containing the value 2 for
+	 DWARF Version 2.1.
+
+	 3. A 4-byte or 8-byte offset into the .debug_info section. [...]
+
+	 4. A 4-byte or 8-byte length containing the size in bytes of
+	 the contents of the .debug_info section generated to
+	 represent this compilation unit. [...]  */
+      length = read_4ubyte_unaligned (dbg, readp);
+      readp += 4;
+      length_bytes = 4;
+      if (length == 0xffffffff)
+	{
+	  length = read_8ubyte_unaligned (dbg, readp);
+	  readp += 8;
+	  length_bytes = 8;
+	}
+
+      version = read_2ubyte_unaligned (dbg, readp);
+      readp += 2;
+      if (unlikely (version != 2))
+	{
+	  __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+	  return DW_DLV_ERROR;
+	}
+
+      if (length_bytes == 4)
+	{
+	  offset = read_4ubyte_unaligned (dbg, readp);
+	  readp += 4;
+	  info_length = read_4ubyte_unaligned (dbg, readp);
+	  readp += 4;
+	}
+      else
+	{
+	  offset = read_8ubyte_unaligned (dbg, readp);
+	  readp += 8;
+	  info_length = read_8ubyte_unaligned (dbg, readp);
+	  readp += 8;
+	}
+
+      global_info =
+	(Dwarf_Global_Info) malloc (sizeof (struct Dwarf_Global_s));
+      if (global_info == NULL)
+	{
+	  __libdwarf_error (dbg, error, DW_E_NOMEM);
+	  return DW_DLV_ERROR;
+	}
+
+      global_info->dbg = dbg;
+      global_info->offset = offset;
+
+      /* Following the section contains tuples of offsets and
+         nul-terminated strings.  */
+      while (1)
+	{
+	  Dwarf_Unsigned die_offset;
+	  struct globallist *new_global;
+
+	  if (length_bytes == 4)
+	    die_offset = read_4ubyte_unaligned (dbg, readp);
+	  else
+	    die_offset = read_8ubyte_unaligned (dbg, readp);
+	  readp += length_bytes;
+
+	  if (die_offset == 0)
+	    /* This closes this entry.  */
+	    break;
+
+	  new_global =
+	    (struct globallist *) alloca (sizeof (struct globallist));
+	  new_global->global =
+	    (Dwarf_Global) malloc (sizeof (struct Dwarf_Global_s));
+	  if (new_global->global == NULL)
+	    {
+	      __libdwarf_error (dbg, error, DW_E_NOMEM);
+	      return DW_DLV_ERROR;
+	    }
+
+	  new_global->global->offset = die_offset;
+	  new_global->global->name = (char *) readp;
+	  new_global->global->info = global_info;
+
+	  new_global->next = globallist;
+	  globallist = new_global;
+	  ++ngloballist;
+
+	  readp = (Dwarf_Small *) rawmemchr (readp, '\0') + 1;
+	}
+    }
+
+  if (ngloballist == 0)
+    return DW_DLV_NO_ENTRY;
+
+  /* Allocate the array for the result.  */
+  *return_count = ngloballist;
+  *globals = (Dwarf_Global *) malloc (ngloballist
+				      * sizeof (struct Dwarf_Global_s));
+  if (*globals == NULL)
+    {
+      __libdwarf_error (dbg, error, DW_E_NOMEM);
+      return DW_DLV_ERROR;
+    }
+
+  while (ngloballist-- > 0)
+    {
+      (*globals)[ngloballist] = globallist->global;
+      globallist = globallist->next;
+    }
+
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_get_loclist_entry.c b/libdwarf/dwarf_get_loclist_entry.c
new file mode 100644
index 0000000..f6510c7
--- /dev/null
+++ b/libdwarf/dwarf_get_loclist_entry.c
@@ -0,0 +1,88 @@
+/* Return location list entry.
+   Copyright (C) 2001, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwarfP.h"
+
+
+int
+dwarf_get_loclist_entry (dbg, offset, hipc_offset, lopc_offset, data,
+			 entry_len, next_entry, error)
+     Dwarf_Debug dbg;
+     Dwarf_Unsigned offset;
+     Dwarf_Addr *hipc_offset;
+     Dwarf_Addr *lopc_offset;
+     Dwarf_Ptr *data;
+     Dwarf_Unsigned *entry_len;
+     Dwarf_Unsigned *next_entry;
+     Dwarf_Error *error;
+{
+  Dwarf_Small *locp;
+
+  /* Make sure we have room for at least two addresses.  */
+  if (unlikely (offset + 2 * dbg->cu_list->address_size
+		> dbg->sections[IDX_debug_loc].size))
+    {
+      __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+      return DW_DLV_ERROR;
+    }
+
+  locp = (Dwarf_Small *) dbg->sections[IDX_debug_loc].addr + offset;
+
+  /* Get the two values.  */
+  if (dbg->cu_list->address_size == 4)
+    {
+      *lopc_offset = read_4ubyte_unaligned (dbg, locp);
+      *hipc_offset = read_4ubyte_unaligned (dbg, locp + 4);
+      locp += 8;
+      offset += 8;
+    }
+  else
+    {
+      *lopc_offset = read_8ubyte_unaligned (dbg, locp);
+      *hipc_offset = read_8ubyte_unaligned (dbg, locp + 8);
+      locp += 16;
+      offset += 16;
+    }
+
+  /* Does this signal the end?  */
+  if (*lopc_offset == 0 && *hipc_offset == 0)
+    return DW_DLV_OK;
+
+  /* Make sure another 2 bytes are available for the length.  */
+  if (unlikely (offset + 2 > dbg->sections[IDX_debug_loc].size))
+    {
+      __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+      return DW_DLV_ERROR;
+    }
+  *entry_len = read_2ubyte_unaligned (dbg, locp);
+  locp += 2;
+  offset += 2;
+  *data = locp;
+
+  /* Now we know how long the block is.  Test whether that much
+     data is available.  */
+  if (unlikely (offset + *entry_len > dbg->sections[IDX_debug_loc].size))
+    {
+      __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+      return DW_DLV_ERROR;
+    }
+
+  *next_entry = offset + *entry_len;
+
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_get_str.c b/libdwarf/dwarf_get_str.c
new file mode 100644
index 0000000..3f289c3
--- /dev/null
+++ b/libdwarf/dwarf_get_str.c
@@ -0,0 +1,43 @@
+/* Return string from debug string section.
+   Copyright (C) 2001, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#include "libdwarfP.h"
+
+
+int
+dwarf_get_str (dbg, offset, string, returned_str_len, error)
+     Dwarf_Debug dbg;
+     Dwarf_Off offset;
+     char **string;
+     Dwarf_Signed *returned_str_len;
+     Dwarf_Error *error;
+{
+  *string = (char *) dbg->sections[IDX_debug_str].addr;
+  if (*string == NULL)
+    return DW_DLV_NO_ENTRY;
+
+  if (unlikely (offset >= dbg->sections[IDX_debug_str].size))
+    return DW_DLV_NO_ENTRY;
+
+  *string += offset;
+  *returned_str_len = strlen (*string);
+
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_getabbrev.c b/libdwarf/dwarf_getabbrev.c
new file mode 100644
index 0000000..2220fc3
--- /dev/null
+++ b/libdwarf/dwarf_getabbrev.c
@@ -0,0 +1,73 @@
+/* Internal abbrev list handling
+   Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include <stdlib.h>
+
+#include <libdwarfP.h>
+
+
+Dwarf_Abbrev
+__libdwarf_get_abbrev (dbg, cu, code, error)
+     Dwarf_Debug dbg;
+     Dwarf_CU_Info cu;
+     Dwarf_Word code;
+     Dwarf_Error *error;
+{
+  Dwarf_Abbrev ent;
+
+  /* See whether the entry is already in the hash table.  */
+  ent = Dwarf_Abbrev_Hash_find (&cu->abbrev_hash, code, NULL);
+  if (ent != NULL)
+    return ent;
+
+  while (1)
+    {
+      Dwarf_Unsigned length;
+      Dwarf_Unsigned attr_count;
+
+      if (dwarf_get_abbrev (dbg, cu->last_abbrev_offset, &ent, &length,
+			    &attr_count, error) != DW_DLV_OK)
+	return NULL;
+
+      if (length == 1)
+	/* This is the end of the list.  */
+	break;
+
+      /* Update the offset to the next record.  */
+      cu->last_abbrev_offset += length;
+
+      /* Insert the new entry into the hashing table.  */
+      if (unlikely (Dwarf_Abbrev_Hash_insert (&cu->abbrev_hash, ent->code, ent)
+		    != 0))
+	{
+	  free (ent);
+	  __libdwarf_error (dbg, error, DW_E_NOMEM);
+	  return NULL;
+	}
+
+      /* Is this the code we are looking for?  */
+      if (ent->code == code)
+	/* Yes!  */
+	return ent;
+    }
+
+  /* If we come here we haven't found anything.  */
+  __libdwarf_error (dbg, error, DW_E_NO_ABBR);
+  return NULL;
+}
diff --git a/libdwarf/dwarf_getconstant.c b/libdwarf/dwarf_getconstant.c
new file mode 100644
index 0000000..39727f8
--- /dev/null
+++ b/libdwarf/dwarf_getconstant.c
@@ -0,0 +1,125 @@
+/* Return constant value of given attribute type associated with die.
+   Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+
+#include <libdwarfP.h>
+
+
+int
+__libdwarf_getconstant (die, name, return_size, error)
+     Dwarf_Die die;
+     Dwarf_Half name;
+     Dwarf_Unsigned *return_size;
+     Dwarf_Error *error;
+{
+  Dwarf_Debug dbg = die->cu->dbg;
+  Dwarf_Small *die_addr;
+  Dwarf_Word u128;
+  Dwarf_Abbrev abbrev;
+  Dwarf_Small *attrp;
+
+  /* Address of the given die.  */
+  die_addr = die->addr;
+
+  /* Get abbrev code.  */
+  get_uleb128 (u128, die_addr);
+  /*  And get the abbreviation itself.  */
+  abbrev = __libdwarf_get_abbrev (dbg, die->cu, u128, error);
+  if (abbrev == NULL)
+    return DW_DLV_ERROR;
+
+  /* This is where the attributes start.  */
+  attrp = abbrev->attrp;
+
+  /* Search the name attribute.  */
+  while (1)
+    {
+      Dwarf_Word attr_name;
+      Dwarf_Word attr_form;
+
+      /* Are we still in bounds?  */
+      if (unlikely (attrp
+		    >= ((Dwarf_Small *) dbg->sections[IDX_debug_abbrev].addr
+			+ dbg->sections[IDX_debug_abbrev].size)))
+	{
+	  __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+	  return DW_DLV_ERROR;
+	}
+
+      /* Get attribute name and form.
+
+	 XXX We don't check whether this reads beyond the end of the
+	 section.  */
+      get_uleb128 (attr_name, attrp);
+      get_uleb128 (attr_form, attrp);
+
+      /* We can stop if we found the attribute with value zero.  */
+      if (attr_name == 0 && attr_form == 0)
+	break;
+
+      /* Is this the name attribute?  */
+      if (unlikely (attr_name == name))
+	{
+	  switch (attr_form)
+	    {
+	    case DW_FORM_data1:
+	      *return_size = *die_addr;
+	      break;
+	    case DW_FORM_data2:
+	      *return_size = read_2ubyte_unaligned (dbg, die_addr);
+	      break;
+	    case DW_FORM_data4:
+	      *return_size = read_4ubyte_unaligned (dbg, die_addr);
+	      break;
+	    case DW_FORM_data8:
+	      *return_size = read_8ubyte_unaligned (dbg, die_addr);
+	      break;
+	    case DW_FORM_sdata:
+	      get_sleb128 (u128, die_addr);
+	      *return_size = u128;
+	      break;
+	    case DW_FORM_udata:
+	      get_uleb128 (u128, die_addr);
+	      *return_size = u128;
+	      break;
+	    default:
+	      __libdwarf_error (dbg, error, DW_E_NO_CONSTANT);
+	      return DW_DLV_ERROR;
+	    }
+
+	  return DW_DLV_OK;
+	}
+
+      /* Skip over the rest of this attribute (if there is any).  */
+      if (attr_form != 0)
+	{
+	  size_t len;
+
+	  if (unlikely (__libdwarf_form_val_len (dbg, die->cu, attr_form,
+						 die_addr, &len, error)
+			!= DW_DLV_OK))
+	    return DW_DLV_ERROR;
+
+	  die_addr += len;
+	}
+    }
+
+  /* No such attribute present.  */
+  return DW_DLV_NO_ENTRY;
+}
diff --git a/libdwarf/dwarf_global_cu_offset.c b/libdwarf/dwarf_global_cu_offset.c
new file mode 100644
index 0000000..b5a30f4
--- /dev/null
+++ b/libdwarf/dwarf_global_cu_offset.c
@@ -0,0 +1,44 @@
+/* Return offset of header of compile unit containing the global definition.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_global_cu_offset (global, return_offset, error)
+     Dwarf_Global global;
+     Dwarf_Off *return_offset;
+     Dwarf_Error *error;
+{
+  Dwarf_Small *cu_header;
+  unsigned int offset_size;
+
+  cu_header =
+    ((Dwarf_Small *) global->info->dbg->sections[IDX_debug_info].addr
+     + global->info->offset);
+  if (read_4ubyte_unaligned_noncvt (cu_header) == 0xffffffff)
+    offset_size = 8;
+  else
+    offset_size = 4;
+
+  *return_offset = global->info->offset + 3 * offset_size - 4 + 3;
+
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_global_die_offset.c b/libdwarf/dwarf_global_die_offset.c
new file mode 100644
index 0000000..654340f
--- /dev/null
+++ b/libdwarf/dwarf_global_die_offset.c
@@ -0,0 +1,33 @@
+/* Return DIE offset for global definition.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_global_die_offset (global, return_offset, error)
+     Dwarf_Global global;
+     Dwarf_Off *return_offset;
+     Dwarf_Error *error;
+{
+  *return_offset = global->info->offset + global->offset;
+
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_global_formref.c b/libdwarf/dwarf_global_formref.c
new file mode 100644
index 0000000..16ea7b7
--- /dev/null
+++ b/libdwarf/dwarf_global_formref.c
@@ -0,0 +1,73 @@
+/* Return .debug_info section global offset of reference associated with form.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_global_formref (attr, return_offset, error)
+     Dwarf_Attribute attr;
+     Dwarf_Off *return_offset;
+     Dwarf_Error *error;
+{
+  switch (attr->form)
+    {
+    case DW_FORM_ref1:
+      *return_offset = *attr->valp + attr->cu->offset;
+      break;
+
+    case DW_FORM_ref2:
+      *return_offset = (read_2ubyte_unaligned (attr->cu->dbg, attr->valp)
+			+ attr->cu->offset);
+      break;
+
+    case DW_FORM_ref4:
+      *return_offset = (read_4ubyte_unaligned (attr->cu->dbg, attr->valp)
+			+ attr->cu->offset);
+      break;
+
+    case DW_FORM_ref8:
+      *return_offset = (read_8ubyte_unaligned (attr->cu->dbg, attr->valp)
+			+ attr->cu->offset);
+      break;
+
+    case DW_FORM_ref_udata:
+      {
+	Dwarf_Off off;
+	Dwarf_Small *attrp = attr->valp;
+	get_uleb128 (off, attrp);
+	*return_offset = off + attr->cu->offset;
+      }
+      break;
+
+    case DW_FORM_ref_addr:
+      if (attr->cu->address_size == 4)
+	*return_offset = read_4ubyte_unaligned (attr->cu->dbg, attr->valp);
+      else
+	*return_offset = read_8ubyte_unaligned (attr->cu->dbg, attr->valp);
+      break;
+
+    default:
+      __libdwarf_error (attr->cu->dbg, error, DW_E_NO_REFERENCE);
+      return DW_DLV_ERROR;
+    }
+
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_global_name_offsets.c b/libdwarf/dwarf_global_name_offsets.c
new file mode 100644
index 0000000..a9b149c
--- /dev/null
+++ b/libdwarf/dwarf_global_name_offsets.c
@@ -0,0 +1,64 @@
+/* Return name, DIE offset, and offset of the compile unit for global
+   definition.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_global_name_offsets (global, return_name, die_offset, cu_offset, error)
+     Dwarf_Global global;
+     char **return_name;
+     Dwarf_Off *die_offset;
+     Dwarf_Off *cu_offset;
+     Dwarf_Error *error;
+{
+  if (return_name != NULL)
+    {
+      *return_name = strdup (global->name);
+      if (*return_name == NULL)
+	{
+	  __libdwarf_error (global->info->dbg, error, DW_E_NOMEM);
+	  return DW_DLV_ERROR;
+	}
+    }
+
+  if (die_offset != NULL)
+    *die_offset = global->offset + global->info->offset;
+
+  /* Determine the size of the CU header.  */
+  if (cu_offset != NULL)
+    {
+      Dwarf_Small *cu_header;
+      unsigned int offset_size;
+
+      cu_header =
+	((Dwarf_Small *) global->info->dbg->sections[IDX_debug_info].addr
+	 + global->info->offset);
+      if (read_4ubyte_unaligned_noncvt (cu_header) == 0xffffffff)
+	offset_size = 8;
+      else
+	offset_size = 4;
+
+      *cu_offset = global->info->offset + 3 * offset_size - 4 + 3;
+    }
+
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_globname.c b/libdwarf/dwarf_globname.c
new file mode 100644
index 0000000..1c56529
--- /dev/null
+++ b/libdwarf/dwarf_globname.c
@@ -0,0 +1,38 @@
+/* Return name for global definition.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_globname (global, return_name, error)
+     Dwarf_Global global;
+     char **return_name;
+     Dwarf_Error *error;
+{
+  *return_name = strdup (global->name);
+  if (*return_name == NULL)
+    {
+      __libdwarf_error (global->info->dbg, error, DW_E_NOMEM);
+      return DW_DLV_ERROR;
+    }
+
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_hasattr.c b/libdwarf/dwarf_hasattr.c
new file mode 100644
index 0000000..337a3e1
--- /dev/null
+++ b/libdwarf/dwarf_hasattr.c
@@ -0,0 +1,98 @@
+/* Determine whether die has attribute specified of given type.
+   Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_hasattr (die, attr, return_bool, error)
+     Dwarf_Die die;
+     Dwarf_Half attr;
+     Dwarf_Bool *return_bool;
+     Dwarf_Error *error;
+{
+  Dwarf_Debug dbg = die->cu->dbg;
+  Dwarf_Small *die_addr;
+  Dwarf_Word u128;
+  Dwarf_Abbrev abbrev;
+  Dwarf_Small *attrp;
+
+  /* Address of the given die.  */
+  die_addr = die->addr;
+
+  /* Get abbrev code.  */
+  get_uleb128 (u128, die_addr);
+  /*  And get the abbreviation itself.  */
+  abbrev = __libdwarf_get_abbrev (dbg, die->cu, u128, error);
+  if (abbrev == NULL)
+    return DW_DLV_ERROR;
+
+  /* This is where the attributes start.  */
+  attrp = abbrev->attrp;
+
+  /* Search the name attribute.  */
+  while (1)
+    {
+      Dwarf_Word attr_name;
+      Dwarf_Word attr_form;
+
+      /* Are we still in bounds?  */
+      if (unlikely (attrp
+		    >= ((Dwarf_Small *) dbg->sections[IDX_debug_abbrev].addr
+			+ dbg->sections[IDX_debug_abbrev].size)))
+	{
+	  __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+	  return DW_DLV_ERROR;
+	}
+
+      /* Get attribute name and form.
+
+	 XXX We don't check whether this reads beyond the end of the
+	 section.  */
+      get_uleb128 (attr_name, attrp);
+      get_uleb128 (attr_form, attrp);
+
+      /* We can stop if we found the attribute with value zero.  */
+      if (attr_name == 0 && attr_form == 0)
+	break;
+
+      /* Is this the name attribute?  */
+      if (attr_name == attr)
+	{
+	  *return_bool = 1;
+	  return DW_DLV_OK;
+	}
+
+      /* Skip over the rest of this attribute (if there is any).  */
+      if (attr_form != 0)
+	{
+	  size_t len;
+
+	  if (unlikely (__libdwarf_form_val_len (dbg, die->cu, attr_form,
+						 die_addr, &len, error)
+			!= DW_DLV_OK))
+	    return DW_DLV_ERROR;
+
+	  die_addr += len;
+	}
+    }
+
+  /* No such attribute present.  */
+  *return_bool = 0;
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_hasform.c b/libdwarf/dwarf_hasform.c
new file mode 100644
index 0000000..cfb6cf9
--- /dev/null
+++ b/libdwarf/dwarf_hasform.c
@@ -0,0 +1,31 @@
+/* Determine whether attribute has given form.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_hasform (attr, form, return_hasform, error)
+     Dwarf_Attribute attr;
+     Dwarf_Half form;
+     Dwarf_Bool *return_hasform;
+     Dwarf_Error *error;
+{
+  *return_hasform = attr->form == form;
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_highpc.c b/libdwarf/dwarf_highpc.c
new file mode 100644
index 0000000..5e56376
--- /dev/null
+++ b/libdwarf/dwarf_highpc.c
@@ -0,0 +1,108 @@
+/* Return high program counter value associated with die.
+   Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_highpc (die, return_highpc, error)
+     Dwarf_Die die;
+     Dwarf_Addr *return_highpc;
+     Dwarf_Error *error;
+{
+  Dwarf_Debug dbg = die->cu->dbg;
+  Dwarf_Small *die_addr;
+  Dwarf_Word u128;
+  Dwarf_Abbrev abbrev;
+  Dwarf_Small *attrp;
+
+  /* Address of the given die.  */
+  die_addr = die->addr;
+
+  /* Get abbrev code.  */
+  get_uleb128 (u128, die_addr);
+  /*  And get the abbreviation itself.  */
+  abbrev = __libdwarf_get_abbrev (dbg, die->cu, u128, error);
+  if (abbrev == NULL)
+    return DW_DLV_ERROR;
+
+  /* This is where the attributes start.  */
+  attrp = abbrev->attrp;
+
+  /* Search the name attribute.  */
+  while (1)
+    {
+      Dwarf_Word attr_name;
+      Dwarf_Word attr_form;
+
+      /* Are we still in bounds?  */
+      if (unlikely  (attrp
+		     >= ((Dwarf_Small *) dbg->sections[IDX_debug_abbrev].addr
+			 + dbg->sections[IDX_debug_abbrev].size)))
+	{
+	  __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+	  return DW_DLV_ERROR;
+	}
+
+      /* Get attribute name and form.
+
+	 XXX We don't check whether this reads beyond the end of the
+	 section.  */
+      get_uleb128 (attr_name, attrp);
+      get_uleb128 (attr_form, attrp);
+
+      /* We can stop if we found the attribute with value zero.  */
+      if (attr_name == 0 && attr_form == 0)
+	break;
+
+      /* Is this the name attribute?  */
+      if (unlikely (attr_name == DW_AT_high_pc))
+	{
+	  if (unlikely (attr_form != DW_FORM_addr))
+	    {
+	      __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+	      return DW_DLV_ERROR;
+	    }
+
+	  if (die->cu->address_size == 4)
+	    *return_highpc = read_4ubyte_unaligned (dbg, die_addr);
+	  else
+	    *return_highpc = read_8ubyte_unaligned (dbg, die_addr);
+
+	  return DW_DLV_OK;
+	}
+
+      /* Skip over the rest of this attribute (if there is any).  */
+      if (attr_form != 0)
+	{
+	  size_t len;
+
+	  if (unlikely (__libdwarf_form_val_len (dbg, die->cu, attr_form,
+						 die_addr, &len, error)
+			!= DW_DLV_OK))
+	    return DW_DLV_ERROR;
+
+	  die_addr += len;
+	}
+    }
+
+  /* No such attribute present.  */
+  return DW_DLV_NO_ENTRY;
+}
diff --git a/libdwarf/dwarf_init.c b/libdwarf/dwarf_init.c
new file mode 100644
index 0000000..bbb8660
--- /dev/null
+++ b/libdwarf/dwarf_init.c
@@ -0,0 +1,92 @@
+/* Create descriptor from file descriptor for processing file.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stddef.h>
+#include <sys/stat.h>
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_init (fd, access, errhand, errarg, dbg, error)
+     int fd;
+     Dwarf_Unsigned access;
+     Dwarf_Handler errhand;
+     Dwarf_Ptr errarg;
+     Dwarf_Debug *dbg;
+     Dwarf_Error *error;
+{
+  Elf *elf;
+  Elf_Cmd cmd;
+  struct Dwarf_Debug_s newdbg;
+  int result = DW_DLV_ERROR;
+
+  switch (access)
+    {
+    case DW_DLC_READ:
+      cmd = ELF_C_READ_MMAP;
+      break;
+    case DW_DLC_WRITE:
+      cmd = ELF_C_WRITE;
+      break;
+    case DW_DLC_RDWR:
+      cmd = ELF_C_RDWR;
+      break;
+    default:
+      /* These are the error values we want to use.  */
+      newdbg.dbg_errhand = errhand;
+      newdbg.dbg_errarg = errarg;
+
+      __libdwarf_error (&newdbg, error, DW_E_INVALID_ACCESS);
+      return DW_DLV_ERROR;
+    }
+
+  /* We have to call `elf_version' here since the user might have not
+     done it or initialized libelf with a different version.  This
+     would break libdwarf since we are using the ELF data structures
+     in a certain way.  */
+  elf_version (EV_CURRENT);
+
+  /* Get an ELF descriptor.  */
+  elf = elf_begin (fd, cmd, NULL);
+  if (elf == NULL)
+    {
+      /* Test why the `elf_begin" call failed.  */
+      struct stat64 st;
+
+      /* These are the error values we want to use.  */
+      newdbg.dbg_errhand = errhand;
+      newdbg.dbg_errarg = errarg;
+
+      if (fstat64 (fd, &st) == 0 && ! S_ISREG (st.st_mode))
+	__libdwarf_error (&newdbg, error, DW_E_NO_REGFILE);
+      else
+	__libdwarf_error (&newdbg, error, DW_E_IO_ERROR);
+    }
+  else
+    {
+      /* Do the real work now that we have an ELF descriptor.  */
+      result = dwarf_elf_init (elf, access, errhand, errarg, dbg, error);
+
+      /* If this failed, free the resources.  */
+      if (result != DW_DLV_OK)
+	elf_end (elf);
+    }
+
+  return result;
+}
diff --git a/libdwarf/dwarf_lineaddr.c b/libdwarf/dwarf_lineaddr.c
new file mode 100644
index 0000000..4bf4943
--- /dev/null
+++ b/libdwarf/dwarf_lineaddr.c
@@ -0,0 +1,30 @@
+/* Return address associate with line.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_lineaddr (line, return_lineaddr, error)
+     Dwarf_Line line;
+     Dwarf_Addr *return_lineaddr;
+     Dwarf_Error *error;
+{
+  *return_lineaddr = line->addr;
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_linebeginstatement.c b/libdwarf/dwarf_linebeginstatement.c
new file mode 100644
index 0000000..d04c6ec
--- /dev/null
+++ b/libdwarf/dwarf_linebeginstatement.c
@@ -0,0 +1,30 @@
+/* Determine whether line is the beginning of a statement.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_linebeginstatement (line, return_bool, error)
+     Dwarf_Line line;
+     Dwarf_Bool *return_bool;
+     Dwarf_Error *error;
+{
+  *return_bool = line->is_stmt;
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_lineblock.c b/libdwarf/dwarf_lineblock.c
new file mode 100644
index 0000000..f15e54b
--- /dev/null
+++ b/libdwarf/dwarf_lineblock.c
@@ -0,0 +1,30 @@
+/* Determine whether line is marked as beginning a basic block.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_lineblock (line, return_bool, error)
+     Dwarf_Line line;
+     Dwarf_Bool *return_bool;
+     Dwarf_Error *error;
+{
+  *return_bool = line->basic_block;
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_lineendsequence.c b/libdwarf/dwarf_lineendsequence.c
new file mode 100644
index 0000000..93cbf8e
--- /dev/null
+++ b/libdwarf/dwarf_lineendsequence.c
@@ -0,0 +1,30 @@
+/* Determine whether line is marked as ending a text sequence.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_lineendsequence (line, return_bool, error)
+     Dwarf_Line line;
+     Dwarf_Bool *return_bool;
+     Dwarf_Error *error;
+{
+  *return_bool = line->end_sequence;
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_lineepiloguebegin.c b/libdwarf/dwarf_lineepiloguebegin.c
new file mode 100644
index 0000000..33df13f
--- /dev/null
+++ b/libdwarf/dwarf_lineepiloguebegin.c
@@ -0,0 +1,30 @@
+/* Determine whether line is marked as beginning the epilogue.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_lineepiloguebegin (line, return_bool, error)
+     Dwarf_Line line;
+     Dwarf_Bool *return_bool;
+     Dwarf_Error *error;
+{
+  *return_bool = line->epilogue_begin;
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_lineno.c b/libdwarf/dwarf_lineno.c
new file mode 100644
index 0000000..83f911d
--- /dev/null
+++ b/libdwarf/dwarf_lineno.c
@@ -0,0 +1,30 @@
+/* Return source statement line number.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_lineno (line, return_lineno, error)
+     Dwarf_Line line;
+     Dwarf_Unsigned *return_lineno;
+     Dwarf_Error *error;
+{
+  *return_lineno = line->line;
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_lineoff.c b/libdwarf/dwarf_lineoff.c
new file mode 100644
index 0000000..82f4bbc
--- /dev/null
+++ b/libdwarf/dwarf_lineoff.c
@@ -0,0 +1,30 @@
+/* Return column at which the statement begins.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_lineoff (line, return_lineoff, error)
+     Dwarf_Line line;
+     Dwarf_Signed *return_lineoff;
+     Dwarf_Error *error;
+{
+  *return_lineoff = line->column ?: -1;
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_lineprologueend.c b/libdwarf/dwarf_lineprologueend.c
new file mode 100644
index 0000000..f202f73
--- /dev/null
+++ b/libdwarf/dwarf_lineprologueend.c
@@ -0,0 +1,30 @@
+/* Determine whether line is marked as ending the prologue.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_lineprologueend (line, return_bool, error)
+     Dwarf_Line line;
+     Dwarf_Bool *return_bool;
+     Dwarf_Error *error;
+{
+  *return_bool = line->prologue_end;
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_linesrc.c b/libdwarf/dwarf_linesrc.c
new file mode 100644
index 0000000..5c99000
--- /dev/null
+++ b/libdwarf/dwarf_linesrc.c
@@ -0,0 +1,44 @@
+/* Return source file for line.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_linesrc (line, return_linesrc, error)
+     Dwarf_Line line;
+     char **return_linesrc;
+     Dwarf_Error *error;
+{
+  if (unlikely (line->file >= line->files->nfiles))
+    {
+      __libdwarf_error (line->files->dbg, error, DW_E_INVALID_DWARF);
+      return DW_DLV_ERROR;
+    }
+
+  *return_linesrc = strdup (line->files->info[line->file].name);
+  if (*return_linesrc == NULL)
+    {
+      __libdwarf_error (line->files->dbg, error, DW_E_NOMEM);
+      return DW_DLV_ERROR;
+    }
+
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_loclist.c b/libdwarf/dwarf_loclist.c
new file mode 100644
index 0000000..22a3944
--- /dev/null
+++ b/libdwarf/dwarf_loclist.c
@@ -0,0 +1,470 @@
+/* Return location expression list.
+   Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include <stdlib.h>
+
+#include <libdwarfP.h>
+
+
+struct loclist
+{
+  Dwarf_Small atom;
+  Dwarf_Unsigned number;
+  Dwarf_Unsigned number2;
+  Dwarf_Unsigned offset;
+  struct loclist *next;
+};
+
+struct locdesclist
+{
+  Dwarf_Addr lopc;
+  Dwarf_Addr hipc;
+  Dwarf_Half cents;
+  struct loclist *s;
+  struct locdesclist *next;
+};
+
+
+int
+dwarf_loclist (attr, llbuf, listlen, error)
+     Dwarf_Attribute attr;
+     Dwarf_Locdesc **llbuf;
+     Dwarf_Signed *listlen;
+     Dwarf_Error *error;
+{
+  Dwarf_CU_Info cu = attr->cu;
+  Dwarf_Debug dbg = cu->dbg;
+  Dwarf_Unsigned offset;
+  Dwarf_Unsigned offset_end;
+  Dwarf_Small *locp;
+  struct locdesclist *locdesclist;
+  Dwarf_Locdesc *result;
+  unsigned int n;
+
+  /* Must by one of the attribute listed below.  */
+  if (attr->code != DW_AT_location
+      && attr->code != DW_AT_data_member_location
+      && attr->code != DW_AT_vtable_elem_location
+      && attr->code != DW_AT_string_length
+      && attr->code != DW_AT_use_location
+      && attr->code != DW_AT_return_addr)
+    {
+      __libdwarf_error (dbg, error, DW_E_WRONG_ATTR);
+      return DW_DLV_ERROR;
+    }
+
+  /* Must have the form data4 or data8 which act as an offset.  */
+  if (attr->form == DW_FORM_data4)
+    offset = read_4ubyte_unaligned (dbg, attr->valp);
+  else if (likely (attr->form == DW_FORM_data8))
+    offset = read_8ubyte_unaligned (dbg, attr->valp);
+  else
+    {
+      __libdwarf_error (dbg, error, DW_E_NO_DATA);
+      return DW_DLV_ERROR;
+    }
+
+  /* Check whether the .debug_loc section is available.  */
+  if (unlikely (dbg->sections[IDX_debug_loc].addr == NULL))
+    {
+      __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+      return DW_DLV_ERROR;
+    }
+
+  /* This is the part of the .debug_loc section we can read.  */
+  locp = (Dwarf_Small *) dbg->sections[IDX_debug_loc].addr + offset;
+  offset_end = offset + dbg->sections[IDX_debug_loc].size;
+
+  locdesclist = NULL;
+  n = 0;
+  while (1)
+    {
+      Dwarf_Addr lopc;
+      Dwarf_Addr hipc;
+      Dwarf_Ptr data;
+      Dwarf_Unsigned len2;
+      struct locdesclist *newdesc;
+      Dwarf_Small *locp;
+      Dwarf_Small *blkendp;
+      Dwarf_Small *blkstartp;
+
+      if (unlikely (dwarf_get_loclist_entry (dbg, offset, &hipc, &lopc, &data,
+					     &len2, &offset, error)
+		    != DW_DLV_OK))
+	return DW_DLV_ERROR;
+
+      /* Does this signal the end?  */
+      if (lopc == 0 && hipc == 0)
+	break;
+
+      locp = data;
+      blkstartp = locp;
+      blkendp = locp + len2;
+
+      /* Create a new Locdesc entry.  */
+      newdesc = (struct locdesclist *) alloca (sizeof (struct locdesclist));
+      newdesc->lopc = lopc;
+      newdesc->hipc = hipc;
+      newdesc->cents = 0;
+      newdesc->s = NULL;
+      newdesc->next = locdesclist;
+      locdesclist = newdesc;
+      ++n;
+
+      /* Decode the opcodes.  It is possible in some situations to
+         have a block of size zero.  */
+      while (locp < blkendp)
+	{
+	  struct loclist *newloc;
+
+	  newloc = (struct loclist *) alloca (sizeof (struct loclist));
+	  newloc->number = 0;
+	  newloc->number2 = 0;
+	  newloc->offset = locp - blkstartp;
+	  newloc->next = newdesc->s;
+	  newdesc->s = newloc;
+	  ++newdesc->cents;
+
+	  newloc->atom = *locp;
+	  switch (*locp++)
+	    {
+	    case DW_OP_addr:
+	      /* Address, depends on address size of CU.  */
+	      if (cu->address_size == 4)
+		{
+		  if (unlikely (locp + 4 > blkendp))
+		    {
+		      __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+		      return DW_DLV_ERROR;
+		    }
+		  newloc->number = read_4ubyte_unaligned (dbg, locp);
+		  locp += 4;
+		}
+	      else
+		{
+		  if (unlikely (locp + 8 > blkendp))
+		    {
+		      __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+		      return DW_DLV_ERROR;
+		    }
+		  newloc->number = read_8ubyte_unaligned (dbg, locp);
+		  locp += 8;
+		}
+	      break;
+
+	    case DW_OP_deref:
+	    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_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_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_nop:
+	    case DW_OP_push_object_address:
+	    case DW_OP_call_ref:
+	      /* No operand.  */
+	      break;
+
+	    case DW_OP_const1u:
+	    case DW_OP_pick:
+	    case DW_OP_deref_size:
+	    case DW_OP_xderef_size:
+	      if (unlikely (locp >= blkendp))
+		{
+		  __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+		  return DW_DLV_ERROR;
+		}
+	      newloc->number = *((uint8_t *) locp)++;
+	      break;
+
+	    case DW_OP_const1s:
+	      if (unlikely (locp >= blkendp))
+		{
+		  __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+		  return DW_DLV_ERROR;
+		}
+	      newloc->number = *((int8_t *) locp)++;
+	      break;
+
+	    case DW_OP_const2u:
+	      if (unlikely (locp + 2 > blkendp))
+		{
+		  __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+		  return DW_DLV_ERROR;
+		}
+	      newloc->number = read_2ubyte_unaligned (dbg, locp);
+	      locp += 2;
+	      break;
+
+	    case DW_OP_const2s:
+	    case DW_OP_skip:
+	    case DW_OP_bra:
+	    case DW_OP_call2:
+	      if (unlikely (locp + 2 > blkendp))
+		{
+		  __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+		  return DW_DLV_ERROR;
+		}
+	      newloc->number = read_2sbyte_unaligned (dbg, locp);
+	      locp += 2;
+	      break;
+
+	    case DW_OP_const4u:
+	      if (unlikely (locp + 4 > blkendp))
+		{
+		  __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+		  return DW_DLV_ERROR;
+		}
+	      newloc->number = read_4ubyte_unaligned (dbg, locp);
+	      locp += 4;
+	      break;
+
+	    case DW_OP_const4s:
+	    case DW_OP_call4:
+	      if (unlikely (locp + 4 > blkendp))
+		{
+		  __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+		  return DW_DLV_ERROR;
+		}
+	      newloc->number = read_4sbyte_unaligned (dbg, locp);
+	      locp += 4;
+	      break;
+
+	    case DW_OP_const8u:
+	      if (unlikely (locp + 8 > blkendp))
+		{
+		  __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+		  return DW_DLV_ERROR;
+		}
+	      newloc->number = read_8ubyte_unaligned (dbg, locp);
+	      locp += 8;
+	      break;
+
+	    case DW_OP_const8s:
+	      if (unlikely (locp + 8 > blkendp))
+		{
+		  __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+		  return DW_DLV_ERROR;
+		}
+	      newloc->number = read_8sbyte_unaligned (dbg, locp);
+	      locp += 8;
+	      break;
+
+	    case DW_OP_constu:
+	    case DW_OP_plus_uconst:
+	    case DW_OP_regx:
+	    case DW_OP_piece:
+	      /* XXX Check size.  */
+	      get_uleb128 (newloc->number, locp);
+	      break;
+
+	    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:
+	      /* XXX Check size.  */
+	      get_sleb128 (newloc->number, locp);
+	      break;
+
+	    case DW_OP_bregx:
+	      /* XXX Check size.  */
+	      get_uleb128 (newloc->number, locp);
+	      get_sleb128 (newloc->number2, locp);
+	      break;
+
+	    default:
+	      __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+	      return DW_DLV_ERROR;
+	    }
+	}
+    }
+
+  if (unlikely (n == 0))
+    {
+      /* This is not allowed.
+
+	 XXX Is it?  */
+      __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+      return DW_DLV_ERROR;
+    }
+
+  /* Allocate the array.  */
+  result = (Dwarf_Locdesc *) malloc (n * sizeof (Dwarf_Locdesc));
+  if (result == NULL)
+    {
+      __libdwarf_error (dbg, error, DW_E_NOMEM);
+      return DW_DLV_ERROR;
+    }
+
+  /* Store the result.  */
+  *llbuf = result;
+  *listlen = n;
+
+  do
+    {
+      unsigned int cents;
+      struct loclist *s;
+
+      /* We populate the array from the back since the list is
+         backwards.  */
+      --n;
+
+      result[n].ld_lopc = locdesclist->lopc;
+      result[n].ld_hipc = locdesclist->hipc;
+      result[n].ld_cents = cents = locdesclist->cents;
+      result[n].ld_s = (Dwarf_Loc *) malloc (cents * sizeof (Dwarf_Loc));
+      if (result == NULL)
+	{
+	  /* XXX Should be bother freeing memory?  */
+	  __libdwarf_error (dbg, error, DW_E_NOMEM);
+	  return DW_DLV_ERROR;
+	}
+
+      s = locdesclist->s;
+      while (cents-- > 0)
+	{
+	  /* This list is also backwards.  */
+	  result[n].ld_s[cents].lr_atom = s->atom;
+	  result[n].ld_s[cents].lr_number = s->number;
+	  result[n].ld_s[cents].lr_number2 = s->number2;
+	  result[n].ld_s[cents].lr_offset = s->offset;
+	  s = s->next;
+	}
+
+      locdesclist = locdesclist->next;
+    }
+  while (n > 0);
+
+  /* We did it.  */
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_lowpc.c b/libdwarf/dwarf_lowpc.c
new file mode 100644
index 0000000..c21edc9
--- /dev/null
+++ b/libdwarf/dwarf_lowpc.c
@@ -0,0 +1,108 @@
+/* Return low program counter value associated with die.
+   Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_lowpc (die, return_lowpc, error)
+     Dwarf_Die die;
+     Dwarf_Addr *return_lowpc;
+     Dwarf_Error *error;
+{
+  Dwarf_Debug dbg = die->cu->dbg;
+  Dwarf_Small *die_addr;
+  Dwarf_Word u128;
+  Dwarf_Abbrev abbrev;
+  Dwarf_Small *attrp;
+
+  /* Address of the given die.  */
+  die_addr = die->addr;
+
+  /* Get abbrev code.  */
+  get_uleb128 (u128, die_addr);
+  /*  And get the abbreviation itself.  */
+  abbrev = __libdwarf_get_abbrev (dbg, die->cu, u128, error);
+  if (abbrev == NULL)
+    return DW_DLV_ERROR;
+
+  /* This is where the attributes start.  */
+  attrp = abbrev->attrp;
+
+  /* Search the name attribute.  */
+  while (1)
+    {
+      Dwarf_Word attr_name;
+      Dwarf_Word attr_form;
+
+      /* Are we still in bounds?  */
+      if (unlikely (attrp
+		    >= ((Dwarf_Small *) dbg->sections[IDX_debug_abbrev].addr
+			+ dbg->sections[IDX_debug_abbrev].size)))
+	{
+	  __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+	  return DW_DLV_ERROR;
+	}
+
+      /* Get attribute name and form.
+
+	 XXX We don't check whether this reads beyond the end of the
+	 section.  */
+      get_uleb128 (attr_name, attrp);
+      get_uleb128 (attr_form, attrp);
+
+      /* We can stop if we found the attribute with value zero.  */
+      if (attr_name == 0 && attr_form == 0)
+	break;
+
+      /* Is this the name attribute?  */
+      if (unlikely (attr_name == DW_AT_low_pc))
+	{
+	  if (unlikely (attr_form != DW_FORM_addr))
+	    {
+	      __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+	      return DW_DLV_ERROR;
+	    }
+
+	  if (die->cu->address_size == 4)
+	    *return_lowpc = read_4ubyte_unaligned (dbg, die_addr);
+	  else
+	    *return_lowpc = read_8ubyte_unaligned (dbg, die_addr);
+
+	  return DW_DLV_OK;
+	}
+
+      /* Skip over the rest of this attribute (if there is any).  */
+      if (attr_form != 0)
+	{
+	  size_t len;
+
+	  if (unlikely (__libdwarf_form_val_len (dbg, die->cu, attr_form,
+						 die_addr, &len, error)
+			!= DW_DLV_OK))
+	    return DW_DLV_ERROR;
+
+	  die_addr += len;
+	}
+    }
+
+  /* No such attribute present.  */
+  return DW_DLV_NO_ENTRY;
+}
diff --git a/libdwarf/dwarf_next_cu_header.c b/libdwarf/dwarf_next_cu_header.c
new file mode 100644
index 0000000..54bb39e
--- /dev/null
+++ b/libdwarf/dwarf_next_cu_header.c
@@ -0,0 +1,234 @@
+/* Get offset of next compilation unit.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include <libdwarfP.h>
+
+
+/* A good initial size for the abbreviation hashing table.  */
+#define DEFAULT_ABBREV_HASH_SIZE	257
+
+
+int
+internal_function
+__libdwarf_get_cu_at_offset (Dwarf_Debug dbg, Dwarf_Unsigned offset,
+			     Dwarf_CU_Info *result_cu, Dwarf_Error *error)
+{
+  Dwarf_CU_Info cu;
+  Dwarf_Small *cu_bytes;
+  Dwarf_Unsigned length;
+  Dwarf_Half offset_size;
+
+  /* Make sure there is enough space in the .debug_info section for at
+     least the initial word.  We cannot test the rest since we don't
+     know yet whether this is a 64-bit object or not.  */
+  if (unlikely (offset + 4 >= dbg->sections[IDX_debug_info].size))
+    {
+      dbg->cu_list_current = NULL;
+      return DW_DLV_NO_ENTRY;
+    }
+
+  /* This points into the .debug_info section to the beginning of the
+     CU entry.  */
+  cu_bytes = (Dwarf_Small *) dbg->sections[IDX_debug_info].addr + offset;
+
+  /* The format of the CU header is described in dwarf2p1 7.5.1:
+
+     1.  A 4-byte or 12-byte unsigned integer representing the length
+	 of the .debug_info contribution for that compilation unit, not
+	 including the length field itself. In the 32-bit DWARF format,
+	 this is a 4-byte unsigned integer (which must be less than
+	 0xffffff00); in the 64-bit DWARF format, this consists of the
+	 4-byte value 0xffffffff followed by an 8-byte unsigned integer
+	 that gives the actual length (see Section 7.4).
+
+      2. A 2-byte unsigned integer representing the version of the
+	 DWARF information for that compilation unit. For DWARF Version
+	 2.1, the value in this field is 2.
+
+      3. A 4-byte or 8-byte unsigned offset into the .debug_abbrev
+	 section. This offset associates the compilation unit with a
+	 particular set of debugging information entry abbreviations. In
+	 the 32-bit DWARF format, this is a 4-byte unsigned length; in
+	 the 64-bit DWARF format, this is an 8-byte unsigned length (see
+	 Section 7.4).
+
+      4. A 1-byte unsigned integer representing the size in bytes of
+	 an address on the target architecture. If the system uses
+	 segmented addressing, this value represents the size of the
+	 offset portion of an address.  */
+  length = read_4ubyte_unaligned (dbg, cu_bytes);
+  cu_bytes += 4;
+  offset_size = 4;
+  if (length == 0xffffffff)
+    offset_size = 8;
+
+  /* Now we know how large the header is.  Note the trick in the
+     computation.  If the offset_size is 4 the '- 4' term undoes the
+     '2 *'.  If offset_size is 8 this term computes the size of the
+     escape value plus the 8 byte offset.  */
+  if (unlikely (offset + 2 * offset_size - 4 + sizeof (Dwarf_Half)
+		+ offset_size + sizeof (Dwarf_Small)
+		>= dbg->sections[IDX_debug_info].size))
+    {
+      dbg->cu_list_current = NULL;
+      return DW_DLV_NO_ENTRY;
+    }
+
+  if (length == 0xffffffff)
+    {
+      /* This is a 64-bit DWARF format.  */
+      length = read_8ubyte_unaligned (dbg, cu_bytes);
+      cu_bytes += 8;
+    }
+
+  /* We know we have enough room in the .debug_section.  Allocate the
+     result data structure.  */
+  cu = (Dwarf_CU_Info) malloc (sizeof (struct Dwarf_CU_Info_s));
+  if (cu == NULL)
+    {
+      __libdwarf_error (dbg, error, DW_E_NOMEM);
+      return DW_DLV_ERROR;
+    }
+
+  /* Store the values in the data structure.  */
+  cu->offset = offset;
+  cu->offset_size = offset_size;
+  cu->length = length;
+
+  /* Store the version stamp.  Always a 16-bit value.  */
+  cu->version_stamp = read_2ubyte_unaligned (dbg, cu_bytes);
+  cu_bytes += 2;
+
+  /* Get offset in .debug_abbrev.  Note that the size of the entry
+     depends on whether this is a 32-bit or 64-bit DWARF definition.  */
+  if (offset_size == 4)
+    cu->abbrev_offset = read_4ubyte_unaligned (dbg, cu_bytes);
+  else
+    cu->abbrev_offset = read_8ubyte_unaligned (dbg, cu_bytes);
+  cu_bytes += offset_size;
+  cu->last_abbrev_offset = cu->abbrev_offset;
+
+  /* The address size.  Always an 8-bit value.  */
+  cu->address_size = *cu_bytes++;
+
+  /* Store the header length.  */
+  cu->header_length = (cu_bytes
+		       - ((Dwarf_Small *) dbg->sections[IDX_debug_info].addr
+			  + offset));
+
+  /* Initilize a few more members.  */
+  if (unlikely (Dwarf_Abbrev_Hash_init (&cu->abbrev_hash,
+					DEFAULT_ABBREV_HASH_SIZE) != 0))
+    {
+      free (cu);
+      __libdwarf_error (dbg, error, DW_E_NOMEM);
+      return DW_DLV_ERROR;
+    }
+
+  /* Remember the debugging handle.  */
+  cu->dbg = dbg;
+
+  /* There is no other entry yet.  */
+  cu->next = NULL;
+
+  /* Enqueue the new entry.  */
+  if (dbg->cu_list == NULL)
+    dbg->cu_list = dbg->cu_list_tail = cu;
+  else
+    {
+      dbg->cu_list_tail->next = cu;
+      dbg->cu_list_tail = cu;
+    }
+  *result_cu = cu;
+
+  return DW_DLV_OK;
+}
+
+
+int
+dwarf_next_cu_header (dbg, cu_header_length, version_stamp, abbrev_offset,
+		      address_size, next_cu_header, error)
+     Dwarf_Debug dbg;
+     Dwarf_Unsigned *cu_header_length;
+     Dwarf_Half *version_stamp;
+     Dwarf_Unsigned *abbrev_offset;
+     Dwarf_Half *address_size;
+     Dwarf_Unsigned *next_cu_header;
+     Dwarf_Error *error;
+{
+  Dwarf_Unsigned offset_next_cu;
+  Dwarf_CU_Info cu;
+
+  if (dbg == NULL)
+    return DW_DLV_ERROR;
+
+  /* Determine offset of next CU header.  If we don't have a current
+     CU this is the first call and we start right at the beginning.  */
+  if (dbg->cu_list_current == NULL)
+    {
+      offset_next_cu = 0;
+      cu = dbg->cu_list;
+    }
+  else
+    {
+      /* We can compute the offset from the information we read from
+	 the last CU header.  */
+      cu = dbg->cu_list_current;
+
+      offset_next_cu = cu->offset + 2 * cu->offset_size - 4 + cu->length;
+
+      /* See whether the next entry entry is available.  */
+      cu = cu->next;
+    }
+
+  /* If the entry is not yet available get it.  */
+  if (cu == NULL)
+    {
+      int res = __libdwarf_get_cu_at_offset (dbg, offset_next_cu, &cu, error);
+
+      /* If it still does not exist, fail.  Note that this can mean an
+	 error or that we reached the end.  */
+      if (res != DW_DLV_OK)
+	return res;
+
+      dbg->cu_list_current = cu;
+      assert (cu != NULL);
+    }
+
+  /* See get_cu_at_offset for an explanation of the trick in this
+     formula.  */
+  *next_cu_header = offset_next_cu + 2 * cu->offset_size - 4 + cu->length;
+
+  /* Extract the information and put it where the user wants it.  */
+  if (cu_header_length != NULL)
+    *cu_header_length = cu->header_length;
+
+  if (version_stamp != NULL)
+    *version_stamp = cu->version_stamp;
+
+  if (abbrev_offset != NULL)
+    *abbrev_offset = cu->abbrev_offset;
+
+  if (address_size != NULL)
+    *address_size = cu->address_size;
+
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_offdie.c b/libdwarf/dwarf_offdie.c
new file mode 100644
index 0000000..2e94d2e
--- /dev/null
+++ b/libdwarf/dwarf_offdie.c
@@ -0,0 +1,123 @@
+/* Return die at given offset.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include <stdlib.h>
+
+#include <libdwarfP.h>
+
+
+/* XXX This function will have to be optimized.  The search is too linear
+   to be performed too often -> O(n²).  */
+static Dwarf_CU_Info
+find_cu (Dwarf_Debug dbg, Dwarf_Off offset, Dwarf_Error *error)
+{
+  Dwarf_CU_Info cu;
+  Dwarf_Word cu_offset;
+
+  /* Search in the CUs already known.  */
+  for (cu = dbg->cu_list; cu != NULL; cu = cu->next)
+    if (cu->offset <= offset
+	&& cu->offset + 2 * cu->offset_size - 4 + cu->length > offset)
+      return cu;
+
+  /* The CU is not yet loaded.  Do this now.  */
+  if (dbg->cu_list_tail == NULL)
+    cu_offset = 0;
+  else
+    cu_offset = (dbg->cu_list_tail->offset
+		 + 2 * dbg->cu_list_tail->offset_size - 4
+		 + dbg->cu_list_tail->length);
+
+  while (1)
+    {
+      /* Get next CU and add it to the end of the list.  */
+      if (__libdwarf_get_cu_at_offset (dbg, cu_offset, &cu, error)
+	  != DW_DLV_OK)
+	return NULL;
+
+      /* Offset of next CU.  */
+      cu_offset += 2 * cu->offset_size - 4 + cu->length;
+
+      /* If this the CU we are looking for?  */
+      if (offset < cu_offset)
+	return cu;
+    }
+}
+
+
+int
+dwarf_offdie (dbg, offset, return_die, error)
+     Dwarf_Debug dbg;
+     Dwarf_Off offset;
+     Dwarf_Die *return_die;
+     Dwarf_Error *error;
+{
+  Dwarf_CU_Info cu;
+  Dwarf_Die new_die;
+  Dwarf_Small *die_addr;
+  Dwarf_Word u128;
+
+  if (offset >= dbg->sections[IDX_debug_info].size)
+    {
+      /* Completely out of bounds.  */
+      __libdwarf_error (dbg, error, DW_E_INVALID_OFFSET);
+      return DW_DLV_ERROR;
+    }
+
+  /* Find the compile unit this address belongs to.  */
+  cu = find_cu (dbg, offset, error);
+  if (cu == NULL)
+    return DW_DLV_ERROR;
+
+  /* Creata a new die.  */
+  new_die = (Dwarf_Die) malloc (sizeof (struct Dwarf_Die_s));
+  if (new_die == NULL)
+    {
+      __libdwarf_error (dbg, error, DW_E_NOMEM);
+      return DW_DLV_ERROR;
+    }
+
+#ifdef DWARF_DEBUG
+  new_die->memtag = DW_DLA_DIE;
+#endif
+
+  /* Remember the address.  */
+  die_addr = (Dwarf_Small *) dbg->sections[IDX_debug_info].addr + offset;
+  new_die->addr = die_addr;
+
+  /* And the compile unit.  */
+  new_die->cu = cu;
+
+  /* 7.5.2  Debugging Information Entry
+
+     Each debugging information entry begins with an unsigned LEB128
+     number containing the abbreviation code for the entry.  */
+  get_uleb128 (u128, die_addr);
+
+  /* Find the abbreviation.  */
+  new_die->abbrev = __libdwarf_get_abbrev (dbg, cu, u128, error);
+  if (new_die->abbrev == NULL)
+    {
+      free (new_die);
+      return DW_DLV_ERROR;
+    }
+
+  *return_die = new_die;
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_seterrarg.c b/libdwarf/dwarf_seterrarg.c
new file mode 100644
index 0000000..8b52d24
--- /dev/null
+++ b/libdwarf/dwarf_seterrarg.c
@@ -0,0 +1,30 @@
+/* Set new error handler argument.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libdwarfP.h>
+
+
+Dwarf_Ptr
+dwarf_seterrarg (dbg, errarg)
+     Dwarf_Debug dbg;
+     Dwarf_Ptr errarg;
+{
+  Dwarf_Ptr old = dbg->dbg_errarg;
+  dbg->dbg_errarg = errarg;
+  return old;
+}
diff --git a/libdwarf/dwarf_seterrhand.c b/libdwarf/dwarf_seterrhand.c
new file mode 100644
index 0000000..199a250
--- /dev/null
+++ b/libdwarf/dwarf_seterrhand.c
@@ -0,0 +1,30 @@
+/* Set new error handler.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libdwarfP.h>
+
+
+Dwarf_Handler
+dwarf_seterrhand (dbg, errhand)
+     Dwarf_Debug dbg;
+     Dwarf_Handler errhand;
+{
+  Dwarf_Handler old = dbg->dbg_errhand;
+  dbg->dbg_errhand = errhand;
+  return old;
+}
diff --git a/libdwarf/dwarf_siblingof.c b/libdwarf/dwarf_siblingof.c
new file mode 100644
index 0000000..04a3ab6
--- /dev/null
+++ b/libdwarf/dwarf_siblingof.c
@@ -0,0 +1,257 @@
+/* Return descriptor for sibling of die.
+   Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include <stdlib.h>
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_siblingof (dbg, die, return_sub, error)
+     Dwarf_Debug dbg;
+     Dwarf_Die die;
+     Dwarf_Die *return_sub;
+     Dwarf_Error *error;
+{
+  Dwarf_Small *die_addr;
+  Dwarf_CU_Info cu;
+  Dwarf_Unsigned u128;
+  Dwarf_Die new_die;
+
+  if (dbg == NULL)
+    return DW_DLV_ERROR;
+
+  if (die == NULL)
+    {
+      Dwarf_Unsigned die_offset;
+
+      /* We are supposed to return the DW_TAG_compile_unit die for the
+	 current compile unit.  For this to succeed the user must have
+	 looked for the compile unit before.  */
+      if (dbg->cu_list_current == NULL)
+	{
+	  __libdwarf_error (dbg, error, DW_E_NO_CU);
+	  return DW_DLV_ERROR;
+	}
+
+      cu = dbg->cu_list_current;
+
+      die_offset = (cu->offset + 2 * cu->offset_size - 4 + sizeof (Dwarf_Half)
+		    + cu->offset_size + 1);
+
+      /* Check whether this is withing the debug section.  */
+      if (die_offset >= dbg->sections[IDX_debug_info].size)
+	return DW_DLV_NO_ENTRY;
+
+      /* Compute the pointer.  */
+      die_addr = ((Dwarf_Small *) dbg->sections[IDX_debug_info].addr
+		  + die_offset);
+    }
+  else
+    {
+      unsigned int level = 0;
+
+      /* We start from the given die.  */
+      cu = die->cu;
+
+      /* Address of the given die.  */
+      die_addr = die->addr;
+
+      /* Search for the beginning of the next die on this level.  We
+         must not return the dies for children of the given die.  */
+      do
+	{
+	  Dwarf_Abbrev abbrev;
+	  Dwarf_Small *attrp;
+	  Dwarf_Word attr_name;
+	  Dwarf_Word attr_form;
+
+	  /* Get abbrev code.  */
+	  get_uleb128 (u128, die_addr);
+	  /*  And get the abbreviation itself.  */
+	  abbrev = __libdwarf_get_abbrev (dbg, cu, u128, error);
+	  if (abbrev == NULL)
+	    return DW_DLV_ERROR;
+
+	  /* This is where the attributes start.  */
+	  attrp = abbrev->attrp;
+
+	  /* Does this abbreviation have children?  */
+	  if (abbrev->has_children)
+	    ++level;
+
+	  while (1)
+	    {
+	      /* Are we still in bounds?  */
+	      if (attrp >= ((Dwarf_Small *)dbg->sections[IDX_debug_abbrev].addr
+			    + dbg->sections[IDX_debug_abbrev].size))
+		{
+		  __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+		  return DW_DLV_ERROR;
+		}
+
+	      /* Get attribute name and form.
+
+		 XXX We don't check whether this reads beyond the end of
+		 the section.  */
+	      get_uleb128 (attr_name, attrp);
+	      get_uleb128 (attr_form, attrp);
+
+	      /* We can stop if we found the attribute with value zero.  */
+	      if (attr_name == 0 && attr_form == 0)
+		break;
+
+	      /* See whether this is an sibling attribute which would help
+		 us to skip ahead.  */
+	      if (attr_name == DW_AT_sibling)
+		{
+		  /* Cool.  We just have to decode the parameter and we know
+		     the offset.  */
+		  Dwarf_Unsigned offset;
+
+		  switch (attr_form)
+		    {
+		    case DW_FORM_ref1:
+		      offset = *die_addr;
+		      break;
+
+		    case DW_FORM_ref2:
+		      offset = read_2ubyte_unaligned (dbg, die_addr);
+		      break;
+
+		    case DW_FORM_ref4:
+		      offset = read_4ubyte_unaligned (dbg, die_addr);
+		      break;
+
+		    case DW_FORM_ref8:
+		      offset = read_8ubyte_unaligned (dbg, die_addr);
+		      break;
+
+		    case DW_FORM_ref_udata:
+		      get_uleb128 (offset, die_addr);
+		      break;
+
+		    default:
+		      /* The above are all legal forms.  Everything else is
+			 an error.  */
+		      __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+		      return DW_DLV_ERROR;
+		    }
+
+		  /* Compute the new address.  Some sanity check first,
+		     though.  */
+		  if (unlikely (offset > 2 * cu->offset_size - 4 + cu->length))
+		    {
+		      __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+		      return DW_DLV_ERROR;
+		    }
+
+		  die_addr =
+		    ((Dwarf_Small *) dbg->sections[IDX_debug_info].addr
+		     + cu->offset + offset);
+
+		  /* Even if the abbreviation has children we have stepped
+		     over them now.  */
+		  if (abbrev->has_children)
+		    --level;
+		  break;
+		}
+
+	      /* Skip over the rest of this attribute (if there is any).  */
+	      if (attr_form != 0)
+		{
+		  size_t len;
+
+		  if (unlikely (__libdwarf_form_val_len (dbg, cu, attr_form,
+							 die_addr, &len, error)
+				!= DW_DLV_OK))
+		    return DW_DLV_ERROR;
+
+		  die_addr += len;
+		}
+	    }
+
+	  /* Check that we are not yet at the end.  */
+	  if (*die_addr == 0)
+	    {
+	      if (level == 0)
+		return DW_DLV_NO_ENTRY;
+
+	      do
+		++die_addr;
+	      while (--level > 0 && *die_addr == 0);
+	    }
+	}
+      while (level > 0);
+    }
+
+  /* Are we at the end.  */
+  if (die != NULL
+      && die_addr >= ((Dwarf_Small *) dbg->sections[IDX_debug_info].addr
+		      + cu->offset + cu->length + 2 * cu->offset_size - 4))
+    return DW_DLV_NO_ENTRY;
+
+  /* See whether there is another sibling available or whether this is
+     the end.  */
+  if (*die_addr == 0)
+    return DW_DLV_NO_ENTRY;
+
+  /* There is more data.  Create the data structure.  */
+  new_die = (Dwarf_Die) malloc (sizeof (struct Dwarf_Die_s));
+  if (new_die == NULL)
+    {
+      __libdwarf_error (dbg, error, DW_E_NOMEM);
+      return DW_DLV_ERROR;
+    }
+
+#ifdef DWARF_DEBUG
+  new_die->memtag = DW_DLA_DIE;
+#endif
+
+  /* Remember the address.  */
+  new_die->addr = die_addr;
+
+  /* And the compile unit.  */
+  new_die->cu = cu;
+
+  /* 7.5.2  Debugging Information Entry
+
+     Each debugging information entry begins with an unsigned LEB128
+     number containing the abbreviation code for the entry.  */
+  get_uleb128 (u128, die_addr);
+
+  /* Find the abbreviation.  */
+  new_die->abbrev = __libdwarf_get_abbrev (dbg, cu, u128, error);
+  if (new_die->abbrev == NULL)
+    {
+      free (new_die);
+      return DW_DLV_ERROR;
+    }
+
+  /* If we are looking for the first entry this must be a compile unit.  */
+  if (die == NULL && unlikely (new_die->abbrev->tag != DW_TAG_compile_unit))
+    {
+      free (new_die);
+      __libdwarf_error (dbg, error, DW_E_1ST_NO_CU);
+      return DW_DLV_ERROR;
+    }
+
+  *return_sub = new_die;
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_srcfiles.c b/libdwarf/dwarf_srcfiles.c
new file mode 100644
index 0000000..1090d83
--- /dev/null
+++ b/libdwarf/dwarf_srcfiles.c
@@ -0,0 +1,344 @@
+/* Return source files of compilation unit.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libdwarfP.h>
+
+
+struct dirlist
+{
+  char *dir;
+  size_t len;
+  struct dirlist *next;
+};
+
+struct filelist
+{
+  char *name;
+  Dwarf_Unsigned mtime;
+  Dwarf_Unsigned length;
+  struct filelist *next;
+};
+
+
+static int
+read_file_names (Dwarf_Debug dbg, char *comp_dir, Dwarf_Small **linepp,
+		 char ***result, Dwarf_Signed *nresult, Dwarf_Error *error)
+{
+  Dwarf_Small *linep = *linepp;
+  struct dirlist comp_dir_elem;
+  struct dirlist *dirlist;
+  unsigned int ndirlist;
+  struct dirlist **dirarray;
+  struct filelist *filelist = NULL;
+  unsigned int nfilelist = 0;
+
+  /* First comes the list of directories.  Add the compilation directory
+     first since the index zero is used for it.  */
+  comp_dir_elem.dir = comp_dir;
+  comp_dir_elem.len = comp_dir ? strlen (comp_dir) : 0;
+  comp_dir_elem.next = NULL;
+  dirlist = &comp_dir_elem;
+  ndirlist = 1;
+
+  while (*linep != 0)
+    {
+      struct dirlist *new_dir = (struct dirlist *) alloca (sizeof (*new_dir));
+
+      new_dir->dir = (char *) linep;
+      new_dir->len = strlen ((char *) linep);
+      new_dir->next = dirlist;
+      dirlist = new_dir;
+      ++ndirlist;
+      linep += new_dir->len + 1;
+    }
+  /* Skip the final NUL byte.  */
+  ++linep;
+
+  /* Rearrange the list in array form.  */
+  dirarray = (struct dirlist **) alloca (sizeof (*dirarray));
+  while (ndirlist-- > 0)
+    {
+      dirarray[ndirlist] = dirlist;
+      dirlist = dirlist->next;
+    }
+
+  /* Now read the files.  */
+  while (*linep != 0)
+    {
+      struct filelist *new_file =
+	(struct filelist *) alloca (sizeof (*new_file));
+      char *fname;
+      size_t fnamelen;
+      Dwarf_Unsigned diridx;
+
+      /* First comes the file name.  */
+      fname = (char *) linep;
+      fnamelen = strlen (fname);
+      linep += fnamelen + 1;
+
+      /* Then the index.  */
+      get_uleb128 (diridx, linep);
+      if (unlikely (diridx >= ndirlist))
+	{
+	  __libdwarf_error (dbg, error, DW_E_INVALID_DIR_IDX);
+	  return DW_DLV_ERROR;
+	}
+
+      if (*fname == '/')
+	/* It's an absolute path.  */
+	new_file->name = strdup (fname);
+      else
+	{
+	  new_file->name = (char *) malloc (dirarray[diridx]->len + 1
+					    + fnamelen + 1);
+	  if (new_file->name != NULL)
+	    {
+	      char *cp = new_file->name;
+
+	      if (dirarray[diridx]->dir != NULL)
+		/* This value could be NULL in case the DW_AT_comp_dir
+		   was not present.  We cannot do much in this case.
+		   The easiest thing is to convert the path in an
+		   absolute path.  */
+		cp = stpcpy (cp, dirarray[diridx]->dir);
+	      *cp++ = '/';
+	      strcpy (cp, fname);
+	    }
+	}
+      if (new_file->name == NULL)
+	{
+	  /* XXX Should we bother to free all the memory?  */
+	  __libdwarf_error (dbg, error, DW_E_NOMEM);
+	  return DW_DLV_ERROR;
+	}
+
+      /* Next comes the modification time.  */
+      get_uleb128 (new_file->mtime, linep);
+
+      /* Finally the length of the file.  */
+      get_uleb128 (new_file->length, linep);
+
+      new_file->next = filelist;
+      filelist = new_file;
+      ++nfilelist;
+    }
+
+  /* Put all the files in an array.  */
+  *result = (char **) malloc (nfilelist * sizeof (char *));
+  if (*result == NULL)
+    {
+      /* XXX Should we bother to free all the memory?  */
+      __libdwarf_error (dbg, error, DW_E_NOMEM);
+      return DW_DLV_ERROR;
+    }
+
+  *nresult = nfilelist;
+  while (nfilelist-- > 0)
+    {
+      (*result)[nfilelist] = filelist->name;
+      filelist = filelist->next;
+    }
+
+  /* Provide caller address of next byte.  */
+  *linepp = linep + 1;
+
+  return DW_DLV_OK;
+}
+
+
+int
+dwarf_srcfiles (die, srcfiles, srcfilecount, error)
+     Dwarf_Die die;
+     char ***srcfiles;
+     Dwarf_Signed *srcfilecount;
+     Dwarf_Error *error;
+{
+  Dwarf_CU_Info cu = die->cu;
+  Dwarf_Debug dbg = cu->dbg;
+  Dwarf_Attribute stmt_list;
+  Dwarf_Attribute comp_dir_attr;
+  char *comp_dir;
+  Dwarf_Unsigned offset;
+  Dwarf_Small *linep;
+  Dwarf_Small *lineendp;
+  Dwarf_Small *header_start;
+  Dwarf_Unsigned header_length;
+  unsigned int unit_length;
+  unsigned int version;
+  unsigned int opcode_base;
+  int length;
+  int res;
+
+  /* For now we haven't found anything.  */
+  *srcfilecount = 0;
+
+  /* The die must be for a compilation unit.  */
+  if (die->abbrev->tag != DW_TAG_compile_unit)
+    {
+      __libdwarf_error (die->cu->dbg, error, DW_E_NO_CU);
+      return DW_DLV_ERROR;
+    }
+
+  /* The die must have a statement list associated.  */
+  res = dwarf_attr (die, DW_AT_stmt_list, &stmt_list, error);
+  if (res != DW_DLV_OK)
+    return res;
+
+  /* Get the offset into the .debug_line section.  */
+  res = dwarf_formudata (stmt_list, &offset, error);
+  if (res != DW_DLV_OK)
+    {
+      dwarf_dealloc (dbg, stmt_list, DW_DLA_ATTR);
+      return res;
+    }
+
+  /* We need a .debug_line section.  */
+  if (dbg->sections[IDX_debug_line].addr == NULL)
+    {
+      dwarf_dealloc (dbg, stmt_list, DW_DLA_ATTR);
+      __libdwarf_error (dbg, error, DW_E_NO_DEBUG_LINE);
+      return DW_DLV_ERROR;
+    }
+
+  linep = (Dwarf_Small *) dbg->sections[IDX_debug_line].addr + offset;
+  lineendp = ((Dwarf_Small *) dbg->sections[IDX_debug_line].addr
+	      + dbg->sections[IDX_debug_line].size);
+
+  /* Test whether at least the first 4 bytes are available.  */
+  if (unlikely (linep + 4 > lineendp))
+    {
+      dwarf_dealloc (dbg, stmt_list, DW_DLA_ATTR);
+      __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+      return DW_DLV_ERROR;
+    }
+
+  /* Get the compilation directory.  */
+  res = dwarf_attr (die, DW_AT_comp_dir, &comp_dir_attr, error);
+  if (unlikely (res == DW_DLV_ERROR)
+      || (res == DW_DLV_OK
+	  && unlikely (dwarf_formstring (comp_dir_attr, &comp_dir, error)
+		       == DW_DLV_ERROR)))
+    {
+      dwarf_dealloc (dbg, stmt_list, DW_DLA_ATTR);
+      __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+      return DW_DLV_ERROR;
+    }
+  else if (res == DW_DLV_OK)
+    dwarf_dealloc (dbg, comp_dir_attr, DW_DLA_ATTR);
+  else
+    comp_dir = NULL;
+
+  /* Read the unit_length.  */
+  unit_length = read_4ubyte_unaligned (dbg, linep);
+  linep += 4;
+  length = 4;
+  if (unit_length == 0xffffffff)
+    {
+      if (unlikely (linep + 8 > lineendp))
+	{
+	  dwarf_dealloc (dbg, stmt_list, DW_DLA_ATTR);
+	  __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+	  return DW_DLV_ERROR;
+	}
+
+      unit_length = read_8ubyte_unaligned (dbg, linep);
+      linep += 8;
+      length = 8;
+    }
+
+  /* Check whether we have enough room in the section.  */
+  if (unlikely (linep + unit_length > lineendp))
+    {
+      dwarf_dealloc (dbg, stmt_list, DW_DLA_ATTR);
+      __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+      return DW_DLV_ERROR;
+    }
+  lineendp = linep + unit_length;
+
+  /* The next element of the header is the version identifier.  */
+  version = read_2ubyte_unaligned (dbg, linep);
+  if (unlikely (version != DWARF_VERSION))
+    {
+      dwarf_dealloc (dbg, stmt_list, DW_DLA_ATTR);
+      __libdwarf_error (dbg, error, DW_E_VERSION_ERROR);
+      return DW_DLV_ERROR;
+    }
+  linep += 2;
+
+  /* Next comes the header length.  */
+  if (length == 4)
+    {
+      header_length = read_4ubyte_unaligned (dbg, linep);
+      linep += 4;
+    }
+  else
+    {
+      header_length = read_8ubyte_unaligned (dbg, linep);
+      linep += 8;
+    }
+  header_start = linep;
+
+  /* Next the minimum instruction length.  Skip it.  */
+  ++linep;
+
+  /* Then the flag determining the default value of the is_stmt
+     register.  Skip it.  */
+  ++linep;
+
+  /* Now the line base.  Skip it.  */
+  ++linep;
+
+  /* And the line range.  Skip it.  */
+  ++linep;
+
+  /* The opcode base.  */
+  opcode_base = *linep++;
+
+  /* Skip the array with the standard opcode length.  */
+  linep += opcode_base - 1;
+
+  /* Next the include directories and the file names.  */
+  if (unlikely (read_file_names (dbg, comp_dir, &linep, srcfiles, srcfilecount,
+				 error) != DW_DLV_OK))
+    {
+      dwarf_dealloc (dbg, stmt_list, DW_DLA_ATTR);
+      return DW_DLV_ERROR;
+    }
+
+  /* Consistency check.  */
+  if (unlikely (linep != header_start + header_length))
+    {
+      int i;
+
+      for (i = 0; i < *srcfilecount; ++i)
+	dwarf_dealloc (dbg, (*srcfiles)[i], DW_DLA_STRING);
+      dwarf_dealloc (dbg, *srcfiles, DW_DLA_LIST);
+
+      dwarf_dealloc (dbg, stmt_list, DW_DLA_ATTR);
+      __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+      return DW_DLV_ERROR;
+    }
+
+  dwarf_dealloc (dbg, stmt_list, DW_DLA_ATTR);
+
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_srclang.c b/libdwarf/dwarf_srclang.c
new file mode 100644
index 0000000..4514063
--- /dev/null
+++ b/libdwarf/dwarf_srclang.c
@@ -0,0 +1,31 @@
+/* Return source language associated with die.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_srclang (die, return_lang, error)
+     Dwarf_Die die;
+     Dwarf_Unsigned *return_lang;
+     Dwarf_Error *error;
+{
+  return __libdwarf_getconstant (die, DW_AT_language, return_lang, error);
+}
diff --git a/libdwarf/dwarf_srclines.c b/libdwarf/dwarf_srclines.c
new file mode 100644
index 0000000..796b790
--- /dev/null
+++ b/libdwarf/dwarf_srclines.c
@@ -0,0 +1,745 @@
+/* Return source lines of compilation unit.
+   Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libdwarfP.h>
+
+
+struct dirlist
+{
+  char *dir;
+  size_t len;
+  struct dirlist *next;
+};
+
+struct filelist
+{
+  char *name;
+  Dwarf_Unsigned mtime;
+  Dwarf_Unsigned length;
+  struct filelist *next;
+};
+
+struct linelist
+{
+  Dwarf_Line line;
+  struct linelist *next;
+};
+
+
+/* Adds a new line to the matrix.  We cannot definte a function because
+   we want to use alloca.  */
+#define NEW_LINE(end_seq) \
+  do {									      \
+       /* Add the new line.  */						      \
+       new_line = (struct linelist *) alloca (sizeof (struct linelist));      \
+       new_line->line = (Dwarf_Line) malloc (sizeof (struct Dwarf_Line_s));   \
+       if (new_line == NULL)						      \
+	 {								      \
+	   /* XXX Should we bother to free the memory?  */		      \
+	   __libdwarf_error (dbg, error, DW_E_NOMEM);			      \
+	   return DW_DLV_ERROR;						      \
+	 }								      \
+									      \
+       /* Set the line information.  */					      \
+       new_line->line->addr = address;					      \
+       new_line->line->file = file;					      \
+       new_line->line->line = line;					      \
+       new_line->line->column = column;					      \
+       new_line->line->is_stmt = is_stmt;				      \
+       new_line->line->basic_block = basic_block;			      \
+       new_line->line->end_sequence = end_seq;				      \
+       new_line->line->prologue_end = prologue_end;			      \
+       new_line->line->epilogue_begin = epilogue_begin;			      \
+									      \
+       new_line->next = linelist;					      \
+       linelist = new_line;						      \
+       ++nlinelist;							      \
+  } while (0)
+
+
+int
+dwarf_srclines (die, linebuf, linecount, error)
+     Dwarf_Die die;
+     Dwarf_Line **linebuf;
+     Dwarf_Signed *linecount;
+     Dwarf_Error *error;
+{
+  Dwarf_CU_Info cu = die->cu;
+  Dwarf_Debug dbg = cu->dbg;
+  Dwarf_Attribute stmt_list;
+  Dwarf_Attribute comp_dir_attr;
+  char *comp_dir;
+  Dwarf_Unsigned offset;
+  Dwarf_Small *linep;
+  Dwarf_Small *lineendp;
+  Dwarf_Small *header_start;
+  Dwarf_Unsigned header_length;
+  Dwarf_File files;
+  Dwarf_Line *lines;
+  unsigned int unit_length;
+  unsigned int version;
+  unsigned int opcode_base;
+  Dwarf_Small *standard_opcode_lengths;
+  unsigned int minimum_instruction_length;
+  unsigned int default_is_stmt;
+  int line_base;
+  unsigned int line_range;
+  int length;
+  struct dirlist comp_dir_elem;
+  struct dirlist *dirlist;
+  unsigned int ndirlist;
+  struct dirlist **dirarray;
+  struct filelist *filelist;
+  unsigned int nfilelist;
+  struct filelist null_file;
+  Dwarf_Unsigned address;
+  size_t file;
+  size_t line;
+  size_t column;
+  int is_stmt;
+  int basic_block;
+  int prologue_end;
+  int epilogue_begin;
+  struct linelist *linelist;
+  unsigned int nlinelist;
+  int res;
+
+  /* The die must be for a compilation unit.  */
+  if (unlikely (die->abbrev->tag != DW_TAG_compile_unit))
+    {
+      __libdwarf_error (die->cu->dbg, error, DW_E_NO_CU);
+      return DW_DLV_ERROR;
+    }
+
+  /* The die must have a statement list associated.  */
+  res = dwarf_attr (die, DW_AT_stmt_list, &stmt_list, error);
+  if (unlikely (res != DW_DLV_OK))
+    return res;
+
+  /* Get the offset into the .debug_line section.  */
+  res = dwarf_formudata (stmt_list, &offset, error);
+  if (unlikely (res != DW_DLV_OK))
+    {
+      dwarf_dealloc (dbg, stmt_list, DW_DLA_ATTR);
+      return res;
+    }
+
+  /* We need a .debug_line section.  */
+  if (dbg->sections[IDX_debug_line].addr == NULL)
+    {
+      dwarf_dealloc (dbg, stmt_list, DW_DLA_ATTR);
+      __libdwarf_error (dbg, error, DW_E_NO_DEBUG_LINE);
+      return DW_DLV_ERROR;
+    }
+
+  linep = (Dwarf_Small *) dbg->sections[IDX_debug_line].addr + offset;
+  lineendp = ((Dwarf_Small *) dbg->sections[IDX_debug_line].addr
+	      + dbg->sections[IDX_debug_line].size);
+
+  /* Test whether at least the first 4 bytes are available.  */
+  if (unlikely (linep + 4 > lineendp))
+    {
+      dwarf_dealloc (dbg, stmt_list, DW_DLA_ATTR);
+      __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+      return DW_DLV_ERROR;
+    }
+
+  /* Get the compilation directory.  */
+  res = dwarf_attr (die, DW_AT_comp_dir, &comp_dir_attr, error);
+  if (unlikely (res == DW_DLV_ERROR)
+      || (res == DW_DLV_OK
+	  && unlikely (dwarf_formstring (comp_dir_attr, &comp_dir, error)
+		       == DW_DLV_ERROR)))
+    {
+      dwarf_dealloc (dbg, stmt_list, DW_DLA_ATTR);
+      __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+      return DW_DLV_ERROR;
+    }
+  else if (res == DW_DLV_OK)
+    dwarf_dealloc (dbg, comp_dir_attr, DW_DLA_ATTR);
+  else
+    comp_dir = NULL;
+
+  /* Read the unit_length.  */
+  unit_length = read_4ubyte_unaligned (dbg, linep);
+  linep += 4;
+  length = 4;
+  if (unit_length == 0xffffffff)
+    {
+      if (unlikely (linep + 8 > lineendp))
+	{
+	  dwarf_dealloc (dbg, stmt_list, DW_DLA_ATTR);
+	  __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+	  return DW_DLV_ERROR;
+	}
+
+      unit_length = read_8ubyte_unaligned (dbg, linep);
+      linep += 8;
+      length = 8;
+    }
+
+  /* Check whether we have enough room in the section.  */
+  if (unlikely (linep + unit_length > lineendp))
+    {
+      dwarf_dealloc (dbg, stmt_list, DW_DLA_ATTR);
+      __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+      return DW_DLV_ERROR;
+    }
+  lineendp = linep + unit_length;
+
+  /* The next element of the header is the version identifier.  */
+  version = read_2ubyte_unaligned (dbg, linep);
+  if (unlikely (version != DWARF_VERSION))
+    {
+      dwarf_dealloc (dbg, stmt_list, DW_DLA_ATTR);
+      __libdwarf_error (dbg, error, DW_E_VERSION_ERROR);
+      return DW_DLV_ERROR;
+    }
+  linep += 2;
+
+  /* Next comes the header length.  */
+  if (length == 4)
+    {
+      header_length = read_4ubyte_unaligned (dbg, linep);
+      linep += 4;
+    }
+  else
+    {
+      header_length = read_8ubyte_unaligned (dbg, linep);
+      linep += 8;
+    }
+  header_start = linep;
+
+  /* Next the minimum instruction length.  */
+  minimum_instruction_length = *linep++;
+
+  /* Then the flag determining the default value of the is_stmt
+     register.  */
+  default_is_stmt = *linep++;
+
+  /* Now the line base.  */
+  line_base = *((signed char *) linep)++;
+
+  /* And the line range.  */
+  line_range = *linep++;
+
+  /* The opcode base.  */
+  opcode_base = *linep++;
+
+  /* Remember array with the standard opcode length (-1 to account for
+     the opcode with value zero not being mentioned).  */
+  standard_opcode_lengths = linep - 1;
+  linep += opcode_base - 1;
+
+  /* First comes the list of directories.  Add the compilation directory
+     first since the index zero is used for it.  */
+  comp_dir_elem.dir = comp_dir;
+  comp_dir_elem.len = comp_dir ? strlen (comp_dir) : 0;
+  comp_dir_elem.next = NULL;
+  dirlist = &comp_dir_elem;
+  ndirlist = 1;
+
+  while (*linep != 0)
+    {
+      struct dirlist *new_dir = (struct dirlist *) alloca (sizeof (*new_dir));
+
+      new_dir->dir = (char *) linep;
+      new_dir->len = strlen ((char *) linep);
+      new_dir->next = dirlist;
+      dirlist = new_dir;
+      ++ndirlist;
+      linep += new_dir->len + 1;
+    }
+  /* Skip the final NUL byte.  */
+  ++linep;
+
+  /* Rearrange the list in array form.  */
+  dirarray = (struct dirlist **) alloca (sizeof (*dirarray));
+  while (ndirlist-- > 0)
+    {
+      dirarray[ndirlist] = dirlist;
+      dirlist = dirlist->next;
+    }
+
+  comp_dir_elem.dir = comp_dir;
+  comp_dir_elem.len = comp_dir ? strlen (comp_dir) : 0;
+  comp_dir_elem.next = NULL;
+  dirlist = &comp_dir_elem;
+  ndirlist = 1;
+
+  /* Now read the files.  */
+  null_file.name = "???";
+  null_file.mtime = 0;
+  null_file.length = 0;
+  null_file.next = NULL;
+  filelist = &null_file;
+  nfilelist = 1;
+
+  while (*linep != 0)
+    {
+      struct filelist *new_file =
+	(struct filelist *) alloca (sizeof (*new_file));
+      char *fname;
+      size_t fnamelen;
+      Dwarf_Unsigned diridx;
+
+      /* First comes the file name.  */
+      fname = (char *) linep;
+      fnamelen = strlen (fname);
+      linep += fnamelen + 1;
+
+      /* Then the index.  */
+      get_uleb128 (diridx, linep);
+      if (unlikely (diridx >= ndirlist))
+	{
+	  dwarf_dealloc (dbg, stmt_list, DW_DLA_ATTR);
+	  __libdwarf_error (dbg, error, DW_E_INVALID_DIR_IDX);
+	  return DW_DLV_ERROR;
+	}
+
+      if (*fname == '/')
+	/* It's an absolute path.  */
+	new_file->name = strdup (fname);
+      else
+	{
+	  new_file->name = (char *) malloc (dirarray[diridx]->len + 1
+					    + fnamelen + 1);
+	  if (new_file->name != NULL)
+	    {
+	      char *cp = new_file->name;
+
+	      if (dirarray[diridx]->dir != NULL)
+		/* This value could be NULL in case the DW_AT_comp_dir
+		   was not present.  We cannot do much in this case.
+		   The easiest thing is to convert the path in an
+		   absolute path.  */
+		cp = stpcpy (cp, dirarray[diridx]->dir);
+	      *cp++ = '/';
+	      strcpy (cp, fname);
+	    }
+	}
+      if (new_file->name == NULL)
+	{
+	  /* XXX Should we bother to free all the memory?  */
+	  dwarf_dealloc (dbg, stmt_list, DW_DLA_ATTR);
+	  __libdwarf_error (dbg, error, DW_E_NOMEM);
+	  return DW_DLV_ERROR;
+	}
+
+      /* Next comes the modification time.  */
+      get_uleb128 (new_file->mtime, linep);
+
+      /* Finally the length of the file.  */
+      get_uleb128 (new_file->length, linep);
+
+      new_file->next = filelist;
+      filelist = new_file;
+      ++nfilelist;
+    }
+  ++linep;
+
+  /* Consistency check.  */
+  if (unlikely (linep != header_start + header_length))
+    {
+      dwarf_dealloc (dbg, stmt_list, DW_DLA_ATTR);
+      __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+      return DW_DLV_ERROR;
+    }
+
+  /* We are about to process the statement program.  Initialize the
+     state machine registers (see 6.2.2 in the v2.1 specification).  */
+  address = 0;
+  file = 1;
+  line = 1;
+  column = 0;
+  is_stmt = default_is_stmt;
+  basic_block = 0;
+  prologue_end = 0;
+  epilogue_begin = 0;
+
+  /* Process the instructions.  */
+  linelist = NULL;
+  nlinelist = 0;
+  while (linep < lineendp)
+    {
+      struct linelist *new_line;
+      unsigned int opcode;
+      unsigned int u128;
+      int s128;
+
+      /* Read the opcode.  */
+      opcode = *linep++;
+
+      /* Is this a special opcode?  */
+      if (likely (opcode >= opcode_base))
+	{
+	  /* Yes.  Handling this is quite easy since the opcode value
+	     is computed with
+
+	     opcode = (desired line increment - line_base)
+		      + (line_range * address advance) + opcode_base
+	  */
+	  int line_increment = line_base + (opcode - opcode_base) % line_range;
+	  unsigned int address_increment = (minimum_instruction_length
+					    * ((opcode - opcode_base)
+					       / line_range));
+
+	  /* Perform the increments.  */
+	  line += line_increment;
+	  address += address_increment;
+
+	  /* Add a new line with the current state machine values.  */
+	  NEW_LINE (0);
+
+	  /* Reset the flags.  */
+	  basic_block = 0;
+	  prologue_end = 0;
+	  epilogue_begin = 0;
+	}
+      else if (opcode == 0)
+	{
+	  /* This an extended opcode.  */
+	  unsigned int len;
+
+	  /* The length.  */
+	  len = *linep++;
+
+	  /* The sub-opecode.  */
+	  opcode = *linep++;
+
+	  switch (opcode)
+	    {
+	    case DW_LNE_end_sequence:
+	      /* Add a new line with the current state machine values.
+		 The is the end of the sequence.  */
+	      NEW_LINE (1);
+
+	      /* Reset the registers.  */
+	      address = 0;
+	      file = 1;
+	      line = 1;
+	      column = 0;
+	      is_stmt = default_is_stmt;
+	      basic_block = 0;
+	      prologue_end = 0;
+	      epilogue_begin = 0;
+	      break;
+
+	    case DW_LNE_set_address:
+	      if (cu->address_size == 4)
+		address = read_4ubyte_unaligned (dbg, linep);
+	      else
+		address = read_8ubyte_unaligned (dbg, linep);
+	      linep += cu->address_size;
+	      break;
+
+	    case DW_LNE_define_file:
+	      {
+		struct filelist *new_file;
+		char *fname;
+		size_t fnamelen;
+		unsigned int diridx;
+		Dwarf_Unsigned mtime;
+		Dwarf_Unsigned length;
+
+		fname = (char *) linep;
+		fnamelen = strlen (fname);
+		linep += fnamelen + 1;
+
+		get_uleb128 (diridx, linep);
+		get_uleb128 (mtime, linep);
+		get_uleb128 (length, linep);
+
+		new_file = (struct filelist *) alloca (sizeof (*new_file));
+		if (fname[0] == '/')
+		  new_file->name = strdup (fname);
+		else
+		  {
+
+		    new_file->name = (char *) malloc (dirarray[diridx]->len + 1
+						      + fnamelen + 1);
+		    if (new_file->name != NULL)
+		      {
+			char *cp = new_file->name;
+
+			if (dirarray[diridx]->dir != NULL)
+			  /* This value could be NULL in case the
+			     DW_AT_comp_dir was not present.  We
+			     cannot do much in this case.  The easiest
+			     thing is to convert the path in an
+			     absolute path.  */
+			  cp = stpcpy (cp, dirarray[diridx]->dir);
+			*cp++ = '/';
+			strcpy (cp, fname);
+		      }
+		  }
+		if (new_file->name == NULL)
+		  {
+		    dwarf_dealloc (dbg, stmt_list, DW_DLA_ATTR);
+		    __libdwarf_error (dbg, error, DW_E_NOMEM);
+		    return DW_DLV_ERROR;
+		  }
+
+		new_file->mtime = mtime;
+		new_file->length = length;
+		new_file->next = filelist;
+		filelist = new_file;
+		++nfilelist;
+	      }
+	      break;
+
+	    default:
+	      /* Unknown, ignore it.  */
+	      linep += len - 1;
+	      break;
+	    }
+	}
+      else if (opcode <= DW_LNS_set_epilog_begin)
+	{
+	  /* This is a known standard opcode.  */
+	  switch (opcode)
+	    {
+	    case DW_LNS_copy:
+	      /* Takes no argument.  */
+	      if (unlikely (standard_opcode_lengths[opcode] != 0))
+		{
+		  /* XXX Free memory.  */
+		  dwarf_dealloc (dbg, stmt_list, DW_DLA_ATTR);
+		  __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+		  return DW_DLV_ERROR;
+		}
+
+	      /* Add a new line with the current state machine values.  */
+	      NEW_LINE (0);
+
+	      /* Reset the flags.  */
+	      basic_block = 0;
+	      /* XXX Whether the following two lines are necessary is
+		 unclear.  I guess the current v2.1 specification has
+		 a bug in that it says clearing these two registers is
+		 not necessary.  */
+	      prologue_end = 0;
+	      epilogue_begin = 0;
+	      break;
+
+	    case DW_LNS_advance_pc:
+	      /* Takes one uleb128 parameter which is added to the address.  */
+	      if (unlikely (standard_opcode_lengths[opcode] != 1))
+		{
+		  /* XXX Free memory.  */
+		  dwarf_dealloc (dbg, stmt_list, DW_DLA_ATTR);
+		  __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+		  return DW_DLV_ERROR;
+		}
+
+	      get_uleb128 (u128, linep);
+	      address += minimum_instruction_length * u128;
+	      break;
+
+	    case DW_LNS_advance_line:
+	      /* Takes one sleb128 parameter which is added to the line.  */
+	      if (unlikely (standard_opcode_lengths[opcode] != 1))
+		{
+		  /* XXX Free memory.  */
+		  dwarf_dealloc (dbg, stmt_list, DW_DLA_ATTR);
+		  __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+		  return DW_DLV_ERROR;
+		}
+
+	      get_sleb128 (s128, linep);
+	      line += s128;
+	      break;
+
+	    case DW_LNS_set_file:
+	      /* Takes one uleb128 parameter which is stored in file.  */
+	      if (unlikely (standard_opcode_lengths[opcode] != 1))
+		{
+		  /* XXX Free memory.  */
+		  dwarf_dealloc (dbg, stmt_list, DW_DLA_ATTR);
+		  __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+		  return DW_DLV_ERROR;
+		}
+
+	      get_uleb128 (u128, linep);
+	      file = u128;
+	      break;
+
+	    case DW_LNS_set_column:
+	      /* Takes one uleb128 parameter which is stored in column.  */
+	      if (unlikely (standard_opcode_lengths[opcode] != 1))
+		{
+		  /* XXX Free memory.  */
+		  dwarf_dealloc (dbg, stmt_list, DW_DLA_ATTR);
+		  __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+		  return DW_DLV_ERROR;
+		}
+
+	      get_uleb128 (u128, linep);
+	      column = u128;
+	      break;
+
+	    case DW_LNS_negate_stmt:
+	      /* Takes no argument.  */
+	      if (unlikely (standard_opcode_lengths[opcode] != 0))
+		{
+		  /* XXX Free memory.  */
+		  dwarf_dealloc (dbg, stmt_list, DW_DLA_ATTR);
+		  __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+		  return DW_DLV_ERROR;
+		}
+
+	      is_stmt = 1 - is_stmt;
+	      break;
+
+	    case DW_LNS_set_basic_block:
+	      /* Takes no argument.  */
+	      if (unlikely (standard_opcode_lengths[opcode] != 0))
+		{
+		  /* XXX Free memory.  */
+		  dwarf_dealloc (dbg, stmt_list, DW_DLA_ATTR);
+		  __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+		  return DW_DLV_ERROR;
+		}
+
+	      basic_block = 1;
+	      break;
+
+	    case DW_LNS_const_add_pc:
+	      /* Takes no argument.  */
+	      if (unlikely (standard_opcode_lengths[opcode] != 0))
+		{
+		  /* XXX Free memory.  */
+		  dwarf_dealloc (dbg, stmt_list, DW_DLA_ATTR);
+		  __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+		  return DW_DLV_ERROR;
+		}
+
+	      address += (minimum_instruction_length
+			  * ((255 - opcode_base) / line_range));
+	      break;
+
+	    case DW_LNS_fixed_advance_pc:
+	      /* Takes one 16 bit parameter which is added to the address.  */
+	      if (unlikely (standard_opcode_lengths[opcode] != 1))
+		{
+		  /* XXX Free memory.  */
+		  dwarf_dealloc (dbg, stmt_list, DW_DLA_ATTR);
+		  __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+		  return DW_DLV_ERROR;
+		}
+
+	      address += read_2ubyte_unaligned (dbg, linep);
+	      linep += 2;
+	      break;
+
+	    case DW_LNS_set_prologue_end:
+	      /* Takes no argument.  */
+	      if (unlikely (standard_opcode_lengths[opcode] != 0))
+		{
+		  /* XXX Free memory.  */
+		  dwarf_dealloc (dbg, stmt_list, DW_DLA_ATTR);
+		  __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+		  return DW_DLV_ERROR;
+		}
+
+	      prologue_end = 1;
+	      break;
+
+	    case DW_LNS_set_epilog_begin:
+	      /* Takes no argument.  */
+	      if (unlikely (standard_opcode_lengths[opcode] != 0))
+		{
+		  /* XXX Free memory.  */
+		  dwarf_dealloc (dbg, stmt_list, DW_DLA_ATTR);
+		  __libdwarf_error (dbg, error, DW_E_INVALID_DWARF);
+		  return DW_DLV_ERROR;
+		}
+
+	      epilogue_begin = 1;
+	      break;
+	    }
+	}
+      else
+	{
+	  /* This is a new opcode the generator but not we know about.
+	     Read the parameters associated with it but then discard
+	     everything.  */
+	  int n;
+
+	  /* Read all the parameters for this opcode.  */
+	  for (n = standard_opcode_lengths[opcode]; n > 0; --n)
+	    {
+	      Dwarf_Unsigned u128;
+	      get_uleb128 (u128, linep);
+	    }
+
+	  /* Next round, ignore this opcode.  */
+	  continue;
+	}
+    }
+
+  /* Put all the files in an array.  */
+  files = (Dwarf_File) malloc (sizeof (struct Dwarf_File_s)
+			       + nfilelist * sizeof (Dwarf_Fileinfo));
+  if (files == NULL)
+    {
+      /* XXX Should we bother to free all the memory?  */
+      dwarf_dealloc (dbg, stmt_list, DW_DLA_ATTR);
+      __libdwarf_error (dbg, error, DW_E_NOMEM);
+      return DW_DLV_ERROR;
+    }
+
+  files->nfiles = nfilelist;
+  while (nfilelist-- > 0)
+    {
+      files->info[nfilelist].name = filelist->name;
+      files->info[nfilelist].mtime = filelist->mtime;
+      files->info[nfilelist].length = filelist->length;
+      filelist = filelist->next;
+    }
+
+  /* Remember the debugging descriptor.  */
+  files->dbg = dbg;
+
+  /* Now put the lines in an array.  */
+  lines = (Dwarf_Line *) malloc (nlinelist * sizeof (Dwarf_Line));
+  if (lines == NULL)
+    {
+      dwarf_dealloc (dbg, stmt_list, DW_DLA_ATTR);
+      __libdwarf_error (dbg, error, DW_E_NOMEM);
+      return DW_DLV_ERROR;
+    }
+
+  *linebuf = lines;
+  *linecount = nlinelist;
+
+  while (nlinelist--)
+    {
+      lines[nlinelist] = linelist->line;
+      linelist->line->files = files;
+      linelist = linelist->next;
+    }
+
+  dwarf_dealloc (dbg, stmt_list, DW_DLA_ATTR);
+
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_tag.c b/libdwarf/dwarf_tag.c
new file mode 100644
index 0000000..3c4d36e
--- /dev/null
+++ b/libdwarf/dwarf_tag.c
@@ -0,0 +1,30 @@
+/* Return tag of die.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_tag (die, tagval, error)
+     Dwarf_Die die;
+     Dwarf_Half *tagval;
+     Dwarf_Error *error;
+{
+  *tagval = die->abbrev->tag;
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_whatattr.c b/libdwarf/dwarf_whatattr.c
new file mode 100644
index 0000000..9887f2e
--- /dev/null
+++ b/libdwarf/dwarf_whatattr.c
@@ -0,0 +1,30 @@
+/* Return code of attribute.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_whatattr (attr, return_attr, error)
+     Dwarf_Attribute attr;
+     Dwarf_Half *return_attr;
+     Dwarf_Error *error;
+{
+  *return_attr = attr->code;
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/dwarf_whatform.c b/libdwarf/dwarf_whatform.c
new file mode 100644
index 0000000..5cb67b3
--- /dev/null
+++ b/libdwarf/dwarf_whatform.c
@@ -0,0 +1,30 @@
+/* Return form of attribute.
+   Copyright (C) 2000, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libdwarfP.h>
+
+
+int
+dwarf_whatform (attr, return_form, error)
+     Dwarf_Attribute attr;
+     Dwarf_Half *return_form;
+     Dwarf_Error *error;
+{
+  *return_form = attr->form;
+  return DW_DLV_OK;
+}
diff --git a/libdwarf/libdwarf.h b/libdwarf/libdwarf.h
new file mode 100644
index 0000000..37c958c
--- /dev/null
+++ b/libdwarf/libdwarf.h
@@ -0,0 +1,514 @@
+/* Interface for libdwarf.
+   Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifndef _LIBDWARF_H
+#define _LIBDWARF_H 1
+
+#include <libelf.h>
+#include <stdint.h>
+
+/* Basic data types.  */
+
+/* Used for boolean values.  */
+typedef int Dwarf_Bool;
+
+/* Numeric values of different sizes.  */
+typedef uint8_t Dwarf_Small;
+typedef uint16_t Dwarf_Half;
+typedef uint64_t Dwarf_Unsigned;
+typedef int64_t Dwarf_Signed;
+
+/* Offsets in the debugging sections.  */
+typedef uint64_t Dwarf_Off;
+
+/* Program counter value in the target object file.  */
+typedef uint64_t Dwarf_Addr;
+
+/* Address in the host process.  */
+typedef void *Dwarf_Ptr;
+
+
+/* Location record.  */
+typedef struct
+  {
+    Dwarf_Small lr_atom;		/* Operation */
+    Dwarf_Unsigned lr_number;		/* Operand */
+    Dwarf_Unsigned lr_number2;		/* Possible second operand */
+    Dwarf_Unsigned lr_offset;		/* Offset in location expression */
+  } Dwarf_Loc;
+
+
+/* Location description.  */
+typedef struct
+   {
+     Dwarf_Addr ld_lopc;		/* Beginning of range */
+     Dwarf_Addr ld_hipc;		/* End of range */
+     Dwarf_Half ld_cents;		/* Number of location records */
+     Dwarf_Loc *ld_s;			/* Array of location records */
+  } Dwarf_Locdesc;
+
+
+/* Error handler function.  */
+typedef struct Dwarf_Error_s *Dwarf_Error;	/* Forward declaration.  */
+typedef void (*Dwarf_Handler) (Dwarf_Error *, Dwarf_Ptr);
+
+/* Descriptor for block of uninterpreted data.  */
+typedef struct
+  {
+    Dwarf_Unsigned bl_len;
+    Dwarf_Ptr bl_data;
+  } Dwarf_Block;
+
+
+/* Descriptor for libdwarf session.  */
+typedef struct Dwarf_Debug_s *Dwarf_Debug;
+
+/* Descriptor for DWARF DIE.  */
+typedef struct Dwarf_Die_s *Dwarf_Die;
+
+/* Descriptor for DWARF attribute list.  */
+typedef struct Dwarf_Attribute_s *Dwarf_Attribute;
+
+/* Descriptor for source lines.  */
+typedef struct Dwarf_Line_s *Dwarf_Line;
+
+/* Descriptor for global name.  */
+typedef struct Dwarf_Global_s *Dwarf_Global;
+
+/* Descriptor for address range.  */
+typedef struct Dwarf_Arange_s *Dwarf_Arange;
+
+/* Descriptor for common information entry.  */
+typedef struct Dwarf_Cie_s *Dwarf_Cie;
+
+/* Descriptor for frame descriptor entry.  */
+typedef struct Dwarf_Fde_s *Dwarf_Fde;
+
+/* Descriptor for abbreviations.  */
+typedef struct Dwarf_Abbrev_s *Dwarf_Abbrev;
+
+
+/* Return values.  */
+enum
+  {
+    DW_DLV_NO_ENTRY = -1,	/* No error, but no entry.  */
+    DW_DLV_OK = 0,		/* Success.  */
+    DW_DLV_ERROR = 1,		/* Failure.  */
+  };
+
+
+/* Values for ACCESS parameter of 'dwarf_init' and 'dwarf_elf_init'.  */
+enum
+  {
+    DW_DLC_READ = 0,		/* Read-only access.  */
+    DW_DLC_WRITE = 1,		/* Write-only access.  */
+    DW_DLC_RDWR = 2		/* Read-write access.  */
+  };
+
+
+/* Open file associates with FD for use with the other functions of
+   this library.  Set the error handler and the parameter passed.  */
+extern int dwarf_init (int fd, Dwarf_Unsigned access,
+		       Dwarf_Handler errhand, Dwarf_Ptr errarg,
+		       Dwarf_Debug *dbg, Dwarf_Error *errdesc);
+
+/* Similar to `dwarf_init' but instead of a file descriptor of ELF
+   descriptor is passed.  */
+extern int dwarf_elf_init (Elf *elf, Dwarf_Unsigned access,
+			   Dwarf_Handler errhand, Dwarf_Ptr errarg,
+			   Dwarf_Debug *dbg, Dwarf_Error *errdesc);
+
+/* Return ELF handle.  */
+extern int dwarf_get_elf_init (Dwarf_Debug dbg, Elf **elf,
+			       Dwarf_Error *errdesc);
+
+/* Free resources allocated for debug handle.  */
+extern int dwarf_finish (Dwarf_Debug dbg, Dwarf_Error *errdesc);
+
+
+/* Return information about current and find new compile unit header.  */
+extern int dwarf_next_cu_header (Dwarf_Debug dbg,
+				 Dwarf_Unsigned *cu_header_length,
+				 Dwarf_Half *version_stamp,
+				 Dwarf_Unsigned *abbrev_offset,
+				 Dwarf_Half *address_size,
+				 Dwarf_Unsigned *next_cu_header,
+				 Dwarf_Error *errdesc);
+
+/* Return sibling of given DIE.  */
+extern int dwarf_siblingof (Dwarf_Debug dbg, Dwarf_Die die,
+			    Dwarf_Die *return_sub, Dwarf_Error *errdesc);
+
+/* Return child of DIE.  */
+extern int dwarf_child (Dwarf_Die die, Dwarf_Die *return_kid,
+			Dwarf_Error *errdesc);
+
+/* Return DIE at given offset.  */
+extern int dwarf_offdie (Dwarf_Debug dbg, Dwarf_Off offset,
+			 Dwarf_Die *return_die, Dwarf_Error *errdesc);
+
+
+/* Return tag of DIE.  */
+extern int dwarf_tag (Dwarf_Die die, Dwarf_Half *tagval, Dwarf_Error *errdesc);
+
+/* Return offset of DIE in .debug_info section.  */
+extern int dwarf_dieoffset (Dwarf_Die die, Dwarf_Off *return_offset,
+			    Dwarf_Error *errdesc);
+
+/* Return offset of DIE in compile unit data.  */
+extern int dwarf_die_CU_offset (Dwarf_Die die, Dwarf_Off *return_offset,
+				Dwarf_Error *errdesc);
+
+/* Return name attribute of DIE.  */
+extern int dwarf_diename (Dwarf_Die die, char **return_name,
+			  Dwarf_Error *errdesc);
+
+/* Return list of attributes for DIE.  */
+extern int dwarf_attrlist (Dwarf_Die die, Dwarf_Attribute **attrbuf,
+			   Dwarf_Signed *attrcount, Dwarf_Error *errdesc);
+
+/* Determine whether DIE has attribute specified of given type.  */
+extern int dwarf_hasattr (Dwarf_Die die, Dwarf_Half attr,
+			  Dwarf_Bool *return_bool, Dwarf_Error *errdesc);
+
+/* Return DIE attribute with specified of given type.  */
+extern int dwarf_attr (Dwarf_Die die, Dwarf_Half attr,
+		       Dwarf_Attribute *return_attr, Dwarf_Error *errdesc);
+
+/* Return low program counter value associated with die.  */
+extern int dwarf_lowpc (Dwarf_Die die, Dwarf_Addr *return_lowpc,
+			Dwarf_Error *errdesc);
+
+/* Return high program counter value associated with die.  */
+extern int dwarf_highpc (Dwarf_Die die, Dwarf_Addr *return_lowpc,
+			 Dwarf_Error *errdesc);
+
+/* Return byte size value associated with die.  */
+extern int dwarf_bytesize (Dwarf_Die die, Dwarf_Unsigned *return_size,
+			   Dwarf_Error *errdesc);
+
+/* Return bit size value associated with die.  */
+extern int dwarf_bitsize (Dwarf_Die die, Dwarf_Unsigned *return_size,
+			  Dwarf_Error *errdesc);
+
+/* Return bit offset value associated with die.  */
+extern int dwarf_bitoffset (Dwarf_Die die, Dwarf_Unsigned *return_size,
+			    Dwarf_Error *errdesc);
+
+/* Return source language associated with die.  */
+extern int dwarf_srclang (Dwarf_Die die, Dwarf_Unsigned *return_lang,
+			  Dwarf_Error *errdesc);
+
+/* Return source language associated with die.  */
+extern int dwarf_arrayorder (Dwarf_Die die, Dwarf_Unsigned *return_order,
+			     Dwarf_Error *errdesc);
+
+
+/* Determine whether attribute has given form.  */
+extern int dwarf_hasform (Dwarf_Attribute attr, Dwarf_Half form,
+			  Dwarf_Bool *return_hasform, Dwarf_Error *errdesc);
+
+/* Return form of attribute.  */
+extern int dwarf_whatform (Dwarf_Attribute attr, Dwarf_Half *return_form,
+			   Dwarf_Error *errdesc);
+
+/* Return code of attribute.  */
+extern int dwarf_whatattr (Dwarf_Attribute attr, Dwarf_Half *return_attr,
+			   Dwarf_Error *errdesc);
+
+/*  Return compile-unit relative offset of reference associated with form.  */
+extern int dwarf_formref (Dwarf_Attribute attr, Dwarf_Off *return_offset,
+			  Dwarf_Error *errdesc);
+
+/*  Return .debug_info section global offset of reference associated
+    with form.  */
+extern int dwarf_global_formref (Dwarf_Attribute attr,
+				 Dwarf_Off *return_offset,
+				 Dwarf_Error *errdesc);
+
+/* Return address represented by attribute.  */
+extern int dwarf_formaddr (Dwarf_Attribute attr, Dwarf_Addr *return_addr,
+			   Dwarf_Error *errdesc);
+
+/* Return flag represented by attribute.  */
+extern int dwarf_formflag (Dwarf_Attribute attr, Dwarf_Bool *return_bool,
+			   Dwarf_Error *errdesc);
+
+/* Return unsigned constant represented by attribute.  */
+extern int dwarf_formudata (Dwarf_Attribute attr, Dwarf_Unsigned *return_uval,
+			    Dwarf_Error *errdesc);
+
+/* Return signed constant represented by attribute.  */
+extern int dwarf_formsdata (Dwarf_Attribute attr, Dwarf_Signed *return_uval,
+			    Dwarf_Error *errdesc);
+
+/* Return block of uninterpreted data represented by attribute.  */
+extern int dwarf_formblock (Dwarf_Attribute attr, Dwarf_Block **return_block,
+			    Dwarf_Error *errdesc);
+
+/* Return string represented by attribute.  */
+extern int dwarf_formstring (Dwarf_Attribute attr, char **return_string,
+			     Dwarf_Error *errdesc);
+
+/* Return location expression list.  */
+extern int dwarf_loclist (Dwarf_Attribute attr, Dwarf_Locdesc **llbuf,
+			  Dwarf_Signed *listlen, Dwarf_Error *errdesc);
+
+
+/* Return source lines of compilation unit.  */
+extern int dwarf_srclines (Dwarf_Die die, Dwarf_Line **linebuf,
+			   Dwarf_Signed *linecount, Dwarf_Error *errdesc);
+
+/* Return files used in compilation unit.  */
+extern int dwarf_srcfiles (Dwarf_Die die, char ***srcfiles,
+			   Dwarf_Signed *srcfilecount, Dwarf_Error *errdesc);
+
+/* Determine whether line is the beginning of a statement.  */
+extern int dwarf_linebeginstatement (Dwarf_Line line, Dwarf_Bool *return_bool,
+				     Dwarf_Error *errdesc);
+
+/* Determine whether line is marked as ending a text sequence.  */
+extern int dwarf_lineendsequence (Dwarf_Line line, Dwarf_Bool *return_bool,
+				  Dwarf_Error *errdesc);
+
+/* Return source statement line number.  */
+extern int dwarf_lineno (Dwarf_Line line, Dwarf_Unsigned *return_lineno,
+			 Dwarf_Error *errdesc);
+
+/* Return address associate with line.  */
+extern int dwarf_lineaddr (Dwarf_Line line, Dwarf_Addr *return_lineaddr,
+			   Dwarf_Error *errdesc);
+
+/* Return column at which the statement begins.  */
+extern int dwarf_lineoff (Dwarf_Line line, Dwarf_Signed *return_lineoff,
+			  Dwarf_Error *errdesc);
+
+/* Return source file for line.  */
+extern int dwarf_linesrc (Dwarf_Line line, char **return_linesrc,
+			  Dwarf_Error *errdesc);
+
+/* Determine whether line is marked as beginning a basic block.  */
+extern int dwarf_lineblock (Dwarf_Line line, Dwarf_Bool *return_bool,
+			    Dwarf_Error *errdesc);
+
+/* Determine whether line is marked as ending the prologue.  */
+extern int dwarf_lineprologueend (Dwarf_Line line, Dwarf_Bool *return_bool,
+				  Dwarf_Error *errdesc);
+
+/* Determine whether line is marked as beginning the epilogue.  */
+extern int dwarf_lineepiloguebegin (Dwarf_Line line, Dwarf_Bool *return_bool,
+				    Dwarf_Error *errdesc);
+
+
+/* Return list of global definitions.  */
+extern int dwarf_get_globals (Dwarf_Debug dbg, Dwarf_Global **globals,
+			      Dwarf_Signed *return_count,
+			      Dwarf_Error *errdesc);
+
+/* Return name for global definition.  */
+extern int dwarf_globname (Dwarf_Global global, char **return_name,
+			   Dwarf_Error *errdesc);
+
+/* Return DIE offset for global definition.  */
+extern int dwarf_global_die_offset (Dwarf_Global global,
+				    Dwarf_Off *return_offset,
+				    Dwarf_Error *errdesc);
+
+/* Return offset of header of compile unit containing the global definition. */
+extern int dwarf_global_cu_offset (Dwarf_Global global,
+				   Dwarf_Off *return_offset,
+				   Dwarf_Error *errdesc);
+
+/* Return name, DIE offset, and offset of the compile unit DIE for the
+   global definition.  */
+extern int dwarf_global_name_offsets (Dwarf_Global global, char **return_name,
+				      Dwarf_Off *die_offset,
+				      Dwarf_Off *cu_offset,
+				      Dwarf_Error *errdesc);
+
+
+/* Find start of macro value.  */
+extern char *dwarf_find_macro_value_start (char *macro_string);
+
+
+/* Return string from debug string section.  */
+extern int dwarf_get_str (Dwarf_Debug dbg, Dwarf_Off offset, char **string,
+			  Dwarf_Signed *returned_str_len,
+			  Dwarf_Error *errdesc);
+
+
+/* Return list address ranges.  */
+extern int dwarf_get_aranges (Dwarf_Debug dbg, Dwarf_Arange **aranges,
+			      Dwarf_Signed *return_count,
+			      Dwarf_Error *errdesc);
+
+/* Find matching range for address.  */
+extern int dwarf_get_arange (Dwarf_Arange *aranges,
+			     Dwarf_Unsigned arange_count, Dwarf_Addr address,
+			     Dwarf_Arange *return_arange,
+			     Dwarf_Error *errdesc);
+
+/* Return offset of compile unit DIE containing the range.  */
+extern int dwarf_get_cu_die_offset (Dwarf_Arange arange,
+				    Dwarf_Off *return_offset,
+				    Dwarf_Error *errdesc);
+
+/* Return start, length, and CU DIE offset of range.  */
+extern int dwarf_get_arange_info (Dwarf_Arange arange, Dwarf_Addr *start,
+				  Dwarf_Unsigned *length,
+				  Dwarf_Off *cu_die_offset,
+				  Dwarf_Error *errdesc);
+
+
+/* Frame descriptor handling.  */
+
+/* Get frame descriptions.  GCC version using .eh_frame.  */
+extern int dwarf_get_fde_list_eh (Dwarf_Debug dbg, Dwarf_Cie **cie_data,
+				  Dwarf_Signed *cie_element_count,
+				  Dwarf_Fde **fde_data,
+				  Dwarf_Signed *fde_element_count,
+				  Dwarf_Error *errdesc);
+
+/* Get CIE of FDE.  */
+extern int dwarf_get_cie_of_fde (Dwarf_Fde fde, Dwarf_Cie *return_cie,
+				 Dwarf_Error *errdesc);
+
+/* Get information about the function range.  */
+extern int dwarf_get_fde_range (Dwarf_Fde fde, Dwarf_Addr *low_pc,
+				Dwarf_Unsigned *func_length,
+				Dwarf_Ptr *fde_bytes,
+				Dwarf_Unsigned *fde_byte_length,
+				Dwarf_Off *cie_offset, Dwarf_Signed *cie_index,
+				Dwarf_Off *fde_offset, Dwarf_Error *errdesc);
+
+/* Get information about CIE.  */
+extern int dwarf_get_cie_info (Dwarf_Cie cie, Dwarf_Unsigned *bytes_in_cie,
+			       Dwarf_Small *version, char **augmenter,
+			       Dwarf_Unsigned *code_alignment_factor,
+			       Dwarf_Signed *data_alignment_factor,
+			       Dwarf_Half *return_address_register,
+			       Dwarf_Ptr *initial_instructions,
+			       Dwarf_Unsigned *initial_instructions_length,
+			       Dwarf_Error *errdesc);
+
+/* Get frame construction instructions of FDE.  */
+extern int dwarf_get_fde_instr_bytes (Dwarf_Fde fde, Dwarf_Ptr *outinstrs,
+				      Dwarf_Unsigned *outlen,
+				      Dwarf_Error *errdesc);
+
+/* Get nth frame descriptions.  */
+extern int dwarf_get_fde_n (Dwarf_Fde *fde_data, Dwarf_Unsigned fde_index,
+			    Dwarf_Fde *returned_fde, Dwarf_Error *errdesc);
+
+/* Find FDE for given address.  */
+extern int dwarf_get_fde_at_pc (Dwarf_Fde *fde_data, Dwarf_Addr pc_of_interest,
+				Dwarf_Fde *returned_fde, Dwarf_Addr *lopc,
+				Dwarf_Addr *hipc, Dwarf_Error *errdesc);
+
+
+/* Return location list entry.  */
+extern int dwarf_get_loclist_entry (Dwarf_Debug dbg, Dwarf_Unsigned offset,
+				    Dwarf_Addr *hipc_offset,
+				    Dwarf_Addr *lopc_offset, Dwarf_Ptr *data,
+				    Dwarf_Unsigned *entry_len,
+				    Dwarf_Unsigned *next_entry,
+				    Dwarf_Error *errdesc);
+
+
+/* Get abbreviation record.  */
+extern int dwarf_get_abbrev (Dwarf_Debug dbg,
+			     Dwarf_Unsigned offset,
+			     Dwarf_Abbrev *returned_abbrev,
+			     Dwarf_Unsigned *length,
+			     Dwarf_Unsigned *attr_count, Dwarf_Error *errdesc);
+
+/* Get tag of abbreviation record.  */
+extern int dwarf_get_abbrev_tag (Dwarf_Abbrev abbrev, Dwarf_Half *return_tag,
+				 Dwarf_Error *errdesc);
+
+/* Get code of abbreviation record.  */
+extern int dwarf_get_abbrev_code (Dwarf_Abbrev abbrev,
+				  Dwarf_Unsigned *return_code,
+				  Dwarf_Error *errdesc);
+
+/* Get children flag of abbreviation record.  */
+extern int dwarf_get_abbrev_children_flag (Dwarf_Abbrev abbrev,
+					   Dwarf_Signed *return_flag,
+					   Dwarf_Error *errdesc);
+
+/* Get attribute from abbreviation record.  */
+extern int dwarf_get_abbrev_entry (Dwarf_Abbrev abbrev, Dwarf_Signed idx,
+				   Dwarf_Half *attr_num, Dwarf_Signed *form,
+				   Dwarf_Off *offset, Dwarf_Error *errdesc);
+
+
+/* Memory handling.  */
+
+/* Values for ALLOC_TYPE parameter of 'dwarf_dealloc'.  */
+enum
+  {
+    DW_DLA_NONE = 0,
+    DW_DLA_STRING,		/* char* */
+    DW_DLA_LOC,			/* Dwarf_Loc */
+    DW_DLA_LOCDESC,		/* Dwarf_Locdesc */
+    DW_DLA_ELLIST,		/* Dwarf_Ellist */
+    DW_DLA_BOUNDS,		/* Dwarf_Bounds */
+    DW_DLA_BLOCK,		/* Dwarf_Block */
+    DW_DLA_DEBUG,		/* Dwarf_Debug */
+    DW_DLA_DIE,			/* Dwarf_Die */
+    DW_DLA_LINE,		/* Dwarf_Line */
+    DW_DLA_ATTR,		/* Dwarf_Attribute */
+    DW_DLA_TYPE,		/* Dwarf_Type */
+    DW_DLA_SUBSCR,		/* Dwarf_Subscr */
+    DW_DLA_GLOBAL,		/* Dwarf_Global */
+    DW_DLA_ERROR,		/* Dwarf_Error */
+    DW_DLA_LIST,		/* a list */
+    DW_DLA_LINEBUF,		/* Dwarf_Line* */
+    DW_DLA_ARANGE,		/* Dwarf_Arange */
+    DW_DLA_ABBREV,		/* Dwarf_Abbrev */
+    DW_DLA_FRAME_OP,		/* Dwarf_Frame_Op */
+    DW_DLA_CIE,			/* Dwarf_Cie */
+    DW_DLA_FDE,			/* Dwarf_Fde */
+    DW_DLA_LOC_BLOCK,		/* Dwarf_Loc Block */
+    DW_DLA_FRAME_BLOCK,		/* Dwarf_Frame Block */
+    DW_DLA_FUNC,		/* Dwarf_Func */
+    DW_DLA_TYPENAME,		/* Dwarf_Type */
+    DW_DLA_VAR,			/* Dwarf_Var */
+    DW_DLA_WEAK,		/* Dwarf_Weak */
+    DW_DLA_ADDR,		/* Dwarf_Addr sized entries */
+  };
+
+/* Deallocate memory.  */
+extern void dwarf_dealloc (Dwarf_Debug dbg, Dwarf_Ptr space,
+			   Dwarf_Unsigned alloc_type);
+
+
+/* Determine size of address of the binary.  */
+extern int dwarf_get_address_size (Dwarf_Debug dbg, Dwarf_Half *addr_size,
+				   Dwarf_Error *errdesc);
+
+
+/* Return error number.  */
+extern Dwarf_Unsigned dwarf_errno (Dwarf_Error errdesc);
+
+/* Return string corresponding to error.  */
+extern const char *dwarf_errmsg (Dwarf_Error errdesc);
+
+
+/* Set new error handler.  */
+extern Dwarf_Handler dwarf_seterrhand (Dwarf_Debug dbg, Dwarf_Handler errhand);
+
+/* Set new error handler argument.  */
+extern Dwarf_Ptr dwarf_seterrarg (Dwarf_Debug dbg, Dwarf_Ptr errarg);
+
+#endif	/* libdwarf.h */
diff --git a/libdwarf/libdwarf.map b/libdwarf/libdwarf.map
new file mode 100644
index 0000000..ec0e805
--- /dev/null
+++ b/libdwarf/libdwarf.map
@@ -0,0 +1,81 @@
+ELFUTILS_1.0 {
+  global:
+    dwarf_arrayorder;
+    dwarf_attr;
+    dwarf_attrlist;
+    dwarf_bitoffset;
+    dwarf_bitsize;
+    dwarf_bytesize;
+    dwarf_child;
+    dwarf_dealloc;
+    dwarf_die_CU_offset;
+    dwarf_diename;
+    dwarf_dieoffset;
+    dwarf_elf_init;
+    dwarf_errmsg;
+    dwarf_errno;
+    dwarf_find_macro_value_start;
+    dwarf_finish;
+    dwarf_formaddr;
+    dwarf_formblock;
+    dwarf_formflag;
+    dwarf_formref;
+    dwarf_formsdata;
+    dwarf_formstring;
+    dwarf_formudata;
+    dwarf_get_abbrev;
+    dwarf_get_abbrev_children_flag;
+    dwarf_get_abbrev_code;
+    dwarf_get_abbrev_entry;
+    dwarf_get_abbrev_tag;
+    dwarf_get_address_size;
+    dwarf_get_arange;
+    dwarf_get_arange_info;
+    dwarf_get_aranges;
+    dwarf_get_cie_info;
+    dwarf_get_cie_of_fde;
+    dwarf_get_cu_die_offset;
+    dwarf_get_elf_init;
+    dwarf_get_fde_at_pc;
+    dwarf_get_fde_instr_bytes;
+    dwarf_get_fde_list_eh;
+    dwarf_get_fde_n;
+    dwarf_get_fde_range;
+    dwarf_get_globals;
+    dwarf_get_loclist_entry;
+    dwarf_get_str;
+    dwarf_global_cu_offset;
+    dwarf_global_die_offset;
+    dwarf_global_formref;
+    dwarf_global_name_offsets;
+    dwarf_globname;
+    dwarf_hasattr;
+    dwarf_hasform;
+    dwarf_highpc;
+    dwarf_init;
+    dwarf_lineaddr;
+    dwarf_linebeginstatement;
+    dwarf_lineblock;
+    dwarf_lineendsequence;
+    dwarf_lineepiloguebegin;
+    dwarf_lineno;
+    dwarf_lineoff;
+    dwarf_lineprologueend;
+    dwarf_linesrc;
+    dwarf_loclist;
+    dwarf_lowpc;
+    dwarf_next_cu_header;
+    dwarf_offdie;
+    dwarf_seterrarg;
+    dwarf_seterrhand;
+    dwarf_siblingof;
+    dwarf_srcfiles;
+    dwarf_srclang;
+    dwarf_srclines;
+    dwarf_tag;
+    dwarf_whatattr;
+    dwarf_whatform;
+
+  local:
+    *;
+};
diff --git a/libdwarf/libdwarfP.h b/libdwarf/libdwarfP.h
new file mode 100644
index 0000000..c6162ee
--- /dev/null
+++ b/libdwarf/libdwarfP.h
@@ -0,0 +1,319 @@
+/* Internal definitions for libdwarf.
+   Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifndef _LIBDWARFP_H
+#define _LIBDWARFP_H 1
+
+#include <libdwarf.h>
+#include <libintl.h>
+#include <limits.h>
+
+#include <dwarf_abbrev_hash.h>
+
+
+/* Version of the DWARF specification we support.  */
+#define DWARF_VERSION 2
+
+/* Version of the CIE format.  */
+#define CIE_VERSION 1
+
+/* Some additional basic types.  */
+typedef unsigned int Dwarf_Word;
+
+
+/* Valid indeces for the section data.  */
+enum
+  {
+    IDX_debug_info = 0,
+    IDX_debug_abbrev,
+    IDX_debug_aranges,
+    IDX_debug_line,
+    IDX_debug_frame,
+    IDX_eh_frame,
+    IDX_debug_loc,
+    IDX_debug_pubnames,
+    IDX_debug_str,
+    IDX_debug_funcnames,
+    IDX_debug_typenames,
+    IDX_debug_varnames,
+    IDX_debug_weaknames,
+    IDX_debug_macinfo,
+    IDX_last
+  };
+
+
+/* This is the structure representing the debugging state.  */
+struct Dwarf_Debug_s
+  {
+#ifdef DWARF_DEBUG
+    int memtag;
+#endif
+
+    Dwarf_Handler dbg_errhand;
+    Dwarf_Ptr dbg_errarg;
+
+    Elf *elf;
+    int other_byte_order;
+
+    Dwarf_Unsigned access;
+
+    /* The section data.  */
+    struct
+    {
+      Dwarf_Small *addr;
+      Dwarf_Unsigned size;
+    } sections[IDX_last];
+
+    /* Compilation unit handling.  To enable efficient searching we
+       keep track of the unit we already found.  */
+    struct Dwarf_CU_Info_s
+    {
+      /* This is the information the 'dwarf_next_cu_header' function
+	 is supposed to return.  */
+      Dwarf_Unsigned header_length;
+      Dwarf_Unsigned length;
+      Dwarf_Unsigned abbrev_offset;
+      Dwarf_Half version_stamp;
+      Dwarf_Half address_size;
+
+      Dwarf_Unsigned offset;		/* In .debug_info section.  */
+
+      /* Used to distinguish between 32-bit and 64-bit DWARF.  */
+      Dwarf_Half offset_size;
+
+      /* Hash table for the abbreviations.  */
+      Dwarf_Abbrev_Hash abbrev_hash;
+      Dwarf_Unsigned last_abbrev_offset;
+
+      Dwarf_Debug dbg;
+
+      struct Dwarf_CU_Info_s *next;
+    } *cu_list;
+    struct Dwarf_CU_Info_s *cu_list_current;
+    struct Dwarf_CU_Info_s *cu_list_tail;
+
+    Dwarf_Unsigned cie_cnt;
+    Dwarf_Unsigned fde_cnt;
+  };
+typedef struct Dwarf_CU_Info_s *Dwarf_CU_Info;
+
+
+/* Memory access macros.  We have to define it here since code in the
+   header needs to know the structure of Dwarf_Debug.  */
+#include "memory-access.h"
+
+
+/* DWARF die representation.  */
+struct Dwarf_Die_s
+  {
+#ifdef DWARF_DEBUG
+    int memtag;
+#endif
+
+    Dwarf_Small *addr;
+    Dwarf_Abbrev abbrev;
+    Dwarf_CU_Info cu;
+  };
+
+
+/* Abbreviation list.  */
+struct Dwarf_Abbrev_s
+  {
+    Dwarf_Unsigned code;	/* The code.  */
+    Dwarf_Half tag;		/* The tag.  */
+    Dwarf_Small *attrp;		/* Pointer to beginning of attributes.  */
+    Dwarf_Unsigned attrcnt;	/* Number of attributes.  */
+    int has_children;		/* Nonzero of abbreviation has children.  */
+    Dwarf_Unsigned offset;	/* Offset in the .debug_abbrev section.  */
+  };
+
+
+/* Attribute list.  */
+struct Dwarf_Attribute_s
+  {
+    Dwarf_Half code;		/* DWARF attribute code.  */
+    Dwarf_Half form;		/* DWARF form.  */
+    Dwarf_Small *valp;
+    Dwarf_CU_Info cu;
+  };
+
+
+/* Structure for error values.  */
+struct Dwarf_Error_s
+  {
+    unsigned int de_error;
+  };
+
+
+/* Files in line information records.  */
+typedef struct Dwarf_File_s
+  {
+    Dwarf_Debug dbg;
+    unsigned int nfiles;
+    struct Dwarf_Fileinfo_s
+    {
+      char *name;
+      Dwarf_Unsigned mtime;
+      Dwarf_Unsigned length;
+    } info[0];
+  } *Dwarf_File;
+typedef struct Dwarf_Fileinfo_s Dwarf_Fileinfo;
+
+
+/* Representation of a row in the line table.  */
+struct Dwarf_Line_s
+  {
+    Dwarf_Addr addr;
+    unsigned int file;
+    int line;
+    unsigned short int column;
+    unsigned int is_stmt:1;
+    unsigned int basic_block:1;
+    unsigned int end_sequence:1;
+    unsigned int prologue_end:1;
+    unsigned int epilogue_begin:1;
+
+    Dwarf_File files;
+  };
+
+
+/* Additional, shared information required for Dwarf_Global handling.  */
+typedef struct Dwarf_Global_Info_s
+  {
+    Dwarf_Debug dbg;
+    Dwarf_Unsigned offset;
+  } *Dwarf_Global_Info;
+
+/* Representation of a global name entry.  */
+struct Dwarf_Global_s
+  {
+    Dwarf_Unsigned offset;
+    char *name;
+    Dwarf_Global_Info info;
+  };
+
+
+/* Additional, shared information required for Dwarf_Arange handling.  */
+typedef struct Dwarf_Arange_Info_s
+  {
+    Dwarf_Debug dbg;
+    Dwarf_Unsigned offset;
+  } *Dwarf_Arange_Info;
+
+/* Representation of an address range entry.  */
+struct Dwarf_Arange_s
+  {
+    Dwarf_Addr address;
+    Dwarf_Unsigned length;
+    Dwarf_Arange_Info info;
+  };
+
+
+/* Representation of a common information entry.  */
+struct Dwarf_Cie_s
+  {
+    Dwarf_Debug dbg;
+    Dwarf_Unsigned length;
+    char *augmentation;
+    Dwarf_Unsigned code_alignment_factor;
+    Dwarf_Signed data_alignment_factor;
+    Dwarf_Small *initial_instructions;
+    Dwarf_Unsigned initial_instructions_length;
+    Dwarf_Small return_address_register;
+    Dwarf_Unsigned offset;
+    Dwarf_Signed index;
+  };
+
+
+/* Representation of a frame descriptor entry.  */
+struct Dwarf_Fde_s
+  {
+    Dwarf_Cie cie;
+    Dwarf_Addr initial_location;
+    Dwarf_Unsigned address_range;
+    Dwarf_Small *instructions;
+    Dwarf_Unsigned instructions_length;
+    Dwarf_Unsigned offset;
+    Dwarf_Small *fde_bytes;
+    Dwarf_Unsigned fde_byte_length;
+  };
+
+
+/* Internal error values.  */
+enum
+  {
+    DW_E_NOERROR = 0,
+    DW_E_INVALID_ACCESS,
+    DW_E_NO_REGFILE,
+    DW_E_IO_ERROR,
+    DW_E_NOMEM,
+    DW_E_NOELF,
+    DW_E_GETEHDR_ERROR,
+    DW_E_INVALID_ELF,
+    DW_E_INVALID_DWARF,
+    DW_E_NO_DWARF,
+    DW_E_NO_CU,
+    DW_E_1ST_NO_CU,
+    DW_E_INVALID_OFFSET,
+    DW_E_INVALID_REFERENCE,
+    DW_E_NO_REFERENCE,
+    DW_E_NO_ADDR,
+    DW_E_NO_FLAG,
+    DW_E_NO_CONSTANT,
+    DW_E_NO_BLOCK,
+    DW_E_NO_STRING,
+    DW_E_WRONG_ATTR,
+    DW_E_NO_DATA,
+    DW_E_NO_DEBUG_LINE,
+    DW_E_VERSION_ERROR,
+    DW_E_INVALID_DIR_IDX,
+    DW_E_INVALID_ADDR,
+    DW_E_NO_ABBR,
+  };
+
+
+/* Handle error according to user's wishes.  */
+extern void __libdwarf_error (Dwarf_Debug dbg, Dwarf_Error *err, int errval)
+     internal_function;
+
+
+/* Find CU at given offset.  */
+extern int __libdwarf_get_cu_at_offset (Dwarf_Debug dbg, Dwarf_Unsigned offset,
+					Dwarf_CU_Info *result_cu,
+					Dwarf_Error *err) internal_function;
+
+/* Find abbreviation.  */
+extern Dwarf_Abbrev __libdwarf_get_abbrev (Dwarf_Debug dbg,
+					   Dwarf_CU_Info cu,
+					   Dwarf_Word code,
+					   Dwarf_Error *err)
+     internal_function;
+
+/* Get constant type attribute value.  */
+extern int __libdwarf_getconstant (Dwarf_Die die, Dwarf_Half name,
+				   Dwarf_Unsigned *return_size,
+				   Dwarf_Error *err) internal_function;
+
+/* Determine length of form parameters.  */
+extern int __libdwarf_form_val_len (Dwarf_Debug dbg, Dwarf_CU_Info cu,
+				    Dwarf_Word form, Dwarf_Small *valp,
+				    size_t *len, Dwarf_Error *err)
+     internal_function;
+
+
+/* gettext helper macros.  */
+#define _(Str) dgettext ("libdwarf", Str)
+#define N_(Str) Str
+
+#endif	/* libdwarfP.h */
diff --git a/libdwarf/memory-access.h b/libdwarf/memory-access.h
new file mode 100644
index 0000000..dcd52b5
--- /dev/null
+++ b/libdwarf/memory-access.h
@@ -0,0 +1,207 @@
+/* Unaligned memory access functionality.
+   Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
+
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
+
+#ifndef _MEMORY_ACCESS_H
+#define _MEMORY_ACCESS_H 1
+
+#include <byteswap.h>
+#include <stdint.h>
+
+
+/* Number decoding macros.  See 7.6 Variable Length Data.  */
+#define get_uleb128(var, addr) \
+  do {									      \
+    Dwarf_Small __b = *addr++;						      \
+    var = __b & 0x7f;							      \
+    if (__b & 0x80)							      \
+      {									      \
+	__b = *addr++;							      \
+	var |= (__b & 0x7f) << 7;					      \
+	if (__b & 0x80)							      \
+	  {								      \
+	    __b = *addr++;						      \
+	    var |= (__b & 0x7f) << 14;					      \
+	    if (__b & 0x80)						      \
+	      {								      \
+		__b = *addr++;						      \
+		var |= (__b & 0x7f) << 21;				      \
+		if (__b & 0x80)						      \
+		  /* Other implementation set VALUE to UINT_MAX in this	      \
+		     case.  So we better do this as well.  */		      \
+		  var = UINT_MAX;					      \
+	      }								      \
+	  }								      \
+      }									      \
+  } while (0)
+
+/* The signed case is a big more complicated.  */
+#define get_sleb128(var, addr) \
+  do {									      \
+    Dwarf_Small __b = *addr++;						      \
+    int32_t __res = __b & 0x7f;						      \
+    if ((__b & 0x80) == 0)						      \
+      {									      \
+	if (__b & 0x40)							      \
+	  __res |= 0xffffff80;						      \
+      }									      \
+    else								      \
+      {									      \
+	__b = *addr++;							      \
+	__res |= (__b & 0x7f) << 7;					      \
+	if ((__b & 0x80) == 0)						      \
+	  {								      \
+	    if (__b & 0x40)						      \
+	      __res |= 0xffffc000;					      \
+	  }								      \
+	else								      \
+	  {								      \
+	    __b = *addr++;						      \
+	    __res |= (__b & 0x7f) << 14;				      \
+	    if ((__b & 0x80) == 0)					      \
+	      {								      \
+		if (__b & 0x40)						      \
+		  __res |= 0xffe00000;					      \
+	      }								      \
+	    else							      \
+	      {								      \
+		__b = *addr++;						      \
+		__res |= (__b & 0x7f) << 21;				      \
+		if ((__b & 0x80) == 0)					      \
+		  {							      \
+		    if (__b & 0x40)					      \
+		      __res |= 0xf0000000;				      \
+		  }							      \
+		else							      \
+		  /* Other implementation set VALUE to INT_MAX in this	      \
+		     case.  So we better do this as well.  */		      \
+		  __res = INT_MAX;					      \
+	      }								      \
+	  }								      \
+      }									      \
+    var = __res;							      \
+  } while (0)
+
+
+/* We use simple memory access functions in case the hardware allows it.
+   The caller has to make sure we don't have alias problems.  */
+#if ALLOW_UNALIGNED
+
+# define read_2ubyte_unaligned(Dbg, Addr) \
+  ((Dbg)->other_byte_order						      \
+   ? bswap_16 (*((uint16_t *) (Addr)))					      \
+   : *((uint16_t *) (Addr)))
+# define read_2sbyte_unaligned(Dbg, Addr) \
+  ((Dbg)->other_byte_order						      \
+   ? (int16_t) bswap_16 (*((int16_t *) (Addr)))				      \
+   : *((int16_t *) (Addr)))
+
+# define read_4ubyte_unaligned_noncvt(Addr) \
+   *((uint32_t *) (Addr))
+# define read_4ubyte_unaligned(Dbg, Addr) \
+  ((Dbg)->other_byte_order						      \
+   ? bswap_32 (*((uint32_t *) (Addr)))					      \
+   : *((uint32_t *) (Addr)))
+# define read_4sbyte_unaligned(Dbg, Addr) \
+  ((Dbg)->other_byte_order						      \
+   ? (int32_t) bswap_32 (*((int32_t *) (Addr)))				      \
+   : *((int32_t *) (Addr)))
+
+# define read_8ubyte_unaligned(Dbg, Addr) \
+  ((Dbg)->other_byte_order						      \
+   ? bswap_64 (*((uint64_t *) (Addr)))					      \
+   : *((uint64_t *) (Addr)))
+# define read_8sbyte_unaligned(Dbg, Addr) \
+  ((Dbg)->other_byte_order						      \
+   ? (int64_t) bswap_64 (*((int64_t *) (Addr)))				      \
+   : *((int64_t *) (Addr)))
+
+#else
+
+# if __GNUC__
+
+union unaligned
+  {
+    void *p;
+    uint16_t u2;
+    uint32_t u4;
+    uint64_t u8;
+    int16_t s2;
+    int32_t s4;
+    int64_t s8;
+  } __attribute__ ((packed));
+
+static inline uint16_t
+read_2ubyte_unaligned (Dwarf_Debug dbg, void *p)
+{
+  union unaligned *up = p;
+  if (dbg->other_byte_order)
+    return bswap_16 (up->u2);
+  return up->u2;
+}
+static inline int16_t
+read_2sbyte_unaligned (Dwarf_Debug dbg, void *p)
+{
+  union unaligned *up = p;
+  if (dbg->other_byte_order)
+    return (int16_t) bswap_16 (up->u2);
+  return up->s2;
+}
+
+static inline uint32_t
+read_4ubyte_unaligned_noncvt (void *p)
+{
+  union unaligned *up = p;
+  return up->u4;
+}
+static inline uint32_t
+read_4ubyte_unaligned (Dwarf_Debug dbg, void *p)
+{
+  union unaligned *up = p;
+  if (dbg->other_byte_order)
+    return bswap_32 (up->u4);
+  return up->u4;
+}
+static inline int32_t
+read_4sbyte_unaligned (Dwarf_Debug dbg, void *p)
+{
+  union unaligned *up = p;
+  if (dbg->other_byte_order)
+    return (int32_t) bswap_32 (up->u4);
+  return up->s4;
+}
+
+static inline uint64_t
+read_8ubyte_unaligned (Dwarf_Debug dbg, void *p)
+{
+  union unaligned *up = p;
+  if (dbg->other_byte_order)
+    return bswap_64 (up->u8);
+  return up->u8;
+}
+static inline int64_t
+read_8sbyte_unaligned (Dwarf_Debug dbg, void *p)
+{
+  union unaligned *up = p;
+  if (dbg->other_byte_order)
+    return (int64_t) bswap_64 (up->u8);
+  return up->s8;
+}
+
+# else
+#  error "TODO"
+# endif
+
+#endif
+
+#endif	/* memory-access.h */