diff options
Diffstat (limited to 'libdwarf')
90 files changed, 8786 insertions, 0 deletions
diff --git a/libdwarf/.cvsignore b/libdwarf/.cvsignore new file mode 100644 index 00000000..70845e08 --- /dev/null +++ b/libdwarf/.cvsignore @@ -0,0 +1 @@ +Makefile.in diff --git a/libdwarf/AVAILABLE b/libdwarf/AVAILABLE new file mode 100644 index 00000000..642dd27e --- /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 00000000..c46ffcb6 --- /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 00000000..8af7a674 --- /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 00000000..81bdcc45 --- /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 00000000..a1964498 --- /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 00000000..45c23462 --- /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 00000000..88f30800 --- /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 00000000..f1b20f4d --- /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 00000000..bef5a112 --- /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 00000000..bfc91654 --- /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 00000000..007975c7 --- /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 00000000..68d728ad --- /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 00000000..ee9c8336 --- /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 00000000..365303bd --- /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 00000000..2d80fd5a --- /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 00000000..2dfcd57a --- /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 00000000..2886f9f8 --- /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 00000000..d69d7474 --- /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 00000000..1d19f416 --- /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 00000000..4d659e09 --- /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 00000000..16c0c45a --- /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 00000000..fdaaf72a --- /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 00000000..f689e79c --- /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 00000000..9adf3ede --- /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 00000000..148508fe --- /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 00000000..44606edd --- /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 00000000..32a98fd8 --- /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 00000000..4ae353a8 --- /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 00000000..8024e763 --- /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 00000000..205a9466 --- /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 00000000..35e133cb --- /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 00000000..0295f9bd --- /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 00000000..079c85a8 --- /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 00000000..08ecb43b --- /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 00000000..4deccd0d --- /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 00000000..b3f9fd1c --- /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 00000000..fe5234c9 --- /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 00000000..02df19d2 --- /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 00000000..4d37e087 --- /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 00000000..b8cabb03 --- /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 00000000..029d9c93 --- /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 00000000..49718e9e --- /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 00000000..a358d5cf --- /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 00000000..9313e95a --- /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 00000000..fee2efdb --- /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 00000000..74a5388e --- /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 00000000..bcda71b0 --- /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 00000000..5531deaf --- /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 00000000..f7049145 --- /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 00000000..01b48ae7 --- /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 00000000..f6510c77 --- /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 00000000..3f289c3d --- /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 00000000..2220fc34 --- /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 00000000..39727f8a --- /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 00000000..b5a30f42 --- /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 00000000..654340fc --- /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 00000000..16ea7b7a --- /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 00000000..a9b149c0 --- /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 00000000..1c565290 --- /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 00000000..337a3e10 --- /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 00000000..cfb6cf99 --- /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 00000000..5e56376d --- /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 00000000..bbb86602 --- /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 00000000..4bf49435 --- /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 00000000..d04c6ec9 --- /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 00000000..f15e54b9 --- /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 00000000..93cbf8ec --- /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 00000000..33df13f1 --- /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 00000000..83f911d5 --- /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 00000000..82f4bbcc --- /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 00000000..f202f73d --- /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 00000000..5c990009 --- /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 00000000..22a3944f --- /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 00000000..c21edc92 --- /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 00000000..54bb39e3 --- /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 00000000..2e94d2ea --- /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 00000000..8b52d24a --- /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 00000000..199a2504 --- /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 00000000..04a3ab6d --- /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 00000000..1090d837 --- /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 00000000..45140633 --- /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 00000000..796b7900 --- /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 00000000..3c4d36ec --- /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 00000000..9887f2e1 --- /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 00000000..5cb67b3d --- /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 00000000..37c958ca --- /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 00000000..ec0e805e --- /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 00000000..c6162eee --- /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 00000000..dcd52b5b --- /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 */ |