diff options
Diffstat (limited to 'src/libdw')
122 files changed, 20096 insertions, 0 deletions
diff --git a/src/libdw/Android.mk b/src/libdw/Android.mk new file mode 100755 index 00000000..5579b244 --- /dev/null +++ b/src/libdw/Android.mk @@ -0,0 +1,184 @@ +# Copyright (C) 2013 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH := $(call my-dir) + +LIBDW_SRC_FILES := \ + cfi.c \ + cie.c \ + dwarf_abbrevhaschildren.c \ + dwarf_abbrev_hash.c \ + dwarf_addrdie.c \ + dwarf_arrayorder.c \ + dwarf_attr.c \ + dwarf_attr_integrate.c \ + dwarf_begin.c \ + dwarf_begin_elf.c \ + dwarf_bitoffset.c \ + dwarf_bitsize.c \ + dwarf_bytesize.c \ + dwarf_cfi_addrframe.c \ + dwarf_child.c \ + dwarf_cuoffset.c \ + dwarf_decl_column.c \ + dwarf_decl_file.c \ + dwarf_decl_line.c \ + dwarf_diecu.c \ + dwarf_diename.c \ + dwarf_dieoffset.c \ + dwarf_end.c \ + dwarf_entry_breakpoints.c \ + dwarf_entrypc.c \ + dwarf_error.c \ + dwarf_filesrc.c \ + dwarf_formaddr.c \ + dwarf_formblock.c \ + dwarf_formflag.c \ + dwarf_formref.c \ + dwarf_formref_die.c \ + dwarf_formsdata.c \ + dwarf_formstring.c \ + dwarf_formudata.c \ + dwarf_frame_cfa.c \ + dwarf_func_inline.c \ + dwarf_getabbrevattr.c \ + dwarf_getabbrev.c \ + dwarf_getabbrevcode.c \ + dwarf_getabbrevtag.c \ + dwarf_getarange_addr.c \ + dwarf_getarangeinfo.c \ + dwarf_getaranges.c \ + dwarf_getattrcnt.c \ + dwarf_getattrs.c \ + dwarf_getcfi.c \ + dwarf_getcfi_elf.c \ + dwarf_getelf.c \ + dwarf_getfuncs.c \ + dwarf_getlocation.c \ + dwarf_getmacros.c \ + dwarf_getpubnames.c \ + dwarf_getscopes.c \ + dwarf_getscopes_die.c \ + dwarf_getscopevar.c \ + dwarf_getsrc_die.c \ + dwarf_getsrcdirs.c \ + dwarf_getsrc_file.c \ + dwarf_getsrcfiles.c \ + dwarf_getsrclines.c \ + dwarf_getstring.c \ + dwarf_hasattr.c \ + dwarf_hasattr_integrate.c \ + dwarf_haschildren.c \ + dwarf_hasform.c \ + dwarf_haspc.c \ + dwarf_highpc.c \ + dwarf_lineaddr.c \ + dwarf_linebeginstatement.c \ + dwarf_lineblock.c \ + dwarf_linecol.c \ + dwarf_lineendsequence.c \ + dwarf_lineepiloguebegin.c \ + dwarf_lineno.c \ + dwarf_lineprologueend.c \ + dwarf_linesrc.c \ + dwarf_lowpc.c \ + dwarf_macro_opcode.c \ + dwarf_macro_param1.c \ + dwarf_macro_param2.c \ + dwarf_next_cfi.c \ + dwarf_nextcu.c \ + dwarf_offabbrev.c \ + dwarf_offdie.c \ + dwarf_onearange.c \ + dwarf_onesrcline.c \ + dwarf_ranges.c \ + dwarf_siblingof.c \ + dwarf_sig8_hash.c \ + dwarf_srclang.c \ + dwarf_tag.c \ + dwarf_whatattr.c \ + dwarf_whatform.c \ + fde.c \ + frame-cache.c \ + libdw_alloc.c \ + libdw_findcu.c \ + libdw_form.c \ + libdw_visit_scopes.c \ + memory-access.c + +ifeq ($(HOST_OS),linux) + +# +# host libdw +# + +include $(CLEAR_VARS) + +# Clang has no nested functions. +LOCAL_CLANG := false + +LOCAL_SRC_FILES := $(LIBDW_SRC_FILES) + +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/.. \ + $(LOCAL_PATH)/../lib \ + $(LOCAL_PATH)/../libdw \ + $(LOCAL_PATH)/../libelf + +LOCAL_CFLAGS += -DHAVE_CONFIG_H -std=gnu99 -D_GNU_SOURCE -DIS_LIBDW + +# to suppress the "pointer of type ‘void *’ used in arithmetic" warning +LOCAL_CFLAGS += -Wno-pointer-arith + +LOCAL_MODULE:= libdw + +LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH) + +include $(BUILD_HOST_STATIC_LIBRARY) + +endif # linux + +# +# target libdw +# + +include $(CLEAR_VARS) + +# Clang has no nested functions. +LOCAL_CLANG := false + +LOCAL_SRC_FILES := $(LIBDW_SRC_FILES) + +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/.. \ + $(LOCAL_PATH)/../lib \ + $(LOCAL_PATH)/../libdw \ + $(LOCAL_PATH)/../libelf + +LOCAL_C_INCLUDES += $(LOCAL_PATH)/../bionic-fixup + +LOCAL_CFLAGS += -include $(LOCAL_PATH)/../bionic-fixup/AndroidFixup.h + +LOCAL_CFLAGS += -DHAVE_CONFIG_H -std=gnu99 -DIS_LIBDW -Werror + +# to suppress the "pointer of type ‘void *’ used in arithmetic" warning +LOCAL_CFLAGS += -Wno-pointer-arith + +LOCAL_MODULE_TAGS := eng + +LOCAL_MODULE:= libdw + +LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH) + +include $(BUILD_STATIC_LIBRARY) diff --git a/src/libdw/ChangeLog b/src/libdw/ChangeLog new file mode 100644 index 00000000..98b67f4a --- /dev/null +++ b/src/libdw/ChangeLog @@ -0,0 +1,1601 @@ +2012-01-31 Mark Wielaard <mjw@redhat.com> + + * dwarf_formudata.c (dwarf_formudata): Handle DW_FORM_sec_offset. + +2011-11-31 Mark Wielaard <mjw@redhat.com> + + * Makefile.am (known-dwarf.h): Run gawk on config/known-dwarf.awk. + +2011-07-14 Mark Wielaard <mjw@redhat.com> + + * libdw.h (dwarf_offdie): Fix documentation to mention .debug_info. + +2011-05-16 Jakub Jelinek <jakub@redhat.com> + + * dwarf.h (DW_OP_GNU_const_type, DW_OP_GNU_regval_type, + DW_OP_GNU_deref_type, DW_OP_GNU_convert, DW_OP_GNU_reinterpret): + New. + +2011-04-26 Mark Wielaard <mjw@redhat.com> + + * dwarf_child (dwarf_child): Sanity check end of section against + cu_data () of die->cu. + +2011-03-22 Mark Wielaard <mjw@redhat.com> + + * dwarf.h: Add DW_TAG_GNU_call_site, + DW_TAG_GNU_call_site_parameter, + DW_AT_GNU_call_site_value, + DW_AT_GNU_call_site_data_value, + DW_AT_GNU_call_site_target, + DW_AT_GNU_call_site_target_clobbered, + DW_AT_GNU_tail_call, + DW_AT_GNU_all_tail_call_sites, + DW_AT_GNU_all_call_sites, + DW_AT_GNU_all_source_call_sites, + and DW_OP_GNU_entry_value. + +2011-03-10 Petr Machata <pmachata@redhat.com> + + * libdw/dwarf_tag.c (__libdw_findabbrev): Reject requests for + abbreviation with code 0. + +2011-03-09 Petr Machata <pmachata@redhat.com> + + * libdw/dwarf_child.c (dwarf_child): Check for section overrun. + +2011-02-23 Roland McGrath <roland@redhat.com> + + * libdwP.h (struct Dwarf) [USE_ZLIB]: New member sectiondata_gzip_mask. + Declare __libdw_free_zdata. + * dwarf_end.c [USE_ZLIB] (__libdw_free_zdata): New function. + (dwarf_end): Call it. + + * dwarf_begin_elf.c (valid_p): Likewise. + (check_section, scngrp_read): Likewise. + (check_section) [USE_ZLIB]: Grok .z* flavors of sections. + +2010-10-13 Roland McGrath <roland@redhat.com> + + * dwarf.h: Add DW_LANG_Go. + +2010-10-05 Roland McGrath <roland@redhat.com> + + * dwarf_getaranges.c: Use malloc rather than alloca, + since the total number of elements can be quite huge. + +2010-07-26 Roland McGrath <roland@redhat.com> + + * dwarf_getlocation_implicit_pointer.c: New file. + * Makefile.am (libdw_a_SOURCES): Add it. + * libdw.map (ELFUTILS_0.149): New set. + Add dwarf_getlocation_implicit_pointer. + * libdw.h: Declare it. + + * dwarf_offdie.c (do_offdie): Renamed to __libdw_offdie, made global. + (dwarf_offdie, dwarf_offdie_types): Update callers. + * libdwP.h: Declare it. + + * dwarf.h: Add DW_OP_GNU_implicit_pointer. + * dwarf_getlocation.c (__libdw_intern_expression): Handle it. + +2010-08-24 Roland McGrath <roland@redhat.com> + + * libdw.map (ELFUTILS_0.149): New set. Add dwfl_dwarf_line. + +2010-07-27 Roland McGrath <roland@redhat.com> + + * dwarf_formref_die.c: Fix sig8 hash insertion. + +2010-06-23 Roland McGrath <roland@redhat.com> + + * cfi.c (dwarf_cfi_validate_fde): Function removed. + * libdw.h: Remove it. + * libdw.map: Likewise. + +2010-06-22 Roland McGrath <roland@redhat.com> + + * dwarf_getlocation.c (check_constant_offset): data[48] are constant. + + * dwarf_getsrclines.c: Fix signed comparison warning in extended + opcode parsing. + +2010-06-21 Roland McGrath <roland@redhat.com> + + * dwarf.h: Add DW_TAG_GNU_* constants. + + * memory-access.h (get_sleb128_rest_return): Fix sign extension for + 10-byte case. + +2010-06-20 Roland McGrath <roland@redhat.com> + + * libdw_findcu.c (__libdw_findcu): Take new flag argument, + to search TUs instead of CUs. + * libdwP.h: Update decl. + (struct Dwarf): New member tu_tree. + * dwarf_end.c (dwarf_end): Clean up tu_tree. + * dwarf_offdie.c (do_offdie): New function, broken out of ... + (dwarf_offdie): ... here. + (dwarf_offdie_types): New function. + * libdw.h: Declare it. + * libdw.map (ELFUTILS_0.148): Add it. + + * libdwP.h (CUDIE): Use cu_data. + * dwarf_formblock.c: Likewise. + * dwarf_formref_die.c: Likewise. + * dwarf_diecu.c: Use CUDIE macro. + * dwarf_formaddr.c: Use cu_sec_idx. + +2010-06-16 Roland McGrath <roland@redhat.com> + + * dwarf_formref_die.c: Use dwarf_offdie only for DW_FORM_ref_addr, so + we don't repeat a CU lookup we've already done. Handle + DW_FORM_ref_sig8 using sig8_hash table and __libdw_intern_next_unit. + + * libdw_findcu.c (__libdw_intern_next_unit): New function, + broken out of ... + (__libdw_findcu): ... here. Call it. + * libdwP.h: Declare it. + (struct Dwarf): New member next_tu_offset. + + * dwarf_sig8_hash.c: New file. + * dwarf_sig8_hash.h: New file. + * Makefile.am (libdw_a_SOURCES, noinst_HEADERS): Add them. + * dwarf_abbrev_hash.c: Include dwarf_sig8_hash.h before + defining NO_UNDEF. + * libdwP.h (struct Dwarf): New member sig8_hash. + * dwarf_begin_elf.c: Call Dwarf_Sig8_Hash_init on it. + * dwarf_end.c: Call Dwarf_Sig8_Hash_free on it. + + * dwarf_nextcu.c (dwarf_next_unit): New function, broken out of ... + (dwarf_nextcu): ... here. Call it. + * libdw.h: Declare it. + * libdwP.h: Add INTDECL. + * libdw_findcu.c (__libdw_findcu): Use it instead of dwarf_nextcu. + * libdw.map (ELFUTILS_0.148): New set, add dwarf_next_unit. + + * libdwP.h (cu_sec_idx, cu_data): New functions. + Use .debug_types when CU is a TU. + * dwarf_cuoffset.c: Use that instead of assuming IDX_debug_info. + * dwarf_siblingof.c: Likewise. + * dwarf_formstring.c: Likewise. + * dwarf_formudata.c (__libdw_formptr, dwarf_formudata): Likewise. + * dwarf_getlocation.c (dwarf_getlocation): Likewise. + (dwarf_getlocation_addr): Likewise. + + * libdwP.h (struct Dwarf_CU): Add new members type_offset, type_sig8. + (DIE_OFFSET_FROM_CU_OFFSET): Take flag argument; if true, compute + .debug_types header size instead of .debug_info header size. + (CUDIE): Use it. + * dwarf_diecu.c: Update caller. + * dwarf_getaranges.c: Likewise. + * dwarf_nextcu.c: Likewise. + * libdw_findcu.c (__libdw_findcu): Initialize new members. + + * fde.c (fde_by_offset): Renamed to ... + (__libdw_fde_by_offset): ... this, made global and internal_function. + Don't take ADDRESS argument. + (__libdw_find_fde): Update caller. Do address sanity check here. + * cfi.h: Declare __libdw_fde_by_offset. + * cfi.c (dwarf_cfi_validate_fde): New function. + * libdw.h: Declare it. + * libdw.map (ELFUTILS_0.148): Add it. + + * cie.c (intern_new_cie): Canonicalize DW_EH_PE_absptr FDE encoding to + either DW_EH_PE_udata8 or DW_EH_PE_udata4. + + * encoded-value.h (read_encoded_value): Handle DW_EH_PE_indirect. + Don't assume DW_EH_PE_aligned refers to native address size. + + * cfi.c (execute_cfi): Barf on CIE initial instructions changing the + address. + +2010-06-17 Roland McGrath <roland@redhat.com> + + * libdwP.h (struct Dwarf_Line_s): Add members isa, discriminator, and + op_index. + * dwarf_getsrclines.c (dwarf_getsrclines): Move NEW_FILE macro guts + into an inner inline function. Set new fields. Check all fields for + overflow when setting. + * dwarf_lineisa.c: New file. + * dwarf_linediscriminator.c: New file. + * dwarf_lineop_index.c: New file. + * Makefile.am (libdw_a_SOURCES): Add them. + * libdw.map (ELFUTILS_0.148): Add them. + * libdw.h: Declare them. + +2010-06-16 Roland McGrath <roland@redhat.com> + + * dwarf_next_cfi.c: Fix version 4 return_address_register decoding. + + * fde.c (fde_by_offset): Renamed to ... + (__libdw_fde_by_offset): ... this, made global and internal_function. + Don't take ADDRESS argument. + (__libdw_find_fde): Update caller. Do address sanity check here. + * cfi.h: Declare __libdw_fde_by_offset. + * cfi.c (dwarf_cfi_validate_fde): New function. + * libdw.h: Declare it. + * libdw.map (ELFUTILS_0.148): Add it. + + * cie.c (intern_new_cie): Canonicalize DW_EH_PE_absptr FDE encoding to + either DW_EH_PE_udata8 or DW_EH_PE_udata4. + + * encoded-value.h (read_encoded_value): Handle DW_EH_PE_indirect. + Don't assume DW_EH_PE_aligned refers to native address size. + + * cfi.c (execute_cfi): Barf on CIE initial instructions changing the + address. + +2010-06-15 Roland McGrath <roland@redhat.com> + + * dwarf_formref.c (__libdw_formref): Diagnose DW_FORM_ref_sig8 like + DW_FORM_ref_addr. + * dwarf_formref_die.c (dwarf_formref_die): Diagnose it the same way + here, since we don't support it yet. + + * dwarf_next_cfi.c: Handle version 4 format. + + * dwarf_getsrclines.c: Handle version 4 format. + +2010-06-01 Roland McGrath <roland@redhat.com> + + * libdwP.h: Remove unused IDX_debug_*names, add IDX_debug_types. + * dwarf_begin_elf.c (dwarf_scnnames): Likewise. + + * libdwP.h (CIE_VERSION): Remove unused macro. + + * dwarf_getsrclines.c: Fix version field test. + * libdwP.h (DWARF_VERSION): Remove useless macro. + + * dwarf_formudata.c (__libdw_formptr): Fix DW_FORM_sec_offset handling. + + * dwarf_formblock.c (dwarf_formblock): Handle DW_FORM_exprloc. + + * libdw_findcu.c (__libdw_findcu): Accept version 4. + +2010-05-31 Mark Wielaard <mjw@redhat.com> + + * cfi.h (dwarf_cfi_cie_p): Move definition from here, to .. + * libdw.h (dwarf_cfi_cie_p): ... here. + +2010-05-31 Mark Wielaard <mjw@redhat.com> + + * dwarf.h: Fix DW_LANG_Python constant. + +2010-05-28 Eduardo Santiago <santiago@redhat.com> + + * dwarf_getlocation.c (dwarf_getlocation): Do attr_ok check first + thing. + +2010-05-27 Roland McGrath <roland@redhat.com> + + * dwarf.h: Add DW_AT_enum_class, DW_AT_linkage_name, + DW_TAG_template_alias, DW_LANG_Python, DW_LNE_set_discriminator. + +2010-05-08 Roland McGrath <roland@redhat.com> + + * dwarf_getlocation.c (__libdw_intern_expression): Take new argument + REF_SIZE. Use that to handle DW_OP_call_ref correctly. + (getlocation): Update caller. + * dwarf_frame_cfa.c (dwarf_frame_cfa): Likewise. + * dwarf_frame_register.c (dwarf_frame_register): Likewise. + * libdwP.h: Update decl. + +2010-04-26 Roland McGrath <roland@redhat.com> + + * cfi.h (struct Dwarf_Frame_s): Add cfa_invalid alternative in cfa_rule. + * cfi.c (execute_cfi): Set that instead of doing cfi_assert for + DW_CFA_def_cfa_{offset*,register} when a non-offset rule is in force. + * dwarf_frame_cfa.c (dwarf_frame_cfa): Handle cfa_invalid. + + * dwarf_getlocation.c (__libdw_intern_expression): Take new arg CFAP. + Prepend DW_OP_call_frame_cfa if true. + (getlocation): Update caller. + * dwarf_frame_cfa.c (dwarf_frame_cfa): Likewise. + * dwarf_frame_register.c (dwarf_frame_register): Likewise. + * libdwP.h: Update decl. + +2010-04-22 Roland McGrath <roland@redhat.com> + + * cfi.c (execute_cfi): Never return without cleanup. + Free FS on failure. + (cie_cache_initial_state): Adjust caller to expect that free. + (__libdw_frame_at_address): Likewise. + +2010-03-10 Roland McGrath <roland@redhat.com> + + * libdw.map (ELFUTILS_0.146): New set. Add dwfl_core_file_report. + +2010-02-15 Roland McGrath <roland@redhat.com> + + * Makefile.am: Use config/eu.am for common stuff. + +2010-02-02 Mark Wielaard <mjw@redhat.com> + + * fde.c (intern_fde): Fix length check for sized_augmentation_data. + +2010-01-07 Roland McGrath <roland@redhat.com> + + * dwarf_getcfi_elf.c (getcfi_phdr): Use elf_getphdrnum. + +2010-01-05 Roland McGrath <roland@redhat.com> + + * dwarf_aggregate_size.c: New file. + * Makefile.am (libdw_a_SOURCES): Add it. + * libdw.h: Declare it. + * libdwP.h: Add INTDECL. + * libdw.map (ELFUTILS_0.144): New set. Add dwarf_aggregate_size. + + * dwarf_srclang.c: Add INTDEF. + * libdwP.h: Add INTDECL. + + * dwarf.h: Add some more DW_AT_GNU_* types from gcc. + + * dwarf.h: Add DW_AT_GNU_vector, DW_AT_GNU_template_name. + +2009-11-21 Roland McGrath <roland@redhat.com> + + * dwarf_getlocation.c (check_constant_offset): Return 1 for all + non-constant forms. + +2009-10-15 Roland McGrath <roland@redhat.com> + + * libdw_form.c (__libdw_form_val_len): Grok DW_FORM_sec_offset, + DW_FORM_exprloc, DW_FORM_flag_present, and DW_FORM_ref_sig8. + +2009-09-17 Roland McGrath <roland@redhat.com> + + * dwarf_getlocation.c (dwarf_getlocation_implicit_value): Make OP + argument a pointer to const. + * libdw.h: Update decl. + +2009-09-10 Roland McGrath <roland@redhat.com> + + * dwarf_getlocation.c (store_implicit_value): New function. + (__libdw_intern_expression): Use it, handle DW_OP_implicit_value. + (dwarf_getlocation_implicit_value): New function. + * libdw.h: Declare it. + * libdw.map (ELFUTILS_0.143): Add it. + +2009-09-09 Mark Wielaard <mjw@redhat.com> + + * dwarf_getcfi.c (dwarf_getcfi): Clear cfi->ebl. + +2009-08-21 Josh Stone <jistone@redhat.com> + + * dwarf_hasattr_integrate.c: Integrate DW_AT_specification too. + +2009-08-10 Roland McGrath <roland@redhat.com> + + * dwarf_getscopevar.c: Use dwarf_diename. + +2009-08-09 Roland McGrath <roland@redhat.com> + + * libdw.map (ELFUTILS_0.143): New version set, + inherits from ELFUTILS_0.142. + * dwarf_arrayorder.c: Use OLD_VERSION and NEW_VERSION to define an + alias in the ELFUTILS_0.122 version set and the default in the new set. + * dwarf_srclang.c: Likewise. + * dwarf_decl_file.c: Likewise. + * dwarf_decl_line.c: Likewise. + * dwarf_decl_column.c: Likewise. + * dwarf_bytesize.c: Likewise. + * dwarf_bitsize.c: Likewise. + * dwarf_bitoffset.c: Likewise. + +2009-08-07 Roland McGrath <roland@redhat.com> + + * dwarf_arrayorder.c: Use dwarf_attr_integrate. + * dwarf_srclang.c: Likewise. + * dwarf_decl_file.c: Likewise. + * dwarf_decl_line.c (__libdw_attr_intval): Likewise. + * dwarf_bytesize.c: Likewise. + * dwarf_bitsize.c: Likewise. + * dwarf_bitoffset.c: Likewise. + +2009-07-22 Roland McGrath <roland@redhat.com> + + * dwarf_frame_cfa.c: Change calling convention. + * libdw.h: Update decl. + + * dwarf_frame_register.c: Change calling/return-value convention for + value-only results and undefined/same_value. + * libdw.h: Update decl. + + * dwarf_getlocation.c (__libdw_intern_expression): Take new bool + argument, append DW_OP_stack_value if set. Don't take NOPS argument, + return that value instead. + (getlocation): Update caller. + * dwarf_frame_cfa.c: Likewise. + * libdwP.h: Update decl. + +2009-07-21 Roland McGrath <roland@redhat.com> + + * dwarf_getsrc_file.c: Ignore a CU that just has no DW_AT_stmt_list. + Fix loop iteration after skipping a bogus or useless CU. + + * dwarf_entry_breakpoints.c: Handle 0 dwarf_errno () as harmless + absence, not DWARF_E_NO_DEBUG_LINE. + +2009-07-20 Roland McGrath <roland@redhat.com> + + * dwarf_getlocation.c (__libdw_intern_expression): + Handle DW_OP_stack_value. + +2009-07-16 Roland McGrath <roland@redhat.com> + + * dwarf_formudata.c (__libdw_formptr): Handle DW_FORM_sec_offset, + reject others when CU's version > 3. + + * dwarf_formflag.c: Handle DW_FORM_flag_present. + + * dwarf.h: Add DW_OP_{implicit,stack}_value from DWARF 4 draft. + Also DW_TAG_type_unit and DW_TAG_rvalue_reference_type. + Also DW_AT_signature, DW_AT_main_subprogram, DW_AT_data_bit_offset, + and DW_AT_const_expr. + Also DW_FORM_sec_offset, DW_FORM_exprloc, DW_FORM_flag_present, + and DW_FORM_ref_sig8. + +2009-07-15 Roland McGrath <roland@redhat.com> + + * dwarf_getlocation.c: Grok DW_OP_form_tls_address, + DW_OP_GNU_push_tls_address, and DW_OP_bit_piece. + +2009-07-13 Roland McGrath <roland@redhat.com> + + * dwarf_getlocation.c: Grok DW_OP_call_frame_cfa. + +2009-07-08 Roland McGrath <roland@redhat.com> + + * libdw.map (ELFUTILS_0.142): Add dwfl_module_dwarf_cfi, + dwfl_module_eh_cfi. + + * libdwP.h (struct Dwarf): Add member `cfi'. + * dwarf_end.c (dwarf_end): Call __libdw_destroy_frame_cache on it. + * dwarf_getcfi.c: New file. + * dwarf_getcfi_elf.c: New file. + * dwarf_cfi_end.c: New file. + * dwarf_cfi_addrframe.c: New file. + * dwarf_frame_cfa.c: New file. + * dwarf_frame_register.c: New file. + * dwarf_frame_return_address_register.c: New file. + * Makefile.am (libdw_a_SOURCES): Add them. + * unwind.h: Declare those functions. + * libdw.map (ELFUTILS_0.142): Export them. + + * dwarf_getlocation.c (__libdw_intern_expression): New function, + broken out of ... + (getlocation): ... here, call it. + * libdwP.h: Declare it. + + * cie.c: New file. + * fde.c: New file. + * frame-cache.c: New file. + * cfi.c: New file. + * cfi.h: New file. + * encoded-value.h: New file. + * Makefile.am (libdw_a_SOURCES, noinst_HEADERS): Add them. + * libdwP.h: Add DWARF_E_INVALID_CFI to errors enum. + * dwarf_error.c (errmsgs): Add element for it. + + * dwarf_next_cfi.c: New file. + * Makefile.am (libdw_a_SOURCES): Add it. + * libdw.h (Dwarf_CIE, Dwarf_FDE, Dwarf_CIE_Entry): New types. + Declare dwarf_next_cfi. + * libdw.map (ELFUTILS_0.142): New set, inherits from ELFUTILS_0.136. + Add dwarf_next_cfi. + + * memory-access.h [! ALLOW_UNALIGNED] + (read_2ubyte_unaligned): Renamed to ... + (read_2ubyte_unaligned_1): ... this. Take bool rather than Dwarf *. + (read_2ubyte_unaligned): Define as macro passing dbg->other_byte_order. + (read_2sbyte_unaligned): Likewise. + (read_4ubyte_unaligned): Likewise. + (read_4sbyte_unaligned): Likewise. + (read_8ubyte_unaligned): Likewise. + (read_8sbyte_unaligned): Likewise. + + * libdwP.h (IDX_eh_frame): Remove it. + * dwarf_begin_elf.c (dwarf_scnnames): Remove its element. + +2009-07-08 Roland McGrath <roland@redhat.com> + + * libdwP.h (struct Dwarf_Line_s): Reorder members to pack better. + + * dwarf_getlocation.c (check_constant_offset): New function. + (dwarf_getlocation, dwarf_getlocation_addr): Call it to + handle DW_AT_data_member_location of data[48] as constant offset. + +2009-06-18 Roland McGrath <roland@redhat.com> + + * libdwP.h (__libdw_read_address_inc): Constify. + (__libdw_read_offset_inc): Likewise. + * dwarf_getaranges.c: Likewise. + * dwarf_getlocation.c: Likewise. + * dwarf_getsrclines.c: Likewise. + * dwarf_nextcu.c: Likewise. + +2009-05-05 Petr Machata <pmachata@redhat.com> + + * libdwP.h (__libdw_formptr): Declare new function. + * dwarf_formudata.c: Implement it here. + * dwarf_getlocation.c (dwarf_getlocation_addr): + Call it instead of hand-rolled offset handling code. + * dwarf_getsrclines.c (dwarf_getsrclines): Likewise. + * dwarf_ranges.c (dwarf_ranges): Likewise. + +2009-05-04 Petr Machata <pmachata@redhat.com> + + * libdwP.h (__libdw_read_begin_end_pair_inc): Declare new function. + * dwarf_ranges.c: Implement it here. + (dwarf_ranges): Call it. + * dwarf_getlocation.c (dwarf_getlocation_addr): Call it also here. + +2009-04-23 Petr Machata <pmachata@redhat.com> + + * dwarf_formaddr.c (dwarf_formaddr): Call __libdw_read_* instead + of read_*ubyte_unaligned. + * dwarf_formref_die.c (dwarf_formref_die): Likewise. + * dwarf_formstring.c (dwarf_formstring): Likewise. + * dwarf_formudate.c (dwarf_formudata): Likewise. + * dwarf_getaranges.c (dwarf_getaranges): Likewise. + * dwarf_getlocation.c (dwarf_getlocation_addr): Likewise. + * dwarf_getpubnames.c (get_offsets): Likewise. + * dwarf_nextcu.c (dwarf_nextcu): Likewise. + +2009-04-23 Petr Machata <pmachata@redhat.com> + + * libdwP.h (__libdw_read_addr_inc, __libdw_read_off_inc, + __libdw_read_addr, __libdw_read_off): Add four new internal + functions. + +2009-05-07 Roland McGrath <roland@redhat.com> + + * dwarf_getmacros.c (dwarf_getmacros): Use absolute section offset in + return value and OFFSET argument, not CU-relative. Only fetch the + attribute data when called with OFFSET of 0. + +2009-05-07 Petr Machata <pmachata@redhat.com> + + * dwarf_getmacros.c (dwarf_getmacros): Take into account offset in + DW_AT_macro_info attribute of CU DIE. + +2009-04-15 Roland McGrath <roland@redhat.com> + + * dwarf.h (DW_CIE_ID): Removed. + (DW_CIE_ID_32, DW_CIE_ID_64): New constants replace it. + +2009-04-01 Roland McGrath <roland@redhat.com> + + * dwarf.h: Add DW_CFA_GNU_negative_offset_extended. + +2009-01-28 Roland McGrath <roland@redhat.com> + + * libdwP.h (struct Dwarf_Line_s): Move out of struct Dwarf_Lines_s + defn so C++ doesn't scope the name to not match the Dwarf_Line typedef. + + * libdwP.h (struct Dwarf_Files_s): Replace dbg field with cu field. + +2009-01-26 Roland McGrath <roland@redhat.com> + + * dwarf_ranges.c: Return 0 when no ranges or *_pc attrs at all. + +2009-01-25 Roland McGrath <roland@redhat.com> + + * dwarf_getattrs.c: Correctly skip attribute values when restarting. + +2009-01-23 Roland McGrath <roland@redhat.com> + + * Makefile.am ($(srcdir)/known-dwarf.h): Target renamed back. + Put these rules under if MAINTAINER_MODE. + +2009-01-22 Roland McGrath <roland@redhat.com> + + * dwarf.h: Add DW_OP_GNU_encoded_addr. + +2009-01-21 Roland McGrath <roland@redhat.com> + + * Makefile.am (CLEANFILES): Renamed to ... + (MOSTLYCLEANFILES): ... here. + (CLEANFILES): New variable, add known-dwarf.h. + +2009-01-17 Roland McGrath <roland@redhat.com> + + * Makefile.am (known-dwarf.h): Target renamed, not in $(srcdir). + Make it unconditional. + (BUILT_SOURCES): Updated. + + * dwarf.h: Add description comments for DW_LANG_* values. + + * Makefile.am [MAINTAINER_MODE] + ($(srcdir)/known-dwarf.h): New target. + (BUILT_SOURCES): Add it. + + * dwarf.h: Add DW_OP_GNU_push_tls_address, DW_OP_GNU_uninit. + +2009-01-10 Ulrich Drepper <drepper@redhat.com> + + * dwarf_error.c: Always use __thread. Remove all !USE_TLS code. + +2009-01-08 Roland McGrath <roland@redhat.com> + + * Makefile.am (libdw.so): Don't depend on $(zip_LIBS), just link it in. + +2008-01-06 Roland McGrath <roland@redhat.com> + + * libdwP.h (struct Dwarf_Abbrev): Change type of 'has_children' to bool. + Reorder members. + * dwarf_haschildren.c: Return -1 for error case, not 0. + + * Makefile.am (libdw.so): Link in $(zip_LIBS). + +2009-01-06 Ulrich Drepper <drepper@redhat.com> + + * dwarf.h: Add definition for unwind and call frame information. + + * memory-access.h: Define read_ubyte_unaligned, read_sbyte_unaligned, + read_ubyte_unaligned_inc, and read_sbyte_unaligned_inc. + +2008-08-15 Roland McGrath <roland@redhat.com> + + * libdw.map (ELFUTILS_0.136): New version set, inherits from + ELFUTILS_0.130. Add dwfl_addrsegment, dwfl_report_segment. + +2008-01-21 Ulrich Drepper <drepper@redhat.com> + + * dwarf_child.c: Minor optimizations. + * dwarf_getattrs.c: Likewise. + * dwarf_getpubnames.c: Likewise. + * dwarf_siblingof.c: Likewise. + * dwarf_tag.c: Likewise. + +2008-01-18 Ulrich Drepper <drepper@redhat.com> + + * dwarf_getsrclines.c (dwarf_getsrclines): Don't require exact match + of DWARF_VERSION comparison, just fail if the file's version is newer. + +2008-01-17 Nick Clifton <nickc@redhat.com> + + * dwarf.h (DWARF3_LENGTH_MIN_ESCAPE_CODE): New define. + (DWARF3_LENGTH_MAX_ESCAPE_CODE): New define. + (DWARF3_LENGTH_64_BIT): New define. + * dwarf_getaranges (dwarf_getaranges): Use the new definitions. + * dwarf_getpubnames: Include dwarf.h. + (get_offsets): Use the new definitions. + * dwarf_getsrclines.c (dwarf_getsrclines): Use the new defintions. + * dwarf_nextcu.c: Include dwarf.h. Correct comment. + (dwarf_nextcu): Use the new definitions. + + * libdwP.h (DIE_OFFSET_FROM_CU_OFFSET): New macro. + * dwarf_diecu.c (dwarf_diecu): Use the new macro. + * dwarf_getaranges (dwarf_getaranges): Use the new macro. + * dwarf_nextcu.c (dwarf_nextcu): Use the new macro. + + * dwarf_getpubnames (get_offsets): Replace assertion with test and + error return. + + * dwarf_entry_breakpoints.c (dwarf_entry_breakpoints): Use CUDIE. + + * dwarf_siblingof (dwarf_siblingof): Detect a NULL return pointer. + Set the address in the return structure to the address of the next + non-sibling die, if there is no sibling and the return pointer is + not the same as the die pointer. + * libdw.h: Expand the description of the dwarf_siblingof prototype. + + * dwarf_child.c: Fix typo in comment. + + * libdwP.h (DWARF_VERSION): Change to 3. + + * dwarf_formref.c (__libdw_formref.c): Handle attributes which do + not have a initialised valp pointer. + + * dwarf_getattrs.c (dwarf_getattrs): Return 1 rather than 0 when + the end of the attributes is reached. When the callback fails, + return the address of the failing attribute, not the address of + its successor. + * libdw.h: Expand the description of the dwarf_getattrs prototype. + + * dwarf_child.c (__libdw_find_attr): Use the new definition. + (dwarf_child): Likewise. + * dwarf_tag.c (__libdw_findabbrev): Likewise. + (dwarf_tag): Likewise. + +2008-01-08 Roland McGrath <roland@redhat.com> + + * Makefile.am (euinclude): Variable removed. + (pkginclude_HEADERS): Set this instead of euinclude_HEADERS. + (libdw.so): Pass -Wl,--enable-new-dtags,-rpath,$(pkglibdir). + +2007-10-17 Roland McGrath <roland@redhat.com> + + * libdw.h (__deprecated_attribute__): New macro. + (dwarf_formref): Mark it deprecated. + * dwarf_formref.c (__libdw_formref): New function, broken out of ... + (dwarf_formref): ... here. Call it. Remove INTDEF. + * libdwP.h: Remove INTDECL. + Declare __libdw_formref. + * dwarf_siblingof.c (dwarf_siblingof): Call __libdw_formref instead. + * dwarf_formref_die.c: Likewise. Handle DW_FORM_ref_addr here. + + * libdw_form.c (__libdw_form_val_len): Fix DW_FORM_ref_addr result, + needs to check CU->version. + + * libdwP.h (struct Dwarf_CU): New member `version'. + * libdw_findcu.c (__libdw_findcu): Initialize it. + + * dwarf_child.c: Return 1 for null entry as first child. + +2007-10-05 Roland McGrath <roland@redhat.com> + + * dwarf_begin_elf.c (check_section): Punt on SHT_NOBITS sections. + + * libdw.h (__extern_inline): Rename to __libdw_extern_inline. + [__OPTIMIZE__] (dwarf_whatattr, dwarf_whatform): Update uses. + +2007-10-03 Roland McGrath <roland@redhat.com> + + * libdw.map (ELFUTILS_0.130: Add dwfl_build_id_find_elf + and dwfl_build_id_find_debuginfo. + + * libdw.map (ELFUTILS_0.130): New version set, inherits from + ELFUTILS_0.127. Add dwfl_module_build_id, dwfl_module_report_build_id. + +2007-10-02 Roland McGrath <roland@redhat.com> + + * libdw_visit_scopes.c (classify_die): Return walk for class_type and + structure_type. + +2007-08-07 Roland McGrath <roland@redhat.com> + + * dwarf_getscopes.c (pc_match): Swallow dwarf_haspc error return when + error code is DWARF_E_NOERROR (0). + + * dwarf_getscopes.c (pc_record): Always bail early if DIE->prune. + Fix typo in __libdw_visit_scopes argument. + + * dwarf_getscopes.c (pc_match): Check dwarf_haspc error return, + swallow DWARF_E_NO_DEBUG_RANGES but not other errors. + +2007-07-03 Roland McGrath <roland@redhat.com> + + * libdw.h (__extern_inline): New macro. + [__OPTIMIZE__] (dwarf_whatattr, dwarf_whatform): Use it. + +2007-04-16 Roland McGrath <roland@redhat.com> + + * libdw.map (ELFUTILS_0.127): Add dwfl_module_address_section. + +2007-04-05 Roland McGrath <roland@redhat.com> + + * dwarf_getsrcdirs.c: New file. + * Makefile.am (libdw_a_SOURCES): Add it. + * libdw.h: Declare dwarf_getsrcdirs. + * libdw.map (ELFUTILS_0.127): Add it. + + * libdwP.h (struct Dwarf_Files_s): New member ndirs. + * dwarf_getsrclines.c (dwarf_getsrclines): Don't clobber NDIRLIST to + zero before we use it to check for DWARF_E_INVALID_DIR_IDX. + Save DIRARRAY in the Dwarf_Files. + + * dwarf_ranges.c (dwarf_ranges): Don't sign-extend 32-bit BEGIN + address to check for all-ones base address entry. Check directly. + Reported by Sébastien Dugué <sebastien.dugue@bull.net>. + +2007-03-25 Roland McGrath <roland@redhat.com> + + * dwarf_begin_elf.c (check_section): Return Dwarf * instead of void. + Return NULL when freeing RESULT on error. + (global_read, scngrp_read): Check return value from check_section, + break out of loop after it has freed RESULT. + (valid_p): Handle null argument. + +2007-03-12 Roland McGrath <roland@redhat.com> + + * libdw.map (ELFUTILS_0.127): Add dwfl_report_begin_add. + +2007-03-04 Roland McGrath <roland@redhat.com> + + * libdw.map (ELFUTILS_0.127): New version set, inherits from + ELFUTILS_0.126. Add dwfl_module_addrsym. + +2007-02-10 Roland McGrath <roland@redhat.com> + + * dwarf.h (DW_OP_fbreg): Comment fix. + +2007-02-03 Roland McGrath <roland@redhat.com> + + * dwarf_getelf.c (dwarf_getelf): Renamed from dwarf_get_elf. + * libdw.map (ELFUTILS_0.126): New version set, inherits from + ELFUTILS_0.122. Move dwarf_getelf there; it was never truly + exported in the past. + +2006-12-17 Roland McGrath <roland@redhat.com> + + * dwarf_getlocation.c (dwarf_getlocation_addr): Use zero as base + address when the CU is missing attributes due to buggy GCC. + +2006-08-29 Roland McGrath <roland@redhat.com> + + * Makefile.am (CLEANFILES): Add libdw.so.$(VERSION). + + * libdw.h (dwarf_diecu): Add __nonnull_attribute__. + (dwarf_child): Don't list arg 1 in __nonnull_attribute__. + + * libdw_alloc.c (__libdw_allocate): Take new ALIGN argument, make sure + result is aligned. Adjust NEWP->remaining here for this allocation. + * libdwP.h: Update decl. + (libdw_alloc): Update caller. + +2006-07-12 Ulrich Drepper <drepper@redhat.com> + + * dwarf_child.c: Adjust for internal_function_def removal. + * dwarf_getabbrev.c: Likewise. + * dwarf_tag.c: Likewise. + * libdw_form.c: Likewise. + * memory-access.c: Likewise. + +2006-06-28 Roland McGrath <roland@redhat.com> + + * libdw.map: Export dwfl_linecu, dwfl_line_comp_dir. + + * libdw.map: Bump to 0.122; export dwfl_module_getsymtab and + dwfl_module_getsym. + +2006-05-27 Ulrich Drepper <drepper@redhat.com> + + * libdw.h: Add extern "C". + +2006-05-22 Ulrich Drepper <drepper@redhat.com> + + * dwarf_getaranges.c (dwarf_getaranges): Handle files without + aranges information. + +2006-05-21 Ulrich Drepper <drepper@redhat.com> + + * libdw.h: Add nonnull attributes to dwarf_tag, dwarf_getattrs, + dwarf_haschildren. + +2006-02-28 Roland McGrath <roland@redhat.com> + + * dwarf.h: Add missing DW_ATE_*, DW_TAG_*, DW_LANG_*, DW_CFA_*, + DW_OP_* values, to match DWARF 3.0. Add new DW_DS_*, DW_END_* + values from DWARF 3.0. + +2006-02-22 Roland McGrath <roland@redhat.com> + + * libdw.map: Bump to 0.120; export dwfl_version. + +2005-12-22 Roland McGrath <roland@redhat.com> + + * libdw.map: Bump to 0.119; export dwfl_linux_proc_maps_report. + +2005-12-12 Roland McGrath <roland@redhat.com> + + * dwarf_ranges.c: Copy CU base address-finding code from + dwarf_getlocation. + +2005-12-09 Roland McGrath <roland@redhat.com> + + * dwarf_getlocation.c (dwarf_getlocation_addr): Add some unlikelys. + Delay CU base lookup until it's needed. + If CU base lookup fails with no error, flag invalid DWARF. + +2005-11-25 Roland McGrath <roland@redhat.com> + + * libdw.map: Bump to 0.118; export dwfl_module_register_names. + +2005-11-15 Roland McGrath <roland@redhat.com> + + * Makefile.am [BUILD_STATIC] (AM_CFLAGS): Add -fpic. + +2005-11-13 Roland McGrath <roland@redhat.com> + + * libdw.map: Bump to 0.117; export dwfl_module_return_value_location. + +2005-10-27 Roland McGrath <roland@redhat.com> + + * dwarf_entry_breakpoints.c (search_range): Fix binary search code; + don't match end_sequence markers. + + * dwarf_getsrclines.c (compare_lines): Sort end_sequence markers + before normal records at the same address. + * dwarf_getsrc_die.c (dwarf_getsrc_die): Don't match an end_sequence + marker. + +2005-10-26 Roland McGrath <roland@redhat.com> + + * dwarf_getfuncs.c (dwarf_getfuncs): Use Dwarf_Die, not Dwarf_Func. + * dwarf_func_file.c: Renamed to ... + * dwarf_decl_file.c: ... here. + * dwarf_func_col.c: Renamed to ... + * dwarf_decl_column.c: ... here. + * dwarf_func_line.c: Renamed to ... + * dwarf_decl_line.c: ... here. + (dwarf_func_line): Renamed to ... + (dwarf_decl_line): ... this. Take a Dwarf_Die * argument. + (__libdw_func_intval): Renamed __libdw_attr_intval. + * dwarf_func_name.c: File removed. + * dwarf_func_lowpc.c: File removed. + * dwarf_func_highpc.c: File removed. + * dwarf_func_entrypc.c: File removed. + * dwarf_func_die.c: File removed. + * Makefile.am (libdw_a_SOURCES): Updated. + * libdw.h: Update decls. + (Dwarf_Func): Type removed. + * libdwP.h: Update decls. + (struct Dwarf_Func_s): Type removed. + * libdw.map: Updated. + + * libdwP.h (CUDIE): New macro. + * dwarf_getlocation.c (dwarf_getlocation_addr): Use it. + * dwarf_getscopes_die.c (dwarf_getscopes_die): Likewise. + * dwarf_ranges.c (dwarf_ranges): Likewise. + + * dwarf_getloclist.c: Renamed to ... + * dwarf_getlocation.c: ... here. + (getloclist): Renamed to getlocation. + (dwarf_getloclist): Renamed to dwarf_getlocation. + (dwarf_addrloclists): Renamed to dwarf_getlocation_addr. + * Makefile.am (libdw_a_SOURCES): Updated. + * libdw.h (dwarf_getloclist): Renamed to dwarf_getlocation. + (dwarf_addrloclists): Renamed dwarf_getlocation_addr. + (Dwarf_Loc): Renamed Dwarf_Op. + * libdwP.h (struct loc_s): Update use. + * libdw.map: Update map. + + * dwarf_entry_breakpoints.c: Use the second line record within the + function, regardless of its source location data. + +2005-10-25 Roland McGrath <roland@redhat.com> + + * dwarf_entry_breakpoints.c: Fall back to entrypc for contiguous too. + + * libdw.map: Add dwarf_entrypc, dwarf_entry_breakpoints. + +2005-10-14 Roland McGrath <roland@redhat.com> + + * dwarf_diecu.c (dwarf_diecu): New file. + * Makefile.am (libdw_a_SOURCES): Add it. + * libdw.h: Declare dwarf_diecu. + * libdw.map: Export it. + + * libdw.map: Bump to 0.116; export dwarf_ranges. + +2005-09-20 Roland McGrath <roland@redhat.com> + + * dwarf_haspc.c: Use dwarf_ranges. + * dwarf_entry_breakpoints.c: Likewise. + + * dwarf_ranges.c: New file. + * Makefile.am (libdw_a_SOURCES): Add it. + * libdw.h: Declare dwarf_ranges. + * libdwP.h: Add INTDECL. + +2005-09-14 Roland McGrath <roland@redhat.com> + + * dwarf_entry_breakpoints.c (dwarf_entry_breakpoints): Fix braino in + prologue_end marker scanning loop. + +2005-09-11 Roland McGrath <roland@redhat.com> + + * dwarf.h: Comment typo fix. + +2005-09-07 Roland McGrath <roland@redhat.com> + + * dwarf_entry_breakpoints.c: New file. + * Makefile.am (libdw_a_SOURCES): Add it. + * libdw.h: Declare dwarf_entry_breakpoints. + + * dwarf_entrypc.c: New file. + * Makefile.am (libdw_a_SOURCES): Add it. + * libdw.h: Declare dwarf_entrypc. + * libdwP.h: Add INTDECL. + +2005-08-28 Ulrich Drepper <drepper@redhat.com> + + * Makefile.am: Use $(LINK) not $(CC) when creating DSO. + (%.os): Use COMPILE.os. + (COMPILE.os): Filter out gconv options. + +2005-08-27 Roland McGrath <roland@redhat.com> + + * dwarf_getscopes.c (dwarf_getscopes): Rewritten using + __libdw_visit_scopes. + + * dwarf_getscopes_die.c: New file. + * Makefile.am (libdw_a_SOURCES): Add it. + * libdw.h: Declare dwarf_getscopes_die. + * libdw.map: Bump to 0.115 and add it. + + * libdw_visit_scopes.c (__libdw_visit_scopes): Pass a struct + containing a DIE and its parent pointer, instead of just Dwarf_Die. + Take two functions for both preorder and postorder visitors. + * libdwP.h: Update decl. + (struct Dwarf_Die_Chain): New type. + * dwarf_func_inline.c: Update uses. + + * dwarf_diename.c (dwarf_diename): Use dwarf_attr_integrate. + Add INTDEF. + * libdwP.h: Add INTDECL. + * dwarf_func_name.c (dwarf_func_name): Use dwarf_diename. + +2005-08-23 Roland McGrath <roland@redhat.com> + + * dwarf_attr_integrate.c (dwarf_attr_integrate): Treat + DW_AT_specification the same as DW_AT_abstract_origin. + +2005-08-20 Roland McGrath <roland@redhat.com> + + * libdw.map: Add dwfl_cumodule, remove dwfl_linecu. + Add dwfl_linux_kernel_report_offline, dwfl_offline_section_address, + and dwfl_report_offline. + +2005-08-19 Roland McGrath <roland@redhat.com> + + * libdw.map: Bump version to ELFUTILS_0.114 for libdwfl changes. + Add dwfl_module_relocate_address, dwfl_module_relocations, + dwfl_module_relocation_info. + +2005-08-18 Roland McGrath <roland@redhat.com> + + * dwarf_getscopes.c (dwarf_getscopes): Include the CU itself as + outermost scope in the results. + +2005-08-15 Roland McGrath <roland@redhat.com> + + * dwarf_func_inline.c: New file. + * Makefile.am (libdw_a_SOURCES): Add it. + * libdw.h: Declare dwarf_func_inline, dwarf_func_inline_instances. + * libdw.map: Add them. + + * dwarf_func_die.c: New file. + * Makefile.am (libdw_a_SOURCES): Add it. + * libdw.h: Declare dwarf_func_die. + * libdw.map: Add it. Bump version to ELFUTILS_0.114. + +2005-08-10 Ulrich Drepper <drepper@redhat.com> + + * dwarf_getsrclines.c (dwarf_getsrclines): Correct fallout of renaming + of DW_LNS_set_epilog_begin. + +2005-08-09 Roland McGrath <roland@redhat.com> + + * dwarf.h (DW_LNS_set_epilog_begin): Renamed DW_LNS_set_epilogue_begin. + + * dwarf_end.c: Add INTDEF. + * dwarf_error.c (dwarf_errmsg): Likewise. + * libdwP.h (dwarf_end, dwarf_errmsg): Add INTDECLs. + +2005-08-01 Roland McGrath <roland@redhat.com> + + * dwarf_getaranges.c (dwarf_getaranges): Check for bogus offset. + * dwarf_getabbrev.c (__libdw_getabbrev): Likewise. + +2005-07-28 Ulrich Drepper <drepper@redhat.com> + + * Makefile.am (libdw.so): No need to link with libeu.a anymore. + (libdw_a_LIBADD): Add all files from libdwfl.a. + +2005-07-27 Roland McGrath <roland@redhat.com> + + * Makefile.am (libdw.so): Link ../libdwfl/libdwfl_pic.a in, + along with ../libebl/libebl.a and ../lib/libeu.a; + depend on ../libelf/libelf.so. + (libdw_so_LDADD): New variable. + * libdw.map: Add dwfl_* symbols formerly in ../libdwfl/libdwfl.map. + + * libdw.map: Define an empty base version and move all symbols to + version ELFUTILS_0.111; don't define ELFUTILS_1.0 at all yet. + +2005-07-23 Ulrich Drepper <drepper@redhat.com> + + * dwarf_error.c: Add internal alias for dwarf_errno. + * libdwP.h: Declare __dwarf_errno_internal. + * dwarf_getloclist.c: Use INTDEF for dwarf_errno. + + * dwarf_error.c [USE_TLS]: Actually use __thread in definition of + global_error. + +2005-06-01 Roland McGrath <roland@redhat.com> + + * dwarf_getaranges.c (dwarf_getaranges): Sort result array. + * dwarf_getarange_addr.c (dwarf_getarange_addr): Use binary search. + +2005-06-08 Roland McGrath <roland@redhat.com> + + * memory-access.h (get_uleb128_step, get_uleb128): Remove casts. + (get_sleb128_step, get_sleb128): Likewise. + * dwarf_getattrs.c (dwarf_getattrs): Add consts. + * dwarf_getloclist.c (getloclist): Likewise. + * dwarf_formblock.c (dwarf_formblock): Likewise. + * dwarf_getsrclines.c (dwarf_getsrclines): Likewise. + * dwarf_getabbrevattr.c (dwarf_getabbrevattr): Likewise. + * dwarf_formref.c (dwarf_formref): Likewise. + * dwarf_formsdata.c (dwarf_formsdata): Likewise. + * dwarf_formudata.c (dwarf_formudata): Likewise. + * dwarf_haschildren.c (dwarf_haschildren): Likewise. + * dwarf_child.c (__libdw_find_attr, __libdw_find_attr): Likewise. + * dwarf_tag.c (dwarf_tag): Likewise. + * dwarf_getabbrev.c (__libdw_getabbrev): Likewise. + * memory-access.c (__libdw_get_uleb128, __libdw_get_sleb128): Likewise. + * libdw_form.c (__libdw_form_val_len): Likewise. + * libdwP.h: Update decl. + +2005-06-04 Roland McGrath <roland@redhat.com> + + * memory-access.h (get_uleb128_rest_return): New macro. + [! IS_LIBDW] (__libdw_get_uleb128): New static, defined using it. + (get_sleb128_rest_return): New macro. + [! IS_LIBDW] (__libdw_get_sleb128): New static, defined using it. + * memory-access.c: New file. + * Makefile.am (libdw_a_SOURCES): Add it. + (DEFS): Add -DIS_LIBDW. + +2005-05-31 Roland McGrath <roland@redhat.com> + + * dwarf_formref_die.c (dwarf_formref_die): Add CU header offset to + formref offset. + +2005-05-30 Roland McGrath <roland@redhat.com> + + * dwarf_getloclist.c (dwarf_addrloclists): Use DW_AT_entry_pc for base + address if DW_AT_low_pc is missing. Not to spec, but GCC generates it. + + * dwarf_getloclist.c (dwarf_addrloclists): Don't sign-extend 4-byte + BEGIN value. Instead, match base address entries separately for + 32/64 size cases. + +2005-05-28 Roland McGrath <roland@redhat.com> + + * dwarf_getloclist.c (dwarf_addrloclists): Fix decoding to advance + past location expression contents. + +2005-05-23 Roland McGrath <roland@redhat.com> + + * dwarf_getsrclines.c: Comment typo fix. + + * dwarf_haspc.c (dwarf_haspc): Fix CU DIE address calculation. + * dwarf_getloclist.c (dwarf_addrloclists): Likewise. + +2005-05-22 Ulrich Drepper <drepper@redhat.com> + + * libdwP.h: Only use INTDECL for alias prototypes. + +2005-05-19 Roland McGrath <roland@redhat.com> + + * dwarf_getloclist.c (attr_ok): Permit DW_AT_static_link too. + + * dwarf_getscopevar.c: New file. + * Makefile.am (libdw_a_SOURCES): Add it. + * libdw.h: Declare dwarf_getscopevar. + + * dwarf_getsrcfiles.c: Add INTDEF. + * dwarf_haschildren.c: Likewise. + * libdwP.h (dwarf_getsrcfiles, dwarf_haschildren): Add INTDECL. + + * dwarf_getscopes.c: New file. + * Makefile.am (libdw_a_SOURCES): Add it. + * libdw.h: Declare dwarf_getscopes. + * libdw.map: Add it. + +2005-05-18 Roland McGrath <roland@redhat.com> + + * libdwP.h (IDX_debug_ranges): New enum constant. + * dwarf_begin_elf.c (dwarf_scnnames): Add it for ".debug_ranges". + * libdwP.h (DWARF_E_NO_DEBUG_RANGES): New enum constant. + * dwarf_error.c (errmsgs): Add it. + * dwarf_haspc.c: New file. + * libdw.h: Declare dwarf_haspc. + * libdw.map: Add it. + * libdwP.h: Add INTDECL. + + * dwarf_attr_integrate.c: New file. + * dwarf_hasattr_integrate.c: New file. + * Makefile.am (libdw_a_SOURCES): Add them. + * libdw.h: Declare dwarf_attr_integrate, dwarf_hasattr_integrate. + * libdw.map: Add them. + + * dwarf_hasattr.c: Add INTDEF. + * libdwP.h: Add INTDECL for it. + + * dwarf_formref_die.c: New file. + * Makefile.am (libdw_a_SOURCES): Add it. + * libdw.h (dwarf_formref_die): Declare it. + * libdwP.h (dwarf_formref_die): Add INTDECL. + * libdw.map: Add it. + + * dwarf_getloclist.c (attr_ok, getloclist): New functions, broken out + of ... + (dwarf_getloclist): ... here. Call them. + (dwarf_addrloclists): New function. + * libdw.h: Declare it. + * libdw.map: Add it. + + * dwarf_getmacros.c (dwarf_getmacros): Don't bail at + DW_MACINFO_end_file. Recognize type 0 as terminator. + +2005-05-05 Roland McGrath <roland@redhat.com> + + * dwarf_getsrc_die.c (dwarf_getsrc_die): Use binary search. + + * dwarf_getsrclines.c (dwarf_getsrclines): Sort result array, since + the line program does not produce all entries in ascending order. + +2005-04-25 Ulrich Drepper <drepper@redhat.com> + + * dwarf_getsrc_file.c (dwarf_getsrc_file): Handle multiple + occurences (e.g., inlines) better. + +2005-04-24 Ulrich Drepper <drepper@redhat.com> + + * libdw.h (DWARF_END_ABBREV): Define. + * dwarf_getabbrev.c (__libdw_getabbrev): Return DWARF_END_ABBREV if + end is reached. + * dwarf_offabbrev.c (dwarf_offabbrev): Return -1 on error, 1 if end + of records reached. + * dwarf_tag.c (__libdw_findabbrev): Also recognize DWARF_END_ABBREV + as error of __libdw_getabbrev. + +2005-04-04 Ulrich Drepper <drepper@redhat.com> + + * dwarf_getsrc_file.c (dwarf_getsrc_file): Minor optimization. + + * dwarf_getsrc_file.c (dwarf_getsrc_file): Always pass number of + results back to caller. + +2005-04-04 Roland McGrath <roland@redhat.com> + + * dwarf_getsrc_file.c (dwarf_getsrc_file): Use size_t for CUHL. + + * dwarf_func_line.c (__libdw_func_intval): Use internal_function in + defn. + +2005-04-04 Ulrich Drepper <drepper@redhat.com> + + * dwarf_getsrc_file.c (dwarf_getsrc_file): Use INTUSE. + + * dwarf_getsrc_file.c: New file. + * Makefile.am (libdw_a_SOURCES): Add dwarf_getsrc_file.c. + * libdw.h: Declare dwarf_getsrc_file. + * libdw.map: Add dwarf_getsrc_file. + +2005-04-02 Ulrich Drepper <drepper@redhat.com> + + * dwarf_func_entrypc.c: New file. + * dwarf_func_col.c: New file. + * dwarf_func_line.c: New file. + * dwarf_func_file.c: New file. + * libdw.h: Add prototypes for new functions. + * libdw.map: Add dwarf_func_entrypc, dwarf_func_col, dwarf_func_line, + dwarf_func_file. + * Makefile.am (libdw_a_SOURCES): Add dwarf_func_entrypc.c, + dwarf_func_col.c, dwarf_func_line.c, dwarf_func_file.c. + * libdwP.h (struct Dwarf_Func_s): Add cudie element. + Declare __libdw_func_intval and __dwarf_formsdata_internal. + * dwarf_getfuncs.c: Also fill in cudie in Dwarf_Func object. + * dwarf_formsdata.c: Use INTUSE and INTDEF to avoid PLTs. + + * dwarf.h: Add some DWARF3 definitions. + +2005-04-01 Ulrich Drepper <drepper@redhat.com> + + * dwarf_getfuncs.c: New file. + * dwarf_func_highpc.c: New file. + * dwarf_func_lowpc.c: New file. + * dwarf_func_name.c: New file. + * Makefile.am (libdw_a_SOURCES): Add dwarf_getfuncs.c, + dwarf_func_highpc.c, dwarf_func_lowpc.c, and dwarf_func_name.c. + * libdw.map: Add dwarf_getfuncs, dwarf_func_highpc, dwarf_func_lowpc, + and dwarf_func_name. + * libdw.h: Add prototypes for new functions. + * dwarf_child.c: Use INTUSE and INTDEF to avoid PLTs. + * dwarf_siblingof.c: Likewise. + * dwarf_dieoffset.c: Likewise. + * dwarf_highpc.c: Likewise. + * dwarf_lowpc.c: Likewise. + * libdwP.h: Add prototypes for internal functions. + Define Dwarf_Func_s structure. + +2005-03-29 Ulrich Drepper <drepper@redhat.com> + + * libdw.h: Add padding in Dwarf_die. + + * dwarf_arrayorder.c: Use INTUSE and INTDEF to avoid PLTs. + * dwarf_attr.c: Likewise. + * dwarf_begin.c: Likewise. + * dwarf_begin_elf.c: Likewise. + * dwarf_bitoffset.c: Likewise. + * dwarf_bitsize.c: Likewise. + * dwarf_bytesize.c: Likewise. + * dwarf_diename.c: Likewise. + * dwarf_formaddr.c: Likewise. + * dwarf_formblock.c: Likewise. + * dwarf_formref.c: Likewise. + * dwarf_formstring.c: Likewise. + * dwarf_formudata.c: Likewise. + * dwarf_getarange_addr.c: Likewise. + * dwarf_getarangeinfo.c: Likewise. + * dwarf_getaranges.c: Likewise. + * dwarf_getloclist.c: Likewise. + * dwarf_getmacros.c: Likewise. + * dwarf_getsrc_die.c: Likewise. + * dwarf_getsrcfiles.c: Likewise. + * dwarf_getsrclines.c: Likewise. + * dwarf_highpc.c: Likewise. + * dwarf_lowpc.c: Likewise. + * dwarf_nextcu.c: Likewise. + * dwarf_offdie.c: Likewise. + * dwarf_siblingof.c: Likewise. + * dwarf_srclang.c: Likewise. + * dwarf_tag.c: Likewise. + * libdw_findcu.c: Likewise. + * libdwP.h: Add prototypes for internal functions. + + * dwarf_addrdie.c: New file. + * dwarf_macro_opcode.c: New file. + * dwarf_macro_param1.c: New file. + * dwarf_macro_param2.c: New file. + * libdw.h: Add declarations. Move Dwarf_Macro definition to libdwP.h. + * libdwP.h: Remove Dwarf_Macro definition. + * Makefile.am (libdw_a_SOURCES): Add dwarf_addrdie.c, + dwarf_macro_opcode.c, dwarf_macro_param1.c, and dwarf_macro_param2.c. + * libdw.map: Add entries for new functions. + +2005-03-21 Ulrich Drepper <drepper@redhat.com> + + * libdw.h: Handle broken gcc < 4. + +2005-02-15 Ulrich Drepper <drepper@redhat.com> + + * Makefile (AM_CFLAGS): Add -Wunused -Wextra -Wformat=2. + + * dwarf_begin_elf.c: Fix warnings. + * dwarf_dieoffset.c: Likewise. + * dwarf_end.c: Likewise. + * dwarf_error.c: Likewise. + * dwarf_getpubnames.c: Likewise. + + * libdwP.h: Add new error values. + * dwarf_error.c: Support new error values. + * dwarf_getpubnames.c: Check parameter value. + +2005-02-05 Ulrich Drepper <drepper@redhat.com> + + * Makefile.am: Check for text relocations in constructed DSO. + + * Makefile.am [MUDFLAP] (AM_CFLAGS): Add -fmudflap. + +2005-02-04 Ulrich Drepper <drepper@redhat.com> + + * dwarf_siblingof.c (dwarf_siblingof): Add some buffer boundary + checks to not read over buffer boundaries for ill-formed DWARF data. + +2004-09-25 Ulrich Drepper <drepper@redhat.com> + + * dwarf_child.c: Make compile with gcc 4.0. + * dwarf_error.c: Likewise. + * dwarf_formblock.c: Likewise. + * dwarf_getabbrev.c: Likewise. + * dwarf_getattrs.c: Likewise. + * dwarf_getsrclines.c: Likewise. + * dwarf_tag.c: Likewise. + * libdw_form.c: Likewise. + +2004-01-20 Ulrich Drepper <drepper@redhat.com> + + * Makefile.am: Support building with mudflap. + + * dwarf_getloclist.c: Fix warnings gcc 3.4 spits out. + * dwarf_getsrclines.c: Likewise. + * dwarf_memory-access.h: Likewise. + +2004-01-19 Ulrich Drepper <drepper@redhat.com> + + * dwarf_getsrcfiles.c: Third parameter can be NULL. + + * libdw.h: Define Dwarf_macro. Declare dwarf_getmacros. + Third parameter of dwarf_getsrcfiles can be NULL. + + * libdw.map: Add dwarf_getmacros. + * Makefile.am (libdw_a_SOURCES): Add dwarf_getmacros. + * dwarf_getmacros.c: New file. + +2004-01-18 Ulrich Drepper <drepper@redhat.com> + + * libdw.h: Second parameter of dwarf_getaranges can be NULL. + + * dwarf_nextcu.c: Return -1 if dwarf parameter is NULL. + + * dwarf_getsrclines.c: + Use read_2ubyte_unaligned_inc instead of _inc-less variant. + + * dwarf_getaranges.c: Allow naranges parameter to be NULL. + + * libdwP.h (_): Use elfutils domain. + + * dwarf_getsrclines.c (dwarf_getsrclines): Add more branch prediction. + + * dwarf_getsrclines.c: Fix typo in comment. + +2004-01-17 Ulrich Drepper <drepper@redhat.com> + + * Makefile.am: Support building with mudflap. + +2004-01-16 Ulrich Drepper <drepper@redhat.com> + + * memory-access.h: Add lots of const in case a pointer passed is const. + + * dwarf_formflag.c: New file. + * dwarf_getattrs.c: New file. + * dwarf_error.c: Add new error value. + * libdw.h: Add prototypes for new functions. Adjust prototype for + dwarf_getpubnames. + * libdw.map: Add new functions. + * dwarf_getpubnames.c: Change type of return value and fourth parameter + to ptrdiff_t. + * libdwP.h: Add new error value. + * Makefile.am (libdw_a_SOURCES): Add dwarf_getattrs.c and + dwarf_formflag.c. + + * dwarf_getpubnames.c (dwarf_getpubnames): Just fail if dbg is NULL. + +2004-01-12 Ulrich Drepper <drepper@redhat.com> + + * dwarf_getarange_addr.c: New file + * dwarf_getarangeinfo.c: New file. + * dwarf_getaranges.c: New file. + * dwarf_onerange.c: New file. + * libdw.h: Declare new functions. Define Dwarf_Arange and + Dwarf_Aranges. + * libdw.map: Add new functions. + * libdwP.h: Add new errors. Add aranges member to struct Dwarf. + Define Dwarf_Aranges_s and Dwarf_Arange_s. + * Makefile.am (libdw_a_SOURCES): Add dwarf_getaranges.c, + dwarf_onearange.c, dwarf_getarangeinfo.c, dwarf_getarange_addr.c. + * dwarf_error.c: Add new message. + +2004-01-11 Ulrich Drepper <drepper@redhat.com> + + * Makefile.am (libdw_a_SOURCES): Add dwarf_lineaddr.c, dwarf_linecol.c, + dwarf_linebeginstatement.c, dwarf_lineendsequence.c, dwarf_lineblock.c, + dwarf_lineprologueend.c, dwarf_lineepiloguebegin.c, dwarf_onesrcline.c. + * dwarf_error.c: Add another message. + * dwarf_getsrc_die.c: Adjust for Dwarf_Files and Dwarf_Lines + introduction. + * dwarf_filesrc.c: Likewise. + * dwarf_getsrcfiles.c: Likewise. + * dwarf_getsrclines.c: Likewise. + * dwarf_lineaddr.c: New file. + * dwarf_linebeginstatement.c: New file. + * dwarf_lineblock.c: New file. + * dwarf_linecol.c: New file. + * dwarf_lineendsequence.c: New file. + * dwarf_lineepiloguebegin.c: New file. + * dwarf_lineno.c: New file. + * dwarf_lineprologueend.c: New file. + * dwarf_onesrcline.c: New file. + * dwarf_lineno.c: Change interface to store result in object pointed + to by second parameter. + * libdw.h: Add prototypes for new functions. Change dwarf_lineno + prototype. Define Dwarf_Files and Dwarf_Lines. + * libdw.map: Add new functions. + * libdwP.h: Define Dwarf_Files_s and Dwarf_Lines_s. + * libdw_findcu.c: Don't initialize nlines field. + + * dwarf_siblingof: Little optimization. + + * dwarf_begin.c: Remember that the ELF descriptor must be closed. + * dwarf_end.c: Close ELF descriptor if free_elf is set. + * libdwP.h (struct Dwarf): Add free_elf field. + + * Makefile.am (libdw_a_SOURCES): Add dwarf_getstring.c and + dwarf_offabbrev.c. + * dwarf_getstring.c: New file. + * dwarf_offabbrev.c: New file. + * libdw.map: Add dwarf_getstring and dwarf_offabbrev. + * dwarf_getabbrev.c (__libdw_getabbrev): Add new dbg and result + parameters. Don't allocate memory if not necessary and don't lookup + previous results if no CU given. + (dwarf_getabbrev): Adjust call to __libdw_getabbrev. + * dwarf_tag.c: Adjust call to __libdw_getabbrev. + * libdw.h: Declare dwarf_offabbrev and dwarf_getstring. + * libdwP.h: Change prototype for __libdw_getabbrev. + + * dwarf_getabbrevattr.c: Add offsetp parameter. Fill in before + returning if this is wanted. + +2004-01-09 Ulrich Drepper <drepper@redhat.com> + + * dwarf_nextcu.c: Add new parameter offset_sizep. Initialize it + with offset_size value. + * libdw.h: Adjust dwarf_nextcu prototype. + * libdwP.h (struct Dwarf_CU): Add offset_size member. + * libdw_findcu.c: Adjust dwarf_nextcu call. Initialize offset_size + member of new CU struct. + * dwarf_formstring.c: Depend on offset_size not address_size for + DW_FORM_strp handling. + * dwarf_form.c: Likewise for DW_FORM_strp and DW_FORM_ref_addr. + + * dwarf_tag.c (__libdw_findabbrev): Return correct value for + failing lookup. + (dwarf_tag): Correctly recognize failed lookup. + + * dwarf_end.c (cu_free): Call tdestroy for locs member. Use new + function noop_free. + * dwarf_error.c: Add message for DWARF_E_NO_BLOCK. + * dwarf_formblock.c: New file. + * dwarf_getloclist.c: Rewrite to handle a single block. + * libdw.h: Define Dwarf_Block. Rename Dwarf_Loc members. Remove + Dwarf_Locdesc definition. Declare dwarf_formblock. Remove + dwarf_getloclistent declaration. + * libdw.map: Add dwarf_formblock, remove dwarf_getloclistent. + * libdwP.h: Define struct loc_s and DWARF_E_NO_BLOCK. + Add locs member to struct Dwarf_CU. + * libdw_fundcu.c: Initialize locs member of new CU. + * Makefile.am (libdw_a_SOURCES): Add dwarf_formblock.c. + Remove dwarf_getloclistent.c. + +2004-01-07 Ulrich Drepper <drepper@redhat.com> + + * libdw.h: Use __nonnull__ attribute only for gcc >= 3.3. + * libdwP.h: Likewise. + + * dwarf_getloclist.c: New file. + * dwarf_getloclistent.c: New file. + * libdw.h: Define Dwarf_Loc and Dwarf_Locdesc. + Declare dwarf_getloclistent and dwarf_getloclist. + * libdw.map: Add dwarf_getloclistent and dwarf_getloclist. + * libdwP.h: Define DWARF_E_NO_LOCLIST. + * Makefile.am (libdw_a_SOURCES): Add dwarf_getloclistent.c and + dwarf_getloclist.c. + + * dwarf_error.c: More error messages. + +2004-01-06 Ulrich Drepper <drepper@redhat.com> + + * dwarf_getsrclines.c: Remove debugging support. + + * dwarf_getsrcfiles.c: New file. + * dwarf_filesrc.c: New file. + * libdw.h: Declare these functions. Define Dwarf_File. + * libdwP.c: Adjust Dwarf_File_s definition. + * libdw.map: Add these functions. + * Makefile.am (libdw_a_SOURCES): Add dwarf_getsrcfiles.c and + dwarf_filesrc.c. + * dwarf_getsrclines.c: Initialize cu->files. + +2004-01-05 Ulrich Drepper <drepper@redhat.com> + + * libdw.h: Add more nonnull function attributes. + + * dwarf_begin_elf.c (dwarf_begin_elf): Don't initialize mem_tail->next. + * dwarf_end.c (cu_free): New function. + (dwarf_end): Also free CU tree. Correct freeing of memory blocks. + * dwarf_error.c (errmsgs): Add new messages. + * dwarf_getsrc_die.c: New file. + * dwarf_getsrclines.c: New file. + * dwarf_lineno.c: New file. + * dwarf_linesrc.c: New file. + * dwarf_nextcu.c (dwarf_nextcu): Use read_*byte_unaligned_inc + instead of the *_inc-less variants. + * libdw.h: Define Dwarf_Line. Add some function attributes. Declare + dwarf_getsrclines, dwarf_getsrc_die, dwarf_lineno, and dwarf_linesrc. + * libdw.map: Add dwarf_getsrclines, dwarf_getsrc_die, dwarf_lineno, + and dwarf_linesrc. + * libdwP.h: Add more error codes. + (struct Dwarf): Remove mem_tail.next member. + (Dwarf_File): Define type. + (struct Dwarf_Line_s): Define type. + (struct Dwarf_CU): Add lines and nlines members. + (libdw_alloc): Define local variable _tail and use it. + Add some function attributes. + * libdw_alloc.c (__libdw_allocate): Don't initialize next member. + * libdw_findcu.c (__libdw_findcu): Initialize lines and nlines members. + * memory-access.h: Add unlikely for the endian conversion paths. + * Makefile.am (AM_CFLAGS): Add -std parameter. + (libdw_a_SOURCES): Add dwarf_getsrclines, dwarf_getsrc_die, + dwarf_lineno, and dwarf_linesrc. + +2003-08-11 Ulrich Drepper <drepper@redhat.com> + + * Moved to CVS archive. diff --git a/src/libdw/Makefile.am b/src/libdw/Makefile.am new file mode 100644 index 00000000..1efda358 --- /dev/null +++ b/src/libdw/Makefile.am @@ -0,0 +1,135 @@ +## Process this file with automake to create Makefile.in +## +## Copyright (C) 2002-2010 Red Hat, Inc. +## This file is part of Red Hat elfutils. +## +## Red Hat elfutils is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by the +## Free Software Foundation; version 2 of the License. +## +## Red Hat elfutils is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License along +## with Red Hat elfutils; if not, write to the Free Software Foundation, +## Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. +## +## Red Hat elfutils is an included package of the Open Invention Network. +## An included package of the Open Invention Network is a package for which +## Open Invention Network licensees cross-license their patents. No patent +## license is granted, either expressly or impliedly, by designation as an +## included package. Should you wish to participate in the Open Invention +## Network licensing program, please visit www.openinventionnetwork.com +## <http://www.openinventionnetwork.com>. +## +include $(top_srcdir)/config/eu.am +DEFS += -DIS_LIBDW +if BUILD_STATIC +AM_CFLAGS += -fpic +endif +INCLUDES += -I$(srcdir)/../libelf +VERSION = 1 + +lib_LIBRARIES = libdw.a +if !MUDFLAP +noinst_LIBRARIES = libdw_pic.a +noinst_PROGRAMS = $(noinst_LIBRARIES:_pic.a=.so) +endif + +include_HEADERS = dwarf.h +pkginclude_HEADERS = libdw.h + +libdw_a_SOURCES = dwarf_begin.c dwarf_begin_elf.c dwarf_end.c dwarf_getelf.c \ + dwarf_getpubnames.c dwarf_getabbrev.c dwarf_tag.c \ + dwarf_error.c dwarf_nextcu.c dwarf_diename.c dwarf_offdie.c \ + dwarf_attr.c dwarf_formstring.c \ + dwarf_abbrev_hash.c dwarf_sig8_hash.c \ + dwarf_attr_integrate.c dwarf_hasattr_integrate.c \ + dwarf_child.c dwarf_haschildren.c dwarf_formaddr.c \ + dwarf_formudata.c dwarf_formsdata.c dwarf_lowpc.c \ + dwarf_entrypc.c dwarf_haspc.c dwarf_highpc.c dwarf_ranges.c \ + dwarf_formref.c dwarf_formref_die.c dwarf_siblingof.c \ + dwarf_dieoffset.c dwarf_cuoffset.c dwarf_diecu.c \ + dwarf_hasattr.c dwarf_hasform.c \ + dwarf_whatform.c dwarf_whatattr.c \ + dwarf_bytesize.c dwarf_arrayorder.c dwarf_bitsize.c \ + dwarf_bitoffset.c dwarf_srclang.c dwarf_getabbrevtag.c \ + dwarf_getabbrevcode.c dwarf_abbrevhaschildren.c \ + dwarf_getattrcnt.c dwarf_getabbrevattr.c \ + dwarf_getsrclines.c dwarf_getsrc_die.c \ + dwarf_getscopes.c dwarf_getscopes_die.c dwarf_getscopevar.c \ + dwarf_linesrc.c dwarf_lineno.c dwarf_lineaddr.c \ + dwarf_linecol.c dwarf_linebeginstatement.c \ + dwarf_lineendsequence.c dwarf_lineblock.c \ + dwarf_lineprologueend.c dwarf_lineepiloguebegin.c \ + dwarf_lineisa.c dwarf_linediscriminator.c \ + dwarf_lineop_index.c \ + dwarf_onesrcline.c dwarf_formblock.c \ + dwarf_getsrcfiles.c dwarf_filesrc.c dwarf_getsrcdirs.c \ + dwarf_getlocation.c dwarf_getstring.c dwarf_offabbrev.c \ + dwarf_getaranges.c dwarf_onearange.c dwarf_getarangeinfo.c \ + dwarf_getarange_addr.c dwarf_getattrs.c dwarf_formflag.c \ + dwarf_getmacros.c dwarf_macro_opcode.c dwarf_macro_param1.c \ + dwarf_macro_param2.c dwarf_addrdie.c \ + dwarf_getfuncs.c \ + dwarf_decl_file.c dwarf_decl_line.c dwarf_decl_column.c \ + dwarf_func_inline.c dwarf_getsrc_file.c \ + libdw_findcu.c libdw_form.c libdw_alloc.c memory-access.c \ + libdw_visit_scopes.c \ + dwarf_entry_breakpoints.c \ + dwarf_next_cfi.c \ + cie.c fde.c cfi.c frame-cache.c \ + dwarf_frame_info.c dwarf_frame_cfa.c dwarf_frame_register.c \ + dwarf_cfi_addrframe.c \ + dwarf_getcfi.c dwarf_getcfi_elf.c dwarf_cfi_end.c \ + dwarf_aggregate_size.c dwarf_getlocation_implicit_pointer.c + +if MAINTAINER_MODE +BUILT_SOURCES = $(srcdir)/known-dwarf.h +MAINTAINERCLEANFILES = $(srcdir)/known-dwarf.h +$(srcdir)/known-dwarf.h: $(top_srcdir)/config/known-dwarf.awk $(srcdir)/dwarf.h + gawk -f $^ > $@.new + mv -f $@.new $@ +endif + +if !MUDFLAP +libdw_pic_a_SOURCES = +am_libdw_pic_a_OBJECTS = $(libdw_a_SOURCES:.c=.os) + +libdw_so_SOURCES = +libdw.so: $(srcdir)/libdw.map libdw_pic.a \ + ../libdwfl/libdwfl_pic.a ../libebl/libebl.a \ + ../libelf/libelf.so +# The rpath is necessary for libebl because its $ORIGIN use will +# not fly in a setuid executable that links in libdw. + $(LINK) -shared -o $@ -Wl,--soname,$@.$(VERSION),-z,defs \ + -Wl,--enable-new-dtags,-rpath,$(pkglibdir) \ + -Wl,--version-script,$<,--no-undefined \ + -Wl,--whole-archive $(filter-out $<,$^) -Wl,--no-whole-archive\ + -ldl $(zip_LIBS) + if readelf -d $@ | fgrep -q TEXTREL; then exit 1; fi + ln -fs $@ $@.$(VERSION) + +install: install-am libdw.so + $(mkinstalldirs) $(DESTDIR)$(libdir) + $(INSTALL_PROGRAM) libdw.so $(DESTDIR)$(libdir)/libdw-$(PACKAGE_VERSION).so + ln -fs libdw-$(PACKAGE_VERSION).so $(DESTDIR)$(libdir)/libdw.so.$(VERSION) + ln -fs libdw.so.$(VERSION) $(DESTDIR)$(libdir)/libdw.so + +uninstall: uninstall-am + rm -f $(DESTDIR)$(libdir)/libdw-$(PACKAGE_VERSION).so + rm -f $(DESTDIR)$(libdir)/libdw.so.$(VERSION) + rm -f $(DESTDIR)$(libdir)/libdw.so + rmdir --ignore-fail-on-non-empty $(DESTDIR)$(includedir)/elfutils +endif + +libdw_a_LIBADD = $(addprefix ../libdwfl/,$(shell $(AR) t ../libdwfl/libdwfl.a)) + +noinst_HEADERS = libdwP.h memory-access.h dwarf_abbrev_hash.h \ + dwarf_sig8_hash.h cfi.h encoded-value.h + +EXTRA_DIST = libdw.map + +MOSTLYCLEANFILES = $(am_libdw_pic_a_OBJECTS) libdw.so.$(VERSION) diff --git a/src/libdw/Makefile.in b/src/libdw/Makefile.in new file mode 100644 index 00000000..6cbfeaaf --- /dev/null +++ b/src/libdw/Makefile.in @@ -0,0 +1,858 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +DIST_COMMON = $(include_HEADERS) $(noinst_HEADERS) \ + $(pkginclude_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(top_srcdir)/config/eu.am ChangeLog +@MUDFLAP_TRUE@am__append_1 = -fmudflap +@BUILD_STATIC_TRUE@am__append_2 = -fpic +@MUDFLAP_FALSE@noinst_PROGRAMS = $(am__EXEEXT_1) +@MUDFLAP_TRUE@am_libdw_pic_a_OBJECTS = +subdir = libdw +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/zip.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)" \ + "$(DESTDIR)$(pkgincludedir)" +LIBRARIES = $(lib_LIBRARIES) $(noinst_LIBRARIES) +AR = ar +ARFLAGS = cru +libdw_a_AR = $(AR) $(ARFLAGS) +libdw_a_DEPENDENCIES = $(addprefix ../libdwfl/,$(shell $(AR) t \ + ../libdwfl/libdwfl.a)) +am_libdw_a_OBJECTS = dwarf_begin.$(OBJEXT) dwarf_begin_elf.$(OBJEXT) \ + dwarf_end.$(OBJEXT) dwarf_getelf.$(OBJEXT) \ + dwarf_getpubnames.$(OBJEXT) dwarf_getabbrev.$(OBJEXT) \ + dwarf_tag.$(OBJEXT) dwarf_error.$(OBJEXT) \ + dwarf_nextcu.$(OBJEXT) dwarf_diename.$(OBJEXT) \ + dwarf_offdie.$(OBJEXT) dwarf_attr.$(OBJEXT) \ + dwarf_formstring.$(OBJEXT) dwarf_abbrev_hash.$(OBJEXT) \ + dwarf_sig8_hash.$(OBJEXT) dwarf_attr_integrate.$(OBJEXT) \ + dwarf_hasattr_integrate.$(OBJEXT) dwarf_child.$(OBJEXT) \ + dwarf_haschildren.$(OBJEXT) dwarf_formaddr.$(OBJEXT) \ + dwarf_formudata.$(OBJEXT) dwarf_formsdata.$(OBJEXT) \ + dwarf_lowpc.$(OBJEXT) dwarf_entrypc.$(OBJEXT) \ + dwarf_haspc.$(OBJEXT) dwarf_highpc.$(OBJEXT) \ + dwarf_ranges.$(OBJEXT) dwarf_formref.$(OBJEXT) \ + dwarf_formref_die.$(OBJEXT) dwarf_siblingof.$(OBJEXT) \ + dwarf_dieoffset.$(OBJEXT) dwarf_cuoffset.$(OBJEXT) \ + dwarf_diecu.$(OBJEXT) dwarf_hasattr.$(OBJEXT) \ + dwarf_hasform.$(OBJEXT) dwarf_whatform.$(OBJEXT) \ + dwarf_whatattr.$(OBJEXT) dwarf_bytesize.$(OBJEXT) \ + dwarf_arrayorder.$(OBJEXT) dwarf_bitsize.$(OBJEXT) \ + dwarf_bitoffset.$(OBJEXT) dwarf_srclang.$(OBJEXT) \ + dwarf_getabbrevtag.$(OBJEXT) dwarf_getabbrevcode.$(OBJEXT) \ + dwarf_abbrevhaschildren.$(OBJEXT) dwarf_getattrcnt.$(OBJEXT) \ + dwarf_getabbrevattr.$(OBJEXT) dwarf_getsrclines.$(OBJEXT) \ + dwarf_getsrc_die.$(OBJEXT) dwarf_getscopes.$(OBJEXT) \ + dwarf_getscopes_die.$(OBJEXT) dwarf_getscopevar.$(OBJEXT) \ + dwarf_linesrc.$(OBJEXT) dwarf_lineno.$(OBJEXT) \ + dwarf_lineaddr.$(OBJEXT) dwarf_linecol.$(OBJEXT) \ + dwarf_linebeginstatement.$(OBJEXT) \ + dwarf_lineendsequence.$(OBJEXT) dwarf_lineblock.$(OBJEXT) \ + dwarf_lineprologueend.$(OBJEXT) \ + dwarf_lineepiloguebegin.$(OBJEXT) dwarf_lineisa.$(OBJEXT) \ + dwarf_linediscriminator.$(OBJEXT) dwarf_lineop_index.$(OBJEXT) \ + dwarf_onesrcline.$(OBJEXT) dwarf_formblock.$(OBJEXT) \ + dwarf_getsrcfiles.$(OBJEXT) dwarf_filesrc.$(OBJEXT) \ + dwarf_getsrcdirs.$(OBJEXT) dwarf_getlocation.$(OBJEXT) \ + dwarf_getstring.$(OBJEXT) dwarf_offabbrev.$(OBJEXT) \ + dwarf_getaranges.$(OBJEXT) dwarf_onearange.$(OBJEXT) \ + dwarf_getarangeinfo.$(OBJEXT) dwarf_getarange_addr.$(OBJEXT) \ + dwarf_getattrs.$(OBJEXT) dwarf_formflag.$(OBJEXT) \ + dwarf_getmacros.$(OBJEXT) dwarf_macro_opcode.$(OBJEXT) \ + dwarf_macro_param1.$(OBJEXT) dwarf_macro_param2.$(OBJEXT) \ + dwarf_addrdie.$(OBJEXT) dwarf_getfuncs.$(OBJEXT) \ + dwarf_decl_file.$(OBJEXT) dwarf_decl_line.$(OBJEXT) \ + dwarf_decl_column.$(OBJEXT) dwarf_func_inline.$(OBJEXT) \ + dwarf_getsrc_file.$(OBJEXT) libdw_findcu.$(OBJEXT) \ + libdw_form.$(OBJEXT) libdw_alloc.$(OBJEXT) \ + memory-access.$(OBJEXT) libdw_visit_scopes.$(OBJEXT) \ + dwarf_entry_breakpoints.$(OBJEXT) dwarf_next_cfi.$(OBJEXT) \ + cie.$(OBJEXT) fde.$(OBJEXT) cfi.$(OBJEXT) \ + frame-cache.$(OBJEXT) dwarf_frame_info.$(OBJEXT) \ + dwarf_frame_cfa.$(OBJEXT) dwarf_frame_register.$(OBJEXT) \ + dwarf_cfi_addrframe.$(OBJEXT) dwarf_getcfi.$(OBJEXT) \ + dwarf_getcfi_elf.$(OBJEXT) dwarf_cfi_end.$(OBJEXT) \ + dwarf_aggregate_size.$(OBJEXT) \ + dwarf_getlocation_implicit_pointer.$(OBJEXT) +libdw_a_OBJECTS = $(am_libdw_a_OBJECTS) +libdw_pic_a_AR = $(AR) $(ARFLAGS) +libdw_pic_a_LIBADD = +libdw_pic_a_OBJECTS = $(am_libdw_pic_a_OBJECTS) +@MUDFLAP_FALSE@am__EXEEXT_1 = libdw.so$(EXEEXT) +PROGRAMS = $(noinst_PROGRAMS) +am_libdw_so_OBJECTS = +libdw_so_OBJECTS = $(am_libdw_so_OBJECTS) +libdw_so_LDADD = $(LDADD) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/config/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +SOURCES = $(libdw_a_SOURCES) $(libdw_pic_a_SOURCES) \ + $(libdw_so_SOURCES) +DIST_SOURCES = $(libdw_a_SOURCES) $(libdw_pic_a_SOURCES) \ + $(libdw_so_SOURCES) +HEADERS = $(include_HEADERS) $(noinst_HEADERS) $(pkginclude_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEBUGPRED = @DEBUGPRED@ +DEFS = -D_GNU_SOURCE -DHAVE_CONFIG_H -DLOCALEDIR='"${localedir}"' \ + -DIS_LIBDW +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EXEEXT = @EXEEXT@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBEBL_SUBDIR = @LIBEBL_SUBDIR@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MODVERSION = @MODVERSION@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +VERSION = 1 +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +base_cpu = @base_cpu@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +eu_version = @eu_version@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +zip_LIBS = @zip_LIBS@ +INCLUDES = -I. -I$(srcdir) -I$(top_srcdir)/lib -I.. \ + -I$(srcdir)/../libelf +AM_CFLAGS = -std=gnu99 -Wall -Wshadow $(if \ + $($(*F)_no_Werror),,-Werror) $(if \ + $($(*F)_no_Wunused),,-Wunused -Wextra) $(if \ + $($(*F)_no_Wformat),-Wno-format,-Wformat=2) $($(*F)_CFLAGS) \ + $(am__append_1) $(am__append_2) +@MUDFLAP_FALSE@libmudflap = +@MUDFLAP_TRUE@libmudflap = -lmudflap +COMPILE.os = $(filter-out -fprofile-arcs -ftest-coverage $(no_mudflap.os),\ + $(COMPILE)) + +CLEANFILES = *.gcno *.gcda +textrel_check = if readelf -d $@ | fgrep -q TEXTREL; then exit 1; fi +lib_LIBRARIES = libdw.a +@MUDFLAP_FALSE@noinst_LIBRARIES = libdw_pic.a +include_HEADERS = dwarf.h +pkginclude_HEADERS = libdw.h +libdw_a_SOURCES = dwarf_begin.c dwarf_begin_elf.c dwarf_end.c dwarf_getelf.c \ + dwarf_getpubnames.c dwarf_getabbrev.c dwarf_tag.c \ + dwarf_error.c dwarf_nextcu.c dwarf_diename.c dwarf_offdie.c \ + dwarf_attr.c dwarf_formstring.c \ + dwarf_abbrev_hash.c dwarf_sig8_hash.c \ + dwarf_attr_integrate.c dwarf_hasattr_integrate.c \ + dwarf_child.c dwarf_haschildren.c dwarf_formaddr.c \ + dwarf_formudata.c dwarf_formsdata.c dwarf_lowpc.c \ + dwarf_entrypc.c dwarf_haspc.c dwarf_highpc.c dwarf_ranges.c \ + dwarf_formref.c dwarf_formref_die.c dwarf_siblingof.c \ + dwarf_dieoffset.c dwarf_cuoffset.c dwarf_diecu.c \ + dwarf_hasattr.c dwarf_hasform.c \ + dwarf_whatform.c dwarf_whatattr.c \ + dwarf_bytesize.c dwarf_arrayorder.c dwarf_bitsize.c \ + dwarf_bitoffset.c dwarf_srclang.c dwarf_getabbrevtag.c \ + dwarf_getabbrevcode.c dwarf_abbrevhaschildren.c \ + dwarf_getattrcnt.c dwarf_getabbrevattr.c \ + dwarf_getsrclines.c dwarf_getsrc_die.c \ + dwarf_getscopes.c dwarf_getscopes_die.c dwarf_getscopevar.c \ + dwarf_linesrc.c dwarf_lineno.c dwarf_lineaddr.c \ + dwarf_linecol.c dwarf_linebeginstatement.c \ + dwarf_lineendsequence.c dwarf_lineblock.c \ + dwarf_lineprologueend.c dwarf_lineepiloguebegin.c \ + dwarf_lineisa.c dwarf_linediscriminator.c \ + dwarf_lineop_index.c \ + dwarf_onesrcline.c dwarf_formblock.c \ + dwarf_getsrcfiles.c dwarf_filesrc.c dwarf_getsrcdirs.c \ + dwarf_getlocation.c dwarf_getstring.c dwarf_offabbrev.c \ + dwarf_getaranges.c dwarf_onearange.c dwarf_getarangeinfo.c \ + dwarf_getarange_addr.c dwarf_getattrs.c dwarf_formflag.c \ + dwarf_getmacros.c dwarf_macro_opcode.c dwarf_macro_param1.c \ + dwarf_macro_param2.c dwarf_addrdie.c \ + dwarf_getfuncs.c \ + dwarf_decl_file.c dwarf_decl_line.c dwarf_decl_column.c \ + dwarf_func_inline.c dwarf_getsrc_file.c \ + libdw_findcu.c libdw_form.c libdw_alloc.c memory-access.c \ + libdw_visit_scopes.c \ + dwarf_entry_breakpoints.c \ + dwarf_next_cfi.c \ + cie.c fde.c cfi.c frame-cache.c \ + dwarf_frame_info.c dwarf_frame_cfa.c dwarf_frame_register.c \ + dwarf_cfi_addrframe.c \ + dwarf_getcfi.c dwarf_getcfi_elf.c dwarf_cfi_end.c \ + dwarf_aggregate_size.c dwarf_getlocation_implicit_pointer.c + +@MAINTAINER_MODE_TRUE@BUILT_SOURCES = $(srcdir)/known-dwarf.h +@MAINTAINER_MODE_TRUE@MAINTAINERCLEANFILES = $(srcdir)/known-dwarf.h +@MUDFLAP_FALSE@libdw_pic_a_SOURCES = +@MUDFLAP_FALSE@am_libdw_pic_a_OBJECTS = $(libdw_a_SOURCES:.c=.os) +@MUDFLAP_FALSE@libdw_so_SOURCES = +libdw_a_LIBADD = $(addprefix ../libdwfl/,$(shell $(AR) t ../libdwfl/libdwfl.a)) +noinst_HEADERS = libdwP.h memory-access.h dwarf_abbrev_hash.h \ + dwarf_sig8_hash.h cfi.h encoded-value.h + +EXTRA_DIST = libdw.map +MOSTLYCLEANFILES = $(am_libdw_pic_a_OBJECTS) libdw.so.$(VERSION) +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/config/eu.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits libdw/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnits libdw/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-libLIBRARIES: $(lib_LIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" + @list='$(lib_LIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(INSTALL_DATA) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(INSTALL_DATA) $$list2 "$(DESTDIR)$(libdir)" || exit $$?; } + @$(POST_INSTALL) + @list='$(lib_LIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + if test -f $$p; then \ + $(am__strip_dir) \ + echo " ( cd '$(DESTDIR)$(libdir)' && $(RANLIB) $$f )"; \ + ( cd "$(DESTDIR)$(libdir)" && $(RANLIB) $$f ) || exit $$?; \ + else :; fi; \ + done + +uninstall-libLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LIBRARIES)'; test -n "$(libdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(libdir)' && rm -f "$$files" )"; \ + cd "$(DESTDIR)$(libdir)" && rm -f $$files + +clean-libLIBRARIES: + -test -z "$(lib_LIBRARIES)" || rm -f $(lib_LIBRARIES) + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libdw.a: $(libdw_a_OBJECTS) $(libdw_a_DEPENDENCIES) + -rm -f libdw.a + $(libdw_a_AR) libdw.a $(libdw_a_OBJECTS) $(libdw_a_LIBADD) + $(RANLIB) libdw.a +libdw_pic.a: $(libdw_pic_a_OBJECTS) $(libdw_pic_a_DEPENDENCIES) + -rm -f libdw_pic.a + $(libdw_pic_a_AR) libdw_pic.a $(libdw_pic_a_OBJECTS) $(libdw_pic_a_LIBADD) + $(RANLIB) libdw_pic.a + +clean-noinstPROGRAMS: + -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) +@MUDFLAP_TRUE@libdw.so$(EXEEXT): $(libdw_so_OBJECTS) $(libdw_so_DEPENDENCIES) +@MUDFLAP_TRUE@ @rm -f libdw.so$(EXEEXT) +@MUDFLAP_TRUE@ $(LINK) $(libdw_so_OBJECTS) $(libdw_so_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfi.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cie.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_abbrev_hash.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_abbrevhaschildren.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_addrdie.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_aggregate_size.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_arrayorder.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_attr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_attr_integrate.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_begin.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_begin_elf.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_bitoffset.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_bitsize.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_bytesize.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_cfi_addrframe.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_cfi_end.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_child.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_cuoffset.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_decl_column.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_decl_file.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_decl_line.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_diecu.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_diename.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_dieoffset.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_end.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_entry_breakpoints.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_entrypc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_error.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_filesrc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_formaddr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_formblock.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_formflag.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_formref.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_formref_die.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_formsdata.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_formstring.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_formudata.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_frame_cfa.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_frame_info.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_frame_register.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_func_inline.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_getabbrev.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_getabbrevattr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_getabbrevcode.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_getabbrevtag.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_getarange_addr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_getarangeinfo.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_getaranges.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_getattrcnt.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_getattrs.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_getcfi.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_getcfi_elf.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_getelf.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_getfuncs.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_getlocation.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_getlocation_implicit_pointer.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_getmacros.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_getpubnames.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_getscopes.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_getscopes_die.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_getscopevar.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_getsrc_die.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_getsrc_file.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_getsrcdirs.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_getsrcfiles.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_getsrclines.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_getstring.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_hasattr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_hasattr_integrate.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_haschildren.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_hasform.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_haspc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_highpc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_lineaddr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_linebeginstatement.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_lineblock.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_linecol.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_linediscriminator.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_lineendsequence.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_lineepiloguebegin.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_lineisa.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_lineno.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_lineop_index.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_lineprologueend.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_linesrc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_lowpc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_macro_opcode.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_macro_param1.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_macro_param2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_next_cfi.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_nextcu.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_offabbrev.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_offdie.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_onearange.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_onesrcline.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_ranges.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_siblingof.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_sig8_hash.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_srclang.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_tag.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_whatattr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf_whatform.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fde.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/frame-cache.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdw_alloc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdw_findcu.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdw_form.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdw_visit_scopes.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memory-access.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` +install-includeHEADERS: $(include_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)" + @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \ + done + +uninstall-includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(includedir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(includedir)" && rm -f $$files +install-pkgincludeHEADERS: $(pkginclude_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(pkgincludedir)" || $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)" + @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkgincludedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkgincludedir)" || exit $$?; \ + done + +uninstall-pkgincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(pkgincludedir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(pkgincludedir)" && rm -f $$files + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(LIBRARIES) $(PROGRAMS) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)" "$(DESTDIR)$(pkgincludedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +@MUDFLAP_TRUE@install: $(BUILT_SOURCES) +@MUDFLAP_TRUE@ $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +@MUDFLAP_TRUE@uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +clean: clean-am + +clean-am: clean-generic clean-libLIBRARIES clean-noinstLIBRARIES \ + clean-noinstPROGRAMS mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-includeHEADERS install-pkgincludeHEADERS + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-includeHEADERS uninstall-libLIBRARIES \ + uninstall-pkgincludeHEADERS + +.MAKE: all check install install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libLIBRARIES clean-noinstLIBRARIES clean-noinstPROGRAMS \ + ctags distclean distclean-compile distclean-generic \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-includeHEADERS install-info \ + install-info-am install-libLIBRARIES install-man install-pdf \ + install-pdf-am install-pkgincludeHEADERS install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \ + ps ps-am tags uninstall uninstall-am uninstall-includeHEADERS \ + uninstall-libLIBRARIES uninstall-pkgincludeHEADERS + + +%.os: %.c %.o +@AMDEP_TRUE@ if $(COMPILE.os) -c -o $@ -fpic -DPIC -DSHARED -MT $@ -MD -MP \ +@AMDEP_TRUE@ -MF "$(DEPDIR)/$*.Tpo" `test -f '$<' || echo '$(srcdir)/'`$<; \ +@AMDEP_TRUE@ then cat "$(DEPDIR)/$*.Tpo" >> "$(DEPDIR)/$*.Po"; \ +@AMDEP_TRUE@ rm -f "$(DEPDIR)/$*.Tpo"; \ +@AMDEP_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@AMDEP_TRUE@ fi +@AMDEP_FALSE@ $(COMPILE.os) -c -o $@ -fpic -DPIC -DSHARED $< +@MAINTAINER_MODE_TRUE@$(srcdir)/known-dwarf.h: $(top_srcdir)/config/known-dwarf.awk $(srcdir)/dwarf.h +@MAINTAINER_MODE_TRUE@ gawk -f $^ > $@.new +@MAINTAINER_MODE_TRUE@ mv -f $@.new $@ +@MUDFLAP_FALSE@libdw.so: $(srcdir)/libdw.map libdw_pic.a \ +@MUDFLAP_FALSE@ ../libdwfl/libdwfl_pic.a ../libebl/libebl.a \ +@MUDFLAP_FALSE@ ../libelf/libelf.so +# The rpath is necessary for libebl because its $ORIGIN use will +# not fly in a setuid executable that links in libdw. +@MUDFLAP_FALSE@ $(LINK) -shared -o $@ -Wl,--soname,$@.$(VERSION),-z,defs \ +@MUDFLAP_FALSE@ -Wl,--enable-new-dtags,-rpath,$(pkglibdir) \ +@MUDFLAP_FALSE@ -Wl,--version-script,$<,--no-undefined \ +@MUDFLAP_FALSE@ -Wl,--whole-archive $(filter-out $<,$^) -Wl,--no-whole-archive\ +@MUDFLAP_FALSE@ -ldl $(zip_LIBS) +@MUDFLAP_FALSE@ if readelf -d $@ | fgrep -q TEXTREL; then exit 1; fi +@MUDFLAP_FALSE@ ln -fs $@ $@.$(VERSION) + +@MUDFLAP_FALSE@install: install-am libdw.so +@MUDFLAP_FALSE@ $(mkinstalldirs) $(DESTDIR)$(libdir) +@MUDFLAP_FALSE@ $(INSTALL_PROGRAM) libdw.so $(DESTDIR)$(libdir)/libdw-$(PACKAGE_VERSION).so +@MUDFLAP_FALSE@ ln -fs libdw-$(PACKAGE_VERSION).so $(DESTDIR)$(libdir)/libdw.so.$(VERSION) +@MUDFLAP_FALSE@ ln -fs libdw.so.$(VERSION) $(DESTDIR)$(libdir)/libdw.so + +@MUDFLAP_FALSE@uninstall: uninstall-am +@MUDFLAP_FALSE@ rm -f $(DESTDIR)$(libdir)/libdw-$(PACKAGE_VERSION).so +@MUDFLAP_FALSE@ rm -f $(DESTDIR)$(libdir)/libdw.so.$(VERSION) +@MUDFLAP_FALSE@ rm -f $(DESTDIR)$(libdir)/libdw.so +@MUDFLAP_FALSE@ rmdir --ignore-fail-on-non-empty $(DESTDIR)$(includedir)/elfutils + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/libdw/cfi.c b/src/libdw/cfi.c new file mode 100644 index 00000000..aeb48e69 --- /dev/null +++ b/src/libdw/cfi.c @@ -0,0 +1,506 @@ +/* CFI program execution. + Copyright (C) 2009-2010 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <dwarf.h> +#include "../libebl/libebl.h" +#include "cfi.h" +#include "memory-access.h" +#include "encoded-value.h" +#include <assert.h> +#include <stdlib.h> +#include <string.h> + +#define CFI_PRIMARY_MAX 0x3f + +static Dwarf_Frame * +duplicate_frame_state (const Dwarf_Frame *original, + Dwarf_Frame *prev) +{ + size_t size = offsetof (Dwarf_Frame, regs[original->nregs]); + Dwarf_Frame *copy = malloc (size); + if (likely (copy != NULL)) + { + memcpy (copy, original, size); + copy->prev = prev; + } + return copy; +} + +/* Returns a DWARF_E_* error code, usually NOERROR or INVALID_CFI. + Frees *STATE on failure. */ +static int +execute_cfi (Dwarf_CFI *cache, + const struct dwarf_cie *cie, + Dwarf_Frame **state, + const uint8_t *program, const uint8_t *const end, bool abi_cfi, + Dwarf_Addr loc, Dwarf_Addr find_pc) +{ + /* The caller should not give us anything out of range. */ + assert (loc <= find_pc); + + int result = DWARF_E_NOERROR; + +#define cfi_assert(ok) do { \ + if (likely (ok)) break; \ + result = DWARF_E_INVALID_CFI; \ + goto out; \ + } while (0) + + Dwarf_Frame *fs = *state; + inline bool enough_registers (Dwarf_Word reg) + { + if (fs->nregs <= reg) + { + size_t size = offsetof (Dwarf_Frame, regs[reg + 1]); + Dwarf_Frame *bigger = realloc (fs, size); + if (unlikely (bigger == NULL)) + { + result = DWARF_E_NOMEM; + return false; + } + else + { + bigger->nregs = reg + 1; + fs = bigger; + } + } + return true; + } + + inline void require_cfa_offset (void) + { + if (unlikely (fs->cfa_rule != cfa_offset)) + fs->cfa_rule = cfa_invalid; + } + +#define register_rule(regno, r_rule, r_value) do { \ + if (unlikely (! enough_registers (regno))) \ + goto out; \ + fs->regs[regno].rule = reg_##r_rule; \ + fs->regs[regno].value = (r_value); \ + } while (0) + + while (program < end) + { + uint8_t opcode = *program++; + Dwarf_Word regno; + Dwarf_Word offset; + Dwarf_Word sf_offset; + Dwarf_Word operand = opcode & CFI_PRIMARY_MAX; + switch (opcode) + { + /* These cases move LOC, i.e. "create a new table row". */ + + case DW_CFA_advance_loc1: + operand = *program++; + case DW_CFA_advance_loc + 0 ... DW_CFA_advance_loc + CFI_PRIMARY_MAX: + advance_loc: + loc += operand * cie->code_alignment_factor; + break; + + case DW_CFA_advance_loc2: + operand = read_2ubyte_unaligned_inc (cache, program); + goto advance_loc; + case DW_CFA_advance_loc4: + operand = read_4ubyte_unaligned_inc (cache, program); + goto advance_loc; + case DW_CFA_MIPS_advance_loc8: + operand = read_8ubyte_unaligned_inc (cache, program); + goto advance_loc; + + case DW_CFA_set_loc: + if (likely (!read_encoded_value (cache, cie->fde_encoding, + &program, &loc))) + break; + result = INTUSE(dwarf_errno) (); + goto out; + + /* Now all following cases affect this row, but do not touch LOC. + These cases end with 'continue'. We only get out of the + switch block for the row-copying (LOC-moving) cases above. */ + + case DW_CFA_def_cfa: + get_uleb128 (operand, program); + get_uleb128 (offset, program); + def_cfa: + fs->cfa_rule = cfa_offset; + fs->cfa_val_reg = operand; + fs->cfa_val_offset = offset; + /* Prime the rest of the Dwarf_Op so dwarf_frame_cfa can use it. */ + fs->cfa_data.offset.atom = DW_OP_bregx; + fs->cfa_data.offset.offset = 0; + continue; + + case DW_CFA_def_cfa_register: + get_uleb128 (regno, program); + require_cfa_offset (); + fs->cfa_val_reg = regno; + continue; + + case DW_CFA_def_cfa_sf: + get_uleb128 (operand, program); + get_sleb128 (sf_offset, program); + offset = sf_offset * cie->data_alignment_factor; + goto def_cfa; + + case DW_CFA_def_cfa_offset: + get_uleb128 (offset, program); + def_cfa_offset: + require_cfa_offset (); + fs->cfa_val_offset = offset; + continue; + + case DW_CFA_def_cfa_offset_sf: + get_sleb128 (sf_offset, program); + offset = sf_offset * cie->data_alignment_factor; + goto def_cfa_offset; + + case DW_CFA_def_cfa_expression: + /* DW_FORM_block is a ULEB128 length followed by that many bytes. */ + get_uleb128 (operand, program); + cfi_assert (operand <= (Dwarf_Word) (end - program)); + fs->cfa_rule = cfa_expr; + fs->cfa_data.expr.data = (unsigned char *) program; + fs->cfa_data.expr.length = operand; + program += operand; + continue; + + case DW_CFA_undefined: + get_uleb128 (regno, program); + register_rule (regno, undefined, 0); + continue; + + case DW_CFA_same_value: + get_uleb128 (regno, program); + register_rule (regno, same_value, 0); + continue; + + case DW_CFA_offset_extended: + get_uleb128 (operand, program); + case DW_CFA_offset + 0 ... DW_CFA_offset + CFI_PRIMARY_MAX: + get_uleb128 (offset, program); + offset *= cie->data_alignment_factor; + offset_extended: + register_rule (operand, offset, offset); + continue; + + case DW_CFA_offset_extended_sf: + get_uleb128 (operand, program); + get_sleb128 (sf_offset, program); + offset_extended_sf: + offset = sf_offset * cie->data_alignment_factor; + goto offset_extended; + + case DW_CFA_GNU_negative_offset_extended: + /* GNU extension obsoleted by DW_CFA_offset_extended_sf. */ + get_uleb128 (operand, program); + get_uleb128 (offset, program); + sf_offset = -offset; + goto offset_extended_sf; + + case DW_CFA_val_offset: + get_uleb128 (operand, program); + get_uleb128 (offset, program); + offset *= cie->data_alignment_factor; + val_offset: + register_rule (operand, val_offset, offset); + continue; + + case DW_CFA_val_offset_sf: + get_uleb128 (operand, program); + get_sleb128 (sf_offset, program); + offset = sf_offset * cie->data_alignment_factor; + goto val_offset; + + case DW_CFA_register: + get_uleb128 (regno, program); + get_uleb128 (operand, program); + register_rule (regno, register, operand); + continue; + + case DW_CFA_expression: + get_uleb128 (regno, program); + offset = program - (const uint8_t *) cache->data->d.d_buf; + /* DW_FORM_block is a ULEB128 length followed by that many bytes. */ + get_uleb128 (operand, program); + cfi_assert (operand <= (Dwarf_Word) (end - program)); + program += operand; + register_rule (regno, expression, offset); + continue; + + case DW_CFA_val_expression: + get_uleb128 (regno, program); + /* DW_FORM_block is a ULEB128 length followed by that many bytes. */ + offset = program - (const uint8_t *) cache->data->d.d_buf; + get_uleb128 (operand, program); + cfi_assert (operand <= (Dwarf_Word) (end - program)); + program += operand; + register_rule (regno, val_expression, offset); + continue; + + case DW_CFA_restore_extended: + get_uleb128 (operand, program); + case DW_CFA_restore + 0 ... DW_CFA_restore + CFI_PRIMARY_MAX: + + if (unlikely (abi_cfi) && likely (opcode == DW_CFA_restore)) + { + /* Special case hack to give backend abi_cfi a shorthand. */ + cache->default_same_value = true; + continue; + } + + /* This can't be used in the CIE's own initial instructions. */ + cfi_assert (cie->initial_state != NULL); + + /* Restore the CIE's initial rule for this register. */ + if (unlikely (! enough_registers (operand))) + goto out; + if (cie->initial_state->nregs > operand) + fs->regs[operand] = cie->initial_state->regs[operand]; + else + fs->regs[operand].rule = reg_unspecified; + continue; + + case DW_CFA_remember_state: + { + /* Duplicate the state and chain the copy on. */ + Dwarf_Frame *copy = duplicate_frame_state (fs, fs); + if (unlikely (copy == NULL)) + { + result = DWARF_E_NOMEM; + goto out; + } + fs = copy; + continue; + } + + case DW_CFA_restore_state: + { + /* Pop the current state off and use the old one instead. */ + Dwarf_Frame *prev = fs->prev; + cfi_assert (prev != NULL); + free (fs); + fs = prev; + continue; + } + + case DW_CFA_nop: + continue; + + case DW_CFA_GNU_window_save: + /* This is magic shorthand used only by SPARC. It's equivalent + to a bunch of DW_CFA_register and DW_CFA_offset operations. */ + if (unlikely (! enough_registers (31))) + goto out; + for (regno = 8; regno < 16; ++regno) + { + /* Find each %oN in %iN. */ + fs->regs[regno].rule = reg_register; + fs->regs[regno].value = regno + 16; + } + unsigned int address_size = (cache->e_ident[EI_CLASS] == ELFCLASS32 + ? 4 : 8); + for (; regno < 32; ++regno) + { + /* Find %l0..%l7 and %i0..%i7 in a block at the CFA. */ + fs->regs[regno].rule = reg_offset; + fs->regs[regno].value = (regno - 16) * address_size; + } + continue; + + case DW_CFA_GNU_args_size: + /* XXX is this useful for anything? */ + get_uleb128 (operand, program); + continue; + + default: + cfi_assert (false); + continue; + } + + /* We get here only for the cases that have just moved LOC. */ + cfi_assert (cie->initial_state != NULL); + if (find_pc >= loc) + /* This advance has not yet reached FIND_PC. */ + fs->start = loc; + else + { + /* We have just advanced past the address we're looking for. + The state currently described is what we want to see. */ + fs->end = loc; + break; + } + } + + /* "The end of the instruction stream can be thought of as a + DW_CFA_set_loc (initial_location + address_range) instruction." + (DWARF 3.0 Section 6.4.3) + + When we fall off the end of the program without an advance_loc/set_loc + that put us past FIND_PC, the final state left by the FDE program + applies to this address (the caller ensured it was inside the FDE). + This address (FDE->end) is already in FS->end as set by the caller. */ + +#undef register_rule +#undef cfi_assert + + out: + + /* Pop any remembered states left on the stack. */ + while (fs->prev != NULL) + { + Dwarf_Frame *prev = fs->prev; + fs->prev = prev->prev; + free (prev); + } + + if (likely (result == DWARF_E_NOERROR)) + *state = fs; + else + free (fs); + + return result; +} + +static int +cie_cache_initial_state (Dwarf_CFI *cache, struct dwarf_cie *cie) +{ + int result = DWARF_E_NOERROR; + + if (likely (cie->initial_state != NULL)) + return result; + + /* This CIE has not been used before. Play out its initial + instructions and cache the initial state that results. + First we'll let the backend fill in the default initial + state for this machine's ABI. */ + + Dwarf_CIE abi_info = { DW_CIE_ID_64, NULL, NULL, 1, 1, -1, "", NULL, 0, 0 }; + + /* Make sure we have a backend handle cached. */ + if (unlikely (cache->ebl == NULL)) + { + cache->ebl = ebl_openbackend (cache->data->s->elf); + if (unlikely (cache->ebl == NULL)) + cache->ebl = (void *) -1l; + } + + /* Fetch the ABI's default CFI program. */ + if (likely (cache->ebl != (void *) -1l) + && unlikely (ebl_abi_cfi (cache->ebl, &abi_info) < 0)) + return DWARF_E_UNKNOWN_ERROR; + + Dwarf_Frame *cie_fs = calloc (1, sizeof (Dwarf_Frame)); + if (unlikely (cie_fs == NULL)) + return DWARF_E_NOMEM; + + /* If the default state of any register is not "undefined" + (i.e. call-clobbered), then the backend supplies instructions + for the standard initial state. */ + if (abi_info.initial_instructions_end > abi_info.initial_instructions) + { + /* Dummy CIE for backend's instructions. */ + struct dwarf_cie abi_cie = + { + .code_alignment_factor = abi_info.code_alignment_factor, + .data_alignment_factor = abi_info.data_alignment_factor, + }; + result = execute_cfi (cache, &abi_cie, &cie_fs, + abi_info.initial_instructions, + abi_info.initial_instructions_end, true, + 0, (Dwarf_Addr) -1l); + } + + /* Now run the CIE's initial instructions. */ + if (cie->initial_instructions_end > cie->initial_instructions + && likely (result == DWARF_E_NOERROR)) + result = execute_cfi (cache, cie, &cie_fs, + cie->initial_instructions, + cie->initial_instructions_end, false, + 0, (Dwarf_Addr) -1l); + + if (likely (result == DWARF_E_NOERROR)) + { + /* Now we have the initial state of things that all + FDEs using this CIE will start from. */ + cie_fs->cache = cache; + cie->initial_state = cie_fs; + } + + return result; +} + +int +internal_function +__libdw_frame_at_address (Dwarf_CFI *cache, struct dwarf_fde *fde, + Dwarf_Addr address, Dwarf_Frame **frame) +{ + int result = cie_cache_initial_state (cache, fde->cie); + if (likely (result == DWARF_E_NOERROR)) + { + Dwarf_Frame *fs = duplicate_frame_state (fde->cie->initial_state, NULL); + if (unlikely (fs == NULL)) + return DWARF_E_NOMEM; + + fs->fde = fde; + fs->start = fde->start; + fs->end = fde->end; + + result = execute_cfi (cache, fde->cie, &fs, + fde->instructions, fde->instructions_end, false, + fde->start, address); + if (likely (result == DWARF_E_NOERROR)) + *frame = fs; + } + return result; +} diff --git a/src/libdw/cfi.h b/src/libdw/cfi.h new file mode 100644 index 00000000..ef9cd7e1 --- /dev/null +++ b/src/libdw/cfi.h @@ -0,0 +1,256 @@ +/* Internal definitions for libdw CFI interpreter. + Copyright (C) 2009-2010 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifndef _UNWINDP_H +#define _UNWINDP_H 1 + +#include "libdwP.h" +#include "libelfP.h" +struct ebl; + +/* Cached CIE representation. */ +struct dwarf_cie +{ + Dwarf_Off offset; /* Our position, as seen in FDEs' CIE_pointer. */ + + Dwarf_Word code_alignment_factor; + Dwarf_Sword data_alignment_factor; + Dwarf_Word return_address_register; + + size_t fde_augmentation_data_size; + + // play out to initial state + const uint8_t *initial_instructions; + const uint8_t *initial_instructions_end; + + const Dwarf_Frame *initial_state; + + uint8_t fde_encoding; /* DW_EH_PE_* for addresses in FDEs. */ + uint8_t lsda_encoding; /* DW_EH_PE_* for LSDA in FDE augmentation. */ + + bool sized_augmentation_data; /* Saw 'z': FDEs have self-sized data. */ + bool signal_frame; /* Saw 'S': FDE is for a signal frame. */ +}; + +/* Cached FDE representation. */ +struct dwarf_fde +{ + struct dwarf_cie *cie; + + /* This FDE describes PC values in [start, end). */ + Dwarf_Addr start; + Dwarf_Addr end; + + const uint8_t *instructions; + const uint8_t *instructions_end; +}; + +/* This holds everything we cache about the CFI from each ELF file's + .debug_frame or .eh_frame section. */ +struct Dwarf_CFI_s +{ + /* Dwarf handle we came from. If null, this is .eh_frame data. */ + Dwarf *dbg; +#define CFI_IS_EH(cfi) ((cfi)->dbg == NULL) + + /* Data of the .debug_frame or .eh_frame section. */ + Elf_Data_Scn *data; + const unsigned char *e_ident; /* For EI_DATA and EI_CLASS. */ + + Dwarf_Addr frame_vaddr; /* DW_EH_PE_pcrel, address of frame section. */ + Dwarf_Addr textrel; /* DW_EH_PE_textrel base address. */ + Dwarf_Addr datarel; /* DW_EH_PE_datarel base address. */ + + /* Location of next unread entry in the section. */ + Dwarf_Off next_offset; + + /* Search tree for the CIEs, indexed by CIE_pointer (section offset). */ + void *cie_tree; + + /* Search tree for the FDEs, indexed by PC address. */ + void *fde_tree; + + /* Search tree for parsed DWARF expressions, indexed by raw pointer. */ + void *expr_tree; + + /* Backend hook. */ + struct ebl *ebl; + + /* Binary search table in .eh_frame_hdr section. */ + const uint8_t *search_table; + Dwarf_Addr search_table_vaddr; + size_t search_table_entries; + uint8_t search_table_encoding; + + /* True if the file has a byte order different from the host. */ + bool other_byte_order; + + /* Default rule for registers not previously mentioned + is same_value, not undefined. */ + bool default_same_value; +}; + + +enum dwarf_frame_rule + { + reg_unspecified, /* Uninitialized state. */ + reg_undefined, /* DW_CFA_undefined */ + reg_same_value, /* DW_CFA_same_value */ + reg_offset, /* DW_CFA_offset_extended et al */ + reg_val_offset, /* DW_CFA_val_offset et al */ + reg_register, /* DW_CFA_register */ + reg_expression, /* DW_CFA_expression */ + reg_val_expression, /* DW_CFA_val_expression */ + }; + +/* This describes what we know about an individual register. */ +struct dwarf_frame_register +{ + enum dwarf_frame_rule rule:3; + + /* The meaning of the value bits depends on the rule: + + Rule Value + ---- ----- + undefined unused + same_value unused + offset(N) N (register saved at CFA + value) + val_offset(N) N (register = CFA + value) + register(R) R (register = register #value) + expression(E) section offset of DW_FORM_block containing E + (register saved at address E computes) + val_expression(E) section offset of DW_FORM_block containing E + (register = value E computes) + */ + Dwarf_Sword value:(sizeof (Dwarf_Sword) * 8 - 3); +}; + +/* This holds everything we know about the state of the frame + at a particular PC location described by an FDE. */ +struct Dwarf_Frame_s +{ + /* This frame description covers PC values in [start, end). */ + Dwarf_Addr start; + Dwarf_Addr end; + + Dwarf_CFI *cache; + + /* Previous state saved by DW_CFA_remember_state, or .cie->initial_state, + or NULL in an initial_state pseudo-frame. */ + Dwarf_Frame *prev; + + /* The FDE that generated this frame state. This points to its CIE, + which has the return_address_register and signal_frame flag. */ + struct dwarf_fde *fde; + + /* The CFA is unknown, is R+N, or is computed by a DWARF expression. + A bogon in the CFI can indicate an invalid/incalculable rule. + We store that as cfa_invalid rather than barfing when processing it, + so callers can ignore the bogon unless they really need that CFA. */ + enum { cfa_undefined, cfa_offset, cfa_expr, cfa_invalid } cfa_rule; + union + { + Dwarf_Op offset; + Dwarf_Block expr; + } cfa_data; + /* We store an offset rule as a DW_OP_bregx operation. */ +#define cfa_val_reg cfa_data.offset.number +#define cfa_val_offset cfa_data.offset.number2 + + size_t nregs; + struct dwarf_frame_register regs[]; +}; + + +/* Clean up the data structure and all it points to. */ +extern void __libdw_destroy_frame_cache (Dwarf_CFI *cache) + __nonnull_attribute__ (1) internal_function; + +/* Enter a CIE encountered while reading through for FDEs. */ +extern void __libdw_intern_cie (Dwarf_CFI *cache, Dwarf_Off offset, + const Dwarf_CIE *info) + __nonnull_attribute__ (1, 3) internal_function; + +/* Look up a CIE_pointer for random access. */ +extern struct dwarf_cie *__libdw_find_cie (Dwarf_CFI *cache, Dwarf_Off offset) + __nonnull_attribute__ (1) internal_function; + + +/* Look for an FDE covering the given PC address. */ +extern struct dwarf_fde *__libdw_find_fde (Dwarf_CFI *cache, + Dwarf_Addr address) + __nonnull_attribute__ (1) internal_function; + +/* Look for an FDE by its offset in the section. */ +extern struct dwarf_fde *__libdw_fde_by_offset (Dwarf_CFI *cache, + Dwarf_Off offset) + __nonnull_attribute__ (1) internal_function; + +/* Process the FDE that contains the given PC address, + to yield the frame state when stopped there. + The return value is a DWARF_E_* error code. */ +extern int __libdw_frame_at_address (Dwarf_CFI *cache, struct dwarf_fde *fde, + Dwarf_Addr address, Dwarf_Frame **frame) + __nonnull_attribute__ (1, 2, 4) internal_function; + + +/* Dummy struct for memory-access.h macros. */ +#define BYTE_ORDER_DUMMY(var, e_ident) \ + const struct { bool other_byte_order; } var = \ + { ((BYTE_ORDER == LITTLE_ENDIAN && e_ident[EI_DATA] == ELFDATA2MSB) \ + || (BYTE_ORDER == BIG_ENDIAN && e_ident[EI_DATA] == ELFDATA2LSB)) } + + +INTDECL (dwarf_next_cfi) +INTDECL (dwarf_getcfi) +INTDECL (dwarf_getcfi_elf) +INTDECL (dwarf_cfi_end) +INTDECL (dwarf_cfi_addrframe) + +#endif /* unwindP.h */ diff --git a/src/libdw/cie.c b/src/libdw/cie.c new file mode 100644 index 00000000..7c93f551 --- /dev/null +++ b/src/libdw/cie.c @@ -0,0 +1,217 @@ +/* CIE reading. + Copyright (C) 2009-2010 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "cfi.h" +#include "encoded-value.h" +#include <assert.h> +#include <search.h> +#include <stdlib.h> + + +static int +compare_cie (const void *a, const void *b) +{ + const struct dwarf_cie *cie1 = a; + const struct dwarf_cie *cie2 = b; + if (cie1->offset < cie2->offset) + return -1; + if (cie1->offset > cie2->offset) + return 1; + return 0; +} + +/* There is no CIE at OFFSET in the tree. Add it. */ +static struct dwarf_cie * +intern_new_cie (Dwarf_CFI *cache, Dwarf_Off offset, const Dwarf_CIE *info) +{ + struct dwarf_cie *cie = malloc (sizeof (struct dwarf_cie)); + if (cie == NULL) + { + __libdw_seterrno (DWARF_E_NOMEM); + return NULL; + } + + cie->offset = offset; + cie->code_alignment_factor = info->code_alignment_factor; + cie->data_alignment_factor = info->data_alignment_factor; + cie->return_address_register = info->return_address_register; + + cie->fde_augmentation_data_size = 0; + cie->sized_augmentation_data = false; + cie->signal_frame = false; + + cie->fde_encoding = DW_EH_PE_absptr; + cie->lsda_encoding = DW_EH_PE_omit; + + /* Grok the augmentation string and its data. */ + const uint8_t *data = info->augmentation_data; + for (const char *ap = info->augmentation; *ap != '\0'; ++ap) + { + uint8_t encoding; + switch (*ap) + { + case 'z': + cie->sized_augmentation_data = true; + continue; + + case 'S': + cie->signal_frame = true; + continue; + + case 'L': /* LSDA pointer encoding byte. */ + cie->lsda_encoding = *data++; + if (!cie->sized_augmentation_data) + cie->fde_augmentation_data_size + += encoded_value_size (&cache->data->d, cache->e_ident, + cie->lsda_encoding, NULL); + continue; + + case 'R': /* FDE address encoding byte. */ + cie->fde_encoding = *data++; + continue; + + case 'P': /* Skip personality routine. */ + encoding = *data++; + data += encoded_value_size (&cache->data->d, cache->e_ident, + encoding, data); + continue; + + default: + /* Unknown augmentation string. If we have 'z' we can ignore it, + otherwise we must bail out. */ + if (cie->sized_augmentation_data) + continue; + } + /* We only get here when we need to bail out. */ + break; + } + + if ((cie->fde_encoding & 0x0f) == DW_EH_PE_absptr) + { + /* Canonicalize encoding to a specific size. */ + assert (DW_EH_PE_absptr == 0); + + /* XXX should get from dwarf_next_cfi with v4 header. */ + uint_fast8_t address_size + = cache->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8; + switch (address_size) + { + case 8: + cie->fde_encoding |= DW_EH_PE_udata8; + break; + case 4: + cie->fde_encoding |= DW_EH_PE_udata4; + break; + default: + free (cie); + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return NULL; + } + } + + /* Save the initial instructions to be played out into initial state. */ + cie->initial_instructions = info->initial_instructions; + cie->initial_instructions_end = info->initial_instructions_end; + cie->initial_state = NULL; + + /* Add the new entry to the search tree. */ + if (tsearch (cie, &cache->cie_tree, &compare_cie) == NULL) + { + free (cie); + __libdw_seterrno (DWARF_E_NOMEM); + return NULL; + } + + return cie; +} + +/* Look up a CIE_pointer for random access. */ +struct dwarf_cie * +internal_function +__libdw_find_cie (Dwarf_CFI *cache, Dwarf_Off offset) +{ + const struct dwarf_cie cie_key = { .offset = offset }; + struct dwarf_cie **found = tfind (&cie_key, &cache->cie_tree, &compare_cie); + if (found != NULL) + return *found; + + /* We have not read this CIE yet. Go find it. */ + Dwarf_Off next_offset = offset; + Dwarf_CFI_Entry entry; + int result = INTUSE(dwarf_next_cfi) (cache->e_ident, + &cache->data->d, CFI_IS_EH (cache), + offset, &next_offset, &entry); + if (result != 0 || entry.cie.CIE_id != DW_CIE_ID_64) + { + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return NULL; + } + + /* If this happened to be what we would have read next, notice it. */ + if (cache->next_offset == offset) + cache->next_offset = next_offset; + + return intern_new_cie (cache, offset, &entry.cie); +} + +/* Enter a CIE encountered while reading through for FDEs. */ +void +internal_function +__libdw_intern_cie (Dwarf_CFI *cache, Dwarf_Off offset, const Dwarf_CIE *info) +{ + const struct dwarf_cie cie_key = { .offset = offset }; + struct dwarf_cie **found = tfind (&cie_key, &cache->cie_tree, &compare_cie); + if (found == NULL) + /* We have not read this CIE yet. Enter it. */ + (void) intern_new_cie (cache, offset, info); +} diff --git a/src/libdw/dwarf.h b/src/libdw/dwarf.h new file mode 100644 index 00000000..e6a83670 --- /dev/null +++ b/src/libdw/dwarf.h @@ -0,0 +1,790 @@ +/* This file defines standard DWARF types, structures, and macros. + Copyright (C) 2000-2011 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#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_parameter = 0x2f, + DW_TAG_template_value_parameter = 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_dwarf_procedure = 0x36, + DW_TAG_restrict_type = 0x37, + DW_TAG_interface_type = 0x38, + DW_TAG_namespace = 0x39, + DW_TAG_imported_module = 0x3a, + DW_TAG_unspecified_type = 0x3b, + DW_TAG_partial_unit = 0x3c, + DW_TAG_imported_unit = 0x3d, + DW_TAG_mutable_type = 0x3e, + DW_TAG_condition = 0x3f, + DW_TAG_shared_type = 0x40, + DW_TAG_type_unit = 0x41, + DW_TAG_rvalue_reference_type = 0x42, + DW_TAG_template_alias = 0x43, + + 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_GNU_BINCL = 0x4104, + DW_TAG_GNU_EINCL = 0x4105, + + DW_TAG_GNU_template_template_param = 0x4106, + DW_TAG_GNU_template_parameter_pack = 0x4107, + DW_TAG_GNU_formal_parameter_pack = 0x4108, + DW_TAG_GNU_call_site = 0x4109, + DW_TAG_GNU_call_site_parameter = 0x410a, + + 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_bit_stride = 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_item = 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_allocated = 0x4e, + DW_AT_associated = 0x4f, + DW_AT_data_location = 0x50, + DW_AT_byte_stride = 0x51, + DW_AT_entry_pc = 0x52, + DW_AT_use_UTF8 = 0x53, + DW_AT_extension = 0x54, + DW_AT_ranges = 0x55, + DW_AT_trampoline = 0x56, + DW_AT_call_column = 0x57, + DW_AT_call_file = 0x58, + DW_AT_call_line = 0x59, + DW_AT_description = 0x5a, + DW_AT_binary_scale = 0x5b, + DW_AT_decimal_scale = 0x5c, + DW_AT_small = 0x5d, + DW_AT_decimal_sign = 0x5e, + DW_AT_digit_count = 0x5f, + DW_AT_picture_string = 0x60, + DW_AT_mutable = 0x61, + DW_AT_threads_scaled = 0x62, + DW_AT_explicit = 0x63, + DW_AT_object_pointer = 0x64, + DW_AT_endianity = 0x65, + DW_AT_elemental = 0x66, + DW_AT_pure = 0x67, + DW_AT_recursive = 0x68, + DW_AT_signature = 0x69, + DW_AT_main_subprogram = 0x6a, + DW_AT_data_bit_offset = 0x6b, + DW_AT_const_expr = 0x6c, + DW_AT_enum_class = 0x6d, + DW_AT_linkage_name = 0x6e, + + 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, + + /* GNU extensions. */ + 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_GNU_vector = 0x2107, + DW_AT_GNU_guarded_by = 0x2108, + DW_AT_GNU_pt_guarded_by = 0x2109, + DW_AT_GNU_guarded = 0x210a, + DW_AT_GNU_pt_guarded = 0x210b, + DW_AT_GNU_locks_excluded = 0x210c, + DW_AT_GNU_exclusive_locks_required = 0x210d, + DW_AT_GNU_shared_locks_required = 0x210e, + DW_AT_GNU_odr_signature = 0x210f, + DW_AT_GNU_template_name = 0x2110, + DW_AT_GNU_call_site_value = 0x2111, + DW_AT_GNU_call_site_data_value = 0x2112, + DW_AT_GNU_call_site_target = 0x2113, + DW_AT_GNU_call_site_target_clobbered = 0x2114, + DW_AT_GNU_tail_call = 0x2115, + DW_AT_GNU_all_tail_call_sites = 0x2116, + DW_AT_GNU_all_call_sites = 0x2117, + DW_AT_GNU_all_source_call_sites = 0x2118, + + 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, + DW_FORM_sec_offset = 0x17, + DW_FORM_exprloc = 0x18, + DW_FORM_flag_present = 0x19, + DW_FORM_ref_sig8 = 0x20 + }; + + +/* 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 offset. */ + 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_form_tls_address = 0x9b,/* TLS offset to address in current thread */ + DW_OP_call_frame_cfa = 0x9c,/* CFA as determined by CFI. */ + DW_OP_bit_piece = 0x9d, /* ULEB128 size and ULEB128 offset in bits. */ + DW_OP_implicit_value = 0x9e, /* DW_FORM_block follows opcode. */ + DW_OP_stack_value = 0x9f, /* No operands, special like DW_OP_piece. */ + + /* GNU extensions. */ + DW_OP_GNU_push_tls_address = 0xe0, + DW_OP_GNU_uninit = 0xf0, + DW_OP_GNU_encoded_addr = 0xf1, + DW_OP_GNU_implicit_pointer = 0xf2, + DW_OP_GNU_entry_value = 0xf3, + DW_OP_GNU_const_type = 0xf4, + DW_OP_GNU_regval_type = 0xf5, + DW_OP_GNU_deref_type = 0xf6, + DW_OP_GNU_convert = 0xf7, + DW_OP_GNU_reinterpret = 0xf9, + + 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_imaginary_float = 0x9, + DW_ATE_packed_decimal = 0xa, + DW_ATE_numeric_string = 0xb, + DW_ATE_edited = 0xc, + DW_ATE_signed_fixed = 0xd, + DW_ATE_unsigned_fixed = 0xe, + DW_ATE_decimal_float = 0xf, + + DW_ATE_lo_user = 0x80, + DW_ATE_hi_user = 0xff + }; + + +/* DWARF decimal sign encodings. */ +enum + { + DW_DS_unsigned = 1, + DW_DS_leading_overpunch = 2, + DW_DS_trailing_overpunch = 3, + DW_DS_leading_separate = 4, + DW_DS_trailing_separate = 5, + }; + + +/* DWARF endianity encodings. */ +enum + { + DW_END_default = 0, + DW_END_big = 1, + DW_END_little = 2, + + DW_END_lo_user = 0x40, + DW_END_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, /* ISO C:1989 */ + DW_LANG_C = 0x0002, /* C */ + DW_LANG_Ada83 = 0x0003, /* ISO Ada:1983 */ + DW_LANG_C_plus_plus = 0x0004, /* ISO C++:1998 */ + DW_LANG_Cobol74 = 0x0005, /* ISO Cobol:1974 */ + DW_LANG_Cobol85 = 0x0006, /* ISO Cobol:1985 */ + DW_LANG_Fortran77 = 0x0007, /* ISO FORTRAN 77 */ + DW_LANG_Fortran90 = 0x0008, /* ISO Fortran 90 */ + DW_LANG_Pascal83 = 0x0009, /* ISO Pascal:1983 */ + DW_LANG_Modula2 = 0x000a, /* ISO Modula-2:1996 */ + DW_LANG_Java = 0x000b, /* Java */ + DW_LANG_C99 = 0x000c, /* ISO C:1999 */ + DW_LANG_Ada95 = 0x000d, /* ISO Ada:1995 */ + DW_LANG_Fortran95 = 0x000e, /* ISO Fortran 95 */ + DW_LANG_PL1 = 0x000f, /* ISO PL/1:1976 */ + DW_LANG_Objc = 0x0010, /* Objective-C */ + DW_LANG_ObjC_plus_plus = 0x0011, /* Objective-C++ */ + DW_LANG_UPC = 0x0012, /* Unified Parallel C */ + DW_LANG_D = 0x0013, /* D */ + DW_LANG_Python = 0x0014, /* Python */ + DW_LANG_Go = 0x0016, /* Google's Go (provisionally in DWARF5) */ + + 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_epilogue_begin = 11, + DW_LNS_set_isa = 12 + }; + + +/* DWARF extended opcode encodings. */ +enum + { + DW_LNE_end_sequence = 1, + DW_LNE_set_address = 2, + DW_LNE_define_file = 3, + DW_LNE_set_discriminator = 4, + + DW_LNE_lo_user = 128, + DW_LNE_hi_user = 255 + }; + + +/* 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_def_cfa_expression = 0x0f, + DW_CFA_expression = 0x10, + DW_CFA_offset_extended_sf = 0x11, + DW_CFA_def_cfa_sf = 0x12, + DW_CFA_def_cfa_offset_sf = 0x13, + DW_CFA_val_offset = 0x14, + DW_CFA_val_offset_sf = 0x15, + DW_CFA_val_expression = 0x16, + + 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_GNU_negative_offset_extended = 0x2f, + DW_CFA_high_user = 0x3f + }; + +/* ID indicating CIE as opposed to FDE in .debug_frame. */ +enum + { + DW_CIE_ID_32 = 0xffffffffU, /* In 32-bit format CIE header. */ + DW_CIE_ID_64 = 0xffffffffffffffffULL /* In 64-bit format CIE header. */ + }; + + +/* Information for GNU unwind information. */ +enum + { + DW_EH_PE_absptr = 0x00, + DW_EH_PE_omit = 0xff, + + /* FDE data encoding. */ + DW_EH_PE_uleb128 = 0x01, + DW_EH_PE_udata2 = 0x02, + DW_EH_PE_udata4 = 0x03, + DW_EH_PE_udata8 = 0x04, + DW_EH_PE_sleb128 = 0x09, + DW_EH_PE_sdata2 = 0x0a, + DW_EH_PE_sdata4 = 0x0b, + DW_EH_PE_sdata8 = 0x0c, + DW_EH_PE_signed = 0x08, + + /* FDE flags. */ + DW_EH_PE_pcrel = 0x10, + DW_EH_PE_textrel = 0x20, + DW_EH_PE_datarel = 0x30, + DW_EH_PE_funcrel = 0x40, + DW_EH_PE_aligned = 0x50, + + DW_EH_PE_indirect = 0x80 + }; + + +/* DWARF XXX. */ +#define DW_ADDR_none 0 + +/* Section 7.2.2 of the DWARF3 specification defines a range of escape + codes that can appear in the length field of certain DWARF structures. + + These defines enumerate the minium and maximum values of this range. + Currently only the maximum value is used (to indicate that 64-bit + values are going to be used in the dwarf data that accompanies the + structure). The other values are reserved. + + Note: There is a typo in DWARF3 spec (published Dec 20, 2005). In + sections 7.4, 7.5.1, 7.19, 7.20 the minimum escape code is referred to + as 0xffffff00 whereas in fact it should be 0xfffffff0. */ +#define DWARF3_LENGTH_MIN_ESCAPE_CODE 0xfffffff0u +#define DWARF3_LENGTH_MAX_ESCAPE_CODE 0xffffffffu +#define DWARF3_LENGTH_64_BIT DWARF3_LENGTH_MAX_ESCAPE_CODE + +#endif /* dwarf.h */ diff --git a/src/libdw/dwarf_abbrev_hash.c b/src/libdw/dwarf_abbrev_hash.c new file mode 100644 index 00000000..bec1ceb2 --- /dev/null +++ b/src/libdw/dwarf_abbrev_hash.c @@ -0,0 +1,66 @@ +/* Implementation of hash table for DWARF .debug_abbrev section content. + Copyright (C) 2000-2010 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2000. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "dwarf_sig8_hash.h" +#define NO_UNDEF +#include "libdwP.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/src/libdw/dwarf_abbrev_hash.h b/src/libdw/dwarf_abbrev_hash.h new file mode 100644 index 00000000..f124d166 --- /dev/null +++ b/src/libdw/dwarf_abbrev_hash.h @@ -0,0 +1,60 @@ +/* Hash table for DWARF .debug_abbrev section content. + Copyright (C) 2000, 2001, 2002 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2000. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#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/src/libdw/dwarf_abbrevhaschildren.c b/src/libdw/dwarf_abbrevhaschildren.c new file mode 100644 index 00000000..4e42a32b --- /dev/null +++ b/src/libdw/dwarf_abbrevhaschildren.c @@ -0,0 +1,65 @@ +/* Return true if abbreviation is children flag set. + Copyright (C) 2003 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2003. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <assert.h> +#include <dwarf.h> +#include "libdwP.h" + + +int +dwarf_abbrevhaschildren (abbrev) + Dwarf_Abbrev *abbrev; +{ + return abbrev == NULL ? -1 : abbrev->has_children; +} diff --git a/src/libdw/dwarf_addrdie.c b/src/libdw/dwarf_addrdie.c new file mode 100644 index 00000000..84618721 --- /dev/null +++ b/src/libdw/dwarf_addrdie.c @@ -0,0 +1,75 @@ +/* Return CU DIE containing given address. + Copyright (C) 2005 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2005. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "libdwP.h" + + +Dwarf_Die * +dwarf_addrdie (dbg, addr, result) + Dwarf *dbg; + Dwarf_Addr addr; + Dwarf_Die *result; +{ + Dwarf_Aranges *aranges; + size_t naranges; + Dwarf_Off off; + + if (INTUSE(dwarf_getaranges) (dbg, &aranges, &naranges) != 0 + || INTUSE(dwarf_getarangeinfo) (INTUSE(dwarf_getarange_addr) (aranges, + addr), + NULL, NULL, &off) != 0) + return NULL; + + return INTUSE(dwarf_offdie) (dbg, off, result); +} diff --git a/src/libdw/dwarf_aggregate_size.c b/src/libdw/dwarf_aggregate_size.c new file mode 100644 index 00000000..e7420141 --- /dev/null +++ b/src/libdw/dwarf_aggregate_size.c @@ -0,0 +1,243 @@ +/* Compute size of an aggregate type from DWARF. + Copyright (C) 2010 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <dwarf.h> +#include "libdwP.h" + + +static Dwarf_Die * +get_type (Dwarf_Die *die, Dwarf_Attribute *attr_mem, Dwarf_Die *type_mem) +{ + return INTUSE(dwarf_formref_die) + (INTUSE(dwarf_attr_integrate) (die, DW_AT_type, attr_mem), type_mem); +} + +static int +array_size (Dwarf_Die *die, Dwarf_Word *size, + Dwarf_Attribute *attr_mem, Dwarf_Die *type_mem) +{ + Dwarf_Word eltsize; + if (INTUSE(dwarf_aggregate_size) (get_type (die, attr_mem, type_mem), + &eltsize) != 0) + return -1; + + /* An array can have DW_TAG_subrange_type or DW_TAG_enumeration_type + children instead that give the size of each dimension. */ + + Dwarf_Die child; + if (INTUSE(dwarf_child) (die, &child) != 0) + return -1; + + bool any = false; + Dwarf_Word total = 0; + do + { + Dwarf_Word count; + switch (INTUSE(dwarf_tag) (&child)) + { + case DW_TAG_subrange_type: + /* This has either DW_AT_count or DW_AT_upper_bound. */ + if (INTUSE(dwarf_attr_integrate) (&child, DW_AT_count, + attr_mem) != NULL) + { + if (INTUSE(dwarf_formudata) (attr_mem, &count) != 0) + return -1; + } + else + { + Dwarf_Sword upper; + Dwarf_Sword lower; + if (INTUSE(dwarf_formsdata) (INTUSE(dwarf_attr_integrate) + (&child, DW_AT_upper_bound, + attr_mem), &upper) != 0) + return -1; + + /* Having DW_AT_lower_bound is optional. */ + if (INTUSE(dwarf_attr_integrate) (&child, DW_AT_lower_bound, + attr_mem) != NULL) + { + if (INTUSE(dwarf_formsdata) (attr_mem, &lower) != 0) + return -1; + } + else + { + /* Determine default lower bound from language, + as per "4.12 Subrange Type Entries". */ + Dwarf_Die cu = CUDIE (die->cu); + switch (INTUSE(dwarf_srclang) (&cu)) + { + case DW_LANG_C: + case DW_LANG_C89: + case DW_LANG_C99: + case DW_LANG_C_plus_plus: + case DW_LANG_Objc: + case DW_LANG_ObjC_plus_plus: + case DW_LANG_Java: + case DW_LANG_D: + case DW_LANG_UPC: + lower = 0; + break; + + case DW_LANG_Ada83: + case DW_LANG_Ada95: + case DW_LANG_Cobol74: + case DW_LANG_Cobol85: + case DW_LANG_Fortran77: + case DW_LANG_Fortran90: + case DW_LANG_Fortran95: + case DW_LANG_Pascal83: + case DW_LANG_Modula2: + case DW_LANG_PL1: + lower = 1; + break; + + default: + return -1; + } + } + if (unlikely (lower > upper)) + return -1; + count = upper - lower + 1; + } + break; + + case DW_TAG_enumeration_type: + /* We have to find the DW_TAG_enumerator child with the + highest value to know the array's element count. */ + count = 0; + Dwarf_Die enum_child; + int has_children = INTUSE(dwarf_child) (die, &enum_child); + if (has_children < 0) + return -1; + if (has_children > 0) + do + if (INTUSE(dwarf_tag) (&enum_child) == DW_TAG_enumerator) + { + Dwarf_Word value; + if (INTUSE(dwarf_formudata) (INTUSE(dwarf_attr_integrate) + (&enum_child, DW_AT_const_value, + attr_mem), &value) != 0) + return -1; + if (value >= count) + count = value + 1; + } + while (INTUSE(dwarf_siblingof) (&enum_child, &enum_child) > 0); + break; + + default: + continue; + } + + /* This is a subrange_type or enumeration_type and we've set COUNT. + Now determine the stride for this array dimension. */ + Dwarf_Word stride = eltsize; + if (INTUSE(dwarf_attr_integrate) (&child, DW_AT_byte_stride, + attr_mem) != NULL) + { + if (INTUSE(dwarf_formudata) (attr_mem, &stride) != 0) + return -1; + } + else if (INTUSE(dwarf_attr_integrate) (&child, DW_AT_bit_stride, + attr_mem) != NULL) + { + if (INTUSE(dwarf_formudata) (attr_mem, &stride) != 0) + return -1; + if (stride % 8) /* XXX maybe compute in bits? */ + return -1; + stride /= 8; + } + + any = true; + total += stride * count; + } + while (INTUSE(dwarf_siblingof) (&child, &child) == 0); + + if (!any) + return -1; + + *size = total; + return 0; +} + +static int +aggregate_size (Dwarf_Die *die, Dwarf_Word *size, Dwarf_Die *type_mem) +{ + Dwarf_Attribute attr_mem; + + if (INTUSE(dwarf_attr_integrate) (die, DW_AT_byte_size, &attr_mem) != NULL) + return INTUSE(dwarf_formudata) (&attr_mem, size); + + switch (INTUSE(dwarf_tag) (die)) + { + case DW_TAG_typedef: + case DW_TAG_subrange_type: + return aggregate_size (get_type (die, &attr_mem, type_mem), + size, type_mem); /* Tail call. */ + + case DW_TAG_array_type: + return array_size (die, size, &attr_mem, type_mem); + } + + /* Most types must give their size directly. */ + return -1; +} + +int +dwarf_aggregate_size (die, size) + Dwarf_Die *die; + Dwarf_Word *size; +{ + Dwarf_Die type_mem; + return aggregate_size (die, size, &type_mem); +} +INTDEF (dwarf_aggregate_size) diff --git a/src/libdw/dwarf_arrayorder.c b/src/libdw/dwarf_arrayorder.c new file mode 100644 index 00000000..4929fb3c --- /dev/null +++ b/src/libdw/dwarf_arrayorder.c @@ -0,0 +1,71 @@ +/* Return array order attribute of DIE. + Copyright (C) 2003, 2005, 2009 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2003. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <dwarf.h> +#include "libdwP.h" + + +int +dwarf_arrayorder (die) + Dwarf_Die *die; +{ + Dwarf_Attribute attr_mem; + Dwarf_Word value; + + return INTUSE(dwarf_formudata) (INTUSE(dwarf_attr_integrate) + (die, DW_AT_ordering, &attr_mem), + &value) == 0 ? (int) value : -1; +} +OLD_VERSION (dwarf_arrayorder, ELFUTILS_0.122) +NEW_VERSION (dwarf_arrayorder, ELFUTILS_0.143) diff --git a/src/libdw/dwarf_attr.c b/src/libdw/dwarf_attr.c new file mode 100644 index 00000000..d3b03244 --- /dev/null +++ b/src/libdw/dwarf_attr.c @@ -0,0 +1,76 @@ +/* Return specific DWARF attribute of a DIE. + Copyright (C) 2003, 2005 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2003. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <dwarf.h> +#include "libdwP.h" + + +Dwarf_Attribute * +dwarf_attr (die, search_name, result) + Dwarf_Die *die; + unsigned int search_name; + Dwarf_Attribute *result; +{ + if (die == NULL) + return NULL; + + /* Search for the attribute with the given name. */ + result->valp = __libdw_find_attr (die, search_name, &result->code, + &result->form); + /* Always fill in the CU information. */ + result->cu = die->cu; + + return result->code == search_name ? result : NULL; +} +INTDEF(dwarf_attr) diff --git a/src/libdw/dwarf_attr_integrate.c b/src/libdw/dwarf_attr_integrate.c new file mode 100644 index 00000000..ce062f5b --- /dev/null +++ b/src/libdw/dwarf_attr_integrate.c @@ -0,0 +1,81 @@ +/* Return specific DWARF attribute of a DIE, integrating indirections. + Copyright (C) 2005 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <dwarf.h> +#include "libdwP.h" + +Dwarf_Attribute * +dwarf_attr_integrate (Dwarf_Die *die, unsigned int search_name, + Dwarf_Attribute *result) +{ + Dwarf_Die die_mem; + + do + { + Dwarf_Attribute *attr = INTUSE(dwarf_attr) (die, search_name, result); + if (attr != NULL) + return attr; + + attr = INTUSE(dwarf_attr) (die, DW_AT_abstract_origin, result); + if (attr == NULL) + attr = INTUSE(dwarf_attr) (die, DW_AT_specification, result); + if (attr == NULL) + break; + + die = INTUSE(dwarf_formref_die) (attr, &die_mem); + } + while (die != NULL); + + return NULL; +} +INTDEF (dwarf_attr_integrate) diff --git a/src/libdw/dwarf_begin.c b/src/libdw/dwarf_begin.c new file mode 100644 index 00000000..8a419147 --- /dev/null +++ b/src/libdw/dwarf_begin.c @@ -0,0 +1,125 @@ +/* Create descriptor from file descriptor for processing file. + Copyright (C) 2002, 2003, 2004, 2005 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <errno.h> +#include <stddef.h> +#include <sys/stat.h> + +#include <libdwP.h> + + +Dwarf * +dwarf_begin (fd, cmd) + int fd; + Dwarf_Cmd cmd; +{ + Elf *elf; + Elf_Cmd elfcmd; + Dwarf *result = NULL; + + switch (cmd) + { + case DWARF_C_READ: + elfcmd = ELF_C_READ_MMAP; + break; + case DWARF_C_WRITE: + elfcmd = ELF_C_WRITE; + break; + case DWARF_C_RDWR: + elfcmd = ELF_C_RDWR; + break; + default: + /* No valid mode. */ + __libdw_seterrno (DWARF_E_INVALID_CMD); + return NULL; + } + + /* 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, elfcmd, NULL); + if (elf == NULL) + { +#ifndef __APPLE__ + /* Test why the `elf_begin" call failed. */ + struct stat64 st; + + if (fstat64 (fd, &st) == 0 && ! S_ISREG (st.st_mode)) + __libdw_seterrno (DWARF_E_NO_REGFILE); + else if (errno == EBADF) + __libdw_seterrno (DWARF_E_INVALID_FILE); + else + __libdw_seterrno (DWARF_E_IO_ERROR); +#else + __libdw_seterrno (DWARF_E_IO_ERROR); +#endif + } + else + { + /* Do the real work now that we have an ELF descriptor. */ + result = INTUSE(dwarf_begin_elf) (elf, cmd, NULL); + + /* If this failed, free the resources. */ + if (result == NULL) + elf_end (elf); + else + result->free_elf = true; + } + + return result; +} diff --git a/src/libdw/dwarf_begin_elf.c b/src/libdw/dwarf_begin_elf.c new file mode 100644 index 00000000..9ec7d51f --- /dev/null +++ b/src/libdw/dwarf_begin_elf.c @@ -0,0 +1,377 @@ +/* Create descriptor from ELF descriptor for processing file. + Copyright (C) 2002-2011 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdbool.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/stat.h> + +#include "libdwP.h" + +#if USE_ZLIB +# include <endian.h> +# define crc32 loser_crc32 +# include <zlib.h> +# undef crc32 +#endif + + +/* Section names. */ +static const char dwarf_scnnames[IDX_last][17] = +{ + [IDX_debug_info] = ".debug_info", + [IDX_debug_types] = ".debug_types", + [IDX_debug_abbrev] = ".debug_abbrev", + [IDX_debug_aranges] = ".debug_aranges", + [IDX_debug_line] = ".debug_line", + [IDX_debug_frame] = ".debug_frame", + [IDX_debug_loc] = ".debug_loc", + [IDX_debug_pubnames] = ".debug_pubnames", + [IDX_debug_str] = ".debug_str", + [IDX_debug_macinfo] = ".debug_macinfo", + [IDX_debug_ranges] = ".debug_ranges" +}; +#define ndwarf_scnnames (sizeof (dwarf_scnnames) / sizeof (dwarf_scnnames[0])) + + +static Dwarf * +check_section (Dwarf *result, GElf_Ehdr *ehdr, Elf_Scn *scn, bool inscngrp) +{ + GElf_Shdr shdr_mem; + GElf_Shdr *shdr; + + /* 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 (); + + /* Ignore any SHT_NOBITS sections. Debugging sections should not + have been stripped, but in case of a corrupt file we won't try + to look at the missing data. */ + if (unlikely (shdr->sh_type == SHT_NOBITS)) + return result; + + /* Make sure the section is part of a section group only iff we + really need it. If we are looking for the global (= non-section + group debug info) we have to ignore all the info in section + groups. If we are looking into a section group we cannot look at + a section which isn't part of the section group. */ + if (! inscngrp && (shdr->sh_flags & SHF_GROUP) != 0) + /* Ignore the section. */ + return result; + + + /* We recognize the DWARF section by their names. This is not very + safe and stable but the best we can do. */ + const char *scnname = elf_strptr (result->elf, ehdr->e_shstrndx, + shdr->sh_name); + if (scnname == NULL) + { + /* The section name must be valid. Otherwise is the ELF file + invalid. */ + __libdw_free_zdata (result); + __libdw_seterrno (DWARF_E_INVALID_ELF); + free (result); + return NULL; + } + + + /* Recognize the various sections. Most names start with .debug_. */ + size_t cnt; + for (cnt = 0; cnt < ndwarf_scnnames; ++cnt) + if (strcmp (scnname, dwarf_scnnames[cnt]) == 0) + { + /* Found it. Remember where the data is. */ + if (unlikely (result->sectiondata[cnt] != NULL)) + /* A section appears twice. That's bad. We ignore the section. */ + break; + + /* Get the section data. */ + Elf_Data *data = elf_getdata (scn, NULL); + if (data != NULL && data->d_size != 0) + /* Yep, there is actually data available. */ + result->sectiondata[cnt] = data; + + break; + } +#if USE_ZLIB + else if (scnname[0] == '.' && scnname[1] == 'z' + && strcmp (&scnname[2], &dwarf_scnnames[cnt][1]) == 0) + { + /* A compressed section. */ + + if (unlikely (result->sectiondata[cnt] != NULL)) + /* A section appears twice. That's bad. We ignore the section. */ + break; + + /* Get the section data. */ + Elf_Data *data = elf_getdata (scn, NULL); + if (data != NULL && data->d_size != 0) + { + /* There is a 12-byte header of "ZLIB" followed by + an 8-byte big-endian size. */ + + if (unlikely (data->d_size < 4 + 8) + || unlikely (memcmp (data->d_buf, "ZLIB", 4) != 0)) + break; + + uint64_t size; + memcpy (&size, data->d_buf + 4, sizeof size); + size = be64toh (size); + + Elf_Data *zdata = malloc (sizeof (Elf_Data) + size); + if (unlikely (zdata == NULL)) + break; + + zdata->d_buf = &zdata[1]; + zdata->d_type = ELF_T_BYTE; + zdata->d_version = EV_CURRENT; + zdata->d_size = size; + zdata->d_off = 0; + zdata->d_align = 1; + + z_stream z = + { + .next_in = data->d_buf + 4 + 8, + .avail_in = data->d_size - 4 - 8, + .next_out = zdata->d_buf, + .avail_out = zdata->d_size + }; + int zrc = inflateInit (&z); + while (z.avail_in > 0 && likely (zrc == Z_OK)) + { + z.next_out = zdata->d_buf + (zdata->d_size - z.avail_out); + zrc = inflate (&z, Z_FINISH); + if (unlikely (zrc != Z_STREAM_END)) + { + zrc = Z_DATA_ERROR; + break; + } + zrc = inflateReset (&z); + } + if (likely (zrc == Z_OK)) + zrc = inflateEnd (&z); + + if (unlikely (zrc != Z_OK) || unlikely (z.avail_out != 0)) + free (zdata); + else + { + result->sectiondata[cnt] = zdata; + result->sectiondata_gzip_mask |= 1U << cnt; + } + } + + break; + } +#endif + + return result; +} + + +/* Check whether all the necessary DWARF information is available. */ +static Dwarf * +valid_p (Dwarf *result) +{ + /* 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 (likely (result != NULL) + && unlikely (result->sectiondata[IDX_debug_info] == NULL)) + { + __libdw_free_zdata (result); + __libdw_seterrno (DWARF_E_NO_DWARF); + free (result); + result = NULL; + } + + return result; +} + + +static Dwarf * +global_read (Dwarf *result, Elf *elf, GElf_Ehdr *ehdr) +{ + Elf_Scn *scn = NULL; + + while (result != NULL && (scn = elf_nextscn (elf, scn)) != NULL) + result = check_section (result, ehdr, scn, false); + + return valid_p (result); +} + + +static Dwarf * +scngrp_read (Dwarf *result, Elf *elf, GElf_Ehdr *ehdr, Elf_Scn *scngrp) +{ + /* SCNGRP is the section descriptor for a section group which might + contain debug sections. */ + Elf_Data *data = elf_getdata (scngrp, NULL); + if (data == NULL) + { + /* We cannot read the section content. Fail! */ + __libdw_free_zdata (result); + free (result); + return NULL; + } + + /* The content of the section is a number of 32-bit words which + represent section indices. The first word is a flag word. */ + Elf32_Word *scnidx = (Elf32_Word *) data->d_buf; + size_t cnt; + for (cnt = 1; cnt * sizeof (Elf32_Word) <= data->d_size; ++cnt) + { + Elf_Scn *scn = elf_getscn (elf, scnidx[cnt]); + if (scn == NULL) + { + /* A section group refers to a non-existing section. Should + never happen. */ + __libdw_free_zdata (result); + __libdw_seterrno (DWARF_E_INVALID_ELF); + free (result); + return NULL; + } + + result = check_section (result, ehdr, scn, true); + if (result == NULL) + break; + } + + return valid_p (result); +} + + +Dwarf * +dwarf_begin_elf (elf, cmd, scngrp) + Elf *elf; + Dwarf_Cmd cmd; + Elf_Scn *scngrp; +{ + GElf_Ehdr *ehdr; + GElf_Ehdr ehdr_mem; + + /* Get the ELF header of the file. We need various pieces of + information from it. */ + ehdr = gelf_getehdr (elf, &ehdr_mem); + if (ehdr == NULL) + { + if (elf_kind (elf) != ELF_K_ELF) + __libdw_seterrno (DWARF_E_NOELF); + else + __libdw_seterrno (DWARF_E_GETEHDR_ERROR); + + return NULL; + } + + + /* Default memory allocation size. */ + size_t mem_default_size = sysconf (_SC_PAGESIZE) - 4 * sizeof (void *); + + /* Allocate the data structure. */ + Dwarf *result = (Dwarf *) calloc (1, sizeof (Dwarf) + mem_default_size); + if (unlikely (result == NULL) + || unlikely (Dwarf_Sig8_Hash_init (&result->sig8_hash, 11) < 0)) + { + free (result); + __libdw_seterrno (DWARF_E_NOMEM); + return NULL; + } + + /* Fill in some values. */ + if ((BYTE_ORDER == LITTLE_ENDIAN && ehdr->e_ident[EI_DATA] == ELFDATA2MSB) + || (BYTE_ORDER == BIG_ENDIAN && ehdr->e_ident[EI_DATA] == ELFDATA2LSB)) + result->other_byte_order = true; + + result->elf = elf; + + /* Initialize the memory handling. */ + result->mem_default_size = mem_default_size; + result->oom_handler = __libdw_oom; + result->mem_tail = (struct libdw_memblock *) (result + 1); + result->mem_tail->size = (result->mem_default_size + - offsetof (struct libdw_memblock, mem)); + result->mem_tail->remaining = result->mem_tail->size; + result->mem_tail->prev = NULL; + + if (cmd == DWARF_C_READ || cmd == DWARF_C_RDWR) + { + /* If the caller provides a section group we get the DWARF + sections only from this setion group. Otherwise we search + for the first section with the required name. Further + sections with the name are ignored. The DWARF specification + does not really say this is allowed. */ + if (scngrp == NULL) + return global_read (result, elf, ehdr); + else + return scngrp_read (result, elf, ehdr, scngrp); + } + else if (cmd == DWARF_C_WRITE) + { + __libdw_seterrno (DWARF_E_UNIMPL); + free (result); + return NULL; + } + + __libdw_seterrno (DWARF_E_INVALID_CMD); + free (result); + return NULL; +} +INTDEF(dwarf_begin_elf) diff --git a/src/libdw/dwarf_bitoffset.c b/src/libdw/dwarf_bitoffset.c new file mode 100644 index 00000000..3ab14683 --- /dev/null +++ b/src/libdw/dwarf_bitoffset.c @@ -0,0 +1,71 @@ +/* Return bit offset attribute of DIE. + Copyright (C) 2003, 2005, 2009 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2003. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <dwarf.h> +#include "libdwP.h" + + +int +dwarf_bitoffset (die) + Dwarf_Die *die; +{ + Dwarf_Attribute attr_mem; + Dwarf_Word value; + + return INTUSE(dwarf_formudata) (INTUSE(dwarf_attr_integrate) + (die, DW_AT_bit_offset, &attr_mem), + &value) == 0 ? (int) value : -1; +} +OLD_VERSION (dwarf_bitoffset, ELFUTILS_0.122) +NEW_VERSION (dwarf_bitoffset, ELFUTILS_0.143) diff --git a/src/libdw/dwarf_bitsize.c b/src/libdw/dwarf_bitsize.c new file mode 100644 index 00000000..67d97dc1 --- /dev/null +++ b/src/libdw/dwarf_bitsize.c @@ -0,0 +1,71 @@ +/* Return bit size attribute of DIE. + Copyright (C) 2003, 2005, 2009 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2003. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <dwarf.h> +#include "libdwP.h" + + +int +dwarf_bitsize (die) + Dwarf_Die *die; +{ + Dwarf_Attribute attr_mem; + Dwarf_Word value; + + return INTUSE(dwarf_formudata) (INTUSE(dwarf_attr_integrate) + (die, DW_AT_bit_size, &attr_mem), + &value) == 0 ? (int) value : -1; +} +OLD_VERSION (dwarf_bitsize, ELFUTILS_0.122) +NEW_VERSION (dwarf_bitsize, ELFUTILS_0.143) diff --git a/src/libdw/dwarf_bytesize.c b/src/libdw/dwarf_bytesize.c new file mode 100644 index 00000000..2f2e1985 --- /dev/null +++ b/src/libdw/dwarf_bytesize.c @@ -0,0 +1,71 @@ +/* Return byte size attribute of DIE. + Copyright (C) 2003, 2005, 2009 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2003. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <dwarf.h> +#include "libdwP.h" + + +int +dwarf_bytesize (die) + Dwarf_Die *die; +{ + Dwarf_Attribute attr_mem; + Dwarf_Word value; + + return INTUSE(dwarf_formudata) (INTUSE(dwarf_attr_integrate) + (die, DW_AT_byte_size, &attr_mem), + &value) == 0 ? (int) value : -1; +} +OLD_VERSION (dwarf_bytesize, ELFUTILS_0.122) +NEW_VERSION (dwarf_bytesize, ELFUTILS_0.143) diff --git a/src/libdw/dwarf_cfi_addrframe.c b/src/libdw/dwarf_cfi_addrframe.c new file mode 100644 index 00000000..79d0e125 --- /dev/null +++ b/src/libdw/dwarf_cfi_addrframe.c @@ -0,0 +1,78 @@ +/* Compute frame state at PC. + Copyright (C) 2009 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "cfi.h" + +int +dwarf_cfi_addrframe (cache, address, frame) + Dwarf_CFI *cache; + Dwarf_Addr address; + Dwarf_Frame **frame; +{ + /* Maybe there was a previous error. */ + if (cache == NULL) + return -1; + + struct dwarf_fde *fde = __libdw_find_fde (cache, address); + if (fde == NULL) + return -1; + + int error = __libdw_frame_at_address (cache, fde, address, frame); + if (error != DWARF_E_NOERROR) + { + __libdw_seterrno (error); + return -1; + } + return 0; +} +INTDEF (dwarf_cfi_addrframe) diff --git a/src/libdw/dwarf_cfi_end.c b/src/libdw/dwarf_cfi_end.c new file mode 100644 index 00000000..5591e2a9 --- /dev/null +++ b/src/libdw/dwarf_cfi_end.c @@ -0,0 +1,70 @@ +/* Clean up Dwarf_CFI structure. + Copyright (C) 2009 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "libdwP.h" +#include "cfi.h" +#include <stdlib.h> + +int +dwarf_cfi_end (cache) + Dwarf_CFI *cache; +{ + if (cache != NULL) + { + __libdw_destroy_frame_cache (cache); + free (cache); + } + + return 0; +} +INTDEF (dwarf_cfi_end) diff --git a/src/libdw/dwarf_child.c b/src/libdw/dwarf_child.c new file mode 100644 index 00000000..0c2df004 --- /dev/null +++ b/src/libdw/dwarf_child.c @@ -0,0 +1,211 @@ +/* Return child of current DIE. + Copyright (C) 2003-2011 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2003. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "libdwP.h" +#include <string.h> + +/* Some arbitrary value not conflicting with any existing code. */ +#define INVALID 0xffffe444 + + +unsigned char * +internal_function +__libdw_find_attr (Dwarf_Die *die, unsigned int search_name, + unsigned int *codep, unsigned int *formp) +{ + Dwarf *dbg = die->cu->dbg; + const unsigned char *readp = (unsigned char *) die->addr; + + /* First we have to get the abbreviation code so that we can decode + the data in the DIE. */ + unsigned int abbrev_code; + get_uleb128 (abbrev_code, readp); + + /* Find the abbreviation entry. */ + Dwarf_Abbrev *abbrevp = die->abbrev; + if (abbrevp == NULL) + { + abbrevp = __libdw_findabbrev (die->cu, abbrev_code); + die->abbrev = abbrevp ?: DWARF_END_ABBREV; + } + if (unlikely (die->abbrev == DWARF_END_ABBREV)) + { + invalid_dwarf: + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return NULL; + } + + /* Search the name attribute. */ + unsigned char *const endp + = ((unsigned char *) dbg->sectiondata[IDX_debug_abbrev]->d_buf + + dbg->sectiondata[IDX_debug_abbrev]->d_size); + + const unsigned char *attrp = die->abbrev->attrp; + while (1) + { + /* Are we still in bounds? This test needs to be refined. */ + if (unlikely (attrp + 1 >= endp)) + goto invalid_dwarf; + + /* Get attribute name and form. + + XXX We don't check whether this reads beyond the end of the + section. */ + unsigned int attr_name; + get_uleb128 (attr_name, attrp); + unsigned int attr_form; + 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 == search_name && search_name != INVALID) + { + if (codep != NULL) + *codep = attr_name; + if (formp != NULL) + *formp = attr_form; + + return (unsigned char *) readp; + } + + /* Skip over the rest of this attribute (if there is any). */ + if (attr_form != 0) + { + size_t len = __libdw_form_val_len (dbg, die->cu, attr_form, readp); + + if (unlikely (len == (size_t) -1l)) + { + readp = NULL; + break; + } + + // XXX We need better boundary checks. + readp += len; + } + } + + // XXX Do we need other values? + if (codep != NULL) + *codep = INVALID; + if (formp != NULL) + *formp = INVALID; + + return (unsigned char *) readp; +} + + +int +dwarf_child (die, result) + Dwarf_Die *die; + Dwarf_Die *result; +{ + /* Ignore previous errors. */ + if (die == NULL) + return -1; + + /* Skip past the last attribute. */ + void *addr = NULL; + + /* If we already know there are no children do not search. */ + if (die->abbrev != DWARF_END_ABBREV + && (die->abbrev == NULL || die->abbrev->has_children)) + addr = __libdw_find_attr (die, INVALID, NULL, NULL); + if (unlikely (die->abbrev == (Dwarf_Abbrev *) -1l)) + return -1; + + /* Make sure the DIE really has children. */ + if (! die->abbrev->has_children) + /* There cannot be any children. */ + return 1; + + if (addr == NULL) + return -1; + + /* RESULT can be the same as DIE. So preserve what we need. */ + struct Dwarf_CU *cu = die->cu; + Elf_Data *cu_sec = cu_data (cu); + + /* It's kosher (just suboptimal) to have a null entry first thing (7.5.3). + So if this starts with ULEB128 of 0 (even with silly encoding of 0), + it is a kosher null entry and we do not really have any children. */ + const unsigned char *code = addr; + const unsigned char *endp = (cu_sec->d_buf + cu_sec->d_size); + while (1) + { + if (unlikely (code >= endp)) /* Truncated section. */ + return 1; + if (unlikely (*code == 0x80)) + ++code; + else + break; + } + if (unlikely (*code == '\0')) + return 1; + + /* Clear the entire DIE structure. This signals we have not yet + determined any of the information. */ + memset (result, '\0', sizeof (Dwarf_Die)); + + /* We have the address. */ + result->addr = addr; + + /* Same CU as the parent. */ + result->cu = cu; + + return 0; +} +INTDEF(dwarf_child) diff --git a/src/libdw/dwarf_cuoffset.c b/src/libdw/dwarf_cuoffset.c new file mode 100644 index 00000000..47653200 --- /dev/null +++ b/src/libdw/dwarf_cuoffset.c @@ -0,0 +1,66 @@ +/* Return offset of DIE in CU. + Copyright (C) 2003-2010 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2003. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <dwarf.h> +#include "libdwP.h" + + +Dwarf_Off +dwarf_cuoffset (die) + Dwarf_Die *die; +{ + return (die == NULL + ? (Dwarf_Off) -1l + : (die->addr - cu_data (die->cu)->d_buf - die->cu->start)); +} diff --git a/src/libdw/dwarf_decl_column.c b/src/libdw/dwarf_decl_column.c new file mode 100644 index 00000000..11ba5d74 --- /dev/null +++ b/src/libdw/dwarf_decl_column.c @@ -0,0 +1,65 @@ +/* Get column number of beginning of given declaration. + Copyright (C) 2005-2009 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2005. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <dwarf.h> +#include "libdwP.h" + + +int +dwarf_decl_column (Dwarf_Die *decl, int *colp) +{ + return __libdw_attr_intval (decl, colp, DW_AT_decl_column); +} +OLD_VERSION (dwarf_decl_column, ELFUTILS_0.122) +NEW_VERSION (dwarf_decl_column, ELFUTILS_0.143) diff --git a/src/libdw/dwarf_decl_file.c b/src/libdw/dwarf_decl_file.c new file mode 100644 index 00000000..c81e35b8 --- /dev/null +++ b/src/libdw/dwarf_decl_file.c @@ -0,0 +1,110 @@ +/* Return file name containing definition of the given function. + Copyright (C) 2005, 2009 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2005. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <assert.h> +#include <dwarf.h> +#include "libdwP.h" + + +const char * +dwarf_decl_file (Dwarf_Die *die) +{ + Dwarf_Attribute attr_mem; + Dwarf_Sword idx = 0; + + if (INTUSE(dwarf_formsdata) (INTUSE(dwarf_attr_integrate) + (die, DW_AT_decl_file, &attr_mem), + &idx) != 0) + return NULL; + + /* Zero means no source file information available. */ + if (idx == 0) + { + __libdw_seterrno (DWARF_E_NO_ENTRY); + return NULL; + } + + /* Get the array of source files for the CU. */ + struct Dwarf_CU *cu = die->cu; + if (cu->lines == NULL) + { + Dwarf_Lines *lines; + size_t nlines; + + /* Let the more generic function do the work. It'll create more + data but that will be needed in an real program anyway. */ + (void) INTUSE(dwarf_getsrclines) (&CUDIE (cu), &lines, &nlines); + assert (cu->lines != NULL); + } + + if (cu->lines == (void *) -1l) + { + /* If the file index is not zero, there must be file information + available. */ + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return NULL; + } + + assert (cu->files != NULL && cu->files != (void *) -1l); + + if (idx >= cu->files->nfiles) + { + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return NULL; + } + + return cu->files->info[idx].name; +} +OLD_VERSION (dwarf_decl_file, ELFUTILS_0.122) +NEW_VERSION (dwarf_decl_file, ELFUTILS_0.143) diff --git a/src/libdw/dwarf_decl_line.c b/src/libdw/dwarf_decl_line.c new file mode 100644 index 00000000..ab64e510 --- /dev/null +++ b/src/libdw/dwarf_decl_line.c @@ -0,0 +1,86 @@ +/* Get line number of beginning of given function. + Copyright (C) 2005, 2009 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2005. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <assert.h> +#include <dwarf.h> +#include <limits.h> +#include "libdwP.h" + + +int +dwarf_decl_line (Dwarf_Die *func, int *linep) +{ + return __libdw_attr_intval (func, linep, DW_AT_decl_line); +} +OLD_VERSION (dwarf_decl_line, ELFUTILS_0.122) +NEW_VERSION (dwarf_decl_line, ELFUTILS_0.143) + + +int internal_function +__libdw_attr_intval (Dwarf_Die *die, int *linep, int attval) +{ + Dwarf_Attribute attr_mem; + Dwarf_Sword line; + + int res = INTUSE(dwarf_formsdata) (INTUSE(dwarf_attr_integrate) + (die, attval, &attr_mem), + &line); + if (res == 0) + { + assert (line >= 0 && line <= INT_MAX); + *linep = line; + } + + return res; +} diff --git a/src/libdw/dwarf_diecu.c b/src/libdw/dwarf_diecu.c new file mode 100644 index 00000000..cd98cf61 --- /dev/null +++ b/src/libdw/dwarf_diecu.c @@ -0,0 +1,76 @@ +/* Return CU DIE containing given DIE. + Copyright (C) 2005-2010 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <string.h> +#include "libdwP.h" + + +Dwarf_Die * +dwarf_diecu (die, result, address_sizep, offset_sizep) + Dwarf_Die *die; + Dwarf_Die *result; + uint8_t *address_sizep; + uint8_t *offset_sizep; +{ + if (die == NULL) + return NULL; + + *result = CUDIE (die->cu); + + if (address_sizep != NULL) + *address_sizep = die->cu->address_size; + if (offset_sizep != NULL) + *offset_sizep = die->cu->offset_size; + + return result; +} diff --git a/src/libdw/dwarf_diename.c b/src/libdw/dwarf_diename.c new file mode 100644 index 00000000..3b66d12e --- /dev/null +++ b/src/libdw/dwarf_diename.c @@ -0,0 +1,69 @@ +/* Return string in name attribute of DIE. + Copyright (C) 2002, 2005 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <dwarf.h> +#include "libdwP.h" + + +const char * +dwarf_diename (die) + Dwarf_Die *die; +{ + Dwarf_Attribute attr_mem; + + return INTUSE(dwarf_formstring) (INTUSE(dwarf_attr_integrate) (die, + DW_AT_name, + &attr_mem)); +} +INTDEF (dwarf_diename) diff --git a/src/libdw/dwarf_dieoffset.c b/src/libdw/dwarf_dieoffset.c new file mode 100644 index 00000000..ac4a84c8 --- /dev/null +++ b/src/libdw/dwarf_dieoffset.c @@ -0,0 +1,67 @@ +/* Return offset of DIE. + Copyright (C) 2003-2010 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2003. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <dwarf.h> +#include "libdwP.h" + + +Dwarf_Off +dwarf_dieoffset (die) + Dwarf_Die *die; +{ + return (die == NULL + ? ~0ul + : (Dwarf_Off) (die->addr - cu_data (die->cu)->d_buf)); +} +INTDEF(dwarf_dieoffset) diff --git a/src/libdw/dwarf_end.c b/src/libdw/dwarf_end.c new file mode 100644 index 00000000..1e733cae --- /dev/null +++ b/src/libdw/dwarf_end.c @@ -0,0 +1,141 @@ +/* Release debugging handling context. + Copyright (C) 2002-2011 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <search.h> +#include <stdlib.h> +#include <assert.h> +#include <string.h> + +#include "libdwP.h" +#include "cfi.h" + + +static void +noop_free (void *arg __attribute__ ((unused))) +{ +} + + +static void +cu_free (void *arg) +{ + struct Dwarf_CU *p = (struct Dwarf_CU *) arg; + + Dwarf_Abbrev_Hash_free (&p->abbrev_hash); + + tdestroy (p->locs, noop_free); +} + + +#if USE_ZLIB +void +internal_function +__libdw_free_zdata (Dwarf *dwarf) +{ + unsigned int gzip_mask = dwarf->sectiondata_gzip_mask; + while (gzip_mask != 0) + { + int i = ffs (gzip_mask); + assert (i > 0); + --i; + assert (i < IDX_last); + free (dwarf->sectiondata[i]); + gzip_mask &= ~(1U << i); + } +} +#endif + +int +dwarf_end (dwarf) + Dwarf *dwarf; +{ + if (dwarf != NULL) + { + if (dwarf->cfi != NULL) + /* Clean up the CFI cache. */ + __libdw_destroy_frame_cache (dwarf->cfi); + + Dwarf_Sig8_Hash_free (&dwarf->sig8_hash); + + /* The search tree for the CUs. NB: the CU data itself is + allocated separately, but the abbreviation hash tables need + to be handled. */ + tdestroy (dwarf->cu_tree, cu_free); + tdestroy (dwarf->tu_tree, cu_free); + + struct libdw_memblock *memp = dwarf->mem_tail; + /* The first block is allocated together with the Dwarf object. */ + while (memp->prev != NULL) + { + struct libdw_memblock *prevp = memp->prev; + free (memp); + memp = prevp; + } + + /* Free the pubnames helper structure. */ + free (dwarf->pubnames_sets); + + __libdw_free_zdata (dwarf); + + /* Free the ELF descriptor if necessary. */ + if (dwarf->free_elf) + elf_end (dwarf->elf); + + /* Free the context descriptor. */ + free (dwarf); + } + + return 0; +} +INTDEF(dwarf_end) diff --git a/src/libdw/dwarf_entry_breakpoints.c b/src/libdw/dwarf_entry_breakpoints.c new file mode 100644 index 00000000..1e5c1b81 --- /dev/null +++ b/src/libdw/dwarf_entry_breakpoints.c @@ -0,0 +1,178 @@ +/* Find entry breakpoint locations for a function. + Copyright (C) 2005-2009 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#include "libdwP.h" +#include <dwarf.h> +#include <stdlib.h> + + +int +dwarf_entry_breakpoints (die, bkpts) + Dwarf_Die *die; + Dwarf_Addr **bkpts; +{ + int nbkpts = 0; + *bkpts = NULL; + + /* Add one breakpoint location to the result vector. */ + inline int add_bkpt (Dwarf_Addr pc) + { + Dwarf_Addr *newlist = realloc (*bkpts, ++nbkpts * sizeof newlist[0]); + if (newlist == NULL) + { + free (*bkpts); + *bkpts = NULL; + __libdw_seterrno (DWARF_E_NOMEM); + return -1; + } + newlist[nbkpts - 1] = pc; + *bkpts = newlist; + return nbkpts; + } + + /* Fallback result, break at the entrypc/lowpc value. */ + inline int entrypc_bkpt (void) + { + Dwarf_Addr pc; + return INTUSE(dwarf_entrypc) (die, &pc) < 0 ? -1 : add_bkpt (pc); + } + + /* Fetch the CU's line records to look for this DIE's addresses. */ + Dwarf_Die cudie = CUDIE (die->cu); + Dwarf_Lines *lines; + size_t nlines; + if (INTUSE(dwarf_getsrclines) (&cudie, &lines, &nlines) < 0) + { + int error = INTUSE (dwarf_errno) (); + if (error == 0) /* CU has no DW_AT_stmt_list. */ + return entrypc_bkpt (); + __libdw_seterrno (error); + return -1; + } + + /* Search a contiguous PC range for prologue-end markers. + If DWARF, look for proper markers. + Failing that, if ADHOC, look for the ad hoc convention. */ + inline int search_range (Dwarf_Addr low, Dwarf_Addr high, + bool dwarf, bool adhoc) + { + size_t l = 0, u = nlines; + while (l < u) + { + size_t idx = (l + u) / 2; + if (lines->info[idx].addr < low) + l = idx + 1; + else if (lines->info[idx].addr > low) + u = idx; + else if (lines->info[idx].end_sequence) + l = idx + 1; + else + { + l = idx; + break; + } + } + if (l < u) + { + if (dwarf) + for (size_t i = l; i < u && lines->info[i].addr < high; ++i) + if (lines->info[i].prologue_end + && add_bkpt (lines->info[i].addr) < 0) + return -1; + if (adhoc && nbkpts == 0) + while (++l < nlines && lines->info[l].addr < high) + if (!lines->info[l].end_sequence) + return add_bkpt (lines->info[l].addr); + return nbkpts; + } + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return -1; + } + + /* Search each contiguous address range for DWARF prologue_end markers. */ + + Dwarf_Addr base; + Dwarf_Addr begin; + Dwarf_Addr end; + ptrdiff_t offset = INTUSE(dwarf_ranges) (die, 0, &base, &begin, &end); + if (offset < 0) + return -1; + + /* Most often there is a single contiguous PC range for the DIE. */ + if (offset == 1) + return search_range (begin, end, true, true) ?: entrypc_bkpt (); + + Dwarf_Addr lowpc = (Dwarf_Addr) -1l; + Dwarf_Addr highpc = (Dwarf_Addr) -1l; + while (offset > 0) + { + /* We have an address range entry. */ + if (search_range (begin, end, true, false) < 0) + return -1; + + if (begin < lowpc) + { + lowpc = begin; + highpc = end; + } + + offset = INTUSE(dwarf_ranges) (die, offset, &base, &begin, &end); + } + + /* If we didn't find any proper DWARF markers, then look in the + lowest-addressed range for an ad hoc marker. Failing that, + fall back to just using the entrypc value. */ + return (nbkpts + ?: (lowpc == (Dwarf_Addr) -1l ? 0 + : search_range (lowpc, highpc, false, true)) + ?: entrypc_bkpt ()); +} diff --git a/src/libdw/dwarf_entrypc.c b/src/libdw/dwarf_entrypc.c new file mode 100644 index 00000000..1719be27 --- /dev/null +++ b/src/libdw/dwarf_entrypc.c @@ -0,0 +1,71 @@ +/* Return entry PC attribute of DIE. + Copyright (C) 2003, 2005 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <dwarf.h> +#include "libdwP.h" + + +int +dwarf_entrypc (die, return_addr) + Dwarf_Die *die; + Dwarf_Addr *return_addr; +{ + Dwarf_Attribute attr_mem; + + return INTUSE(dwarf_formaddr) (INTUSE(dwarf_attr) (die, DW_AT_entry_pc, + &attr_mem) + ?: INTUSE(dwarf_attr) (die, DW_AT_low_pc, + &attr_mem), + return_addr); +} +INTDEF(dwarf_entrypc) diff --git a/src/libdw/dwarf_error.c b/src/libdw/dwarf_error.c new file mode 100644 index 00000000..a298a19d --- /dev/null +++ b/src/libdw/dwarf_error.c @@ -0,0 +1,145 @@ +/* Retrieve ELF descriptor used for DWARF access. + Copyright (C) 2002, 2003, 2004, 2005, 2009 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <assert.h> +#include <stddef.h> + +#include "libdwP.h" + + +/* The error number. */ +#ifdef __APPLE__ +static int global_error; +#else +static __thread int global_error; +#endif + + +int +dwarf_errno (void) +{ + int result = global_error; + global_error = DWARF_E_NOERROR; + return result; +} +INTDEF(dwarf_errno) + + +/* XXX For now we use string pointers. Once the table stablelizes + make it more DSO-friendly. */ +static const char *errmsgs[] = + { + [DWARF_E_NOERROR] = N_("no error"), + [DWARF_E_UNKNOWN_ERROR] = N_("unknown error"), + [DWARF_E_INVALID_ACCESS] = N_("invalid access"), + [DWARF_E_NO_REGFILE] = N_("no regular file"), + [DWARF_E_IO_ERROR] = N_("I/O error"), + [DWARF_E_INVALID_ELF] = N_("invalid ELF file"), + [DWARF_E_NO_DWARF] = N_("no DWARF information"), + [DWARF_E_NOELF] = N_("no ELF file"), + [DWARF_E_GETEHDR_ERROR] = N_("cannot get ELF header"), + [DWARF_E_NOMEM] = N_("out of memory"), + [DWARF_E_UNIMPL] = N_("not implemented"), + [DWARF_E_INVALID_CMD] = N_("invalid command"), + [DWARF_E_INVALID_VERSION] = N_("invalid version"), + [DWARF_E_INVALID_FILE] = N_("invalid file"), + [DWARF_E_NO_ENTRY] = N_("no entries found"), + [DWARF_E_INVALID_DWARF] = N_("invalid DWARF"), + [DWARF_E_NO_STRING] = N_("no string data"), + [DWARF_E_NO_ADDR] = N_("no address value"), + [DWARF_E_NO_CONSTANT] = N_("no constant value"), + [DWARF_E_NO_REFERENCE] = N_("no reference value"), + [DWARF_E_INVALID_REFERENCE] = N_("invalid reference value"), + [DWARF_E_NO_DEBUG_LINE] = N_(".debug_line section missing"), + [DWARF_E_INVALID_DEBUG_LINE] = N_("invalid .debug_line section"), + [DWARF_E_TOO_BIG] = N_("debug information too big"), + [DWARF_E_VERSION] = N_("invalid DWARF version"), + [DWARF_E_INVALID_DIR_IDX] = N_("invalid directory index"), + [DWARF_E_ADDR_OUTOFRANGE] = N_("address out of range"), + [DWARF_E_NO_LOCLIST] = N_("no location list value"), + [DWARF_E_NO_BLOCK] = N_("no block data"), + [DWARF_E_INVALID_LINE_IDX] = N_("invalid line index"), + [DWARF_E_INVALID_ARANGE_IDX] = N_("invalid address range index"), + [DWARF_E_NO_MATCH] = N_("no matching address range"), + [DWARF_E_NO_FLAG] = N_("no flag value"), + [DWARF_E_INVALID_OFFSET] = N_("invalid offset"), + [DWARF_E_NO_DEBUG_RANGES] = N_(".debug_ranges section missing"), + [DWARF_E_INVALID_CFI] = N_("invalid CFI section"), + }; +#define nerrmsgs (sizeof (errmsgs) / sizeof (errmsgs[0])) + + +void +__libdw_seterrno (value) + int value; +{ + global_error = (value >= 0 && value < (int) nerrmsgs + ? value : DWARF_E_UNKNOWN_ERROR); +} + + +const char * +dwarf_errmsg (error) + int error; +{ + int last_error = global_error; + + if (error == 0) + return last_error != 0 ? _(errmsgs[last_error]) : NULL; + else if (error < -1 || error >= (int) nerrmsgs) + return _(errmsgs[DWARF_E_UNKNOWN_ERROR]); + + return _(errmsgs[error == -1 ? last_error : error]); +} +INTDEF(dwarf_errmsg) diff --git a/src/libdw/dwarf_filesrc.c b/src/libdw/dwarf_filesrc.c new file mode 100644 index 00000000..b48340d4 --- /dev/null +++ b/src/libdw/dwarf_filesrc.c @@ -0,0 +1,72 @@ +/* Find source file information. + Copyright (C) 2004 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2004. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "libdwP.h" + + +const char * +dwarf_filesrc (Dwarf_Files *file, size_t idx, Dwarf_Word *mtime, + Dwarf_Word *length) +{ + if (file == NULL || idx >= file->nfiles) + return NULL; + + if (mtime != NULL) + *mtime = file->info[idx].mtime; + + if (length != NULL) + *length = file->info[idx].length; + + return file->info[idx].name; +} diff --git a/src/libdw/dwarf_formaddr.c b/src/libdw/dwarf_formaddr.c new file mode 100644 index 00000000..a8c786ff --- /dev/null +++ b/src/libdw/dwarf_formaddr.c @@ -0,0 +1,80 @@ +/* Return address represented by attribute. + Copyright (C) 2003-2010 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2003. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <dwarf.h> +#include "libdwP.h" + + +int +dwarf_formaddr (attr, return_addr) + Dwarf_Attribute *attr; + Dwarf_Addr *return_addr; +{ + if (attr == NULL) + return -1; + + if (unlikely (attr->form != DW_FORM_addr)) + { + __libdw_seterrno (DWARF_E_NO_ADDR); + return -1; + } + + if (__libdw_read_address (attr->cu->dbg, + cu_sec_idx (attr->cu), attr->valp, + attr->cu->address_size, return_addr)) + return -1; + + return 0; +} +INTDEF(dwarf_formaddr) diff --git a/src/libdw/dwarf_formblock.c b/src/libdw/dwarf_formblock.c new file mode 100644 index 00000000..4eb815c4 --- /dev/null +++ b/src/libdw/dwarf_formblock.c @@ -0,0 +1,110 @@ +/* Return block represented by attribute. + Copyright (C) 2004-2010 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2004. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <dwarf.h> +#include "libdwP.h" + + +int +dwarf_formblock (attr, return_block) + Dwarf_Attribute *attr; + Dwarf_Block *return_block; +{ + if (attr == NULL) + return -1; + + const unsigned char *datap; + + switch (attr->form) + { + case DW_FORM_block1: + return_block->length = *(uint8_t *) attr->valp; + return_block->data = attr->valp + 1; + break; + + case DW_FORM_block2: + return_block->length = read_2ubyte_unaligned (attr->cu->dbg, attr->valp); + return_block->data = attr->valp + 2; + break; + + case DW_FORM_block4: + return_block->length = read_4ubyte_unaligned (attr->cu->dbg, attr->valp); + return_block->data = attr->valp + 4; + break; + + case DW_FORM_block: + case DW_FORM_exprloc: + datap = attr->valp; + get_uleb128 (return_block->length, datap); + return_block->data = (unsigned char *) datap; + break; + + default: + __libdw_seterrno (DWARF_E_NO_BLOCK); + return -1; + } + + if (unlikely (cu_data (attr->cu)->d_size + - (return_block->data + - (unsigned char *) cu_data (attr->cu)->d_buf) + < return_block->length)) + { + /* Block does not fit. */ + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return -1; + } + + return 0; +} +INTDEF(dwarf_formblock) diff --git a/src/libdw/dwarf_formflag.c b/src/libdw/dwarf_formflag.c new file mode 100644 index 00000000..fb60c8e6 --- /dev/null +++ b/src/libdw/dwarf_formflag.c @@ -0,0 +1,82 @@ +/* Return flag represented by attribute. + Copyright (C) 2004-2009 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2004. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <dwarf.h> +#include "libdwP.h" + + +int +dwarf_formflag (attr, return_bool) + Dwarf_Attribute *attr; + bool *return_bool; +{ + if (attr == NULL) + return -1; + + if (attr->form == DW_FORM_flag_present) + { + *return_bool = true; + return 0; + } + + if (unlikely (attr->form != DW_FORM_flag)) + { + __libdw_seterrno (DWARF_E_NO_FLAG); + return -1; + } + + *return_bool = *attr->valp != 0; + + return 0; +} diff --git a/src/libdw/dwarf_formref.c b/src/libdw/dwarf_formref.c new file mode 100644 index 00000000..e4d35ae8 --- /dev/null +++ b/src/libdw/dwarf_formref.c @@ -0,0 +1,118 @@ +/* Return reference offset represented by attribute. + Copyright (C) 2003-2010 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2003. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <dwarf.h> +#include "libdwP.h" + +int +__libdw_formref (attr, return_offset) + Dwarf_Attribute *attr; + Dwarf_Off *return_offset; +{ + const unsigned char *datap; + + if (attr->valp == NULL) + { + __libdw_seterrno (DWARF_E_INVALID_REFERENCE); + return -1; + } + + 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: + datap = attr->valp; + get_uleb128 (*return_offset, datap); + break; + + case DW_FORM_ref_addr: + case DW_FORM_ref_sig8: + __libdw_seterrno (DWARF_E_INVALID_REFERENCE); + return -1; + + default: + __libdw_seterrno (DWARF_E_NO_REFERENCE); + return -1; + } + + return 0; +} + +/* This is the old public entry point. + It is now deprecated in favor of dwarf_formref_die. */ +int +dwarf_formref (attr, return_offset) + Dwarf_Attribute *attr; + Dwarf_Off *return_offset; +{ + if (attr == NULL) + return -1; + + return __libdw_formref (attr, return_offset); +} diff --git a/src/libdw/dwarf_formref_die.c b/src/libdw/dwarf_formref_die.c new file mode 100644 index 00000000..3ec770d2 --- /dev/null +++ b/src/libdw/dwarf_formref_die.c @@ -0,0 +1,131 @@ +/* Look up the DIE in a reference-form attribute. + Copyright (C) 2005-2010 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <string.h> +#include "libdwP.h" +#include <dwarf.h> + + +Dwarf_Die * +dwarf_formref_die (attr, result) + Dwarf_Attribute *attr; + Dwarf_Die *result; +{ + if (attr == NULL) + return NULL; + + struct Dwarf_CU *cu = attr->cu; + + Dwarf_Off offset; + if (attr->form == DW_FORM_ref_addr) + { + /* This has an absolute offset. */ + + uint8_t ref_size = (cu->version == 2 + ? cu->address_size + : cu->offset_size); + + if (__libdw_read_offset (cu->dbg, IDX_debug_info, attr->valp, + ref_size, &offset, IDX_debug_info, 0)) + return NULL; + + return INTUSE(dwarf_offdie) (cu->dbg, offset, result); + } + + Elf_Data *data; + if (attr->form == DW_FORM_ref_sig8) + { + /* This doesn't have an offset, but instead a value we + have to match in the .debug_types type unit headers. */ + + uint64_t sig = read_8ubyte_unaligned (cu->dbg, attr->valp); + cu = Dwarf_Sig8_Hash_find (&cu->dbg->sig8_hash, sig, NULL); + if (cu == NULL) + /* Not seen before. We have to scan through the type units. */ + do + { + cu = __libdw_intern_next_unit (attr->cu->dbg, true); + if (cu == NULL) + { + __libdw_seterrno (INTUSE(dwarf_errno) () + ?: DWARF_E_INVALID_REFERENCE); + return NULL; + } + Dwarf_Sig8_Hash_insert (&cu->dbg->sig8_hash, cu->type_sig8, cu); + } + while (cu->type_sig8 != sig); + + data = cu->dbg->sectiondata[IDX_debug_types]; + offset = cu->type_offset; + } + else + { + /* Other forms produce an offset from the CU. */ + if (unlikely (__libdw_formref (attr, &offset) != 0)) + return NULL; + + data = cu_data (cu); + } + + if (unlikely (data->d_size - cu->start <= offset)) + { + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return NULL; + } + + memset (result, '\0', sizeof (Dwarf_Die)); + result->addr = (char *) data->d_buf + cu->start + offset; + result->cu = cu; + return result; +} +INTDEF (dwarf_formref_die) diff --git a/src/libdw/dwarf_formsdata.c b/src/libdw/dwarf_formsdata.c new file mode 100644 index 00000000..ab7249d1 --- /dev/null +++ b/src/libdw/dwarf_formsdata.c @@ -0,0 +1,104 @@ +/* Return signed constant represented by attribute. + Copyright (C) 2003, 2005 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2003. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <dwarf.h> +#include "libdwP.h" + + +int +dwarf_formsdata (attr, return_sval) + Dwarf_Attribute *attr; + Dwarf_Sword *return_sval; +{ + if (attr == NULL) + return -1; + + const unsigned char *datap; + + 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: + datap = attr->valp; + get_sleb128 (*return_sval, datap); + break; + + case DW_FORM_udata: + datap = attr->valp; + get_uleb128 (*return_sval, datap); + break; + + default: + __libdw_seterrno (DWARF_E_NO_CONSTANT); + return -1; + } + + return 0; +} +INTDEF(dwarf_formsdata) diff --git a/src/libdw/dwarf_formstring.c b/src/libdw/dwarf_formstring.c new file mode 100644 index 00000000..1dee9b2d --- /dev/null +++ b/src/libdw/dwarf_formstring.c @@ -0,0 +1,88 @@ +/* Return string associated with given attribute. + Copyright (C) 2003-2010 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2003. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <dwarf.h> +#include "libdwP.h" + + +const char * +dwarf_formstring (attrp) + Dwarf_Attribute *attrp; +{ + /* Ignore earlier errors. */ + if (attrp == NULL) + return NULL; + + /* We found it. Now determine where the string is stored. */ + if (attrp->form == DW_FORM_string) + /* A simple inlined string. */ + return (const char *) attrp->valp; + + Dwarf *dbg = attrp->cu->dbg; + + if (unlikely (attrp->form != DW_FORM_strp) + || dbg->sectiondata[IDX_debug_str] == NULL) + { + __libdw_seterrno (DWARF_E_NO_STRING); + return NULL; + } + + uint64_t off; + if (__libdw_read_offset (dbg, cu_sec_idx (attrp->cu), attrp->valp, + attrp->cu->offset_size, &off, IDX_debug_str, 1)) + return NULL; + + return (const char *) dbg->sectiondata[IDX_debug_str]->d_buf + off; +} +INTDEF(dwarf_formstring) diff --git a/src/libdw/dwarf_formudata.c b/src/libdw/dwarf_formudata.c new file mode 100644 index 00000000..07efbe0b --- /dev/null +++ b/src/libdw/dwarf_formudata.c @@ -0,0 +1,233 @@ +/* Return unsigned constant represented by attribute. + Copyright (C) 2003-2012 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2003. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <dwarf.h> +#include "libdwP.h" + +internal_function unsigned char * +__libdw_formptr (Dwarf_Attribute *attr, int sec_index, + int err_nodata, unsigned char **endpp, + Dwarf_Off *offsetp) +{ + if (attr == NULL) + return NULL; + + const Elf_Data *d = attr->cu->dbg->sectiondata[sec_index]; + if (unlikely (d == NULL)) + { + __libdw_seterrno (err_nodata); + return NULL; + } + + Dwarf_Word offset; + if (attr->form == DW_FORM_sec_offset) + { + if (__libdw_read_offset (attr->cu->dbg, cu_sec_idx (attr->cu), attr->valp, + attr->cu->offset_size, &offset, sec_index, 0)) + return NULL; + } + else if (attr->cu->version > 3) + goto invalid; + else + switch (attr->form) + { + case DW_FORM_data4: + case DW_FORM_data8: + if (__libdw_read_offset (attr->cu->dbg, cu_sec_idx (attr->cu), + attr->valp, + attr->form == DW_FORM_data4 ? 4 : 8, + &offset, sec_index, 0)) + return NULL; + break; + + default: + if (INTUSE(dwarf_formudata) (attr, &offset)) + return NULL; + }; + + unsigned char *readp = d->d_buf + offset; + unsigned char *endp = d->d_buf + d->d_size; + if (unlikely (readp >= endp)) + { + invalid: + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return NULL; + } + + if (endpp != NULL) + *endpp = endp; + if (offsetp != NULL) + *offsetp = offset; + return readp; +} + +int +dwarf_formudata (attr, return_uval) + Dwarf_Attribute *attr; + Dwarf_Word *return_uval; +{ + if (attr == NULL) + return -1; + + const unsigned char *datap; + + 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: + case DW_FORM_data8: + case DW_FORM_sec_offset: + /* Before DWARF4 data4 and data8 are pure constants unless the + attribute also allows offsets (*ptr classes), since DWARF4 + they are always just constants (start_scope is special though, + since it only could express a rangelist since DWARF4). */ + if (attr->form == DW_FORM_sec_offset + || (attr->cu->version < 4 && attr->code != DW_AT_start_scope)) + { + switch (attr->code) + { + case DW_AT_data_member_location: + case DW_AT_frame_base: + case DW_AT_location: + case DW_AT_return_addr: + case DW_AT_segment: + case DW_AT_static_link: + case DW_AT_string_length: + case DW_AT_use_location: + case DW_AT_vtable_elem_location: + /* loclistptr */ + if (__libdw_formptr (attr, IDX_debug_loc, + DWARF_E_NO_LOCLIST, NULL, + return_uval) == NULL) + return -1; + break; + + case DW_AT_macro_info: + /* macptr */ + if (__libdw_formptr (attr, IDX_debug_macinfo, + DWARF_E_NO_ENTRY, NULL, + return_uval) == NULL) + return -1; + break; + + case DW_AT_ranges: + case DW_AT_start_scope: + /* rangelistptr */ + if (__libdw_formptr (attr, IDX_debug_ranges, + DWARF_E_NO_DEBUG_RANGES, NULL, + return_uval) == NULL) + return -1; + break; + + case DW_AT_stmt_list: + /* lineptr */ + if (__libdw_formptr (attr, IDX_debug_line, + DWARF_E_NO_DEBUG_LINE, NULL, + return_uval) == NULL) + return -1; + break; + + default: + /* sec_offset can only be used by one of the above attrs. */ + if (attr->form == DW_FORM_sec_offset) + { + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return -1; + } + + /* Not one of the special attributes, just a constant. */ + if (__libdw_read_address (attr->cu->dbg, cu_sec_idx (attr->cu), + attr->valp, + attr->form == DW_FORM_data4 ? 4 : 8, + return_uval)) + return -1; + break; + } + } + else + { + /* We are dealing with a constant data4 or data8. */ + if (__libdw_read_address (attr->cu->dbg, cu_sec_idx (attr->cu), + attr->valp, + attr->form == DW_FORM_data4 ? 4 : 8, + return_uval)) + return -1; + } + break; + + case DW_FORM_sdata: + datap = attr->valp; + get_sleb128 (*return_uval, datap); + break; + + case DW_FORM_udata: + datap = attr->valp; + get_uleb128 (*return_uval, datap); + break; + + default: + __libdw_seterrno (DWARF_E_NO_CONSTANT); + return -1; + } + + return 0; +} +INTDEF(dwarf_formudata) diff --git a/src/libdw/dwarf_frame_cfa.c b/src/libdw/dwarf_frame_cfa.c new file mode 100644 index 00000000..2f3268a8 --- /dev/null +++ b/src/libdw/dwarf_frame_cfa.c @@ -0,0 +1,101 @@ +/* Get CFA expression for frame. + Copyright (C) 2009-2010 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "cfi.h" +#include <dwarf.h> +#include <stdlib.h> + +int +dwarf_frame_cfa (fs, ops, nops) + Dwarf_Frame *fs; + Dwarf_Op **ops; + size_t *nops; +{ + /* Maybe there was a previous error. */ + if (fs == NULL) + return -1; + + int result = 0; + switch (fs->cfa_rule) + { + case cfa_undefined: + *ops = NULL; + *nops = 0; + break; + + case cfa_offset: + /* The Dwarf_Op was already fully initialized by execute_cfi. */ + *ops = &fs->cfa_data.offset; + *nops = 1; + break; + + case cfa_expr: + /* Parse the expression into internal form. */ + result = __libdw_intern_expression + (NULL, fs->cache->other_byte_order, + fs->cache->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8, 4, + &fs->cache->expr_tree, &fs->cfa_data.expr, false, false, + ops, nops, IDX_debug_frame); + break; + + case cfa_invalid: + __libdw_seterrno (DWARF_E_INVALID_CFI); + result = -1; + break; + + default: + abort (); + } + + return result; +} diff --git a/src/libdw/dwarf_frame_info.c b/src/libdw/dwarf_frame_info.c new file mode 100644 index 00000000..4bdd8068 --- /dev/null +++ b/src/libdw/dwarf_frame_info.c @@ -0,0 +1,74 @@ +/* Get return address register for frame. + Copyright (C) 2009 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "cfi.h" + +int +dwarf_frame_info (fs, start, end, signalp) + Dwarf_Frame *fs; + Dwarf_Addr *start; + Dwarf_Addr *end; + bool *signalp; +{ + /* Maybe there was a previous error. */ + if (fs == NULL) + return -1; + + if (start != NULL) + *start = fs->start; + if (end != NULL) + *end = fs->end; + if (signalp != NULL) + *signalp = fs->fde->cie->signal_frame; + return fs->fde->cie->return_address_register; +} diff --git a/src/libdw/dwarf_frame_register.c b/src/libdw/dwarf_frame_register.c new file mode 100644 index 00000000..ae0db020 --- /dev/null +++ b/src/libdw/dwarf_frame_register.c @@ -0,0 +1,142 @@ +/* Get register location expression for frame. + Copyright (C) 2009-2010 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "cfi.h" +#include <dwarf.h> + +int +dwarf_frame_register (fs, regno, ops_mem, ops, nops) + Dwarf_Frame *fs; + int regno; + Dwarf_Op ops_mem[3]; + Dwarf_Op **ops; + size_t *nops; +{ + /* Maybe there was a previous error. */ + if (fs == NULL) + return -1; + + if (unlikely (regno < 0)) + { + __libdw_seterrno (DWARF_E_INVALID_ACCESS); + return -1; + } + + *ops = ops_mem; + *nops = 0; + + if (unlikely ((size_t) regno >= fs->nregs)) + goto default_rule; + + const struct dwarf_frame_register *reg = &fs->regs[regno]; + + switch (reg->rule) + { + case reg_unspecified: + default_rule: + /* Use the default rule for registers not yet mentioned in CFI. */ + if (fs->cache->default_same_value) + goto same_value; + /*FALLTHROUGH*/ + case reg_undefined: + /* The value is known to be unavailable. */ + break; + + case reg_same_value: + same_value: + /* The location is not known here, but the caller might know it. */ + *ops = NULL; + break; + + case reg_offset: + case reg_val_offset: + ops_mem[(*nops)++] = (Dwarf_Op) { .atom = DW_OP_call_frame_cfa }; + if (reg->value != 0) + ops_mem[(*nops)++] = (Dwarf_Op) { .atom = DW_OP_plus_uconst, + .number = reg->value }; + if (reg->rule == reg_val_offset) + /* A value, not a location. */ + ops_mem[(*nops)++] = (Dwarf_Op) { .atom = DW_OP_stack_value }; + *ops = ops_mem; + break; + + case reg_register: + ops_mem[(*nops)++] = (Dwarf_Op) { .atom = DW_OP_regx, + .number = reg->value }; + break; + + case reg_val_expression: + case reg_expression: + { + unsigned int address_size = (fs->cache->e_ident[EI_CLASS] == ELFCLASS32 + ? 4 : 8); + + Dwarf_Block block; + const uint8_t *p = fs->cache->data->d.d_buf + reg->value; + get_uleb128 (block.length, p); + block.data = (void *) p; + + /* Parse the expression into internal form. */ + if (__libdw_intern_expression (NULL, + fs->cache->other_byte_order, + address_size, 4, + &fs->cache->expr_tree, &block, + true, reg->rule == reg_val_expression, + ops, nops, IDX_debug_frame) < 0) + return -1; + break; + } + } + + return 0; +} diff --git a/src/libdw/dwarf_func_inline.c b/src/libdw/dwarf_func_inline.c new file mode 100644 index 00000000..6018691a --- /dev/null +++ b/src/libdw/dwarf_func_inline.c @@ -0,0 +1,121 @@ +/* Convenience functions for handling DWARF descriptions of inline functions. + Copyright (C) 2005,2006 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under an Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) and to distribute linked + combinations including the two. Non-GPL Code permitted under this + exception must only link to the code of Red Hat elfutils through those + well defined interfaces identified in the file named EXCEPTION found in + the source code files (the "Approved Interfaces"). The files of Non-GPL + Code may instantiate templates or use macros or inline functions from + the Approved Interfaces without causing the resulting work to be covered + by the GNU General Public License. Only Red Hat, Inc. may make changes + or additions to the list of Approved Interfaces. Red Hat's grant of + this exception is conditioned upon your not adding any new exceptions. + If you wish to add a new Approved Interface or exception, please contact + Red Hat. You must obey the GNU General Public License in all respects + for all of the Red Hat elfutils code and other code used in conjunction + with Red Hat elfutils except the Non-GPL Code covered by this exception. + If you modify this file, you may extend this exception to your version + of the file, but you are not obligated to do so. If you do not wish to + provide this exception without modification, you must delete this + exception statement from your version and license this file solely under + the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "libdwP.h" +#include <dwarf.h> + +struct visitor_info +{ + void *die_addr; + int (*callback) (Dwarf_Die *, void *); + void *arg; +}; + +static int +scope_visitor (unsigned int depth __attribute__ ((unused)), + struct Dwarf_Die_Chain *die, void *arg) +{ + struct visitor_info *const v = arg; + + if (INTUSE(dwarf_tag) (&die->die) != DW_TAG_inlined_subroutine) + return DWARF_CB_OK; + + Dwarf_Attribute attr_mem; + Dwarf_Attribute *attr = INTUSE(dwarf_attr) (&die->die, DW_AT_abstract_origin, + &attr_mem); + if (attr == NULL) + return DWARF_CB_OK; + + Dwarf_Die origin_mem; + Dwarf_Die *origin = INTUSE(dwarf_formref_die) (attr, &origin_mem); + if (origin == NULL) + return DWARF_CB_ABORT; + + if (origin->addr != v->die_addr) + return DWARF_CB_OK; + + return (*v->callback) (&die->die, v->arg); +} + +int +dwarf_func_inline (Dwarf_Die *func) +{ + Dwarf_Attribute attr_mem; + Dwarf_Word val; + if (INTUSE(dwarf_formudata) (INTUSE(dwarf_attr) (func, DW_AT_inline, + &attr_mem), + &val) == 0) + switch (val) + { + case DW_INL_not_inlined: + return 0; + + case DW_INL_declared_not_inlined: + return -1; + + case DW_INL_inlined: + case DW_INL_declared_inlined: + return 1; + } + + return 0; +} + +int +dwarf_func_inline_instances (Dwarf_Die *func, + int (*callback) (Dwarf_Die *, void *), + void *arg) +{ + struct visitor_info v = { func->addr, callback, arg }; + struct Dwarf_Die_Chain cu = { .die = CUDIE (func->cu), .parent = NULL }; + return __libdw_visit_scopes (0, &cu, &scope_visitor, NULL, &v); +} diff --git a/src/libdw/dwarf_getabbrev.c b/src/libdw/dwarf_getabbrev.c new file mode 100644 index 00000000..07bf6dfc --- /dev/null +++ b/src/libdw/dwarf_getabbrev.c @@ -0,0 +1,170 @@ +/* Get abbreviation at given offset. + Copyright (C) 2003, 2004, 2005, 2006 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2003. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <assert.h> +#include <dwarf.h> +#include "libdwP.h" + + +Dwarf_Abbrev * +internal_function +__libdw_getabbrev (dbg, cu, offset, lengthp, result) + Dwarf *dbg; + struct Dwarf_CU *cu; + Dwarf_Off offset; + size_t *lengthp; + Dwarf_Abbrev *result; +{ + /* Don't fail if there is not .debug_abbrev section. */ + if (dbg->sectiondata[IDX_debug_abbrev] == NULL) + return NULL; + + if (offset >= dbg->sectiondata[IDX_debug_abbrev]->d_size) + { + __libdw_seterrno (DWARF_E_INVALID_OFFSET); + return NULL; + } + + const unsigned char *abbrevp + = (unsigned char *) dbg->sectiondata[IDX_debug_abbrev]->d_buf + offset; + + if (*abbrevp == '\0') + /* We are past the last entry. */ + return DWARF_END_ABBREV; + + /* 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. */ + const unsigned char *start_abbrevp = abbrevp; + unsigned int code; + get_uleb128 (code, abbrevp); + + /* Check whether this code is already in the hash table. */ + bool foundit = false; + Dwarf_Abbrev *abb = NULL; + if (cu == NULL + || (abb = Dwarf_Abbrev_Hash_find (&cu->abbrev_hash, code, NULL)) == NULL) + { + if (result == NULL) + abb = libdw_typed_alloc (dbg, Dwarf_Abbrev); + else + abb = result; + } + else + { + foundit = true; + + assert (abb->offset == offset); + + /* If the caller doesn't need the length we are done. */ + if (lengthp == NULL) + goto out; + } + + /* If there is already a value in the hash table we are going to + overwrite its content. This must not be a problem, since the + content better be the same. */ + abb->code = code; + get_uleb128 (abb->tag, abbrevp); + abb->has_children = *abbrevp++ == DW_CHILDREN_yes; + abb->attrp = (unsigned char *) abbrevp; + abb->offset = offset; + + /* Skip over all the attributes and count them while doing so. */ + abb->attrcnt = 0; + unsigned int attrname; + unsigned int attrform; + do + { + get_uleb128 (attrname, abbrevp); + get_uleb128 (attrform, abbrevp); + } + while (attrname != 0 && attrform != 0 && ++abb->attrcnt); + + /* Return the length to the caller if she asked for it. */ + if (lengthp != NULL) + *lengthp = abbrevp - start_abbrevp; + + /* Add the entry to the hash table. */ + if (cu != NULL && ! foundit) + (void) Dwarf_Abbrev_Hash_insert (&cu->abbrev_hash, abb->code, abb); + + out: + return abb; +} + + +Dwarf_Abbrev * +dwarf_getabbrev (die, offset, lengthp) + Dwarf_Die *die; + Dwarf_Off offset; + size_t *lengthp; +{ + return __libdw_getabbrev (die->cu->dbg, die->cu, + die->cu->orig_abbrev_offset + offset, lengthp, + NULL); +} diff --git a/src/libdw/dwarf_getabbrevattr.c b/src/libdw/dwarf_getabbrevattr.c new file mode 100644 index 00000000..05da17c9 --- /dev/null +++ b/src/libdw/dwarf_getabbrevattr.c @@ -0,0 +1,100 @@ +/* Get specific attribute of abbreviation. + Copyright (C) 2003, 2004, 2005 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2003. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <assert.h> +#include <dwarf.h> +#include "libdwP.h" + + +int +dwarf_getabbrevattr (abbrev, idx, namep, formp, offsetp) + Dwarf_Abbrev *abbrev; + size_t idx; + unsigned int *namep; + unsigned int *formp; + Dwarf_Off *offsetp; +{ + if (abbrev == NULL) + return -1; + + size_t cnt = 0; + const unsigned char *attrp = abbrev->attrp; + const unsigned char *start_attrp; + unsigned int name; + unsigned int form; + + do + { + start_attrp = attrp; + + /* Attribute code and form are encoded as ULEB128 values. */ + get_uleb128 (name, attrp); + get_uleb128 (form, attrp); + + /* If both values are zero the index is out of range. */ + if (name == 0 && form == 0) + return -1; + } + while (cnt++ < idx); + + /* Store the result if requested. */ + if (namep != NULL) + *namep = name; + if (formp != NULL) + *formp = form; + if (offsetp != NULL) + *offsetp = (start_attrp - abbrev->attrp) + abbrev->offset; + + return 0; +} diff --git a/src/libdw/dwarf_getabbrevcode.c b/src/libdw/dwarf_getabbrevcode.c new file mode 100644 index 00000000..edf492d8 --- /dev/null +++ b/src/libdw/dwarf_getabbrevcode.c @@ -0,0 +1,65 @@ +/* Get abbreviation code. + Copyright (C) 2003 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2003. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <assert.h> +#include <dwarf.h> +#include "libdwP.h" + + +unsigned int +dwarf_getabbrevcode (abbrev) + Dwarf_Abbrev *abbrev; +{ + return abbrev == NULL ? 0 : abbrev->code; +} diff --git a/src/libdw/dwarf_getabbrevtag.c b/src/libdw/dwarf_getabbrevtag.c new file mode 100644 index 00000000..4f1f72ca --- /dev/null +++ b/src/libdw/dwarf_getabbrevtag.c @@ -0,0 +1,65 @@ +/* Get abbreviation tag. + Copyright (C) 2003 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2003. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <assert.h> +#include <dwarf.h> +#include "libdwP.h" + + +unsigned int +dwarf_getabbrevtag (abbrev) + Dwarf_Abbrev *abbrev; +{ + return abbrev == NULL ? 0 : abbrev->tag; +} diff --git a/src/libdw/dwarf_getarange_addr.c b/src/libdw/dwarf_getarange_addr.c new file mode 100644 index 00000000..855c855b --- /dev/null +++ b/src/libdw/dwarf_getarange_addr.c @@ -0,0 +1,83 @@ +/* Get address range which includes given address. + Copyright (C) 2004, 2005 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2004. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <libdwP.h> + + +Dwarf_Arange * +dwarf_getarange_addr (aranges, addr) + Dwarf_Aranges *aranges; + Dwarf_Addr addr; +{ + if (aranges == NULL) + return NULL; + + /* The ranges are sorted by address, so we can use binary search. */ + size_t l = 0, u = aranges->naranges; + while (l < u) + { + size_t idx = (l + u) / 2; + if (addr < aranges->info[idx].addr) + u = idx; + else if (addr > aranges->info[idx].addr + && addr - aranges->info[idx].addr >= aranges->info[idx].length) + l = idx + 1; + else + return &aranges->info[idx]; + } + + __libdw_seterrno (DWARF_E_NO_MATCH); + return NULL; +} +INTDEF(dwarf_getarange_addr) diff --git a/src/libdw/dwarf_getarangeinfo.c b/src/libdw/dwarf_getarangeinfo.c new file mode 100644 index 00000000..7cefbf71 --- /dev/null +++ b/src/libdw/dwarf_getarangeinfo.c @@ -0,0 +1,74 @@ +/* Return list address ranges. + Copyright (C) 2000, 2001, 2002, 2004, 2005 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2000. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <libdwP.h> + + +int +dwarf_getarangeinfo (Dwarf_Arange *arange, Dwarf_Addr *addrp, + Dwarf_Word *lengthp, Dwarf_Off *offsetp) +{ + if (arange == NULL) + return -1; + + if (addrp != NULL) + *addrp = arange->addr; + if (lengthp != NULL) + *lengthp = arange->length; + if (offsetp != NULL) + *offsetp = arange->offset; + + return 0; +} +INTDEF(dwarf_getarangeinfo) diff --git a/src/libdw/dwarf_getaranges.c b/src/libdw/dwarf_getaranges.c new file mode 100644 index 00000000..f18d63d0 --- /dev/null +++ b/src/libdw/dwarf_getaranges.c @@ -0,0 +1,283 @@ +/* Return list address ranges. + Copyright (C) 2000-2010 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2000. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdlib.h> +#include <assert.h> +#include "libdwP.h" +#include <dwarf.h> + +struct arangelist +{ + Dwarf_Arange arange; + struct arangelist *next; +}; + +/* Compare by Dwarf_Arange.addr, given pointers into an array of pointeers. */ +static int +compare_aranges (const void *a, const void *b) +{ + struct arangelist *const *p1 = a, *const *p2 = b; + struct arangelist *l1 = *p1, *l2 = *p2; + return l1->arange.addr - l2->arange.addr; +} + +int +dwarf_getaranges (dbg, aranges, naranges) + Dwarf *dbg; + Dwarf_Aranges **aranges; + size_t *naranges; +{ + if (dbg == NULL) + return -1; + + if (dbg->aranges != NULL) + { + *aranges = dbg->aranges; + if (naranges != NULL) + *naranges = dbg->aranges->naranges; + return 0; + } + + if (dbg->sectiondata[IDX_debug_aranges] == NULL) + { + /* No such section. */ + *aranges = NULL; + if (naranges != NULL) + *naranges = 0; + return 0; + } + + if (dbg->sectiondata[IDX_debug_aranges]->d_buf == NULL) + return -1; + + struct arangelist *arangelist = NULL; + unsigned int narangelist = 0; + + const unsigned char *readp = dbg->sectiondata[IDX_debug_aranges]->d_buf; + const unsigned char *readendp + = readp + dbg->sectiondata[IDX_debug_aranges]->d_size; + + while (readp < readendp) + { + const unsigned char *hdrstart = readp; + + /* 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. */ + Dwarf_Word length = read_4ubyte_unaligned_inc (dbg, readp); + unsigned int length_bytes = 4; + if (length == DWARF3_LENGTH_64_BIT) + { + length = read_8ubyte_unaligned_inc (dbg, readp); + length_bytes = 8; + } + else if (unlikely (length >= DWARF3_LENGTH_MIN_ESCAPE_CODE + && length <= DWARF3_LENGTH_MAX_ESCAPE_CODE)) + goto invalid; + + unsigned int version = read_2ubyte_unaligned_inc (dbg, readp); + if (version != 2) + { + invalid: + __libdw_seterrno (DWARF_E_INVALID_DWARF); + fail: + while (arangelist != NULL) + { + struct arangelist *next = arangelist->next; + free (arangelist); + arangelist = next; + } + return -1; + } + + Dwarf_Word offset; + if (__libdw_read_offset_inc (dbg, + IDX_debug_aranges, &readp, + length_bytes, &offset, IDX_debug_info, 4)) + goto fail; + + unsigned int address_size = *readp++; + if (address_size != 4 && address_size != 8) + goto invalid; + + /* Ignore the segment size value. */ + // XXX Really? + (void) *readp++; + + /* Round the address to the next multiple of 2*address_size. */ + readp += ((2 * address_size - ((readp - hdrstart) % (2 * address_size))) + % (2 * address_size)); + + while (1) + { + Dwarf_Word range_address; + Dwarf_Word range_length; + + if (__libdw_read_address_inc (dbg, IDX_debug_aranges, &readp, + address_size, &range_address)) + goto fail; + + if (address_size == 4) + range_length = read_4ubyte_unaligned_inc (dbg, readp); + else + range_length = read_8ubyte_unaligned_inc (dbg, readp); + + /* Two zero values mark the end. */ + if (range_address == 0 && range_length == 0) + break; + + /* We don't use alloca for these temporary structures because + the total number of them can be quite large. */ + struct arangelist *new_arange = malloc (sizeof *new_arange); + if (unlikely (new_arange == NULL)) + { + __libdw_seterrno (DWARF_E_NOMEM); + goto fail; + } + + new_arange->arange.addr = range_address; + new_arange->arange.length = range_length; + + /* We store the actual CU DIE offset, not the CU header offset. */ + const char *cu_header = (dbg->sectiondata[IDX_debug_info]->d_buf + + offset); + unsigned int offset_size; + if (read_4ubyte_unaligned_noncvt (cu_header) == DWARF3_LENGTH_64_BIT) + offset_size = 8; + else + offset_size = 4; + new_arange->arange.offset = DIE_OFFSET_FROM_CU_OFFSET (offset, + offset_size, + false); + + new_arange->next = arangelist; + arangelist = new_arange; + ++narangelist; + + /* Sanity-check the data. */ + if (unlikely (new_arange->arange.offset + >= dbg->sectiondata[IDX_debug_info]->d_size)) + goto invalid; + } + } + + if (narangelist == 0) + { + assert (arangelist == NULL); + if (naranges != NULL) + *naranges = 0; + *aranges = NULL; + return 0; + } + + /* Allocate the array for the result. */ + void *buf = libdw_alloc (dbg, Dwarf_Aranges, + sizeof (Dwarf_Aranges) + + narangelist * sizeof (Dwarf_Arange), 1); + + /* First use the buffer for the pointers, and sort the entries. + We'll write the pointers in the end of the buffer, and then + copy into the buffer from the beginning so the overlap works. */ + assert (sizeof (Dwarf_Arange) >= sizeof (Dwarf_Arange *)); + struct arangelist **sortaranges + = (buf + sizeof (Dwarf_Aranges) + + ((sizeof (Dwarf_Arange) - sizeof sortaranges[0]) * narangelist)); + + /* The list is in LIFO order and usually they come in clumps with + ascending addresses. So fill from the back to probably start with + runs already in order before we sort. */ + unsigned int i = narangelist; + while (i-- > 0) + { + sortaranges[i] = arangelist; + arangelist = arangelist->next; + } + assert (arangelist == NULL); + + /* Sort by ascending address. */ + qsort (sortaranges, narangelist, sizeof sortaranges[0], &compare_aranges); + + /* Now that they are sorted, put them in the final array. + The buffers overlap, so we've clobbered the early elements + of SORTARANGES by the time we're reading the later ones. */ + *aranges = buf; + (*aranges)->dbg = dbg; + (*aranges)->naranges = narangelist; + dbg->aranges = *aranges; + if (naranges != NULL) + *naranges = narangelist; + for (i = 0; i < narangelist; ++i) + { + struct arangelist *elt = sortaranges[i]; + (*aranges)->info[i] = elt->arange; + free (elt); + } + + return 0; +} +INTDEF(dwarf_getaranges) diff --git a/src/libdw/dwarf_getattrcnt.c b/src/libdw/dwarf_getattrcnt.c new file mode 100644 index 00000000..f85adf0f --- /dev/null +++ b/src/libdw/dwarf_getattrcnt.c @@ -0,0 +1,69 @@ +/* Get number of attributes of abbreviation. + Copyright (C) 2003, 2004 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2003. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "libdwP.h" + + +int +dwarf_getattrcnt (abbrev, attrcntp) + Dwarf_Abbrev *abbrev; + size_t *attrcntp; +{ + if (abbrev == NULL) + return -1; + + *attrcntp = abbrev->attrcnt; + + return 0; +} diff --git a/src/libdw/dwarf_getattrs.c b/src/libdw/dwarf_getattrs.c new file mode 100644 index 00000000..051dc25f --- /dev/null +++ b/src/libdw/dwarf_getattrs.c @@ -0,0 +1,146 @@ +/* Get attributes of the DIE. + Copyright (C) 2004, 2005, 2008, 2009 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2004. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "libdwP.h" + + +ptrdiff_t +dwarf_getattrs (Dwarf_Die *die, int (*callback) (Dwarf_Attribute *, void *), + void *arg, ptrdiff_t offset) +{ + if (die == NULL) + return -1l; + + if (unlikely (offset == 1)) + return 1; + + const unsigned char *die_addr = die->addr; + + /* Get the abbreviation code. */ + unsigned int u128; + get_uleb128 (u128, die_addr); + + if (die->abbrev == NULL) + /* Find the abbreviation. */ + die->abbrev = __libdw_findabbrev (die->cu, u128); + + if (unlikely (die->abbrev == DWARF_END_ABBREV)) + { + invalid_dwarf: + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return -1l; + } + + /* This is where the attributes start. */ + const unsigned char *attrp = die->abbrev->attrp; + const unsigned char *const offset_attrp = die->abbrev->attrp + offset; + + /* Go over the list of attributes. */ + Dwarf *dbg = die->cu->dbg; + while (1) + { + /* Are we still in bounds? */ + if (unlikely (attrp + >= ((unsigned char *) dbg->sectiondata[IDX_debug_abbrev]->d_buf + + dbg->sectiondata[IDX_debug_abbrev]->d_size))) + goto invalid_dwarf; + + /* Get attribute name and form. */ + Dwarf_Attribute attr; + const unsigned char *remembered_attrp = attrp; + + // XXX Fix bound checks + get_uleb128 (attr.code, attrp); + get_uleb128 (attr.form, attrp); + + /* We can stop if we found the attribute with value zero. */ + if (attr.code == 0 && attr.form == 0) + /* Do not return 0 here - there would be no way to + distinguish this value from the attribute at offset 0. + Instead we return +1 which would never be a valid + offset of an attribute. */ + return 1l; + + /* If we are not to OFFSET_ATTRP yet, we just have to skip + the values of the intervening attributes. */ + if (remembered_attrp >= offset_attrp) + { + /* Fill in the rest. */ + attr.valp = (unsigned char *) die_addr; + attr.cu = die->cu; + + /* Now call the callback function. */ + if (callback (&attr, arg) != DWARF_CB_OK) + /* Return the offset of the start of the attribute, so that + dwarf_getattrs() can be restarted from this point if the + caller so desires. */ + return remembered_attrp - die->abbrev->attrp; + } + + /* Skip over the rest of this attribute (if there is any). */ + if (attr.form != 0) + { + size_t len = __libdw_form_val_len (dbg, die->cu, attr.form, + die_addr); + + if (unlikely (len == (size_t) -1l)) + /* Something wrong with the file. */ + return -1l; + + // XXX We need better boundary checks. + die_addr += len; + } + } + /* NOTREACHED */ +} diff --git a/src/libdw/dwarf_getcfi.c b/src/libdw/dwarf_getcfi.c new file mode 100644 index 00000000..c935631e --- /dev/null +++ b/src/libdw/dwarf_getcfi.c @@ -0,0 +1,94 @@ +/* Get CFI from DWARF file. + Copyright (C) 2009 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "libdwP.h" +#include "cfi.h" +#include <dwarf.h> + +Dwarf_CFI * +dwarf_getcfi (dbg) + Dwarf *dbg; +{ + if (dbg == NULL) + return NULL; + + if (dbg->cfi == NULL && dbg->sectiondata[IDX_debug_frame] != NULL) + { + Dwarf_CFI *cfi = libdw_typed_alloc (dbg, Dwarf_CFI); + + cfi->dbg = dbg; + cfi->data = (Elf_Data_Scn *) dbg->sectiondata[IDX_debug_frame]; + + cfi->search_table = NULL; + cfi->search_table_vaddr = 0; + cfi->search_table_entries = 0; + cfi->search_table_encoding = DW_EH_PE_omit; + + cfi->frame_vaddr = 0; + cfi->textrel = 0; + cfi->datarel = 0; + + cfi->e_ident = (unsigned char *) elf_getident (dbg->elf, NULL); + cfi->other_byte_order = dbg->other_byte_order; + + cfi->next_offset = 0; + cfi->cie_tree = cfi->fde_tree = cfi->expr_tree = NULL; + + cfi->ebl = NULL; + + dbg->cfi = cfi; + } + + return dbg->cfi; +} +INTDEF (dwarf_getcfi) diff --git a/src/libdw/dwarf_getcfi_elf.c b/src/libdw/dwarf_getcfi_elf.c new file mode 100644 index 00000000..64a2a885 --- /dev/null +++ b/src/libdw/dwarf_getcfi_elf.c @@ -0,0 +1,336 @@ +/* Get CFI from ELF file's exception-handling info. + Copyright (C) 2009-2010 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include "libdwP.h" +#include "cfi.h" +#include "encoded-value.h" +#include <dwarf.h> + + +static Dwarf_CFI * +allocate_cfi (Elf *elf, GElf_Addr vaddr) +{ + Dwarf_CFI *cfi = calloc (1, sizeof *cfi); + if (cfi == NULL) + { + __libdw_seterrno (DWARF_E_NOMEM); + return NULL; + } + + cfi->e_ident = (unsigned char *) elf_getident (elf, NULL); + if (cfi->e_ident == NULL) + { + free (cfi); + __libdw_seterrno (DWARF_E_GETEHDR_ERROR); + return NULL; + } + + if ((BYTE_ORDER == LITTLE_ENDIAN && cfi->e_ident[EI_DATA] == ELFDATA2MSB) + || (BYTE_ORDER == BIG_ENDIAN && cfi->e_ident[EI_DATA] == ELFDATA2LSB)) + cfi->other_byte_order = true; + + cfi->frame_vaddr = vaddr; + cfi->textrel = 0; /* XXX ? */ + cfi->datarel = 0; /* XXX ? */ + + return cfi; +} + +static const uint8_t * +parse_eh_frame_hdr (const uint8_t *hdr, size_t hdr_size, GElf_Addr hdr_vaddr, + const GElf_Ehdr *ehdr, GElf_Addr *eh_frame_vaddr, + size_t *table_entries, uint8_t *table_encoding) +{ + const uint8_t *h = hdr; + + if (*h++ != 1) /* version */ + return (void *) -1l; + + uint8_t eh_frame_ptr_encoding = *h++; + uint8_t fde_count_encoding = *h++; + uint8_t fde_table_encoding = *h++; + + if (eh_frame_ptr_encoding == DW_EH_PE_omit) + return (void *) -1l; + + /* Dummy used by read_encoded_value. */ + Elf_Data_Scn dummy_cfi_hdr_data = + { + .d = { .d_buf = (void *) hdr, .d_size = hdr_size } + }; + Dwarf_CFI dummy_cfi = + { + .e_ident = ehdr->e_ident, + .datarel = hdr_vaddr, + .frame_vaddr = hdr_vaddr, + .data = &dummy_cfi_hdr_data, + }; + + if (unlikely (read_encoded_value (&dummy_cfi, eh_frame_ptr_encoding, &h, + eh_frame_vaddr))) + return (void *) -1l; + + if (fde_count_encoding != DW_EH_PE_omit) + { + Dwarf_Word fde_count; + if (unlikely (read_encoded_value (&dummy_cfi, fde_count_encoding, &h, + &fde_count))) + return (void *) -1l; + if (fde_count != 0 && (size_t) fde_count == fde_count + && fde_table_encoding != DW_EH_PE_omit + && (fde_table_encoding &~ DW_EH_PE_signed) != DW_EH_PE_uleb128) + { + *table_entries = fde_count; + *table_encoding = fde_table_encoding; + return h; + } + } + + return NULL; +} + +static Dwarf_CFI * +getcfi_gnu_eh_frame (Elf *elf, const GElf_Ehdr *ehdr, const GElf_Phdr *phdr) +{ + if (unlikely (phdr->p_filesz < 4)) + goto invalid; + + Elf_Data *data = elf_getdata_rawchunk (elf, phdr->p_offset, phdr->p_filesz, + ELF_T_BYTE); + if (data == NULL) + { + invalid_hdr: + invalid: + /* XXX might be read error or corrupt phdr */ + __libdw_seterrno (DWARF_E_INVALID_CFI); + return NULL; + } + + Dwarf_Addr eh_frame_ptr; + size_t search_table_entries; + uint8_t search_table_encoding; + const uint8_t *search_table = parse_eh_frame_hdr (data->d_buf, phdr->p_filesz, + phdr->p_vaddr, ehdr, + &eh_frame_ptr, + &search_table_entries, + &search_table_encoding); + if (search_table == (void *) -1l) + goto invalid_hdr; + + Dwarf_Off eh_frame_offset = eh_frame_ptr - phdr->p_vaddr + phdr->p_offset; + Dwarf_Word eh_frame_size = 0; + + /* XXX we have no way without section headers to know the size + of the .eh_frame data. Calculate the largest it might possibly be. + This won't be wasteful if the file is already mmap'd, but if it isn't + it might be quite excessive. */ + size_t filesize; + if (elf_rawfile (elf, &filesize) != NULL) + eh_frame_size = filesize - eh_frame_offset; + + data = elf_getdata_rawchunk (elf, eh_frame_offset, eh_frame_size, ELF_T_BYTE); + if (data == NULL) + { + __libdw_seterrno (DWARF_E_INVALID_ELF); /* XXX might be read error */ + return NULL; + } + Dwarf_CFI *cfi = allocate_cfi (elf, eh_frame_ptr); + if (cfi != NULL) + { + cfi->data = (Elf_Data_Scn *) data; + + if (search_table != NULL) + { + cfi->search_table = search_table; + cfi->search_table_vaddr = phdr->p_vaddr; + cfi->search_table_encoding = search_table_encoding; + cfi->search_table_entries = search_table_entries; + } + } + return cfi; +} + +/* Search the phdrs for PT_GNU_EH_FRAME. */ +static Dwarf_CFI * +getcfi_phdr (Elf *elf, const GElf_Ehdr *ehdr) +{ + size_t phnum; + if (unlikely (elf_getphdrnum (elf, &phnum) != 0)) + return NULL; + + for (size_t i = 0; i < phnum; ++i) + { + GElf_Phdr phdr_mem; + GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem); + if (unlikely (phdr == NULL)) + return NULL; + if (phdr->p_type == PT_GNU_EH_FRAME) + return getcfi_gnu_eh_frame (elf, ehdr, phdr); + } + + __libdw_seterrno (DWARF_E_NO_DWARF); + return NULL; +} + +static Dwarf_CFI * +getcfi_scn_eh_frame (Elf *elf, const GElf_Ehdr *ehdr, + Elf_Scn *scn, GElf_Shdr *shdr, + Elf_Scn *hdr_scn, GElf_Addr hdr_vaddr) +{ + Elf_Data *data = elf_rawdata (scn, NULL); + if (data == NULL) + { + __libdw_seterrno (DWARF_E_INVALID_ELF); + return NULL; + } + Dwarf_CFI *cfi = allocate_cfi (elf, shdr->sh_addr); + if (cfi != NULL) + { + cfi->data = (Elf_Data_Scn *) data; + if (hdr_scn != NULL) + { + Elf_Data *hdr_data = elf_rawdata (hdr_scn, NULL); + if (hdr_data != NULL) + { + GElf_Addr eh_frame_vaddr; + cfi->search_table_vaddr = hdr_vaddr; + cfi->search_table + = parse_eh_frame_hdr (hdr_data->d_buf, hdr_data->d_size, + hdr_vaddr, ehdr, &eh_frame_vaddr, + &cfi->search_table_entries, + &cfi->search_table_encoding); + if (cfi->search_table == (void *) -1l) + { + free (cfi); + /* XXX might be read error or corrupt phdr */ + __libdw_seterrno (DWARF_E_INVALID_CFI); + return NULL; + } + + /* Sanity check. */ + if (unlikely (eh_frame_vaddr != shdr->sh_addr)) + cfi->search_table = NULL; + } + } + } + return cfi; +} + +/* Search for the sections named ".eh_frame" and ".eh_frame_hdr". */ +static Dwarf_CFI * +getcfi_shdr (Elf *elf, const GElf_Ehdr *ehdr) +{ + size_t shstrndx; + if (elf_getshdrstrndx (elf, &shstrndx) != 0) + { + __libdw_seterrno (DWARF_E_GETEHDR_ERROR); + return NULL; + } + + if (shstrndx != 0) + { + Elf_Scn *hdr_scn = NULL; + GElf_Addr hdr_vaddr = 0; + Elf_Scn *scn = NULL; + while ((scn = elf_nextscn (elf, scn)) != NULL) + { + GElf_Shdr shdr_mem; + GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); + if (shdr == NULL) + continue; + const char *name = elf_strptr (elf, shstrndx, shdr->sh_name); + if (name == NULL) + continue; + if (!strcmp (name, ".eh_frame_hdr")) + { + hdr_scn = scn; + hdr_vaddr = shdr->sh_addr; + } + else if (!strcmp (name, ".eh_frame")) + return getcfi_scn_eh_frame (elf, ehdr, scn, shdr, + hdr_scn, hdr_vaddr); + } + } + + return (void *) -1l; +} + +Dwarf_CFI * +dwarf_getcfi_elf (elf) + Elf *elf; +{ + if (elf_kind (elf) != ELF_K_ELF) + { + __libdw_seterrno (DWARF_E_NOELF); + return NULL; + } + + GElf_Ehdr ehdr_mem; + GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem); + if (unlikely (ehdr == NULL)) + { + __libdw_seterrno (DWARF_E_INVALID_ELF); + return NULL; + } + + Dwarf_CFI *result = getcfi_shdr (elf, ehdr); + if (result == (void *) -1l) + result = getcfi_phdr (elf, ehdr); + + return result; +} +INTDEF (dwarf_getcfi_elf) diff --git a/src/libdw/dwarf_getelf.c b/src/libdw/dwarf_getelf.c new file mode 100644 index 00000000..daf3b9a7 --- /dev/null +++ b/src/libdw/dwarf_getelf.c @@ -0,0 +1,69 @@ +/* Retrieve ELF descriptor used for DWARF access. + Copyright (C) 2002, 2004, 2007 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stddef.h> + +#include "libdwP.h" + + +Elf * +dwarf_getelf (dwarf) + Dwarf *dwarf; +{ + if (dwarf == NULL) + /* Some error occurred before. */ + return NULL; + + return dwarf->elf; +} diff --git a/src/libdw/dwarf_getfuncs.c b/src/libdw/dwarf_getfuncs.c new file mode 100644 index 00000000..c0352fbf --- /dev/null +++ b/src/libdw/dwarf_getfuncs.c @@ -0,0 +1,94 @@ +/* Get function information. + Copyright (C) 2005 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2005. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <dwarf.h> +#include "libdwP.h" + + +ptrdiff_t +dwarf_getfuncs (Dwarf_Die *cudie, int (*callback) (Dwarf_Die *, void *), + void *arg, ptrdiff_t offset) +{ + if (unlikely (cudie == NULL + || INTUSE(dwarf_tag) (cudie) != DW_TAG_compile_unit)) + return -1; + + Dwarf_Die die_mem; + Dwarf_Die *die; + + int res; + if (offset == 0) + res = INTUSE(dwarf_child) (cudie, &die_mem); + else + { + die = INTUSE(dwarf_offdie) (cudie->cu->dbg, offset, &die_mem); + res = INTUSE(dwarf_siblingof) (die, &die_mem); + } + die = res != 0 ? NULL : &die_mem; + + while (die != NULL) + { + if (INTUSE(dwarf_tag) (die) == DW_TAG_subprogram) + { + if (callback (die, arg) != DWARF_CB_OK) + return INTUSE(dwarf_dieoffset) (die); + } + + if (INTUSE(dwarf_siblingof) (die, &die_mem) != 0) + break; + } + + /* That's all. */ + return 0; +} diff --git a/src/libdw/dwarf_getlocation.c b/src/libdw/dwarf_getlocation.c new file mode 100644 index 00000000..f7a60f9f --- /dev/null +++ b/src/libdw/dwarf_getlocation.c @@ -0,0 +1,682 @@ +/* Return location expression list. + Copyright (C) 2000-2010 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2000. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <dwarf.h> +#include <search.h> +#include <stdlib.h> +#include <assert.h> + +#include <libdwP.h> + + +static bool +attr_ok (Dwarf_Attribute *attr) +{ + if (attr == NULL) + return false; + + /* Must be one of the attributes listed below. */ + switch (attr->code) + { + case DW_AT_location: + case DW_AT_data_member_location: + case DW_AT_vtable_elem_location: + case DW_AT_string_length: + case DW_AT_use_location: + case DW_AT_frame_base: + case DW_AT_return_addr: + case DW_AT_static_link: + break; + + default: + __libdw_seterrno (DWARF_E_NO_LOCLIST); + return false; + } + + return true; +} + + +struct loclist +{ + uint8_t atom; + Dwarf_Word number; + Dwarf_Word number2; + Dwarf_Word offset; + struct loclist *next; +}; + + +static int +loc_compare (const void *p1, const void *p2) +{ + const struct loc_s *l1 = (const struct loc_s *) p1; + const struct loc_s *l2 = (const struct loc_s *) p2; + + if ((uintptr_t) l1->addr < (uintptr_t) l2->addr) + return -1; + if ((uintptr_t) l1->addr > (uintptr_t) l2->addr) + return 1; + + return 0; +} + +/* For each DW_OP_implicit_value, we store a special entry in the cache. + This points us directly to the block data for later fetching. */ +static void +store_implicit_value (Dwarf *dbg, void **cache, Dwarf_Op *op, + unsigned char *data) +{ + struct loc_block_s *block = libdw_alloc (dbg, struct loc_block_s, + sizeof (struct loc_block_s), 1); + block->addr = op; + block->data = data + op->number2; + block->length = op->number; + (void) tsearch (block, cache, loc_compare); +} + +int +dwarf_getlocation_implicit_value (attr, op, return_block) + Dwarf_Attribute *attr; + const Dwarf_Op *op; + Dwarf_Block *return_block; +{ + if (attr == NULL) + return -1; + + struct loc_block_s fake = { .addr = (void *) op }; + struct loc_block_s **found = tfind (&fake, &attr->cu->locs, loc_compare); + if (unlikely (found == NULL)) + { + __libdw_seterrno (DWARF_E_NO_BLOCK); + return -1; + } + + return_block->length = (*found)->length; + return_block->data = (*found)->data; + return 0; +} + +/* DW_AT_data_member_location can be a constant as well as a loclistptr. + Only data[48] indicate a loclistptr. */ +static int +check_constant_offset (Dwarf_Attribute *attr, + Dwarf_Op **llbuf, size_t *listlen) +{ + if (attr->code != DW_AT_data_member_location) + return 1; + + switch (attr->form) + { + /* Punt for any non-constant form. */ + default: + return 1; + + case DW_FORM_data1: + case DW_FORM_data2: + case DW_FORM_data4: + case DW_FORM_data8: + case DW_FORM_sdata: + case DW_FORM_udata: + break; + } + + /* Check whether we already cached this location. */ + struct loc_s fake = { .addr = attr->valp }; + struct loc_s **found = tfind (&fake, &attr->cu->locs, loc_compare); + + if (found == NULL) + { + Dwarf_Word offset; + if (INTUSE(dwarf_formudata) (attr, &offset) != 0) + return -1; + + Dwarf_Op *result = libdw_alloc (attr->cu->dbg, + Dwarf_Op, sizeof (Dwarf_Op), 1); + + result->atom = DW_OP_plus_uconst; + result->number = offset; + result->number2 = 0; + result->offset = 0; + + /* Insert a record in the search tree so we can find it again later. */ + struct loc_s *newp = libdw_alloc (attr->cu->dbg, + struct loc_s, sizeof (struct loc_s), + 1); + newp->addr = attr->valp; + newp->loc = result; + newp->nloc = 1; + + found = tsearch (newp, &attr->cu->locs, loc_compare); + } + + assert ((*found)->nloc == 1); + + if (llbuf != NULL) + { + *llbuf = (*found)->loc; + *listlen = 1; + } + + return 0; +} + +int +internal_function +__libdw_intern_expression (Dwarf *dbg, bool other_byte_order, + unsigned int address_size, unsigned int ref_size, + void **cache, const Dwarf_Block *block, + bool cfap, bool valuep, + Dwarf_Op **llbuf, size_t *listlen, int sec_index) +{ + /* Check whether we already looked at this list. */ + struct loc_s fake = { .addr = block->data }; + struct loc_s **found = tfind (&fake, cache, loc_compare); + if (found != NULL) + { + /* We already saw it. */ + *llbuf = (*found)->loc; + *listlen = (*found)->nloc; + + if (valuep) + { + assert (*listlen > 1); + assert ((*llbuf)[*listlen - 1].atom == DW_OP_stack_value); + } + + return 0; + } + + const unsigned char *data = block->data; + const unsigned char *const end_data = data + block->length; + + const struct { bool other_byte_order; } bo = { other_byte_order }; + + struct loclist *loclist = NULL; + unsigned int n = 0; + /* Decode the opcodes. It is possible in some situations to have a + block of size zero. */ + while (data < end_data) + { + struct loclist *newloc; + newloc = (struct loclist *) alloca (sizeof (struct loclist)); + newloc->number = 0; + newloc->number2 = 0; + newloc->offset = data - block->data; + newloc->next = loclist; + loclist = newloc; + ++n; + + switch ((newloc->atom = *data++)) + { + case DW_OP_addr: + /* Address, depends on address size of CU. */ + if (__libdw_read_address_inc (dbg, sec_index, &data, + address_size, &newloc->number)) + return -1; + break; + + case DW_OP_call_ref: + /* DW_FORM_ref_addr, depends on offset size of CU. */ + if (__libdw_read_offset_inc (dbg, sec_index, &data, ref_size, + &newloc->number, IDX_debug_info, 0)) + return -1; + 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 ... DW_OP_lit31: + case DW_OP_reg0 ... DW_OP_reg31: + case DW_OP_nop: + case DW_OP_push_object_address: + case DW_OP_call_frame_cfa: + case DW_OP_form_tls_address: + case DW_OP_GNU_push_tls_address: + case DW_OP_stack_value: + /* No operand. */ + break; + + case DW_OP_const1u: + case DW_OP_pick: + case DW_OP_deref_size: + case DW_OP_xderef_size: + if (unlikely (data >= end_data)) + { + invalid: + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return -1; + } + + newloc->number = *data++; + break; + + case DW_OP_const1s: + if (unlikely (data >= end_data)) + goto invalid; + + newloc->number = *((int8_t *) data); + ++data; + break; + + case DW_OP_const2u: + if (unlikely (data + 2 > end_data)) + goto invalid; + + newloc->number = read_2ubyte_unaligned_inc (&bo, data); + break; + + case DW_OP_const2s: + case DW_OP_skip: + case DW_OP_bra: + case DW_OP_call2: + if (unlikely (data + 2 > end_data)) + goto invalid; + + newloc->number = read_2sbyte_unaligned_inc (&bo, data); + break; + + case DW_OP_const4u: + if (unlikely (data + 4 > end_data)) + goto invalid; + + newloc->number = read_4ubyte_unaligned_inc (&bo, data); + break; + + case DW_OP_const4s: + case DW_OP_call4: + if (unlikely (data + 4 > end_data)) + goto invalid; + + newloc->number = read_4sbyte_unaligned_inc (&bo, data); + break; + + case DW_OP_const8u: + if (unlikely (data + 8 > end_data)) + goto invalid; + + newloc->number = read_8ubyte_unaligned_inc (&bo, data); + break; + + case DW_OP_const8s: + if (unlikely (data + 8 > end_data)) + goto invalid; + + newloc->number = read_8sbyte_unaligned_inc (&bo, data); + 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, data); + break; + + case DW_OP_consts: + case DW_OP_breg0 ... DW_OP_breg31: + case DW_OP_fbreg: + /* XXX Check size. */ + get_sleb128 (newloc->number, data); + break; + + case DW_OP_bregx: + /* XXX Check size. */ + get_uleb128 (newloc->number, data); + get_sleb128 (newloc->number2, data); + break; + + case DW_OP_bit_piece: + /* XXX Check size. */ + get_uleb128 (newloc->number, data); + get_uleb128 (newloc->number2, data); + break; + + case DW_OP_implicit_value: + /* This cannot be used in a CFI expression. */ + if (unlikely (dbg == NULL)) + goto invalid; + + /* XXX Check size. */ + get_uleb128 (newloc->number, data); /* Block length. */ + if (unlikely ((Dwarf_Word) (end_data - data) < newloc->number)) + goto invalid; + newloc->number2 = data - block->data; /* Relative block offset. */ + data += newloc->number; /* Skip the block. */ + break; + + case DW_OP_GNU_implicit_pointer: + /* DW_FORM_ref_addr, depends on offset size of CU. */ + if (__libdw_read_offset_inc (dbg, sec_index, &data, ref_size, + &newloc->number, IDX_debug_info, 0)) + return -1; + /* XXX Check size. */ + get_uleb128 (newloc->number2, data); /* Byte offset. */ + break; + + default: + goto invalid; + } + } + + if (unlikely (n == 0)) + { + /* This is not allowed. + + XXX Is it? */ + goto invalid; + } + + if (valuep) + { + struct loclist *newloc; + newloc = (struct loclist *) alloca (sizeof (struct loclist)); + newloc->atom = DW_OP_stack_value; + newloc->number = 0; + newloc->number2 = 0; + newloc->offset = data - block->data; + newloc->next = loclist; + loclist = newloc; + ++n; + } + + if (cfap) + ++n; + + /* Allocate the array. */ + Dwarf_Op *result; + if (dbg != NULL) + result = libdw_alloc (dbg, Dwarf_Op, sizeof (Dwarf_Op), n); + else + { + result = malloc (sizeof *result * n); + if (result == NULL) + { + nomem: + __libdw_seterrno (DWARF_E_NOMEM); + return -1; + } + } + + /* Store the result. */ + *llbuf = result; + *listlen = n; + + if (cfap) + { + /* Synthesize the operation to push the CFA before the expression. */ + --n; + result[0].atom = DW_OP_call_frame_cfa; + result[0].number = 0; + result[0].number2 = 0; + result[0].offset = -1; + } + + do + { + /* We populate the array from the back since the list is backwards. */ + --n; + result[n].atom = loclist->atom; + result[n].number = loclist->number; + result[n].number2 = loclist->number2; + result[n].offset = loclist->offset; + + if (result[n].atom == DW_OP_implicit_value) + store_implicit_value (dbg, cache, &result[n], block->data); + + loclist = loclist->next; + } + while (n > 0); + + /* Insert a record in the search tree so that we can find it again later. */ + struct loc_s *newp; + if (dbg != NULL) + newp = libdw_alloc (dbg, struct loc_s, sizeof (struct loc_s), 1); + else + { + newp = malloc (sizeof *newp); + if (newp == NULL) + { + free (result); + goto nomem; + } + } + + newp->addr = block->data; + newp->loc = result; + newp->nloc = *listlen; + (void) tsearch (newp, cache, loc_compare); + + /* We did it. */ + return 0; +} + +static int +getlocation (struct Dwarf_CU *cu, const Dwarf_Block *block, + Dwarf_Op **llbuf, size_t *listlen, int sec_index) +{ + return __libdw_intern_expression (cu->dbg, cu->dbg->other_byte_order, + cu->address_size, (cu->version == 2 + ? cu->address_size + : cu->offset_size), + &cu->locs, block, + false, false, + llbuf, listlen, sec_index); +} + +int +dwarf_getlocation (attr, llbuf, listlen) + Dwarf_Attribute *attr; + Dwarf_Op **llbuf; + size_t *listlen; +{ + if (! attr_ok (attr)) + return -1; + + int result = check_constant_offset (attr, llbuf, listlen); + if (result != 1) + return result; + + /* If it has a block form, it's a single location expression. */ + Dwarf_Block block; + if (INTUSE(dwarf_formblock) (attr, &block) != 0) + return -1; + + return getlocation (attr->cu, &block, llbuf, listlen, cu_sec_idx (attr->cu)); +} + +int +dwarf_getlocation_addr (attr, address, llbufs, listlens, maxlocs) + Dwarf_Attribute *attr; + Dwarf_Addr address; + Dwarf_Op **llbufs; + size_t *listlens; + size_t maxlocs; +{ + if (! attr_ok (attr)) + return -1; + + if (llbufs == NULL) + maxlocs = SIZE_MAX; + + /* If it has a block form, it's a single location expression. */ + Dwarf_Block block; + if (INTUSE(dwarf_formblock) (attr, &block) == 0) + { + if (maxlocs == 0) + return 0; + if (llbufs != NULL && + getlocation (attr->cu, &block, &llbufs[0], &listlens[0], + cu_sec_idx (attr->cu)) != 0) + return -1; + return listlens[0] == 0 ? 0 : 1; + } + + int error = INTUSE(dwarf_errno) (); + if (unlikely (error != DWARF_E_NO_BLOCK)) + { + __libdw_seterrno (error); + return -1; + } + + int result = check_constant_offset (attr, &llbufs[0], &listlens[0]); + if (result != 1) + return result ?: 1; + + unsigned char *endp; + unsigned char *readp = __libdw_formptr (attr, IDX_debug_loc, + DWARF_E_NO_LOCLIST, &endp, NULL); + if (readp == NULL) + return -1; + + Dwarf_Addr base = (Dwarf_Addr) -1; + size_t got = 0; + while (got < maxlocs) + { + if (endp - readp < attr->cu->address_size * 2) + { + invalid: + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return -1; + } + + Dwarf_Addr begin; + Dwarf_Addr end; + + int status + = __libdw_read_begin_end_pair_inc (attr->cu->dbg, IDX_debug_loc, + &readp, attr->cu->address_size, + &begin, &end, &base); + if (status == 2) /* End of list entry. */ + break; + else if (status == 1) /* Base address selected. */ + continue; + else if (status < 0) + return status; + + if (endp - readp < 2) + goto invalid; + + /* We have a location expression. */ + block.length = read_2ubyte_unaligned_inc (attr->cu->dbg, readp); + block.data = readp; + if (endp - readp < (ptrdiff_t) block.length) + goto invalid; + readp += block.length; + + if (base == (Dwarf_Addr) -1) + { + /* Fetch the CU's base address. */ + Dwarf_Die cudie = CUDIE (attr->cu); + + /* Find the base address of the compilation unit. It will + normally be specified by DW_AT_low_pc. In DWARF-3 draft 4, + the base address could be overridden by DW_AT_entry_pc. It's + been removed, but GCC emits DW_AT_entry_pc and not DW_AT_lowpc + for compilation units with discontinuous ranges. */ + Dwarf_Attribute attr_mem; + if (unlikely (INTUSE(dwarf_lowpc) (&cudie, &base) != 0) + && INTUSE(dwarf_formaddr) (INTUSE(dwarf_attr) (&cudie, + DW_AT_entry_pc, + &attr_mem), + &base) != 0) + { + if (INTUSE(dwarf_errno) () != 0) + return -1; + + /* The compiler provided no base address when it should + have. Buggy GCC does this when it used absolute + addresses in the location list and no DW_AT_ranges. */ + base = 0; + } + } + + if (address >= base + begin && address < base + end) + { + /* This one matches the address. */ + if (llbufs != NULL + && unlikely (getlocation (attr->cu, &block, + &llbufs[got], &listlens[got], + IDX_debug_loc) != 0)) + return -1; + ++got; + } + } + + return got; +} diff --git a/src/libdw/dwarf_getlocation_implicit_pointer.c b/src/libdw/dwarf_getlocation_implicit_pointer.c new file mode 100644 index 00000000..4d9f6b99 --- /dev/null +++ b/src/libdw/dwarf_getlocation_implicit_pointer.c @@ -0,0 +1,86 @@ +/* Return associated attribute for DW_OP_GNU_implicit_pointer. + Copyright (C) 2010 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "libdwP.h" +#include <dwarf.h> + + +int +dwarf_getlocation_implicit_pointer (attr, op, result) + Dwarf_Attribute *attr; + const Dwarf_Op *op; + Dwarf_Attribute *result; +{ + if (attr == NULL) + return -1; + + if (unlikely (op->atom != DW_OP_GNU_implicit_pointer)) + { + __libdw_seterrno (DWARF_E_INVALID_ACCESS); + return -1; + } + + Dwarf_Die die; + if (__libdw_offdie (attr->cu->dbg, op->number, &die, + attr->cu->type_offset != 0) == NULL) + return -1; + + if (INTUSE(dwarf_attr) (&die, DW_AT_location, result) == NULL + && INTUSE(dwarf_attr) (&die, DW_AT_const_value, result) == NULL) + { + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return -1; + } + + return 0; +} diff --git a/src/libdw/dwarf_getmacros.c b/src/libdw/dwarf_getmacros.c new file mode 100644 index 00000000..b9ec34b9 --- /dev/null +++ b/src/libdw/dwarf_getmacros.c @@ -0,0 +1,165 @@ +/* Get macro information. + Copyright (C) 2002-2009 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <dwarf.h> +#include <string.h> + +#include <libdwP.h> + + +ptrdiff_t +dwarf_getmacros (die, callback, arg, offset) + Dwarf_Die *die; + int (*callback) (Dwarf_Macro *, void *); + void *arg; + ptrdiff_t offset; +{ + if (die == NULL) + return -1; + + Elf_Data *d = die->cu->dbg->sectiondata[IDX_debug_macinfo]; + if (unlikely (d == NULL) || unlikely (d->d_buf == NULL)) + { + __libdw_seterrno (DWARF_E_NO_ENTRY); + return -1; + } + + if (offset == 0) + { + /* Get the appropriate attribute. */ + Dwarf_Attribute attr; + if (INTUSE(dwarf_attr) (die, DW_AT_macro_info, &attr) == NULL) + return -1; + + /* Offset into the .debug_macinfo section. */ + Dwarf_Word macoff; + if (INTUSE(dwarf_formudata) (&attr, &macoff) != 0) + return -1; + + offset = macoff; + } + if (unlikely (offset > (ptrdiff_t) d->d_size)) + goto invalid; + + const unsigned char *readp = d->d_buf + offset; + const unsigned char *readendp = d->d_buf + d->d_size; + + if (readp == readendp) + return 0; + + while (readp < readendp) + { + unsigned int opcode = *readp++; + unsigned int u128; + unsigned int u128_2 = 0; + const char *str = NULL; + const unsigned char *endp; + + switch (opcode) + { + case DW_MACINFO_define: + case DW_MACINFO_undef: + case DW_MACINFO_vendor_ext: + /* For the first two opcodes the parameters are + line, string + For the latter + number, string. + We can treat these cases together. */ + get_uleb128 (u128, readp); + + endp = memchr (readp, '\0', readendp - readp); + if (endp == NULL) + goto invalid; + + str = (char *) readp; + readp = endp + 1; + break; + + case DW_MACINFO_start_file: + /* The two parameters are line and file index. */ + get_uleb128 (u128, readp); + get_uleb128 (u128_2, readp); + break; + + case DW_MACINFO_end_file: + /* No parameters for this one. */ + u128 = 0; + break; + + case 0: + /* Nothing more to do. */ + return 0; + + default: + goto invalid; + } + + Dwarf_Macro mac; + mac.opcode = opcode; + mac.param1 = u128; + if (str == NULL) + mac.param2.u = u128_2; + else + mac.param2.s = str; + + if (callback (&mac, arg) != DWARF_CB_OK) + return readp - (const unsigned char *) d->d_buf; + } + + /* If we come here the termination of the data for the CU is not + present. */ + invalid: + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return -1; +} diff --git a/src/libdw/dwarf_getpubnames.c b/src/libdw/dwarf_getpubnames.c new file mode 100644 index 00000000..5560a758 --- /dev/null +++ b/src/libdw/dwarf_getpubnames.c @@ -0,0 +1,252 @@ +/* Get public symbol information. + Copyright (C) 2002, 2003, 2004, 2005, 2008 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <assert.h> +#include <stdlib.h> +#include <string.h> +#include <sys/param.h> + +#include <libdwP.h> +#include <dwarf.h> + + +static int +get_offsets (Dwarf *dbg) +{ + size_t allocated = 0; + size_t cnt = 0; + struct pubnames_s *mem = NULL; + const size_t entsize = sizeof (struct pubnames_s); + unsigned char *const startp = dbg->sectiondata[IDX_debug_pubnames]->d_buf; + unsigned char *readp = startp; + unsigned char *endp = readp + dbg->sectiondata[IDX_debug_pubnames]->d_size; + + while (readp + 14 < endp) + { + /* If necessary, allocate more entries. */ + if (cnt >= allocated) + { + allocated = MAX (10, 2 * allocated); + struct pubnames_s *newmem + = (struct pubnames_s *) realloc (mem, allocated * entsize); + if (newmem == NULL) + { + __libdw_seterrno (DWARF_E_NOMEM); + err_return: + free (mem); + return -1; + } + + mem = newmem; + } + + /* Read the set header. */ + int len_bytes = 4; + Dwarf_Off len = read_4ubyte_unaligned_inc (dbg, readp); + if (len == DWARF3_LENGTH_64_BIT) + { + len = read_8ubyte_unaligned_inc (dbg, readp); + len_bytes = 8; + } + else if (unlikely (len >= DWARF3_LENGTH_MIN_ESCAPE_CODE + && len <= DWARF3_LENGTH_MAX_ESCAPE_CODE)) + { + __libdw_seterrno (DWARF_E_INVALID_DWARF); + goto err_return; + } + + /* Now we know the offset of the first offset/name pair. */ + mem[cnt].set_start = readp + 2 + 2 * len_bytes - startp; + mem[cnt].address_len = len_bytes; + if (mem[cnt].set_start >= dbg->sectiondata[IDX_debug_pubnames]->d_size) + /* Something wrong, the first entry is beyond the end of + the section. */ + break; + + /* Read the version. It better be two for now. */ + uint16_t version = read_2ubyte_unaligned (dbg, readp); + if (unlikely (version != 2)) + { + __libdw_seterrno (DWARF_E_INVALID_VERSION); + goto err_return; + } + + /* Get the CU offset. */ + if (__libdw_read_offset (dbg, IDX_debug_pubnames, readp + 2, len_bytes, + &mem[cnt].cu_offset, IDX_debug_info, 3)) + /* Error has been already set in reader. */ + goto err_return; + + /* Determine the size of the CU header. */ + unsigned char *infop + = ((unsigned char *) dbg->sectiondata[IDX_debug_info]->d_buf + + mem[cnt].cu_offset); + if (read_4ubyte_unaligned_noncvt (infop) == DWARF3_LENGTH_64_BIT) + mem[cnt].cu_header_size = 23; + else + mem[cnt].cu_header_size = 11; + + ++cnt; + + /* Advance to the next set. */ + readp += len; + } + + if (mem == NULL) + { + __libdw_seterrno (DWARF_E_NO_ENTRY); + return -1; + } + + dbg->pubnames_sets = (struct pubnames_s *) realloc (mem, cnt * entsize); + dbg->pubnames_nsets = cnt; + + return 0; +} + + +ptrdiff_t +dwarf_getpubnames (dbg, callback, arg, offset) + Dwarf *dbg; + int (*callback) (Dwarf *, Dwarf_Global *, void *); + void *arg; + ptrdiff_t offset; +{ + if (dbg == NULL) + return -1l; + + if (unlikely (offset < 0)) + { + __libdw_seterrno (DWARF_E_INVALID_OFFSET); + return -1l; + } + + /* Make sure it is a valid offset. */ + if (unlikely (dbg->sectiondata[IDX_debug_pubnames] == NULL + || ((size_t) offset + >= dbg->sectiondata[IDX_debug_pubnames]->d_size))) + /* No (more) entry. */ + return 0; + + /* If necessary read the set information. */ + if (dbg->pubnames_nsets == 0 && unlikely (get_offsets (dbg) != 0)) + return -1l; + + /* Find the place where to start. */ + size_t cnt; + if (offset == 0) + { + cnt = 0; + offset = dbg->pubnames_sets[0].set_start; + } + else + { + for (cnt = 0; cnt + 1 < dbg->pubnames_nsets; ++cnt) + if ((Dwarf_Off) offset >= dbg->pubnames_sets[cnt].set_start) + { + assert ((Dwarf_Off) offset + < dbg->pubnames_sets[cnt + 1].set_start); + break; + } + assert (cnt + 1 < dbg->pubnames_nsets); + } + + unsigned char *startp + = (unsigned char *) dbg->sectiondata[IDX_debug_pubnames]->d_buf; + unsigned char *readp = startp + offset; + while (1) + { + Dwarf_Global gl; + + gl.cu_offset = (dbg->pubnames_sets[cnt].cu_offset + + dbg->pubnames_sets[cnt].cu_header_size); + + while (1) + { + /* READP points to the next offset/name pair. */ + if (dbg->pubnames_sets[cnt].address_len == 4) + gl.die_offset = read_4ubyte_unaligned_inc (dbg, readp); + else + gl.die_offset = read_8ubyte_unaligned_inc (dbg, readp); + + /* If the offset is zero we reached the end of the set. */ + if (gl.die_offset == 0) + break; + + /* Add the CU offset. */ + gl.die_offset += dbg->pubnames_sets[cnt].cu_offset; + + gl.name = (char *) readp; + readp = (unsigned char *) rawmemchr (gl.name, '\0') + 1; + + /* We found name and DIE offset. Report it. */ + if (callback (dbg, &gl, arg) != DWARF_CB_OK) + { + /* The user wants us to stop. Return the offset of the + next entry. */ + return readp - startp; + } + } + + if (++cnt == dbg->pubnames_nsets) + /* This was the last set. */ + break; + + startp = (unsigned char *) dbg->sectiondata[IDX_debug_pubnames]->d_buf; + readp = startp + dbg->pubnames_sets[cnt].set_start; + } + + /* We are done. No more entries. */ + return 0; +} diff --git a/src/libdw/dwarf_getscopes.c b/src/libdw/dwarf_getscopes.c new file mode 100644 index 00000000..73431ba7 --- /dev/null +++ b/src/libdw/dwarf_getscopes.c @@ -0,0 +1,222 @@ +/* Return scope DIEs containing PC address. + Copyright (C) 2005, 2007 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <assert.h> +#include <stdlib.h> +#include "libdwP.h" +#include <dwarf.h> + + +struct args +{ + Dwarf_Addr pc; + Dwarf_Die *scopes; + unsigned int inlined, nscopes; + Dwarf_Die inlined_origin; +}; + +/* Preorder visitor: prune the traversal if this DIE does not contain PC. */ +static int +pc_match (unsigned int depth, struct Dwarf_Die_Chain *die, void *arg) +{ + struct args *a = arg; + + if (a->scopes != NULL) + die->prune = true; + else + { + /* dwarf_haspc returns an error if there are no appropriate attributes. + But we use it indiscriminantly instead of presuming which tags can + have PC attributes. So when it fails for that reason, treat it just + as a nonmatching return. */ + int result = INTUSE(dwarf_haspc) (&die->die, a->pc); + if (result < 0) + { + int error = INTUSE(dwarf_errno) (); + if (error != DWARF_E_NOERROR && error != DWARF_E_NO_DEBUG_RANGES) + { + __libdw_seterrno (error); + return -1; + } + result = 0; + } + if (result == 0) + die->prune = true; + + if (!die->prune + && INTUSE (dwarf_tag) (&die->die) == DW_TAG_inlined_subroutine) + a->inlined = depth; + } + + return 0; +} + +/* Preorder visitor for second partial traversal after finding a + concrete inlined instance. */ +static int +origin_match (unsigned int depth, struct Dwarf_Die_Chain *die, void *arg) +{ + struct args *a = arg; + + if (die->die.addr != a->inlined_origin.addr) + return 0; + + /* We have a winner! This is the abstract definition of the inline + function of which A->scopes[A->nscopes - 1] is a concrete instance. + */ + + unsigned int nscopes = a->nscopes + depth; + Dwarf_Die *scopes = realloc (a->scopes, nscopes * sizeof scopes[0]); + if (scopes == NULL) + { + free (a->scopes); + __libdw_seterrno (DWARF_E_NOMEM); + return -1; + } + + a->scopes = scopes; + do + { + die = die->parent; + scopes[a->nscopes++] = die->die; + } + while (a->nscopes < nscopes); + assert (die->parent == NULL); + return a->nscopes; +} + +/* Postorder visitor: first (innermost) call wins. */ +static int +pc_record (unsigned int depth, struct Dwarf_Die_Chain *die, void *arg) +{ + struct args *a = arg; + + if (die->prune) + return 0; + + if (a->scopes == NULL) + { + /* We have hit the innermost DIE that contains the target PC. */ + + a->nscopes = depth + 1 - a->inlined; + a->scopes = malloc (a->nscopes * sizeof a->scopes[0]); + if (a->scopes == NULL) + { + __libdw_seterrno (DWARF_E_NOMEM); + return -1; + } + + for (unsigned int i = 0; i < a->nscopes; ++i) + { + a->scopes[i] = die->die; + die = die->parent; + } + + if (a->inlined == 0) + { + assert (die == NULL); + return a->nscopes; + } + + /* This is the concrete inlined instance itself. + Record its abstract_origin pointer. */ + Dwarf_Die *const inlinedie = &a->scopes[depth - a->inlined]; + + assert (INTUSE (dwarf_tag) (inlinedie) == DW_TAG_inlined_subroutine); + Dwarf_Attribute attr_mem; + Dwarf_Attribute *attr = INTUSE (dwarf_attr) (inlinedie, + DW_AT_abstract_origin, + &attr_mem); + if (INTUSE (dwarf_formref_die) (attr, &a->inlined_origin) == NULL) + return -1; + return 0; + } + + + /* We've recorded the scopes back to one that is a concrete inlined + instance. Now return out of the traversal back to the scope + containing that instance. */ + + assert (a->inlined); + if (depth >= a->inlined) + /* Not there yet. */ + return 0; + + /* Now we are in a scope that contains the concrete inlined instance. + Search it for the inline function's abstract definition. + If we don't find it, return to search the containing scope. + If we do find it, the nonzero return value will bail us out + of the postorder traversal. */ + return __libdw_visit_scopes (depth, die, &origin_match, NULL, a); +} + + +int +dwarf_getscopes (Dwarf_Die *cudie, Dwarf_Addr pc, Dwarf_Die **scopes) +{ + if (cudie == NULL) + return -1; + + struct Dwarf_Die_Chain cu = { .parent = NULL, .die = *cudie }; + struct args a = { .pc = pc }; + + int result = __libdw_visit_scopes (0, &cu, &pc_match, &pc_record, &a); + + if (result == 0 && a.scopes != NULL) + result = __libdw_visit_scopes (0, &cu, &origin_match, NULL, &a); + + if (result > 0) + *scopes = a.scopes; + + return result; +} diff --git a/src/libdw/dwarf_getscopes_die.c b/src/libdw/dwarf_getscopes_die.c new file mode 100644 index 00000000..07fb9b00 --- /dev/null +++ b/src/libdw/dwarf_getscopes_die.c @@ -0,0 +1,95 @@ +/* Return scope DIEs containing given DIE. + Copyright (C) 2005 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#include "libdwP.h" +#include <assert.h> +#include <stdlib.h> + +static int +scope_visitor (unsigned int depth, struct Dwarf_Die_Chain *die, void *arg) +{ + if (die->die.addr != *(void **) arg) + return 0; + + Dwarf_Die *scopes = malloc (depth * sizeof scopes[0]); + if (scopes == NULL) + { + __libdw_seterrno (DWARF_E_NOMEM); + return -1; + } + + unsigned int i = 0; + do + { + scopes[i++] = die->die; + die = die->parent; + } + while (die != NULL); + assert (i == depth); + + *(void **) arg = scopes; + return depth; +} + +int +dwarf_getscopes_die (Dwarf_Die *die, Dwarf_Die **scopes) +{ + if (die == NULL) + return -1; + + struct Dwarf_Die_Chain cu = { .die = CUDIE (die->cu), .parent = NULL }; + void *info = die->addr; + int result = __libdw_visit_scopes (1, &cu, &scope_visitor, NULL, &info); + if (result > 0) + *scopes = info; + return result; +} diff --git a/src/libdw/dwarf_getscopevar.c b/src/libdw/dwarf_getscopevar.c new file mode 100644 index 00000000..6ce214f5 --- /dev/null +++ b/src/libdw/dwarf_getscopevar.c @@ -0,0 +1,175 @@ +/* Find a named variable or parameter within given scopes. + Copyright (C) 2005-2009 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdbool.h> +#include <string.h> +#include "libdwP.h" +#include <dwarf.h> + + +/* Find the containing CU's files. */ +static int +getfiles (Dwarf_Die *die, Dwarf_Files **files) +{ + return INTUSE(dwarf_getsrcfiles) (&CUDIE (die->cu), files, NULL); +} + +/* Fetch an attribute that should have a constant integer form. */ +static int +getattr (Dwarf_Die *die, int search_name, Dwarf_Word *value) +{ + Dwarf_Attribute attr_mem; + return INTUSE(dwarf_formudata) (INTUSE(dwarf_attr) (die, search_name, + &attr_mem), value); +} + +/* Search SCOPES[0..NSCOPES-1] for a variable called NAME. + Ignore the first SKIP_SHADOWS scopes that match the name. + If MATCH_FILE is not null, accept only declaration in that source file; + if MATCH_LINENO or MATCH_LINECOL are also nonzero, accept only declaration + at that line and column. + + If successful, fill in *RESULT with the DIE of the variable found, + and return N where SCOPES[N] is the scope defining the variable. + Return -1 for errors or -2 for no matching variable found. */ + +int +dwarf_getscopevar (Dwarf_Die *scopes, int nscopes, + const char *name, int skip_shadows, + const char *match_file, int match_lineno, int match_linecol, + Dwarf_Die *result) +{ + /* Match against the given file name. */ + size_t match_file_len = match_file == NULL ? 0 : strlen (match_file); + bool lastfile_matches = false; + const char *lastfile = NULL; + inline bool file_matches (Dwarf_Files *files, size_t idx) + { + if (idx >= files->nfiles) + return false; + + const char *file = files->info[idx].name; + if (file != lastfile) + { + size_t len = strlen (file); + lastfile_matches = (len >= match_file_len + && !memcmp (match_file, file, match_file_len) + && (len == match_file_len + || file[len - match_file_len - 1] == '/')); + } + return lastfile_matches; + } + + /* Start with the innermost scope and move out. */ + for (int out = 0; out < nscopes; ++out) + if (INTUSE(dwarf_haschildren) (&scopes[out])) + { + if (INTUSE(dwarf_child) (&scopes[out], result) != 0) + return -1; + do + { + switch (INTUSE(dwarf_tag) (result)) + { + case DW_TAG_variable: + case DW_TAG_formal_parameter: + break; + + default: + continue; + } + + /* Only get here for a variable or parameter. Check the name. */ + const char *diename = INTUSE(dwarf_diename) (result); + if (diename != NULL && !strcmp (name, diename)) + { + /* We have a matching name. */ + + if (skip_shadows > 0) + { + /* Punt this scope for the one it shadows. */ + --skip_shadows; + break; + } + + if (match_file != NULL) + { + /* Check its decl_file. */ + + Dwarf_Word i; + Dwarf_Files *files; + if (getattr (result, DW_AT_decl_file, &i) != 0 + || getfiles (&scopes[out], &files) != 0) + break; + + if (!file_matches (files, i)) + break; + + if (match_lineno > 0 + && (getattr (result, DW_AT_decl_line, &i) != 0 + || (int) i != match_lineno)) + break; + if (match_linecol > 0 + && (getattr (result, DW_AT_decl_column, &i) != 0 + || (int) i != match_linecol)) + break; + } + + /* We have a winner! */ + return out; + } + } + while (INTUSE(dwarf_siblingof) (result, result) == 0); + } + + return -2; +} diff --git a/src/libdw/dwarf_getsrc_die.c b/src/libdw/dwarf_getsrc_die.c new file mode 100644 index 00000000..96aa41fd --- /dev/null +++ b/src/libdw/dwarf_getsrc_die.c @@ -0,0 +1,99 @@ +/* Find line information for address. + Copyright (C) 2004, 2005 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2004. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "libdwP.h" +#include <assert.h> + + +Dwarf_Line * +dwarf_getsrc_die (Dwarf_Die *cudie, Dwarf_Addr addr) +{ + Dwarf_Lines *lines; + size_t nlines; + + if (INTUSE(dwarf_getsrclines) (cudie, &lines, &nlines) != 0) + return NULL; + + /* The lines are sorted by address, so we can use binary search. */ + size_t l = 0, u = nlines; + while (l < u) + { + size_t idx = (l + u) / 2; + if (addr < lines->info[idx].addr) + u = idx; + else if (addr > lines->info[idx].addr || lines->info[idx].end_sequence) + l = idx + 1; + else + return &lines->info[idx]; + } + + if (nlines > 0) + assert (lines->info[nlines - 1].end_sequence); + + /* If none were equal, the closest one below is what we want. We + never want the last one, because it's the end-sequence marker + with an address at the high bound of the CU's code. If the debug + information is faulty and no end-sequence marker is present, we + still ignore it. */ + if (u > 0 && u < nlines && addr > lines->info[u - 1].addr) + { + while (lines->info[u - 1].end_sequence && u > 0) + --u; + if (u > 0) + return &lines->info[u - 1]; + } + + __libdw_seterrno (DWARF_E_ADDR_OUTOFRANGE); + return NULL; +} diff --git a/src/libdw/dwarf_getsrc_file.c b/src/libdw/dwarf_getsrc_file.c new file mode 100644 index 00000000..bc612f6c --- /dev/null +++ b/src/libdw/dwarf_getsrc_file.c @@ -0,0 +1,199 @@ +/* Find line information for given file/line/column triple. + Copyright (C) 2005-2009 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2005. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <assert.h> +#include <limits.h> +#include <stdlib.h> +#include <string.h> + +#include "libdwP.h" + + +int +dwarf_getsrc_file (Dwarf *dbg, const char *fname, int lineno, int column, + Dwarf_Line ***srcsp, size_t *nsrcs) +{ + if (dbg == NULL) + return -1; + + bool is_basename = strchr (fname, '/') == NULL; + + size_t max_match = *nsrcs ?: ~0u; + size_t act_match = *nsrcs; + size_t cur_match = 0; + Dwarf_Line **match = *nsrcs == 0 ? NULL : *srcsp; + + size_t cuhl; + Dwarf_Off noff; + for (Dwarf_Off off = 0; + INTUSE(dwarf_nextcu) (dbg, off, &noff, &cuhl, NULL, NULL, NULL) == 0; + off = noff) + { + Dwarf_Die cudie_mem; + Dwarf_Die *cudie = INTUSE(dwarf_offdie) (dbg, off + cuhl, &cudie_mem); + if (cudie == NULL) + continue; + + /* Get the line number information for this file. */ + Dwarf_Lines *lines; + size_t nlines; + if (INTUSE(dwarf_getsrclines) (cudie, &lines, &nlines) != 0) + { + /* Ignore a CU that just has no DW_AT_stmt_list at all. */ + int error = INTUSE(dwarf_errno) (); + if (error == 0) + continue; + __libdw_seterrno (error); + return -1; + } + + /* Search through all the line number records for a matching + file and line/column number. If any of the numbers is zero, + no match is performed. */ + unsigned int lastfile = UINT_MAX; + bool lastmatch = false; + for (size_t cnt = 0; cnt < nlines; ++cnt) + { + Dwarf_Line *line = &lines->info[cnt]; + + if (lastfile != line->file) + { + lastfile = line->file; + if (lastfile >= line->files->nfiles) + { + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return -1; + } + + /* Match the name with the name the user provided. */ + const char *fname2 = line->files->info[lastfile].name; + if (is_basename) + lastmatch = strcmp (basename (fname2), fname) == 0; + else + lastmatch = strcmp (fname2, fname) == 0; + } + if (!lastmatch) + continue; + + /* See whether line and possibly column match. */ + if (lineno != 0 + && (lineno > line->line + || (column != 0 && column > line->column))) + /* Cannot match. */ + continue; + + /* Determine whether this is the best match so far. */ + size_t inner; + for (inner = 0; inner < cur_match; ++inner) + if (match[inner]->files == line->files + && match[inner]->file == line->file) + break; + if (inner < cur_match + && (match[inner]->line != line->line + || match[inner]->line != lineno + || (column != 0 + && (match[inner]->column != line->column + || match[inner]->column != column)))) + { + /* We know about this file already. If this is a better + match for the line number, use it. */ + if (match[inner]->line >= line->line + && (match[inner]->line != line->line + || match[inner]->column >= line->column)) + /* Use the new line. Otherwise the old one. */ + match[inner] = line; + continue; + } + + if (cur_match < max_match) + { + if (cur_match == act_match) + { + /* Enlarge the array for the results. */ + act_match += 10; + Dwarf_Line **newp = realloc (match, + act_match + * sizeof (Dwarf_Line *)); + if (newp == NULL) + { + free (match); + __libdw_seterrno (DWARF_E_NOMEM); + return -1; + } + match = newp; + } + + match[cur_match++] = line; + } + } + + /* If we managed to find as many matches as the user requested + already, there is no need to go on to the next CU. */ + if (cur_match == max_match) + break; + } + + if (cur_match > 0) + { + assert (*nsrcs == 0 || *srcsp == match); + + *nsrcs = cur_match; + *srcsp = match; + + return 0; + } + + __libdw_seterrno (DWARF_E_NO_MATCH); + return -1; +} diff --git a/src/libdw/dwarf_getsrcdirs.c b/src/libdw/dwarf_getsrcdirs.c new file mode 100644 index 00000000..74786dd0 --- /dev/null +++ b/src/libdw/dwarf_getsrcdirs.c @@ -0,0 +1,69 @@ +/* Find include directories in source file information. + Copyright (C) 2007 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "libdwP.h" + + +int +dwarf_getsrcdirs (files, result, ndirs) + Dwarf_Files *files; + const char *const **result; + size_t *ndirs; +{ + if (files == NULL) + return -1; + + *result = (void *) &files->info[files->nfiles]; + *ndirs = files->ndirs; + return 0; +} diff --git a/src/libdw/dwarf_getsrcfiles.c b/src/libdw/dwarf_getsrcfiles.c new file mode 100644 index 00000000..ee4de520 --- /dev/null +++ b/src/libdw/dwarf_getsrcfiles.c @@ -0,0 +1,96 @@ +/* Return source file information of CU. + Copyright (C) 2004, 2005 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2004. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <assert.h> +#include <dwarf.h> +#include "libdwP.h" + + +int +dwarf_getsrcfiles (Dwarf_Die *cudie, Dwarf_Files **files, size_t *nfiles) +{ + if (unlikely (cudie == NULL + || INTUSE(dwarf_tag) (cudie) != DW_TAG_compile_unit)) + return -1; + + int res = -1; + + /* Get the information if it is not already known. */ + struct Dwarf_CU *const cu = cudie->cu; + if (cu->lines == NULL) + { + Dwarf_Lines *lines; + size_t nlines; + + /* Let the more generic function do the work. It'll create more + data but that will be needed in an real program anyway. */ + res = INTUSE(dwarf_getsrclines) (cudie, &lines, &nlines); + } + else if (cu->files != (void *) -1l) + /* We already have the information. */ + res = 0; + + if (likely (res == 0)) + { + assert (cu->files != NULL && cu->files != (void *) -1l); + *files = cu->files; + if (nfiles != NULL) + *nfiles = cu->files->nfiles; + } + + // XXX Eventually: unlocking here. + + return res; +} +INTDEF (dwarf_getsrcfiles) diff --git a/src/libdw/dwarf_getsrclines.c b/src/libdw/dwarf_getsrclines.c new file mode 100644 index 00000000..6840b2b5 --- /dev/null +++ b/src/libdw/dwarf_getsrclines.c @@ -0,0 +1,753 @@ +/* Return line number information of CU. + Copyright (C) 2004-2010 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2004. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <assert.h> +#include <stdlib.h> +#include <string.h> +#include "dwarf.h" +#include "libdwP.h" + + +struct filelist +{ + Dwarf_Fileinfo info; + struct filelist *next; +}; + +struct linelist +{ + Dwarf_Line line; + struct linelist *next; +}; + + +/* Compare by Dwarf_Line.addr, given pointers into an array of pointers. */ +static int +compare_lines (const void *a, const void *b) +{ + Dwarf_Line *const *p1 = a; + Dwarf_Line *const *p2 = b; + + if ((*p1)->addr == (*p2)->addr) + /* An end_sequence marker precedes a normal record at the same address. */ + return (*p2)->end_sequence - (*p1)->end_sequence; + + return (*p1)->addr - (*p2)->addr; +} + +int +dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines, size_t *nlines) +{ + if (unlikely (cudie == NULL + || INTUSE(dwarf_tag) (cudie) != DW_TAG_compile_unit)) + return -1; + + int res = -1; + + /* Get the information if it is not already known. */ + struct Dwarf_CU *const cu = cudie->cu; + if (cu->lines == NULL) + { + /* Failsafe mode: no data found. */ + cu->lines = (void *) -1l; + cu->files = (void *) -1l; + + /* The die must have a statement list associated. */ + Dwarf_Attribute stmt_list_mem; + Dwarf_Attribute *stmt_list = INTUSE(dwarf_attr) (cudie, DW_AT_stmt_list, + &stmt_list_mem); + + /* Get the offset into the .debug_line section. NB: this call + also checks whether the previous dwarf_attr call failed. */ + const unsigned char *lineendp; + const unsigned char *linep + = __libdw_formptr (stmt_list, IDX_debug_line, DWARF_E_NO_DEBUG_LINE, + (unsigned char **) &lineendp, NULL); + if (linep == NULL) + goto out; + + /* Get the compilation directory. */ + Dwarf_Attribute compdir_attr_mem; + Dwarf_Attribute *compdir_attr = INTUSE(dwarf_attr) (cudie, + DW_AT_comp_dir, + &compdir_attr_mem); + const char *comp_dir = INTUSE(dwarf_formstring) (compdir_attr); + + if (unlikely (linep + 4 > lineendp)) + { + invalid_data: + __libdw_seterrno (DWARF_E_INVALID_DEBUG_LINE); + goto out; + } + + Dwarf *dbg = cu->dbg; + Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep); + unsigned int length = 4; + if (unlikely (unit_length == DWARF3_LENGTH_64_BIT)) + { + if (unlikely (linep + 8 > lineendp)) + goto invalid_data; + unit_length = read_8ubyte_unaligned_inc (dbg, linep); + length = 8; + } + + /* Check whether we have enough room in the section. */ + if (unit_length < 2 + length + 5 * 1 + || unlikely (linep + unit_length > lineendp)) + goto invalid_data; + lineendp = linep + unit_length; + + /* The next element of the header is the version identifier. */ + uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep); + if (unlikely (version < 2) || unlikely (version > 4)) + { + __libdw_seterrno (DWARF_E_VERSION); + goto out; + } + + /* Next comes the header length. */ + Dwarf_Word header_length; + if (length == 4) + header_length = read_4ubyte_unaligned_inc (dbg, linep); + else + header_length = read_8ubyte_unaligned_inc (dbg, linep); + const unsigned char *header_start = linep; + + /* Next the minimum instruction length. */ + uint_fast8_t minimum_instr_len = *linep++; + + /* Next the maximum operations per instruction, in version 4 format. */ + uint_fast8_t max_ops_per_instr = 1; + if (version >= 4) + { + if (unlikely (lineendp - linep < 5)) + goto invalid_data; + max_ops_per_instr = *linep++; + if (unlikely (max_ops_per_instr == 0)) + goto invalid_data; + } + + /* Then the flag determining the default value of the is_stmt + register. */ + uint_fast8_t default_is_stmt = *linep++; + + /* Now the line base. */ + int_fast8_t line_base = (int8_t) *linep++; + + /* And the line range. */ + uint_fast8_t line_range = *linep++; + + /* The opcode base. */ + uint_fast8_t opcode_base = *linep++; + + /* Remember array with the standard opcode length (-1 to account for + the opcode with value zero not being mentioned). */ + const uint8_t *standard_opcode_lengths = linep - 1; + if (unlikely (lineendp - linep < opcode_base - 1)) + goto invalid_data; + linep += opcode_base - 1; + + /* First comes the list of directories. Add the compilation + directory first since the index zero is used for it. */ + struct dirlist + { + const char *dir; + size_t len; + struct dirlist *next; + } comp_dir_elem = + { + .dir = comp_dir, + .len = comp_dir ? strlen (comp_dir) : 0, + .next = NULL + }; + struct dirlist *dirlist = &comp_dir_elem; + unsigned int ndirlist = 1; + + // XXX Directly construct array to conserve memory? + while (*linep != 0) + { + struct dirlist *new_dir = + (struct dirlist *) alloca (sizeof (*new_dir)); + + new_dir->dir = (char *) linep; + uint8_t *endp = memchr (linep, '\0', lineendp - linep); + if (endp == NULL) + goto invalid_data; + new_dir->len = endp - linep; + new_dir->next = dirlist; + dirlist = new_dir; + ++ndirlist; + linep = endp + 1; + } + /* Skip the final NUL byte. */ + ++linep; + + /* Rearrange the list in array form. */ + struct dirlist **dirarray + = (struct dirlist **) alloca (ndirlist * sizeof (*dirarray)); + for (unsigned int n = ndirlist; n-- > 0; dirlist = dirlist->next) + dirarray[n] = dirlist; + + /* Now read the files. */ + struct filelist null_file = + { + .info = + { + .name = "???", + .mtime = 0, + .length = 0 + }, + .next = NULL + }; + struct filelist *filelist = &null_file; + unsigned int nfilelist = 1; + + if (unlikely (linep >= lineendp)) + goto invalid_data; + while (*linep != 0) + { + struct filelist *new_file = + (struct filelist *) alloca (sizeof (*new_file)); + + /* First comes the file name. */ + char *fname = (char *) linep; + uint8_t *endp = memchr (fname, '\0', lineendp - linep); + if (endp == NULL) + goto invalid_data; + size_t fnamelen = endp - (uint8_t *) fname; + linep = endp + 1; + + /* Then the index. */ + Dwarf_Word diridx; + get_uleb128 (diridx, linep); + if (unlikely (diridx >= ndirlist)) + { + __libdw_seterrno (DWARF_E_INVALID_DIR_IDX); + goto out; + } + + if (*fname == '/') + /* It's an absolute path. */ + new_file->info.name = fname; + else + { + new_file->info.name = libdw_alloc (dbg, char, 1, + dirarray[diridx]->len + 1 + + fnamelen + 1); + char *cp = new_file->info.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); + assert (strlen (new_file->info.name) + < dirarray[diridx]->len + 1 + fnamelen + 1); + } + + /* Next comes the modification time. */ + get_uleb128 (new_file->info.mtime, linep); + + /* Finally the length of the file. */ + get_uleb128 (new_file->info.length, linep); + + new_file->next = filelist; + filelist = new_file; + ++nfilelist; + } + /* Skip the final NUL byte. */ + ++linep; + + /* Consistency check. */ + if (unlikely (linep != header_start + header_length)) + { + __libdw_seterrno (DWARF_E_INVALID_DWARF); + goto out; + } + + /* We are about to process the statement program. Initialize the + state machine registers (see 6.2.2 in the v2.1 specification). */ + Dwarf_Word addr = 0; + unsigned int op_index = 0; + unsigned int file = 1; + int line = 1; + unsigned int column = 0; + uint_fast8_t is_stmt = default_is_stmt; + bool basic_block = false; + bool prologue_end = false; + bool epilogue_begin = false; + unsigned int isa = 0; + unsigned int discriminator = 0; + + /* Apply the "operation advance" from a special opcode + or DW_LNS_advance_pc (as per DWARF4 6.2.5.1). */ + inline void advance_pc (unsigned int op_advance) + { + addr += minimum_instr_len * ((op_index + op_advance) + / max_ops_per_instr); + op_index = (op_index + op_advance) % max_ops_per_instr; + } + + /* Process the instructions. */ + struct linelist *linelist = NULL; + unsigned int nlinelist = 0; + + /* Adds a new line to the matrix. + We cannot simply define a function because we want to use alloca. */ +#define NEW_LINE(end_seq) \ + do { \ + if (unlikely (add_new_line (alloca (sizeof (struct linelist)), \ + end_seq))) \ + goto invalid_data; \ + } while (0) + + inline bool add_new_line (struct linelist *new_line, bool end_sequence) + { + /* Set the line information. For some fields we use bitfields, + so we would lose information if the encoded values are too large. + Check just for paranoia, and call the data "invalid" if it + violates our assumptions on reasonable limits for the values. */ +#define SET(field) \ + do { \ + new_line->line.field = field; \ + if (unlikely (new_line->line.field != field)) \ + return true; \ + } while (0) + + SET (addr); + SET (op_index); + SET (file); + SET (line); + SET (column); + SET (is_stmt); + SET (basic_block); + SET (end_sequence); + SET (prologue_end); + SET (epilogue_begin); + SET (isa); + SET (discriminator); + +#undef SET + + new_line->next = linelist; + linelist = new_line; + ++nlinelist; + + return false; + } + + while (linep < lineendp) + { + 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); + + /* Perform the increments. */ + line += line_increment; + advance_pc ((opcode - opcode_base) / line_range); + + /* Add a new line with the current state machine values. */ + NEW_LINE (0); + + /* Reset the flags. */ + basic_block = false; + prologue_end = false; + epilogue_begin = false; + discriminator = 0; + } + else if (opcode == 0) + { + /* This an extended opcode. */ + if (unlikely (lineendp - linep < 2)) + goto invalid_data; + + /* The length. */ + uint_fast8_t len = *linep++; + + if (unlikely ((size_t) (lineendp - linep) < len)) + goto invalid_data; + + /* The sub-opcode. */ + 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. */ + addr = 0; + op_index = 0; + file = 1; + line = 1; + column = 0; + is_stmt = default_is_stmt; + basic_block = false; + prologue_end = false; + epilogue_begin = false; + isa = 0; + discriminator = 0; + break; + + case DW_LNE_set_address: + /* The value is an address. The size is defined as + apporiate for the target machine. We use the + address size field from the CU header. */ + op_index = 0; + if (unlikely (lineendp - linep < cu->address_size)) + goto invalid_data; + if (__libdw_read_address_inc (dbg, IDX_debug_line, &linep, + cu->address_size, &addr)) + goto out; + break; + + case DW_LNE_define_file: + { + char *fname = (char *) linep; + uint8_t *endp = memchr (linep, '\0', lineendp - linep); + if (endp == NULL) + goto invalid_data; + size_t fnamelen = endp - linep; + linep = endp + 1; + + unsigned int diridx; + get_uleb128 (diridx, linep); + Dwarf_Word mtime; + get_uleb128 (mtime, linep); + Dwarf_Word filelength; + get_uleb128 (filelength, linep); + + struct filelist *new_file = + (struct filelist *) alloca (sizeof (*new_file)); + if (fname[0] == '/') + new_file->info.name = fname; + else + { + new_file->info.name = + libdw_alloc (dbg, char, 1, (dirarray[diridx]->len + 1 + + fnamelen + 1)); + char *cp = new_file->info.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); + } + + new_file->info.mtime = mtime; + new_file->info.length = filelength; + new_file->next = filelist; + filelist = new_file; + ++nfilelist; + } + break; + + case DW_LNE_set_discriminator: + /* Takes one ULEB128 parameter, the discriminator. */ + if (unlikely (standard_opcode_lengths[opcode] != 1)) + goto invalid_data; + + get_uleb128 (discriminator, linep); + break; + + default: + /* Unknown, ignore it. */ + if (unlikely ((size_t) (lineendp - (linep - 1)) < len)) + goto invalid_data; + linep += len - 1; + break; + } + } + else if (opcode <= DW_LNS_set_isa) + { + /* This is a known standard opcode. */ + switch (opcode) + { + case DW_LNS_copy: + /* Takes no argument. */ + if (unlikely (standard_opcode_lengths[opcode] != 0)) + goto invalid_data; + + /* Add a new line with the current state machine values. */ + NEW_LINE (0); + + /* Reset the flags. */ + basic_block = false; + prologue_end = false; + epilogue_begin = false; + discriminator = 0; + break; + + case DW_LNS_advance_pc: + /* Takes one uleb128 parameter which is added to the + address. */ + if (unlikely (standard_opcode_lengths[opcode] != 1)) + goto invalid_data; + + get_uleb128 (u128, linep); + advance_pc (u128); + break; + + case DW_LNS_advance_line: + /* Takes one sleb128 parameter which is added to the + line. */ + if (unlikely (standard_opcode_lengths[opcode] != 1)) + goto invalid_data; + + 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)) + goto invalid_data; + + 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)) + goto invalid_data; + + get_uleb128 (u128, linep); + column = u128; + break; + + case DW_LNS_negate_stmt: + /* Takes no argument. */ + if (unlikely (standard_opcode_lengths[opcode] != 0)) + goto invalid_data; + + is_stmt = 1 - is_stmt; + break; + + case DW_LNS_set_basic_block: + /* Takes no argument. */ + if (unlikely (standard_opcode_lengths[opcode] != 0)) + goto invalid_data; + + basic_block = true; + break; + + case DW_LNS_const_add_pc: + /* Takes no argument. */ + if (unlikely (standard_opcode_lengths[opcode] != 0)) + goto invalid_data; + + advance_pc ((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) + || unlikely (lineendp - linep < 2)) + goto invalid_data; + + addr += read_2ubyte_unaligned_inc (dbg, linep); + op_index = 0; + break; + + case DW_LNS_set_prologue_end: + /* Takes no argument. */ + if (unlikely (standard_opcode_lengths[opcode] != 0)) + goto invalid_data; + + prologue_end = true; + break; + + case DW_LNS_set_epilogue_begin: + /* Takes no argument. */ + if (unlikely (standard_opcode_lengths[opcode] != 0)) + goto invalid_data; + + epilogue_begin = true; + break; + + case DW_LNS_set_isa: + /* Takes one uleb128 parameter which is stored in isa. */ + if (unlikely (standard_opcode_lengths[opcode] != 1)) + goto invalid_data; + + get_uleb128 (isa, linep); + break; + } + } + else + { + /* This is a new opcode the generator but not we know about. + Read the parameters associated with it but then discard + everything. Read all the parameters for this opcode. */ + for (int n = standard_opcode_lengths[opcode]; n > 0; --n) + get_uleb128 (u128, linep); + + /* Next round, ignore this opcode. */ + continue; + } + } + + /* Put all the files in an array. */ + Dwarf_Files *files = libdw_alloc (dbg, Dwarf_Files, + sizeof (Dwarf_Files) + + nfilelist * sizeof (Dwarf_Fileinfo) + + (ndirlist + 1) * sizeof (char *), + 1); + const char **dirs = (void *) &files->info[nfilelist]; + + files->nfiles = nfilelist; + while (nfilelist-- > 0) + { + files->info[nfilelist] = filelist->info; + filelist = filelist->next; + } + assert (filelist == NULL); + + /* Put all the directory strings in an array. */ + files->ndirs = ndirlist; + for (unsigned int i = 0; i < ndirlist; ++i) + dirs[i] = dirarray[i]->dir; + dirs[ndirlist] = NULL; + + /* Remember the referring CU. */ + files->cu = cu; + + /* Make the file data structure available through the CU. */ + cu->files = files; + + void *buf = libdw_alloc (dbg, Dwarf_Lines, (sizeof (Dwarf_Lines) + + (sizeof (Dwarf_Line) + * nlinelist)), 1); + + /* First use the buffer for the pointers, and sort the entries. + We'll write the pointers in the end of the buffer, and then + copy into the buffer from the beginning so the overlap works. */ + assert (sizeof (Dwarf_Line) >= sizeof (Dwarf_Line *)); + Dwarf_Line **sortlines = (buf + sizeof (Dwarf_Lines) + + ((sizeof (Dwarf_Line) + - sizeof (Dwarf_Line *)) * nlinelist)); + + /* The list is in LIFO order and usually they come in clumps with + ascending addresses. So fill from the back to probably start with + runs already in order before we sort. */ + unsigned int i = nlinelist; + while (i-- > 0) + { + sortlines[i] = &linelist->line; + linelist = linelist->next; + } + assert (linelist == NULL); + + /* Sort by ascending address. */ + qsort (sortlines, nlinelist, sizeof sortlines[0], &compare_lines); + + /* Now that they are sorted, put them in the final array. + The buffers overlap, so we've clobbered the early elements + of SORTLINES by the time we're reading the later ones. */ + cu->lines = buf; + cu->lines->nlines = nlinelist; + for (i = 0; i < nlinelist; ++i) + { + cu->lines->info[i] = *sortlines[i]; + cu->lines->info[i].files = files; + } + + /* Success. */ + res = 0; + } + else if (cu->lines != (void *) -1l) + /* We already have the information. */ + res = 0; + + if (likely (res == 0)) + { + *lines = cu->lines; + *nlines = cu->lines->nlines; + } + out: + + // XXX Eventually: unlocking here. + + return res; +} +INTDEF(dwarf_getsrclines) diff --git a/src/libdw/dwarf_getstring.c b/src/libdw/dwarf_getstring.c new file mode 100644 index 00000000..d5e7abfd --- /dev/null +++ b/src/libdw/dwarf_getstring.c @@ -0,0 +1,87 @@ +/* Get string. + Copyright (C) 2004 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2004. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <string.h> +#include "libdwP.h" + + +const char * +dwarf_getstring (dbg, offset, lenp) + Dwarf *dbg; + Dwarf_Off offset; + size_t *lenp; +{ + if (dbg == NULL) + return NULL; + + if (dbg->sectiondata[IDX_debug_str] == NULL + || offset >= dbg->sectiondata[IDX_debug_str]->d_size) + { + no_string: + __libdw_seterrno (DWARF_E_NO_STRING); + return NULL; + } + + const char *result = ((const char *) dbg->sectiondata[IDX_debug_str]->d_buf + + offset); + const char *endp = memchr (result, '\0', + dbg->sectiondata[IDX_debug_str]->d_size - offset); + if (endp == NULL) + goto no_string; + + if (lenp != NULL) + *lenp = endp - result; + + return result; +} diff --git a/src/libdw/dwarf_hasattr.c b/src/libdw/dwarf_hasattr.c new file mode 100644 index 00000000..b1c4292a --- /dev/null +++ b/src/libdw/dwarf_hasattr.c @@ -0,0 +1,73 @@ +/* Check whether given DIE has specific attribute. + Copyright (C) 2003, 2005 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2003. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <dwarf.h> +#include "libdwP.h" + + +int +dwarf_hasattr (die, search_name) + Dwarf_Die *die; + unsigned int search_name; +{ + if (die == NULL) + return 0; + + /* Search for the attribute with the given name. */ + unsigned int code; + (void) __libdw_find_attr (die, search_name, &code, NULL); + + return code == search_name; +} +INTDEF (dwarf_hasattr) diff --git a/src/libdw/dwarf_hasattr_integrate.c b/src/libdw/dwarf_hasattr_integrate.c new file mode 100644 index 00000000..806742d6 --- /dev/null +++ b/src/libdw/dwarf_hasattr_integrate.c @@ -0,0 +1,80 @@ +/* Check whether DIE has specific attribute, integrating DW_AT_abstract_origin. + Copyright (C) 2005 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <dwarf.h> +#include "libdwP.h" + +int +dwarf_hasattr_integrate (Dwarf_Die *die, unsigned int search_name) +{ + Dwarf_Die die_mem; + + do + { + if (INTUSE(dwarf_hasattr) (die, search_name)) + return 1; + + Dwarf_Attribute attr_mem; + Dwarf_Attribute *attr = INTUSE(dwarf_attr) (die, DW_AT_abstract_origin, + &attr_mem); + if (attr == NULL) + attr = INTUSE(dwarf_attr) (die, DW_AT_specification, &attr_mem); + if (attr == NULL) + break; + + die = INTUSE(dwarf_formref_die) (attr, &die_mem); + } + while (die != NULL); + + return 0; +} diff --git a/src/libdw/dwarf_haschildren.c b/src/libdw/dwarf_haschildren.c new file mode 100644 index 00000000..d9a47ad2 --- /dev/null +++ b/src/libdw/dwarf_haschildren.c @@ -0,0 +1,85 @@ +/* Return string associated with given attribute. + Copyright (C) 2003, 2005, 2008 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2003. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "libdwP.h" +#include <string.h> + + +int +dwarf_haschildren (die) + Dwarf_Die *die; +{ + /* Find the abbreviation entry. */ + Dwarf_Abbrev *abbrevp = die->abbrev; + if (abbrevp != DWARF_END_ABBREV) + { + const unsigned char *readp = (unsigned char *) die->addr; + + /* First we have to get the abbreviation code so that we can decode + the data in the DIE. */ + unsigned int abbrev_code; + get_uleb128 (abbrev_code, readp); + + abbrevp = __libdw_findabbrev (die->cu, abbrev_code); + die->abbrev = abbrevp ?: DWARF_END_ABBREV; + } + if (unlikely (die->abbrev == DWARF_END_ABBREV)) + { + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return -1; + } + + return die->abbrev->has_children; +} +INTDEF (dwarf_haschildren) diff --git a/src/libdw/dwarf_hasform.c b/src/libdw/dwarf_hasform.c new file mode 100644 index 00000000..66e0e746 --- /dev/null +++ b/src/libdw/dwarf_hasform.c @@ -0,0 +1,68 @@ +/* Check whether given attribute has specific form. + Copyright (C) 2003 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2003. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <dwarf.h> +#include "libdwP.h" + + +int +dwarf_hasform (attr, search_form) + Dwarf_Attribute *attr; + unsigned int search_form; +{ + if (attr == NULL) + return 0; + + return attr->form == search_form; +} diff --git a/src/libdw/dwarf_haspc.c b/src/libdw/dwarf_haspc.c new file mode 100644 index 00000000..58b87b65 --- /dev/null +++ b/src/libdw/dwarf_haspc.c @@ -0,0 +1,75 @@ +/* Determine whether a DIE covers a PC address. + Copyright (C) 2005 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "libdwP.h" +#include <dwarf.h> + + +int +dwarf_haspc (Dwarf_Die *die, Dwarf_Addr pc) +{ + if (die == NULL) + return -1; + + Dwarf_Addr base; + Dwarf_Addr begin; + Dwarf_Addr end; + ptrdiff_t offset = 0; + while ((offset = INTUSE(dwarf_ranges) (die, offset, &base, + &begin, &end)) > 0) + if (pc >= begin && pc < end) + return 1; + + return offset; +} +INTDEF (dwarf_haspc) diff --git a/src/libdw/dwarf_highpc.c b/src/libdw/dwarf_highpc.c new file mode 100644 index 00000000..c88e0721 --- /dev/null +++ b/src/libdw/dwarf_highpc.c @@ -0,0 +1,70 @@ +/* Return high PC attribute of DIE. + Copyright (C) 2003, 2005 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2003. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <dwarf.h> +#include "libdwP.h" + + +int +dwarf_highpc (die, return_addr) + Dwarf_Die *die; + Dwarf_Addr *return_addr; +{ + Dwarf_Attribute attr_mem; + + return INTUSE(dwarf_formaddr) (INTUSE(dwarf_attr) (die, DW_AT_high_pc, + &attr_mem), + return_addr); +} +INTDEF(dwarf_highpc) diff --git a/src/libdw/dwarf_lineaddr.c b/src/libdw/dwarf_lineaddr.c new file mode 100644 index 00000000..c59dd5d5 --- /dev/null +++ b/src/libdw/dwarf_lineaddr.c @@ -0,0 +1,67 @@ +/* Return line address. + Copyright (C) 2004 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2004. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "libdwP.h" + + +int +dwarf_lineaddr (Dwarf_Line *line, Dwarf_Addr *addrp) +{ + if (line == NULL) + return -1; + + *addrp = line->addr; + + return 0; +} diff --git a/src/libdw/dwarf_linebeginstatement.c b/src/libdw/dwarf_linebeginstatement.c new file mode 100644 index 00000000..2a99e675 --- /dev/null +++ b/src/libdw/dwarf_linebeginstatement.c @@ -0,0 +1,67 @@ +/* Return true if record is for beginning of a statement. + Copyright (C) 2004 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2004. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "libdwP.h" + + +int +dwarf_linebeginstatement (Dwarf_Line *line, bool *flagp) +{ + if (line == NULL) + return -1; + + *flagp = line->is_stmt; + + return 0; +} diff --git a/src/libdw/dwarf_lineblock.c b/src/libdw/dwarf_lineblock.c new file mode 100644 index 00000000..5ad2bb57 --- /dev/null +++ b/src/libdw/dwarf_lineblock.c @@ -0,0 +1,67 @@ +/* Return true if record is for beginning of a basic block. + Copyright (C) 2004 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2004. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "libdwP.h" + + +int +dwarf_lineblock (Dwarf_Line *line, bool *flagp) +{ + if (line == NULL) + return -1; + + *flagp = line->basic_block; + + return 0; +} diff --git a/src/libdw/dwarf_linecol.c b/src/libdw/dwarf_linecol.c new file mode 100644 index 00000000..8a1228c2 --- /dev/null +++ b/src/libdw/dwarf_linecol.c @@ -0,0 +1,67 @@ +/* Return column in line. + Copyright (C) 2004 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2004. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "libdwP.h" + + +int +dwarf_linecol (Dwarf_Line *line, int *colp) +{ + if (line == NULL) + return -1; + + *colp = line->column; + + return 0; +} diff --git a/src/libdw/dwarf_linediscriminator.c b/src/libdw/dwarf_linediscriminator.c new file mode 100644 index 00000000..d17a99f2 --- /dev/null +++ b/src/libdw/dwarf_linediscriminator.c @@ -0,0 +1,66 @@ +/* Return code path discriminator in line record. + Copyright (C) 2010 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "libdwP.h" + + +int +dwarf_linediscriminator (Dwarf_Line *line, unsigned int *discp) +{ + if (line == NULL) + return -1; + + *discp = line->discriminator; + + return 0; +} diff --git a/src/libdw/dwarf_lineendsequence.c b/src/libdw/dwarf_lineendsequence.c new file mode 100644 index 00000000..cea86aac --- /dev/null +++ b/src/libdw/dwarf_lineendsequence.c @@ -0,0 +1,67 @@ +/* Return true if record is for end of sequence. + Copyright (C) 2004 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2004. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "libdwP.h" + + +int +dwarf_lineendsequence (Dwarf_Line *line, bool *flagp) +{ + if (line == NULL) + return -1; + + *flagp = line->end_sequence; + + return 0; +} diff --git a/src/libdw/dwarf_lineepiloguebegin.c b/src/libdw/dwarf_lineepiloguebegin.c new file mode 100644 index 00000000..9d806117 --- /dev/null +++ b/src/libdw/dwarf_lineepiloguebegin.c @@ -0,0 +1,67 @@ +/* Return true if record is for beginning of epilogue. + Copyright (C) 2004 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2004. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "libdwP.h" + + +int +dwarf_lineepiloguebegin (Dwarf_Line *line, bool *flagp) +{ + if (line == NULL) + return -1; + + *flagp = line->epilogue_begin; + + return 0; +} diff --git a/src/libdw/dwarf_lineisa.c b/src/libdw/dwarf_lineisa.c new file mode 100644 index 00000000..064761e0 --- /dev/null +++ b/src/libdw/dwarf_lineisa.c @@ -0,0 +1,66 @@ +/* Return ISA in line. + Copyright (C) 2010 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "libdwP.h" + + +int +dwarf_lineisa (Dwarf_Line *line, unsigned int *isap) +{ + if (line == NULL) + return -1; + + *isap = line->isa; + + return 0; +} diff --git a/src/libdw/dwarf_lineno.c b/src/libdw/dwarf_lineno.c new file mode 100644 index 00000000..98840b15 --- /dev/null +++ b/src/libdw/dwarf_lineno.c @@ -0,0 +1,67 @@ +/* Return line number. + Copyright (C) 2004 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2004. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "libdwP.h" + + +int +dwarf_lineno (Dwarf_Line *line, int *linep) +{ + if (line == NULL) + return -1; + + *linep = line->line; + + return 0; +} diff --git a/src/libdw/dwarf_lineop_index.c b/src/libdw/dwarf_lineop_index.c new file mode 100644 index 00000000..3b433104 --- /dev/null +++ b/src/libdw/dwarf_lineop_index.c @@ -0,0 +1,66 @@ +/* Return line VLIW operation index. + Copyright (C) 2010 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "libdwP.h" + + +int +dwarf_lineop_index (Dwarf_Line *line, unsigned int *idxp) +{ + if (line == NULL) + return -1; + + *idxp = line->op_index; + + return 0; +} diff --git a/src/libdw/dwarf_lineprologueend.c b/src/libdw/dwarf_lineprologueend.c new file mode 100644 index 00000000..c7a05572 --- /dev/null +++ b/src/libdw/dwarf_lineprologueend.c @@ -0,0 +1,67 @@ +/* Return true if record is for end of prologue. + Copyright (C) 2004 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2004. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "libdwP.h" + + +int +dwarf_lineprologueend (Dwarf_Line *line, bool *flagp) +{ + if (line == NULL) + return -1; + + *flagp = line->prologue_end; + + return 0; +} diff --git a/src/libdw/dwarf_linesrc.c b/src/libdw/dwarf_linesrc.c new file mode 100644 index 00000000..6ecce93f --- /dev/null +++ b/src/libdw/dwarf_linesrc.c @@ -0,0 +1,77 @@ +/* Find line information for address. + Copyright (C) 2004 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2004. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "libdwP.h" + + +const char * +dwarf_linesrc (Dwarf_Line *line, Dwarf_Word *mtime, Dwarf_Word *length) +{ + if (line == NULL) + return NULL; + + if (line->file >= line->files->nfiles) + { + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return NULL; + } + + if (mtime != NULL) + *mtime = line->files->info[line->file].mtime; + + if (length != NULL) + *length = line->files->info[line->file].length; + + return line->files->info[line->file].name; +} diff --git a/src/libdw/dwarf_lowpc.c b/src/libdw/dwarf_lowpc.c new file mode 100644 index 00000000..97ece031 --- /dev/null +++ b/src/libdw/dwarf_lowpc.c @@ -0,0 +1,70 @@ +/* Return low PC attribute of DIE. + Copyright (C) 2003, 2005 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2003. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <dwarf.h> +#include "libdwP.h" + + +int +dwarf_lowpc (die, return_addr) + Dwarf_Die *die; + Dwarf_Addr *return_addr; +{ + Dwarf_Attribute attr_mem; + + return INTUSE(dwarf_formaddr) (INTUSE(dwarf_attr) (die, DW_AT_low_pc, + &attr_mem), + return_addr); +} +INTDEF(dwarf_lowpc) diff --git a/src/libdw/dwarf_macro_opcode.c b/src/libdw/dwarf_macro_opcode.c new file mode 100644 index 00000000..c40ebc7c --- /dev/null +++ b/src/libdw/dwarf_macro_opcode.c @@ -0,0 +1,67 @@ +/* Return macro opcode. + Copyright (C) 2005 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2005. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "libdwP.h" + + +int +dwarf_macro_opcode (Dwarf_Macro *macro, unsigned int *opcodep) +{ + if (macro == NULL) + return -1; + + *opcodep = macro->opcode; + + return 0; +} diff --git a/src/libdw/dwarf_macro_param1.c b/src/libdw/dwarf_macro_param1.c new file mode 100644 index 00000000..409865f5 --- /dev/null +++ b/src/libdw/dwarf_macro_param1.c @@ -0,0 +1,67 @@ +/* Return first macro parameter. + Copyright (C) 2005 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2005. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "libdwP.h" + + +int +dwarf_macro_param1 (Dwarf_Macro *macro, Dwarf_Word *paramp) +{ + if (macro == NULL) + return -1; + + *paramp = macro->param1; + + return 0; +} diff --git a/src/libdw/dwarf_macro_param2.c b/src/libdw/dwarf_macro_param2.c new file mode 100644 index 00000000..c1eff939 --- /dev/null +++ b/src/libdw/dwarf_macro_param2.c @@ -0,0 +1,70 @@ +/* Return second macro parameter. + Copyright (C) 2005 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2005. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "libdwP.h" + + +int +dwarf_macro_param2 (Dwarf_Macro *macro, Dwarf_Word *paramp, const char **strp) +{ + if (macro == NULL) + return -1; + + if (paramp != NULL) + *paramp = macro->param2.u; + if (strp != NULL) + *strp = macro->param2.s; + + return 0; +} diff --git a/src/libdw/dwarf_next_cfi.c b/src/libdw/dwarf_next_cfi.c new file mode 100644 index 00000000..0e90457d --- /dev/null +++ b/src/libdw/dwarf_next_cfi.c @@ -0,0 +1,257 @@ +/* Advance to next CFI entry. + Copyright (C) 2009-2010 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "cfi.h" +#include "encoded-value.h" + +#include <string.h> + + +int +dwarf_next_cfi (e_ident, data, eh_frame_p, off, next_off, entry) + const unsigned char e_ident[]; + Elf_Data *data; + bool eh_frame_p; + Dwarf_Off off; + Dwarf_Off *next_off; + Dwarf_CFI_Entry *entry; +{ + /* Dummy struct for memory-access.h macros. */ + BYTE_ORDER_DUMMY (dw, e_ident); + + /* If we reached the end before don't do anything. */ + if (off == (Dwarf_Off) -1l + /* Make sure there is enough space in the .debug_frame 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. */ + || unlikely (off + 4 >= data->d_size)) + { + *next_off = (Dwarf_Off) -1l; + return 1; + } + + /* This points into the .debug_frame section at the start of the entry. */ + const uint8_t *bytes = data->d_buf + off; + const uint8_t *limit = data->d_buf + data->d_size; + + /* The format of a CFI entry is described in DWARF3 6.4.1: + */ + + uint64_t length = read_4ubyte_unaligned_inc (&dw, bytes); + size_t offset_size = 4; + if (length == DWARF3_LENGTH_64_BIT) + { + /* This is the 64-bit DWARF format. */ + offset_size = 8; + if (unlikely (limit - bytes < 8)) + { + invalid: + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return -1; + } + length = read_8ubyte_unaligned_inc (&dw, bytes); + } + if (unlikely ((uint64_t) (limit - bytes) < length) + || unlikely (length < offset_size + 1)) + goto invalid; + + /* Now we know how large the entry 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. */ + *next_off = off + (2 * offset_size - 4) + length; + + limit = bytes + length; + + const uint8_t *const cie_pointer_start = bytes; + if (offset_size == 8) + entry->cie.CIE_id = read_8ubyte_unaligned_inc (&dw, bytes); + else + { + entry->cie.CIE_id = read_4ubyte_unaligned_inc (&dw, bytes); + /* Canonicalize the 32-bit CIE_ID value to 64 bits. */ + if (!eh_frame_p && entry->cie.CIE_id == DW_CIE_ID_32) + entry->cie.CIE_id = DW_CIE_ID_64; + } + if (eh_frame_p) + { + /* Canonicalize the .eh_frame CIE pointer to .debug_frame format. */ + if (entry->cie.CIE_id == 0) + entry->cie.CIE_id = DW_CIE_ID_64; + else + { + /* In .eh_frame format, a CIE pointer is the distance from where + it appears back to the beginning of the CIE. */ + ptrdiff_t pos = cie_pointer_start - (const uint8_t *) data->d_buf; + if (unlikely (entry->cie.CIE_id > (Dwarf_Off) pos) + || unlikely (pos <= (ptrdiff_t) offset_size)) + goto invalid; + entry->cie.CIE_id = pos - entry->cie.CIE_id; + } + } + + if (entry->cie.CIE_id == DW_CIE_ID_64) + { + /* Read the version stamp. Always an 8-bit value. */ + uint8_t version = *bytes++; + + if (version != 1 && (unlikely (version < 3) || unlikely (version > 4))) + goto invalid; + + entry->cie.augmentation = (const char *) bytes; + + bytes = memchr (bytes, '\0', limit - bytes); + if (unlikely (bytes == NULL)) + goto invalid; + ++bytes; + + /* The address size for CFI is implicit in the ELF class. */ + uint_fast8_t address_size = e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8; + uint_fast8_t segment_size = 0; + if (version >= 4) + { + if (unlikely (limit - bytes < 5)) + goto invalid; + /* XXX We don't actually support address_size not matching the class. + To do so, we'd have to return it here so that intern_new_cie + could use it choose a specific fde_encoding. */ + if (unlikely (*bytes != address_size)) + { + __libdw_seterrno (DWARF_E_VERSION); + return -1; + } + address_size = *bytes++; + segment_size = *bytes++; + /* We don't actually support segment selectors. We'd have to + roll this into the fde_encoding bits or something. */ + if (unlikely (segment_size != 0)) + { + __libdw_seterrno (DWARF_E_VERSION); + return -1; + } + } + + const char *ap = entry->cie.augmentation; + + /* g++ v2 "eh" has pointer immediately following augmentation string, + so it must be handled first. */ + if (unlikely (ap[0] == 'e' && ap[1] == 'h')) + { + ap += 2; + bytes += address_size; + } + + get_uleb128 (entry->cie.code_alignment_factor, bytes); + get_sleb128 (entry->cie.data_alignment_factor, bytes); + + if (version >= 3) /* DWARF 3+ */ + get_uleb128 (entry->cie.return_address_register, bytes); + else /* DWARF 2 */ + entry->cie.return_address_register = *bytes++; + + /* If we have sized augmentation data, + we don't need to grok it all. */ + entry->cie.fde_augmentation_data_size = 0; + bool sized_augmentation = *ap == 'z'; + if (sized_augmentation) + { + get_uleb128 (entry->cie.augmentation_data_size, bytes); + if ((Dwarf_Word) (limit - bytes) < entry->cie.augmentation_data_size) + goto invalid; + entry->cie.augmentation_data = bytes; + bytes += entry->cie.augmentation_data_size; + } + else + { + entry->cie.augmentation_data = bytes; + + for (; *ap != '\0'; ++ap) + { + uint8_t encoding; + switch (*ap) + { + case 'L': /* Skip LSDA pointer encoding byte. */ + case 'R': /* Skip FDE address encoding byte. */ + encoding = *bytes++; + entry->cie.fde_augmentation_data_size + += encoded_value_size (data, e_ident, encoding, NULL); + continue; + case 'P': /* Skip encoded personality routine pointer. */ + encoding = *bytes++; + bytes += encoded_value_size (data, e_ident, encoding, bytes); + continue; + case 'S': /* Skip signal-frame flag. */ + continue; + default: + /* Unknown augmentation string. initial_instructions might + actually start with some augmentation data. */ + break; + } + break; + } + entry->cie.augmentation_data_size + = bytes - entry->cie.augmentation_data; + } + + entry->cie.initial_instructions = bytes; + entry->cie.initial_instructions_end = limit; + } + else + { + entry->fde.start = bytes; + entry->fde.end = limit; + } + + return 0; +} +INTDEF (dwarf_next_cfi) diff --git a/src/libdw/dwarf_nextcu.c b/src/libdw/dwarf_nextcu.c new file mode 100644 index 00000000..2e8f4d79 --- /dev/null +++ b/src/libdw/dwarf_nextcu.c @@ -0,0 +1,220 @@ +/* Advance to next CU header. + Copyright (C) 2002-2010 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <libdwP.h> +#include <dwarf.h> + + +int +dwarf_next_unit (dwarf, off, next_off, header_sizep, versionp, abbrev_offsetp, + address_sizep, offset_sizep, type_signaturep, type_offsetp) + Dwarf *dwarf; + Dwarf_Off off; + Dwarf_Off *next_off; + size_t *header_sizep; + Dwarf_Half *versionp; + Dwarf_Off *abbrev_offsetp; + uint8_t *address_sizep; + uint8_t *offset_sizep; + uint64_t *type_signaturep; + Dwarf_Off *type_offsetp; +{ + const bool debug_types = type_signaturep != NULL; + const size_t sec_idx = debug_types ? IDX_debug_types : IDX_debug_info; + + /* Maybe there has been an error before. */ + if (dwarf == NULL) + return -1; + + /* If we reached the end before don't do anything. */ + if (off == (Dwarf_Off) -1l + || unlikely (dwarf->sectiondata[sec_idx] == NULL) + /* 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. */ + || unlikely (off + 4 >= dwarf->sectiondata[sec_idx]->d_size)) + { + *next_off = (Dwarf_Off) -1l; + return 1; + } + + /* This points into the .debug_info section to the beginning of the + CU entry. */ + const unsigned char *data = dwarf->sectiondata[sec_idx]->d_buf; + const unsigned char *bytes = data + off; + + /* 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 + 0xfffffff0); 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.2.2). + + 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. */ + uint64_t length = read_4ubyte_unaligned_inc (dwarf, bytes); + size_t offset_size = 4; + /* Lengths of 0xfffffff0 - 0xffffffff are escape codes. Oxffffffff is + used to indicate that 64-bit dwarf information is being used, the + other values are currently reserved. */ + if (length == DWARF3_LENGTH_64_BIT) + offset_size = 8; + else if (unlikely (length >= DWARF3_LENGTH_MIN_ESCAPE_CODE + && length <= DWARF3_LENGTH_MAX_ESCAPE_CODE)) + { + invalid: + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return -1; + } + + /* Now we know how large the header is. */ + if (unlikely (DIE_OFFSET_FROM_CU_OFFSET (off, offset_size, debug_types) + >= dwarf->sectiondata[sec_idx]->d_size)) + { + *next_off = -1; + return 1; + } + + if (length == DWARF3_LENGTH_64_BIT) + /* This is a 64-bit DWARF format. */ + length = read_8ubyte_unaligned_inc (dwarf, bytes); + + /* Read the version stamp. Always a 16-bit value. */ + uint_fast16_t version = read_2ubyte_unaligned_inc (dwarf, bytes); + + /* 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. */ + uint64_t abbrev_offset; + if (__libdw_read_offset_inc (dwarf, sec_idx, &bytes, offset_size, + &abbrev_offset, IDX_debug_abbrev, 0)) + return -1; + + /* The address size. Always an 8-bit value. */ + uint8_t address_size = *bytes++; + + if (debug_types) + { + uint64_t type_sig8 = read_8ubyte_unaligned_inc (dwarf, bytes); + + Dwarf_Off type_offset; + if (__libdw_read_offset_inc (dwarf, sec_idx, &bytes, offset_size, + &type_offset, sec_idx, 0)) + return -1; + + /* Validate that the TYPE_OFFSET points past the header. */ + if (unlikely (type_offset < (size_t) (bytes - (data + off)))) + goto invalid; + + *type_signaturep = type_sig8; + if (type_offsetp != NULL) + *type_offsetp = type_offset; + } + + /* Store the header length. */ + if (header_sizep != NULL) + *header_sizep = bytes - (data + off); + + if (versionp != NULL) + *versionp = version; + + if (abbrev_offsetp != NULL) + *abbrev_offsetp = abbrev_offset; + + if (address_sizep != NULL) + *address_sizep = address_size; + + /* Store the offset size. */ + if (offset_sizep != NULL) + *offset_sizep = offset_size; + + /* See definition of DIE_OFFSET_FROM_CU_OFFSET macro + for an explanation of the trick in this expression. */ + *next_off = off + 2 * offset_size - 4 + length; + + return 0; +} +INTDEF(dwarf_next_unit) + +int +dwarf_nextcu (dwarf, off, next_off, header_sizep, abbrev_offsetp, + address_sizep, offset_sizep) + Dwarf *dwarf; + Dwarf_Off off; + Dwarf_Off *next_off; + size_t *header_sizep; + Dwarf_Off *abbrev_offsetp; + uint8_t *address_sizep; + uint8_t *offset_sizep; +{ + return INTUSE(dwarf_next_unit) (dwarf, off, next_off, header_sizep, NULL, + abbrev_offsetp, address_sizep, offset_sizep, + NULL, NULL); +} +INTDEF(dwarf_nextcu) diff --git a/src/libdw/dwarf_offabbrev.c b/src/libdw/dwarf_offabbrev.c new file mode 100644 index 00000000..2cac2794 --- /dev/null +++ b/src/libdw/dwarf_offabbrev.c @@ -0,0 +1,72 @@ +/* Get abbreviation at given offset. + Copyright (C) 2004, 2005 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2004. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "libdwP.h" + + +int +dwarf_offabbrev (Dwarf *dbg, Dwarf_Off offset, size_t *lengthp, + Dwarf_Abbrev *abbrevp) +{ + if (dbg == NULL) + return -1; + + Dwarf_Abbrev *abbrev = __libdw_getabbrev (dbg, NULL, offset, lengthp, + abbrevp); + + if (abbrev == NULL) + return -1; + + return abbrev == DWARF_END_ABBREV ? 1 : 0; +} diff --git a/src/libdw/dwarf_offdie.c b/src/libdw/dwarf_offdie.c new file mode 100644 index 00000000..4c650cfd --- /dev/null +++ b/src/libdw/dwarf_offdie.c @@ -0,0 +1,111 @@ +/* Return DIE at given offset. + Copyright (C) 2002-2010 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <string.h> +#include "libdwP.h" + + +Dwarf_Die * +internal_function +__libdw_offdie (Dwarf *dbg, Dwarf_Off offset, Dwarf_Die *result, + bool debug_types) +{ + if (dbg == NULL) + return NULL; + + Elf_Data *const data = dbg->sectiondata[debug_types ? IDX_debug_types + : IDX_debug_info]; + if (offset >= data->d_size) + { + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return NULL; + } + + /* Clear the entire DIE structure. This signals we have not yet + determined any of the information. */ + memset (result, '\0', sizeof (Dwarf_Die)); + + result->addr = (char *) data->d_buf + offset; + + /* Get the CU. */ + result->cu = __libdw_findcu (dbg, offset, debug_types); + if (result->cu == NULL) + { + /* This should never happen. The input file is malformed. */ + __libdw_seterrno (DWARF_E_INVALID_DWARF); + result = NULL; + } + + return result; +} + + +Dwarf_Die * +dwarf_offdie (dbg, offset, result) + Dwarf *dbg; + Dwarf_Off offset; + Dwarf_Die *result; +{ + return __libdw_offdie (dbg, offset, result, false); +} +INTDEF(dwarf_offdie) + +Dwarf_Die * +dwarf_offdie_types (dbg, offset, result) + Dwarf *dbg; + Dwarf_Off offset; + Dwarf_Die *result; +{ + return __libdw_offdie (dbg, offset, result, true); +} diff --git a/src/libdw/dwarf_onearange.c b/src/libdw/dwarf_onearange.c new file mode 100644 index 00000000..5a9b9f39 --- /dev/null +++ b/src/libdw/dwarf_onearange.c @@ -0,0 +1,71 @@ +/* Return one of the address range entries. + Copyright (C) 2004 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2004. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "libdwP.h" + + +Dwarf_Arange * +dwarf_onearange (Dwarf_Aranges *aranges, size_t idx) +{ + if (aranges == NULL) + return NULL; + + if (idx >= aranges->naranges) + { + __libdw_seterrno (DWARF_E_INVALID_ARANGE_IDX); + return NULL; + } + + return &aranges->info[idx]; +} diff --git a/src/libdw/dwarf_onesrcline.c b/src/libdw/dwarf_onesrcline.c new file mode 100644 index 00000000..3e716304 --- /dev/null +++ b/src/libdw/dwarf_onesrcline.c @@ -0,0 +1,71 @@ +/* Return one of the sources lines of a CU. + Copyright (C) 2004 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2004. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "libdwP.h" + + +Dwarf_Line * +dwarf_onesrcline (Dwarf_Lines *lines, size_t idx) +{ + if (lines == NULL) + return NULL; + + if (idx >= lines->nlines) + { + __libdw_seterrno (DWARF_E_INVALID_LINE_IDX); + return NULL; + } + + return &lines->info[idx]; +} diff --git a/src/libdw/dwarf_ranges.c b/src/libdw/dwarf_ranges.c new file mode 100644 index 00000000..50fb6ba2 --- /dev/null +++ b/src/libdw/dwarf_ranges.c @@ -0,0 +1,211 @@ +/* Enumerate the PC ranges covered by a DIE. + Copyright (C) 2005, 2007, 2009 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "libdwP.h" +#include <dwarf.h> +#include <assert.h> + +/* Read up begin/end pair and increment read pointer. + - If it's normal range record, set up `*beginp' and `*endp' and return 0. + - If it's base address selection record, set up `*basep' and return 1. + - If it's end of rangelist, don't set anything and return 2 + - If an error occurs, don't set anything and return -1. */ +internal_function int +__libdw_read_begin_end_pair_inc (Dwarf *dbg, int sec_index, + unsigned char **addrp, int width, + Dwarf_Addr *beginp, Dwarf_Addr *endp, + Dwarf_Addr *basep) +{ + Dwarf_Addr escape = (width == 8 ? (Elf64_Addr) -1 + : (Elf64_Addr) (Elf32_Addr) -1); + Dwarf_Addr begin; + Dwarf_Addr end; + + unsigned char *addr = *addrp; + bool begin_relocated = READ_AND_RELOCATE (__libdw_relocate_address, begin); + bool end_relocated = READ_AND_RELOCATE (__libdw_relocate_address, end); + *addrp = addr; + + /* Unrelocated escape for begin means base address selection. */ + if (begin == escape && !begin_relocated) + { + if (unlikely (end == escape)) + { + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return -1; + } + + if (basep != NULL) + *basep = end; + return 1; + } + + /* Unrelocated pair of zeroes means end of range list. */ + if (begin == 0 && end == 0 && !begin_relocated && !end_relocated) + return 2; + + /* Don't check for begin_relocated == end_relocated. Serve the data + to the client even though it may be buggy. */ + *beginp = begin; + *endp = end; + + return 0; +} + +ptrdiff_t +dwarf_ranges (Dwarf_Die *die, ptrdiff_t offset, Dwarf_Addr *basep, + Dwarf_Addr *startp, Dwarf_Addr *endp) +{ + if (die == NULL) + return -1; + + if (offset == 0 + /* Usually there is a single contiguous range. */ + && INTUSE(dwarf_highpc) (die, endp) == 0 + && INTUSE(dwarf_lowpc) (die, startp) == 0) + /* A offset into .debug_ranges will never be 1, it must be at least a + multiple of 4. So we can return 1 as a special case value to mark + there are no ranges to look for on the next call. */ + return 1; + + if (offset == 1) + return 0; + + /* We have to look for a noncontiguous range. */ + + const Elf_Data *d = die->cu->dbg->sectiondata[IDX_debug_ranges]; + if (d == NULL && offset != 0) + { + __libdw_seterrno (DWARF_E_NO_DEBUG_RANGES); + return -1; + } + + unsigned char *readp; + unsigned char *readendp; + if (offset == 0) + { + Dwarf_Attribute attr_mem; + Dwarf_Attribute *attr = INTUSE(dwarf_attr) (die, DW_AT_ranges, + &attr_mem); + if (attr == NULL) + /* No PC attributes in this DIE at all, so an empty range list. */ + return 0; + + Dwarf_Word start_offset; + if ((readp = __libdw_formptr (attr, IDX_debug_ranges, + DWARF_E_NO_DEBUG_RANGES, + &readendp, &start_offset)) == NULL) + return -1; + + offset = start_offset; + assert ((Dwarf_Word) offset == start_offset); + + /* Fetch the CU's base address. */ + Dwarf_Die cudie = CUDIE (attr->cu); + + /* Find the base address of the compilation unit. It will + normally be specified by DW_AT_low_pc. In DWARF-3 draft 4, + the base address could be overridden by DW_AT_entry_pc. It's + been removed, but GCC emits DW_AT_entry_pc and not DW_AT_lowpc + for compilation units with discontinuous ranges. */ + if (unlikely (INTUSE(dwarf_lowpc) (&cudie, basep) != 0) + && INTUSE(dwarf_formaddr) (INTUSE(dwarf_attr) (&cudie, + DW_AT_entry_pc, + &attr_mem), + basep) != 0) + { + if (INTUSE(dwarf_errno) () == 0) + { + invalid: + __libdw_seterrno (DWARF_E_INVALID_DWARF); + } + return -1; + } + } + else + { + if (__libdw_offset_in_section (die->cu->dbg, + IDX_debug_ranges, offset, 1)) + return -1l; + + readp = d->d_buf + offset; + readendp = d->d_buf + d->d_size; + } + + next: + if (readendp - readp < die->cu->address_size * 2) + goto invalid; + + Dwarf_Addr begin; + Dwarf_Addr end; + + switch (__libdw_read_begin_end_pair_inc (die->cu->dbg, IDX_debug_ranges, + &readp, die->cu->address_size, + &begin, &end, basep)) + { + case 0: + break; + case 1: + goto next; + case 2: + return 0; + default: + return -1l; + } + + /* We have an address range entry. */ + *startp = *basep + begin; + *endp = *basep + end; + return readp - (unsigned char *) d->d_buf; +} +INTDEF (dwarf_ranges) diff --git a/src/libdw/dwarf_siblingof.c b/src/libdw/dwarf_siblingof.c new file mode 100644 index 00000000..f8e54c18 --- /dev/null +++ b/src/libdw/dwarf_siblingof.c @@ -0,0 +1,159 @@ +/* Return sibling of given DIE. + Copyright (C) 2003-2010 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2003. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "libdwP.h" +#include <dwarf.h> +#include <string.h> + + +int +dwarf_siblingof (die, result) + Dwarf_Die *die; + Dwarf_Die *result; +{ + /* Ignore previous errors. */ + if (die == NULL) + return -1; + + if (result == NULL) + return -1; + + if (result != die) + result->addr = NULL; + + unsigned int level = 0; + + /* Copy of the current DIE. */ + Dwarf_Die this_die = *die; + /* Temporary attributes we create. */ + Dwarf_Attribute sibattr; + /* Copy of the CU in the request. */ + sibattr.cu = this_die.cu; + /* That's the address we start looking. */ + unsigned char *addr = this_die.addr; + /* End of the buffer. */ + unsigned char *endp + = ((unsigned char *) cu_data (sibattr.cu)->d_buf + sibattr.cu->end); + + /* Search for the beginning of the next die on this level. We + must not return the dies for children of the given die. */ + do + { + /* Find the end of the DIE or the sibling attribute. */ + addr = __libdw_find_attr (&this_die, DW_AT_sibling, &sibattr.code, + &sibattr.form); + if (sibattr.code == DW_AT_sibling) + { + Dwarf_Off offset; + sibattr.valp = addr; + if (unlikely (__libdw_formref (&sibattr, &offset) != 0)) + /* Something went wrong. */ + return -1; + + /* Compute the next address. */ + addr = ((unsigned char *) cu_data (sibattr.cu)->d_buf + + sibattr.cu->start + offset); + } + else if (unlikely (addr == NULL) + || unlikely (this_die.abbrev == DWARF_END_ABBREV)) + return -1; + else if (this_die.abbrev->has_children) + /* This abbreviation has children. */ + ++level; + + + while (1) + { + /* Make sure we are still in range. Some producers might skip + the trailing NUL bytes. */ + if (addr >= endp) + return 1; + + if (*addr != '\0') + break; + + if (level-- == 0) + { + if (result != die) + result->addr = addr; + /* No more sibling at all. */ + return 1; + } + + ++addr; + } + + /* Initialize the 'current DIE'. */ + this_die.addr = addr; + this_die.abbrev = NULL; + } + while (level > 0); + + /* Maybe we reached the end of the CU. */ + if (addr >= endp) + return 1; + + /* Clear the entire DIE structure. This signals we have not yet + determined any of the information. */ + memset (result, '\0', sizeof (Dwarf_Die)); + + /* We have the address. */ + result->addr = addr; + + /* Same CU as the parent. */ + result->cu = sibattr.cu; + + return 0; +} +INTDEF(dwarf_siblingof) diff --git a/src/libdw/dwarf_sig8_hash.c b/src/libdw/dwarf_sig8_hash.c new file mode 100644 index 00000000..53c07eac --- /dev/null +++ b/src/libdw/dwarf_sig8_hash.c @@ -0,0 +1,62 @@ +/* Implementation of hash table for DWARF .debug_types section content. + Copyright (C) 2010 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#define NO_UNDEF +#include "dwarf_sig8_hash.h" +#undef NO_UNDEF + +/* This is defined in dwarf_abbrev_hash.c, we can just use it here. */ +#define next_prime __libdwarf_next_prime +extern size_t next_prime (size_t) attribute_hidden; + +#include <dynamicsizehash.c> diff --git a/src/libdw/dwarf_sig8_hash.h b/src/libdw/dwarf_sig8_hash.h new file mode 100644 index 00000000..0d8932b5 --- /dev/null +++ b/src/libdw/dwarf_sig8_hash.h @@ -0,0 +1,59 @@ +/* Hash table for DWARF .debug_types section content. + Copyright (C) 2010 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifndef _DWARF_SIG8_HASH_H +#define _DWARF_SIG8_HASH_H 1 + +#define NAME Dwarf_Sig8_Hash +#define TYPE struct Dwarf_CU * +#define COMPARE(a, b) (0) + +#include <dynamicsizehash.h> + +#endif /* dwarf_sig8_hash.h */ diff --git a/src/libdw/dwarf_srclang.c b/src/libdw/dwarf_srclang.c new file mode 100644 index 00000000..305ffcd0 --- /dev/null +++ b/src/libdw/dwarf_srclang.c @@ -0,0 +1,72 @@ +/* Return source language attribute of DIE. + Copyright (C) 2003-2010 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2003. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <dwarf.h> +#include "libdwP.h" + + +int +dwarf_srclang (die) + Dwarf_Die *die; +{ + Dwarf_Attribute attr_mem; + Dwarf_Word value; + + return INTUSE(dwarf_formudata) (INTUSE(dwarf_attr_integrate) + (die, DW_AT_language, &attr_mem), + &value) == 0 ? (int) value : -1; +} +INTDEF (dwarf_srclang) +OLD_VERSION (dwarf_srclang, ELFUTILS_0.122) +NEW_VERSION (dwarf_srclang, ELFUTILS_0.143) diff --git a/src/libdw/dwarf_tag.c b/src/libdw/dwarf_tag.c new file mode 100644 index 00000000..fa8b384c --- /dev/null +++ b/src/libdw/dwarf_tag.c @@ -0,0 +1,126 @@ +/* Return tag of given DIE. + Copyright (C) 2003-2011 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2003. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "libdwP.h" + + +Dwarf_Abbrev * +internal_function +__libdw_findabbrev (struct Dwarf_CU *cu, unsigned int code) +{ + Dwarf_Abbrev *abb; + + /* Abbreviation code can never have a value of 0. */ + if (unlikely (code == 0)) + return DWARF_END_ABBREV; + + /* See whether the entry is already in the hash table. */ + abb = Dwarf_Abbrev_Hash_find (&cu->abbrev_hash, code, NULL); + if (abb == NULL) + while (cu->last_abbrev_offset != (size_t) -1l) + { + size_t length; + + /* Find the next entry. It gets automatically added to the + hash table. */ + abb = __libdw_getabbrev (cu->dbg, cu, cu->last_abbrev_offset, &length, + NULL); + if (abb == NULL || abb == DWARF_END_ABBREV) + { + /* Make sure we do not try to search for it again. */ + cu->last_abbrev_offset = (size_t) -1l; + return DWARF_END_ABBREV; + } + + cu->last_abbrev_offset += length; + + /* Is this the code we are looking for? */ + if (abb->code == code) + break; + } + + /* This is our second (or third, etc.) call to __libdw_findabbrev + and the code is invalid. */ + if (unlikely (abb == NULL)) + abb = DWARF_END_ABBREV; + + return abb; +} + + +int +dwarf_tag (die) + Dwarf_Die *die; +{ + /* Do we already know the abbreviation? */ + if (die->abbrev == NULL) + { + /* Get the abbreviation code. */ + unsigned int u128; + const unsigned char *addr = die->addr; + get_uleb128 (u128, addr); + + /* Find the abbreviation. */ + die->abbrev = __libdw_findabbrev (die->cu, u128); + } + + if (unlikely (die->abbrev == DWARF_END_ABBREV)) + { + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return DW_TAG_invalid; + } + + return die->abbrev->tag; +} +INTDEF(dwarf_tag) diff --git a/src/libdw/dwarf_whatattr.c b/src/libdw/dwarf_whatattr.c new file mode 100644 index 00000000..9b8bddf1 --- /dev/null +++ b/src/libdw/dwarf_whatattr.c @@ -0,0 +1,64 @@ +/* Return attribute code of given attribute. + Copyright (C) 2003 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2003. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <dwarf.h> +#include "libdwP.h" + + +unsigned int +dwarf_whatattr (attr) + Dwarf_Attribute *attr; +{ + return attr == NULL ? 0 : attr->code; +} diff --git a/src/libdw/dwarf_whatform.c b/src/libdw/dwarf_whatform.c new file mode 100644 index 00000000..8a9076b8 --- /dev/null +++ b/src/libdw/dwarf_whatform.c @@ -0,0 +1,64 @@ +/* Return form code of given attribute. + Copyright (C) 2003 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2003. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <dwarf.h> +#include "libdwP.h" + + +unsigned int +dwarf_whatform (attr) + Dwarf_Attribute *attr; +{ + return attr == NULL ? 0 : attr->form; +} diff --git a/src/libdw/encoded-value.h b/src/libdw/encoded-value.h new file mode 100644 index 00000000..e118a1c4 --- /dev/null +++ b/src/libdw/encoded-value.h @@ -0,0 +1,216 @@ +/* DW_EH_PE_* support for libdw unwinder. + Copyright (C) 2009-2010 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifndef _ENCODED_VALUE_H +#define _ENCODED_VALUE_H 1 + +#include <dwarf.h> +#include <stdlib.h> +#include "libdwP.h" + + +static size_t __attribute__ ((unused)) +encoded_value_size (const Elf_Data *data, const unsigned char e_ident[], + uint8_t encoding, const uint8_t *p) +{ + if (encoding == DW_EH_PE_omit) + return 0; + + switch (encoding & 0x07) + { + case DW_EH_PE_udata2: + return 2; + case DW_EH_PE_udata4: + return 4; + case DW_EH_PE_udata8: + return 8; + + case DW_EH_PE_absptr: + return e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8; + + case DW_EH_PE_uleb128: + if (p != NULL) + { + const uint8_t *end = p; + while (end < (uint8_t *) data->d_buf + data->d_size) + if (*end++ & 0x80u) + return end - p; + } + + default: + abort (); + return 0; + } +} + +static inline int __attribute__ ((unused)) +__libdw_cfi_read_address_inc (const Dwarf_CFI *cache, + const unsigned char **addrp, + int width, Dwarf_Addr *ret) +{ + width = width ?: cache->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8; + + if (cache->dbg != NULL) + return __libdw_read_address_inc (cache->dbg, IDX_debug_frame, + addrp, width, ret); + + /* Only .debug_frame might have relocation to consider. + Read plain values from .eh_frame data. */ + + if (width == 4) + *ret = read_4ubyte_unaligned_inc (cache, *addrp); + else + *ret = read_8ubyte_unaligned_inc (cache, *addrp); + return 0; +} + +static bool __attribute__ ((unused)) +read_encoded_value (const Dwarf_CFI *cache, uint8_t encoding, const uint8_t **p, + Dwarf_Addr *result) +{ + *result = 0; + switch (encoding & 0x70) + { + case DW_EH_PE_absptr: + break; + case DW_EH_PE_pcrel: + *result = (cache->frame_vaddr + + (*p - (const uint8_t *) cache->data->d.d_buf)); + break; + case DW_EH_PE_textrel: + // ia64: segrel + *result = cache->textrel; + break; + case DW_EH_PE_datarel: + // i386: GOTOFF + // ia64: gprel + *result = cache->datarel; + break; + case DW_EH_PE_funcrel: /* XXX */ + break; + case DW_EH_PE_aligned: + { + const size_t size = encoded_value_size (&cache->data->d, cache->e_ident, + encoding, *p); + size_t align = ((cache->frame_vaddr + + (*p - (const uint8_t *) cache->data->d.d_buf)) + & (size - 1)); + if (align != 0) + *p += size - align; + break; + } + + default: + abort (); + } + + Dwarf_Addr value; + switch (encoding & 0x0f) + { + case DW_EH_PE_udata2: + value = read_2ubyte_unaligned_inc (cache, *p); + break; + + case DW_EH_PE_sdata2: + value = read_2sbyte_unaligned_inc (cache, *p); + break; + + case DW_EH_PE_udata4: + if (__libdw_cfi_read_address_inc (cache, p, 4, &value)) + return true; + break; + + case DW_EH_PE_sdata4: + if (__libdw_cfi_read_address_inc (cache, p, 4, &value)) + return true; + value = (Dwarf_Sword) (Elf32_Sword) value; /* Sign-extend. */ + break; + + case DW_EH_PE_udata8: + case DW_EH_PE_sdata8: + if (__libdw_cfi_read_address_inc (cache, p, 8, &value)) + return true; + break; + + case DW_EH_PE_absptr: + if (__libdw_cfi_read_address_inc (cache, p, 0, &value)) + return true; + break; + + case DW_EH_PE_uleb128: + get_uleb128 (value, *p); + break; + + case DW_EH_PE_sleb128: + get_sleb128 (value, *p); + break; + + default: + abort (); + } + + *result += value; + + if (encoding & DW_EH_PE_indirect) + { + if (unlikely (*result < cache->frame_vaddr)) + return true; + *result -= cache->frame_vaddr; + if (unlikely (*result > (cache->data->d.d_size + - encoded_value_size (NULL, cache->e_ident, + DW_EH_PE_absptr, NULL)))) + return true; + const uint8_t *ptr = cache->data->d.d_buf + *result; + return __libdw_cfi_read_address_inc (cache, &ptr, 0, result); + } + + return false; +} + +#endif /* encoded-value.h */ diff --git a/src/libdw/fde.c b/src/libdw/fde.c new file mode 100644 index 00000000..5685252b --- /dev/null +++ b/src/libdw/fde.c @@ -0,0 +1,311 @@ +/* FDE reading. + Copyright (C) 2009-2010 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "cfi.h" +#include <search.h> +#include <stdlib.h> + +#include "encoded-value.h" + +static int +compare_fde (const void *a, const void *b) +{ + const struct dwarf_fde *fde1 = a; + const struct dwarf_fde *fde2 = b; + + /* Find out which of the two arguments is the search value. + It has end offset 0. */ + if (fde1->end == 0) + { + if (fde1->start < fde2->start) + return -1; + if (fde1->start >= fde2->end) + return 1; + } + else + { + if (fde2->start < fde1->start) + return 1; + if (fde2->start >= fde1->end) + return -1; + } + + return 0; +} + +static struct dwarf_fde * +intern_fde (Dwarf_CFI *cache, const Dwarf_FDE *entry) +{ + /* Look up the new entry's CIE. */ + struct dwarf_cie *cie = __libdw_find_cie (cache, entry->CIE_pointer); + if (cie == NULL) + return (void *) -1l; + + struct dwarf_fde *fde = malloc (sizeof (struct dwarf_fde)); + if (fde == NULL) + { + __libdw_seterrno (DWARF_E_NOMEM); + return NULL; + } + + fde->instructions = entry->start; + fde->instructions_end = entry->end; + if (unlikely (read_encoded_value (cache, cie->fde_encoding, + &fde->instructions, &fde->start)) + || unlikely (read_encoded_value (cache, cie->fde_encoding & 0x0f, + &fde->instructions, &fde->end))) + return NULL; + fde->end += fde->start; + + fde->cie = cie; + + if (cie->sized_augmentation_data) + { + /* The CIE augmentation says the FDE has a DW_FORM_block + before its actual instruction stream. */ + Dwarf_Word len; + get_uleb128 (len, fde->instructions); + if ((Dwarf_Word) (fde->instructions_end - fde->instructions) < len) + { + free (fde); + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return NULL; + } + fde->instructions += len; + } + else + /* We had to understand all of the CIE augmentation string. + We've recorded the number of data bytes in FDEs. */ + fde->instructions += cie->fde_augmentation_data_size; + + /* Add the new entry to the search tree. */ + if (tsearch (fde, &cache->fde_tree, &compare_fde) == NULL) + { + free (fde); + __libdw_seterrno (DWARF_E_NOMEM); + return NULL; + } + + return fde; +} + +struct dwarf_fde * +internal_function +__libdw_fde_by_offset (Dwarf_CFI *cache, Dwarf_Off offset) +{ + Dwarf_CFI_Entry entry; + Dwarf_Off next_offset; + int result = INTUSE(dwarf_next_cfi) (cache->e_ident, + &cache->data->d, CFI_IS_EH (cache), + offset, &next_offset, &entry); + if (result != 0) + { + if (result > 0) + invalid: + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return NULL; + } + + if (unlikely (dwarf_cfi_cie_p (&entry))) + goto invalid; + + /* We have a new FDE to consider. */ + struct dwarf_fde *fde = intern_fde (cache, &entry.fde); + if (fde == (void *) -1l || fde == NULL) + return NULL; + + /* If this happened to be what we would have read next, notice it. */ + if (cache->next_offset == offset) + cache->next_offset = next_offset; + + return fde; +} + +/* Use a binary search table in .eh_frame_hdr format, yield an FDE offset. */ +static Dwarf_Off +binary_search_fde (Dwarf_CFI *cache, Dwarf_Addr address) +{ + const size_t size = 2 * encoded_value_size (&cache->data->d, cache->e_ident, + cache->search_table_encoding, + NULL); + + /* Dummy used by read_encoded_value. */ + Dwarf_CFI dummy_cfi = + { + .e_ident = cache->e_ident, + .datarel = cache->search_table_vaddr, + .frame_vaddr = cache->search_table_vaddr, + }; + + size_t l = 0, u = cache->search_table_entries; + while (l < u) + { + size_t idx = (l + u) / 2; + + const uint8_t *p = &cache->search_table[idx * size]; + Dwarf_Addr start; + if (unlikely (read_encoded_value (&dummy_cfi, + cache->search_table_encoding, &p, + &start))) + break; + if (address < start) + u = idx; + else + { + Dwarf_Addr fde; + if (unlikely (read_encoded_value (&dummy_cfi, + cache->search_table_encoding, &p, + &fde))) + break; + if (address >= start) + { + l = idx + 1; + + /* If this is the last entry, its upper bound is assumed to be + the end of the module. + XXX really should be end of containing PT_LOAD segment */ + if (l < cache->search_table_entries) + { + /* Look at the start address in the following entry. */ + Dwarf_Addr end; + if (unlikely (read_encoded_value + (&dummy_cfi, cache->search_table_encoding, &p, + &end))) + break; + if (address >= end) + continue; + } + + return fde - cache->frame_vaddr; + } + } + } + + return (Dwarf_Off) -1l; +} + +struct dwarf_fde * +internal_function +__libdw_find_fde (Dwarf_CFI *cache, Dwarf_Addr address) +{ + /* Look for a cached FDE covering this address. */ + + const struct dwarf_fde fde_key = { .start = address, .end = 0 }; + struct dwarf_fde **found = tfind (&fde_key, &cache->fde_tree, &compare_fde); + if (found != NULL) + return *found; + + /* Use .eh_frame_hdr binary search table if possible. */ + if (cache->search_table != NULL) + { + Dwarf_Off offset = binary_search_fde (cache, address); + if (offset == (Dwarf_Off) -1l) + goto no_match; + struct dwarf_fde *fde = __libdw_fde_by_offset (cache, offset); + if (unlikely (fde != NULL) + /* Sanity check the address range. */ + && unlikely (address < fde->start || address >= fde->end)) + { + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return NULL; + } + return fde; + } + + /* It's not there. Read more CFI entries until we find it. */ + while (1) + { + Dwarf_Off last_offset = cache->next_offset; + Dwarf_CFI_Entry entry; + int result = INTUSE(dwarf_next_cfi) (cache->e_ident, + &cache->data->d, CFI_IS_EH (cache), + last_offset, &cache->next_offset, + &entry); + if (result > 0) + break; + if (result < 0) + { + if (cache->next_offset == last_offset) + /* We couldn't progress past the bogus FDE. */ + break; + /* Skip the loser and look at the next entry. */ + continue; + } + + if (dwarf_cfi_cie_p (&entry)) + { + /* This is a CIE, not an FDE. We eagerly intern these + because the next FDE will usually refer to this CIE. */ + __libdw_intern_cie (cache, last_offset, &entry.cie); + continue; + } + + /* We have a new FDE to consider. */ + struct dwarf_fde *fde = intern_fde (cache, &entry.fde); + + if (fde == (void *) -1l) /* Bad FDE, but we can keep looking. */ + continue; + + if (fde == NULL) /* Bad data. */ + return NULL; + + /* Is this the one we're looking for? */ + if (fde->start <= address && fde->end > address) + return fde; + } + + no_match: + /* We found no FDE covering this address. */ + __libdw_seterrno (DWARF_E_NO_MATCH); + return NULL; +} diff --git a/src/libdw/frame-cache.c b/src/libdw/frame-cache.c new file mode 100644 index 00000000..f4876638 --- /dev/null +++ b/src/libdw/frame-cache.c @@ -0,0 +1,87 @@ +/* Frame cache handling. + Copyright (C) 2009 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "cfi.h" +#include <search.h> +#include <stdlib.h> + + +static void +free_cie (void *arg) +{ + struct dwarf_cie *cie = arg; + + free ((Dwarf_Frame *) cie->initial_state); + free (cie); +} + +#define free_fde free + +static void +free_expr (void *arg) +{ + struct loc_s *loc = arg; + + free (loc->loc); + free (loc); +} + +void +internal_function +__libdw_destroy_frame_cache (Dwarf_CFI *cache) +{ + /* Most of the data is in our two search trees. */ + tdestroy (cache->fde_tree, free_fde); + tdestroy (cache->cie_tree, free_cie); + tdestroy (cache->expr_tree, free_expr); +} diff --git a/src/libdw/libdw.h b/src/libdw/libdw.h new file mode 100644 index 00000000..e001b7a4 --- /dev/null +++ b/src/libdw/libdw.h @@ -0,0 +1,875 @@ +/* Interfaces for libdw. + Copyright (C) 2002-2010 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifndef _LIBDW_H +#define _LIBDW_H 1 + +#include <gelf.h> +#include <stdbool.h> +#include <stddef.h> + + +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) +# define __nonnull_attribute__(...) __attribute__ ((__nonnull__ (__VA_ARGS__))) +# define __deprecated_attribute__ __attribute__ ((__deprecated__)) +#else +# define __nonnull_attribute__(args...) +# define __deprecated_attribute__ +#endif + + +#ifdef __GNUC_STDC_INLINE__ +# define __libdw_extern_inline extern __inline __attribute__ ((__gnu_inline__)) +#else +# define __libdw_extern_inline extern __inline +#endif + + +/* Mode for the session. */ +typedef enum + { + DWARF_C_READ, /* Read .. */ + DWARF_C_RDWR, /* Read and write .. */ + DWARF_C_WRITE, /* Write .. */ + } +Dwarf_Cmd; + + +/* Callback results. */ +enum +{ + DWARF_CB_OK = 0, + DWARF_CB_ABORT +}; + + +/* Error values. */ +enum + { + DW_TAG_invalid = 0 +#define DW_TAG_invalid DW_TAG_invalid + }; + + +/* Type for offset in DWARF file. */ +typedef GElf_Off Dwarf_Off; + +/* Type for address in DWARF file. */ +typedef GElf_Addr Dwarf_Addr; + +/* Integer types. Big enough to hold any numeric value. */ +typedef GElf_Xword Dwarf_Word; +typedef GElf_Sxword Dwarf_Sword; +/* For the times we know we do not need that much. */ +typedef GElf_Half Dwarf_Half; + + +/* DWARF abbreviation record. */ +typedef struct Dwarf_Abbrev Dwarf_Abbrev; + +/* Returned to show the last DIE has be returned. */ +#define DWARF_END_ABBREV ((Dwarf_Abbrev *) -1l) + +/* Source code line information for CU. */ +typedef struct Dwarf_Lines_s Dwarf_Lines; + +/* One source code line information. */ +typedef struct Dwarf_Line_s Dwarf_Line; + +/* Source file information. */ +typedef struct Dwarf_Files_s Dwarf_Files; + +/* One address range record. */ +typedef struct Dwarf_Arange_s Dwarf_Arange; + +/* Address ranges of a file. */ +typedef struct Dwarf_Aranges_s Dwarf_Aranges; + +/* CU representation. */ +struct Dwarf_CU; + +/* Macro information. */ +typedef struct Dwarf_Macro_s Dwarf_Macro; + +/* Attribute representation. */ +typedef struct +{ + unsigned int code; + unsigned int form; + unsigned char *valp; + struct Dwarf_CU *cu; +} Dwarf_Attribute; + + +/* Data block representation. */ +typedef struct +{ + Dwarf_Word length; + unsigned char *data; +} Dwarf_Block; + + +/* DIE information. */ +typedef struct +{ + /* The offset can be computed from the address. */ + void *addr; + struct Dwarf_CU *cu; + Dwarf_Abbrev *abbrev; + // XXX We'll see what other information will be needed. + long int padding__; +} Dwarf_Die; + +/* Returned to show the last DIE has be returned. */ +#define DWARF_END_DIE ((Dwarf_Die *) -1l) + + +/* Global symbol information. */ +typedef struct +{ + Dwarf_Off cu_offset; + Dwarf_Off die_offset; + const char *name; +} Dwarf_Global; + + +/* One operation in a DWARF location expression. + A location expression is an array of these. */ +typedef struct +{ + uint8_t atom; /* Operation */ + Dwarf_Word number; /* Operand */ + Dwarf_Word number2; /* Possible second operand */ + Dwarf_Word offset; /* Offset in location expression */ +} Dwarf_Op; + + +/* This describes one Common Information Entry read from a CFI section. + Pointers here point into the DATA->d_buf block passed to dwarf_next_cfi. */ +typedef struct +{ + Dwarf_Off CIE_id; /* Always DW_CIE_ID_64 in Dwarf_CIE structures. */ + + /* Instruction stream describing initial state used by FDEs. If + we did not understand the whole augmentation string and it did + not use 'z', then there might be more augmentation data here + (and in FDEs) before the actual instructions. */ + const uint8_t *initial_instructions; + const uint8_t *initial_instructions_end; + + Dwarf_Word code_alignment_factor; + Dwarf_Sword data_alignment_factor; + Dwarf_Word return_address_register; + + const char *augmentation; /* Augmentation string. */ + + /* Augmentation data, might be NULL. The size is correct only if + we understood the augmentation string sufficiently. */ + const uint8_t *augmentation_data; + size_t augmentation_data_size; + size_t fde_augmentation_data_size; +} Dwarf_CIE; + +/* This describes one Frame Description Entry read from a CFI section. + Pointers here point into the DATA->d_buf block passed to dwarf_next_cfi. */ +typedef struct +{ + /* Section offset of CIE this FDE refers to. This will never be + DW_CIE_ID_64 in an FDE. If this value is DW_CIE_ID_64, this is + actually a Dwarf_CIE structure. */ + Dwarf_Off CIE_pointer; + + /* We can't really decode anything further without looking up the CIE + and checking its augmentation string. Here follows the encoded + initial_location and address_range, then any augmentation data, + then the instruction stream. This FDE describes PC locations in + the byte range [initial_location, initial_location+address_range). + When the CIE augmentation string uses 'z', the augmentation data is + a DW_FORM_block (self-sized). Otherwise, when we understand the + augmentation string completely, fde_augmentation_data_size gives + the number of bytes of augmentation data before the instructions. */ + const uint8_t *start; + const uint8_t *end; +} Dwarf_FDE; + +/* Each entry in a CFI section is either a CIE described by Dwarf_CIE or + an FDE described by Dward_FDE. Check CIE_id to see which you have. */ +typedef union +{ + Dwarf_Off CIE_id; /* Always DW_CIE_ID_64 in Dwarf_CIE structures. */ + Dwarf_CIE cie; + Dwarf_FDE fde; +} Dwarf_CFI_Entry; + +#define dwarf_cfi_cie_p(entry) ((entry)->cie.CIE_id == DW_CIE_ID_64) + +/* Opaque type representing a frame state described by CFI. */ +typedef struct Dwarf_Frame_s Dwarf_Frame; + +/* Opaque type representing a CFI section found in a DWARF or ELF file. */ +typedef struct Dwarf_CFI_s Dwarf_CFI; + + +/* Handle for debug sessions. */ +typedef struct Dwarf Dwarf; + + +/* Out-Of-Memory handler. */ +#if __GNUC__ < 4 +typedef void (*Dwarf_OOM) (void); +#else +typedef void (*__attribute__ ((noreturn)) Dwarf_OOM) (void); +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Create a handle for a new debug session. */ +extern Dwarf *dwarf_begin (int fildes, Dwarf_Cmd cmd); + +/* Create a handle for a new debug session for an ELF file. */ +extern Dwarf *dwarf_begin_elf (Elf *elf, Dwarf_Cmd cmd, Elf_Scn *scngrp); + +/* Retrieve ELF descriptor used for DWARF access. */ +extern Elf *dwarf_getelf (Dwarf *dwarf); + +/* Release debugging handling context. */ +extern int dwarf_end (Dwarf *dwarf); + + +/* Get the data block for the .debug_info section. */ +extern Elf_Data *dwarf_getscn_info (Dwarf *dwarf); + +/* Read the header for the DWARF CU. */ +extern int dwarf_nextcu (Dwarf *dwarf, Dwarf_Off off, Dwarf_Off *next_off, + size_t *header_sizep, Dwarf_Off *abbrev_offsetp, + uint8_t *address_sizep, uint8_t *offset_sizep) + __nonnull_attribute__ (3); + +/* Read the header of a DWARF CU or type unit. If TYPE_SIGNATUREP is not + null, this reads a type unit from the .debug_types section; otherwise + this reads a CU from the .debug_info section. */ +extern int dwarf_next_unit (Dwarf *dwarf, Dwarf_Off off, Dwarf_Off *next_off, + size_t *header_sizep, Dwarf_Half *versionp, + Dwarf_Off *abbrev_offsetp, + uint8_t *address_sizep, uint8_t *offset_sizep, + uint64_t *type_signaturep, Dwarf_Off *type_offsetp) + __nonnull_attribute__ (3); + + +/* Decode one DWARF CFI entry (CIE or FDE) from the raw section data. + The E_IDENT from the originating ELF file indicates the address + size and byte order used in the CFI section contained in DATA; + EH_FRAME_P should be true for .eh_frame format and false for + .debug_frame format. OFFSET is the byte position in the section + to start at; on return *NEXT_OFFSET is filled in with the byte + position immediately after this entry. + + On success, returns 0 and fills in *ENTRY; use dwarf_cfi_cie_p to + see whether ENTRY->cie or ENTRY->fde is valid. + + On errors, returns -1. Some format errors will permit safely + skipping to the next CFI entry though the current one is unusable. + In that case, *NEXT_OFF will be updated before a -1 return. + + If there are no more CFI entries left in the section, + returns 1 and sets *NEXT_OFFSET to (Dwarf_Off) -1. */ +extern int dwarf_next_cfi (const unsigned char e_ident[], + Elf_Data *data, bool eh_frame_p, + Dwarf_Off offset, Dwarf_Off *next_offset, + Dwarf_CFI_Entry *entry) + __nonnull_attribute__ (1, 2, 5, 6); + +/* Use the CFI in the DWARF .debug_frame section. + Returns NULL if there is no such section (not an error). + The pointer returned can be used until dwarf_end is called on DWARF, + and must not be passed to dwarf_cfi_end. + Calling this more than once returns the same pointer. */ +extern Dwarf_CFI *dwarf_getcfi (Dwarf *dwarf); + +/* Use the CFI in the ELF file's exception-handling data. + Returns NULL if there is no such data. + The pointer returned can be used until elf_end is called on ELF, + and must be passed to dwarf_cfi_end before then. + Calling this more than once allocates independent data structures. */ +extern Dwarf_CFI *dwarf_getcfi_elf (Elf *elf); + +/* Release resources allocated by dwarf_getcfi_elf. */ +extern int dwarf_cfi_end (Dwarf_CFI *cache); + + +/* Return DIE at given offset in .debug_info section. */ +extern Dwarf_Die *dwarf_offdie (Dwarf *dbg, Dwarf_Off offset, + Dwarf_Die *result) __nonnull_attribute__ (3); + +/* Return DIE at given offset in .debug_types section. */ +extern Dwarf_Die *dwarf_offdie_types (Dwarf *dbg, Dwarf_Off offset, + Dwarf_Die *result) + __nonnull_attribute__ (3); + +/* Return offset of DIE. */ +extern Dwarf_Off dwarf_dieoffset (Dwarf_Die *die); + +/* Return offset of DIE in CU. */ +extern Dwarf_Off dwarf_cuoffset (Dwarf_Die *die); + +/* Return CU DIE containing given DIE. */ +extern Dwarf_Die *dwarf_diecu (Dwarf_Die *die, Dwarf_Die *result, + uint8_t *address_sizep, uint8_t *offset_sizep) + __nonnull_attribute__ (2); + +/* Return CU DIE containing given address. */ +extern Dwarf_Die *dwarf_addrdie (Dwarf *dbg, Dwarf_Addr addr, + Dwarf_Die *result) __nonnull_attribute__ (3); + +/* Return child of current DIE. */ +extern int dwarf_child (Dwarf_Die *die, Dwarf_Die *result) + __nonnull_attribute__ (2); + +/* Locates the first sibling of DIE and places it in RESULT. + Returns 0 if a sibling was found, -1 if something went wrong. + Returns 1 if no sibling could be found and, if RESULT is not + the same as DIE, it sets RESULT->addr to the address of the + (non-sibling) DIE that follows this one, or NULL if this DIE + was the last one in the compilation unit. */ +extern int dwarf_siblingof (Dwarf_Die *die, Dwarf_Die *result) + __nonnull_attribute__ (2); + +/* Check whether the DIE has children. */ +extern int dwarf_haschildren (Dwarf_Die *die) __nonnull_attribute__ (1); + +/* Walks the attributes of DIE, starting at the one OFFSET bytes in, + calling the CALLBACK function for each one. Stops if the callback + function ever returns a value other than DWARF_CB_OK and returns the + offset of the offending attribute. If the end of the attributes + is reached 1 is returned. If something goes wrong -1 is returned and + the dwarf error number is set. */ +extern ptrdiff_t dwarf_getattrs (Dwarf_Die *die, + int (*callback) (Dwarf_Attribute *, void *), + void *arg, ptrdiff_t offset) + __nonnull_attribute__ (2); + +/* Return tag of given DIE. */ +extern int dwarf_tag (Dwarf_Die *die) __nonnull_attribute__ (1); + + +/* Return specific attribute of DIE. */ +extern Dwarf_Attribute *dwarf_attr (Dwarf_Die *die, unsigned int search_name, + Dwarf_Attribute *result) + __nonnull_attribute__ (3); + +/* Check whether given DIE has specific attribute. */ +extern int dwarf_hasattr (Dwarf_Die *die, unsigned int search_name); + +/* These are the same as dwarf_attr and dwarf_hasattr, respectively, + but they resolve an indirect attribute through DW_AT_abstract_origin. */ +extern Dwarf_Attribute *dwarf_attr_integrate (Dwarf_Die *die, + unsigned int search_name, + Dwarf_Attribute *result) + __nonnull_attribute__ (3); +extern int dwarf_hasattr_integrate (Dwarf_Die *die, unsigned int search_name); + + + + +/* Check whether given attribute has specific form. */ +extern int dwarf_hasform (Dwarf_Attribute *attr, unsigned int search_form); + +/* Return attribute code of given attribute. */ +extern unsigned int dwarf_whatattr (Dwarf_Attribute *attr); + +/* Return form code of given attribute. */ +extern unsigned int dwarf_whatform (Dwarf_Attribute *attr); + + +/* Return string associated with given attribute. */ +extern const char *dwarf_formstring (Dwarf_Attribute *attrp); + +/* Return unsigned constant represented by attribute. */ +extern int dwarf_formudata (Dwarf_Attribute *attr, Dwarf_Word *return_uval) + __nonnull_attribute__ (2); + +/* Return signed constant represented by attribute. */ +extern int dwarf_formsdata (Dwarf_Attribute *attr, Dwarf_Sword *return_uval) + __nonnull_attribute__ (2); + +/* Return address represented by attribute. */ +extern int dwarf_formaddr (Dwarf_Attribute *attr, Dwarf_Addr *return_addr) + __nonnull_attribute__ (2); + +/* This function is deprecated. Always use dwarf_formref_die instead. + Return reference offset represented by attribute. */ +extern int dwarf_formref (Dwarf_Attribute *attr, Dwarf_Off *return_offset) + __nonnull_attribute__ (2) __deprecated_attribute__; + +/* Look up the DIE in a reference-form attribute. */ +extern Dwarf_Die *dwarf_formref_die (Dwarf_Attribute *attr, Dwarf_Die *die_mem) + __nonnull_attribute__ (2); + +/* Return block represented by attribute. */ +extern int dwarf_formblock (Dwarf_Attribute *attr, Dwarf_Block *return_block) + __nonnull_attribute__ (2); + +/* Return flag represented by attribute. */ +extern int dwarf_formflag (Dwarf_Attribute *attr, bool *return_bool) + __nonnull_attribute__ (2); + + +/* Simplified attribute value access functions. */ + +/* Return string in name attribute of DIE. */ +extern const char *dwarf_diename (Dwarf_Die *die); + +/* Return high PC attribute of DIE. */ +extern int dwarf_highpc (Dwarf_Die *die, Dwarf_Addr *return_addr) + __nonnull_attribute__ (2); + +/* Return low PC attribute of DIE. */ +extern int dwarf_lowpc (Dwarf_Die *die, Dwarf_Addr *return_addr) + __nonnull_attribute__ (2); + +/* Return entry_pc or low_pc attribute of DIE. */ +extern int dwarf_entrypc (Dwarf_Die *die, Dwarf_Addr *return_addr) + __nonnull_attribute__ (2); + +/* Return 1 if DIE's lowpc/highpc or ranges attributes match the PC address, + 0 if not, or -1 for errors. */ +extern int dwarf_haspc (Dwarf_Die *die, Dwarf_Addr pc); + +/* Enumerate the PC address ranges covered by this DIE, covering all + addresses where dwarf_haspc returns true. In the first call OFFSET + should be zero and *BASEP need not be initialized. Returns -1 for + errors, zero when there are no more address ranges to report, or a + nonzero OFFSET value to pass to the next call. Each subsequent call + must preserve *BASEP from the prior call. Successful calls fill in + *STARTP and *ENDP with a contiguous address range. */ +extern ptrdiff_t dwarf_ranges (Dwarf_Die *die, + ptrdiff_t offset, Dwarf_Addr *basep, + Dwarf_Addr *startp, Dwarf_Addr *endp); + + +/* Return byte size attribute of DIE. */ +extern int dwarf_bytesize (Dwarf_Die *die); + +/* Return bit size attribute of DIE. */ +extern int dwarf_bitsize (Dwarf_Die *die); + +/* Return bit offset attribute of DIE. */ +extern int dwarf_bitoffset (Dwarf_Die *die); + +/* Return array order attribute of DIE. */ +extern int dwarf_arrayorder (Dwarf_Die *die); + +/* Return source language attribute of DIE. */ +extern int dwarf_srclang (Dwarf_Die *die); + + +/* Get abbreviation at given offset for given DIE. */ +extern Dwarf_Abbrev *dwarf_getabbrev (Dwarf_Die *die, Dwarf_Off offset, + size_t *lengthp); + +/* Get abbreviation at given offset in .debug_abbrev section. */ +extern int dwarf_offabbrev (Dwarf *dbg, Dwarf_Off offset, size_t *lengthp, + Dwarf_Abbrev *abbrevp) + __nonnull_attribute__ (4); + +/* Get abbreviation code. */ +extern unsigned int dwarf_getabbrevcode (Dwarf_Abbrev *abbrev); + +/* Get abbreviation tag. */ +extern unsigned int dwarf_getabbrevtag (Dwarf_Abbrev *abbrev); + +/* Return true if abbreviation is children flag set. */ +extern int dwarf_abbrevhaschildren (Dwarf_Abbrev *abbrev); + +/* Get number of attributes of abbreviation. */ +extern int dwarf_getattrcnt (Dwarf_Abbrev *abbrev, size_t *attrcntp) + __nonnull_attribute__ (2); + +/* Get specific attribute of abbreviation. */ +extern int dwarf_getabbrevattr (Dwarf_Abbrev *abbrev, size_t idx, + unsigned int *namep, unsigned int *formp, + Dwarf_Off *offset); + + +/* Get string from-debug_str section. */ +extern const char *dwarf_getstring (Dwarf *dbg, Dwarf_Off offset, + size_t *lenp); + + +/* Get public symbol information. */ +extern ptrdiff_t dwarf_getpubnames (Dwarf *dbg, + int (*callback) (Dwarf *, Dwarf_Global *, + void *), + void *arg, ptrdiff_t offset) + __nonnull_attribute__ (2); + + +/* Get source file information for CU. */ +extern int dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines, + size_t *nlines) __nonnull_attribute__ (2, 3); + +/* Return one of the source lines of the CU. */ +extern Dwarf_Line *dwarf_onesrcline (Dwarf_Lines *lines, size_t idx); + +/* Get the file source files used in the CU. */ +extern int dwarf_getsrcfiles (Dwarf_Die *cudie, Dwarf_Files **files, + size_t *nfiles) + __nonnull_attribute__ (2); + + +/* Get source for address in CU. */ +extern Dwarf_Line *dwarf_getsrc_die (Dwarf_Die *cudie, Dwarf_Addr addr); + +/* Get source for file and line number. */ +extern int dwarf_getsrc_file (Dwarf *dbg, const char *fname, int line, int col, + Dwarf_Line ***srcsp, size_t *nsrcs) + __nonnull_attribute__ (2, 5, 6); + + +/* Return line address. */ +extern int dwarf_lineaddr (Dwarf_Line *line, Dwarf_Addr *addrp); + +/* Return line VLIW operation index. */ +extern int dwarf_lineop_index (Dwarf_Line *line, unsigned int *op_indexp); + +/* Return line number. */ +extern int dwarf_lineno (Dwarf_Line *line, int *linep) + __nonnull_attribute__ (2); + +/* Return column in line. */ +extern int dwarf_linecol (Dwarf_Line *line, int *colp) + __nonnull_attribute__ (2); + +/* Return true if record is for beginning of a statement. */ +extern int dwarf_linebeginstatement (Dwarf_Line *line, bool *flagp) + __nonnull_attribute__ (2); + +/* Return true if record is for end of sequence. */ +extern int dwarf_lineendsequence (Dwarf_Line *line, bool *flagp) + __nonnull_attribute__ (2); + +/* Return true if record is for beginning of a basic block. */ +extern int dwarf_lineblock (Dwarf_Line *line, bool *flagp) + __nonnull_attribute__ (2); + +/* Return true if record is for end of prologue. */ +extern int dwarf_lineprologueend (Dwarf_Line *line, bool *flagp) + __nonnull_attribute__ (2); + +/* Return true if record is for beginning of epilogue. */ +extern int dwarf_lineepiloguebegin (Dwarf_Line *line, bool *flagp) + __nonnull_attribute__ (2); + +/* Return instruction-set architecture in this record. */ +extern int dwarf_lineisa (Dwarf_Line *line, unsigned int *isap) + __nonnull_attribute__ (2); + +/* Return code path discriminator in this record. */ +extern int dwarf_linediscriminator (Dwarf_Line *line, unsigned int *discp) + __nonnull_attribute__ (2); + + +/* Find line information for address. */ +extern const char *dwarf_linesrc (Dwarf_Line *line, + Dwarf_Word *mtime, Dwarf_Word *length); + +/* Return file information. */ +extern const char *dwarf_filesrc (Dwarf_Files *file, size_t idx, + Dwarf_Word *mtime, Dwarf_Word *length); + +/* Return the directory list used in the file information extracted. + (*RESULT)[0] is the CU's DW_AT_comp_dir value, and may be null. + (*RESULT)[0..*NDIRS-1] are the compile-time include directory path + encoded by the compiler. */ +extern int dwarf_getsrcdirs (Dwarf_Files *files, + const char *const **result, size_t *ndirs) + __nonnull_attribute__ (2, 3); + + +/* Return location expression, decoded as a list of operations. */ +extern int dwarf_getlocation (Dwarf_Attribute *attr, Dwarf_Op **expr, + size_t *exprlen) __nonnull_attribute__ (2, 3); + +/* Return location expressions. If the attribute uses a location list, + ADDRESS selects the relevant location expressions from the list. + There can be multiple matches, resulting in multiple expressions to + return. EXPRS and EXPRLENS are parallel arrays of NLOCS slots to + fill in. Returns the number of locations filled in, or -1 for + errors. If EXPRS is a null pointer, stores nothing and returns the + total number of locations. A return value of zero means that the + location list indicated no value is accessible. */ +extern int dwarf_getlocation_addr (Dwarf_Attribute *attr, Dwarf_Addr address, + Dwarf_Op **exprs, size_t *exprlens, + size_t nlocs); + +/* Return the block associated with a DW_OP_implicit_value operation. + The OP pointer must point into an expression that dwarf_getlocation + or dwarf_getlocation_addr has returned given the same ATTR. */ +extern int dwarf_getlocation_implicit_value (Dwarf_Attribute *attr, + const Dwarf_Op *op, + Dwarf_Block *return_block) + __nonnull_attribute__ (2, 3); + +/* Return the attribute indicated by a DW_OP_GNU_implicit_pointer operation. + The OP pointer must point into an expression that dwarf_getlocation + or dwarf_getlocation_addr has returned given the same ATTR. + The result is the DW_AT_location or DW_AT_const_value attribute + of the OP->number DIE. */ +extern int dwarf_getlocation_implicit_pointer (Dwarf_Attribute *attr, + const Dwarf_Op *op, + Dwarf_Attribute *result) + __nonnull_attribute__ (2, 3); + + +/* Compute the byte-size of a type DIE according to DWARF rules. + For most types, this is just DW_AT_byte_size. + For DW_TAG_array_type it can apply much more complex rules. */ +extern int dwarf_aggregate_size (Dwarf_Die *die, Dwarf_Word *size); + + +/* Return scope DIEs containing PC address. + Sets *SCOPES to a malloc'd array of Dwarf_Die structures, + and returns the number of elements in the array. + (*SCOPES)[0] is the DIE for the innermost scope containing PC, + (*SCOPES)[1] is the DIE for the scope containing that scope, and so on. + Returns -1 for errors or 0 if no scopes match PC. */ +extern int dwarf_getscopes (Dwarf_Die *cudie, Dwarf_Addr pc, + Dwarf_Die **scopes); + +/* Return scope DIEs containing the given DIE. + Sets *SCOPES to a malloc'd array of Dwarf_Die structures, + and returns the number of elements in the array. + (*SCOPES)[0] is a copy of DIE. + (*SCOPES)[1] is the DIE for the scope containing that scope, and so on. + Returns -1 for errors or 0 if DIE is not found in any scope entry. */ +extern int dwarf_getscopes_die (Dwarf_Die *die, Dwarf_Die **scopes); + + +/* Search SCOPES[0..NSCOPES-1] for a variable called NAME. + Ignore the first SKIP_SHADOWS scopes that match the name. + If MATCH_FILE is not null, accept only declaration in that source file; + if MATCH_LINENO or MATCH_LINECOL are also nonzero, accept only declaration + at that line and column. + + If successful, fill in *RESULT with the DIE of the variable found, + and return N where SCOPES[N] is the scope defining the variable. + Return -1 for errors or -2 for no matching variable found. */ +extern int dwarf_getscopevar (Dwarf_Die *scopes, int nscopes, + const char *name, int skip_shadows, + const char *match_file, + int match_lineno, int match_linecol, + Dwarf_Die *result); + + + +/* Return list address ranges. */ +extern int dwarf_getaranges (Dwarf *dbg, Dwarf_Aranges **aranges, + size_t *naranges) + __nonnull_attribute__ (2); + +/* Return one of the address range entries. */ +extern Dwarf_Arange *dwarf_onearange (Dwarf_Aranges *aranges, size_t idx); + +/* Return information in address range record. */ +extern int dwarf_getarangeinfo (Dwarf_Arange *arange, Dwarf_Addr *addrp, + Dwarf_Word *lengthp, Dwarf_Off *offsetp); + +/* Get address range which includes given address. */ +extern Dwarf_Arange *dwarf_getarange_addr (Dwarf_Aranges *aranges, + Dwarf_Addr addr); + + + +/* Get functions in CUDIE. */ +extern ptrdiff_t dwarf_getfuncs (Dwarf_Die *cudie, + int (*callback) (Dwarf_Die *, void *), + void *arg, ptrdiff_t offset); + + +/* Return file name containing definition of the given declaration. */ +extern const char *dwarf_decl_file (Dwarf_Die *decl); + +/* Get line number of beginning of given declaration. */ +extern int dwarf_decl_line (Dwarf_Die *decl, int *linep) + __nonnull_attribute__ (2); + +/* Get column number of beginning of given declaration. */ +extern int dwarf_decl_column (Dwarf_Die *decl, int *colp) + __nonnull_attribute__ (2); + + +/* Return nonzero if given function is an abstract inline definition. */ +extern int dwarf_func_inline (Dwarf_Die *func); + +/* Find each concrete inlined instance of the abstract inline definition. */ +extern int dwarf_func_inline_instances (Dwarf_Die *func, + int (*callback) (Dwarf_Die *, void *), + void *arg); + + +/* Find the appropriate PC location or locations for function entry + breakpoints for the given DW_TAG_subprogram DIE. Returns -1 for errors. + On success, returns the number of breakpoint locations (never zero) + and sets *BKPTS to a malloc'd vector of addresses. */ +extern int dwarf_entry_breakpoints (Dwarf_Die *die, Dwarf_Addr **bkpts); + + +/* Call callback function for each of the macro information entry for + the CU. */ +extern ptrdiff_t dwarf_getmacros (Dwarf_Die *cudie, + int (*callback) (Dwarf_Macro *, void *), + void *arg, ptrdiff_t offset) + __nonnull_attribute__ (2); + +/* Return macro opcode. */ +extern int dwarf_macro_opcode (Dwarf_Macro *macro, unsigned int *opcodep) + __nonnull_attribute__ (2); + +/* Return first macro parameter. */ +extern int dwarf_macro_param1 (Dwarf_Macro *macro, Dwarf_Word *paramp) + __nonnull_attribute__ (2); + +/* Return second macro parameter. */ +extern int dwarf_macro_param2 (Dwarf_Macro *macro, Dwarf_Word *paramp, + const char **strp); + + +/* Compute what's known about a call frame when the PC is at ADDRESS. + Returns 0 for success or -1 for errors. + On success, *FRAME is a malloc'd pointer. */ +extern int dwarf_cfi_addrframe (Dwarf_CFI *cache, + Dwarf_Addr address, Dwarf_Frame **frame) + __nonnull_attribute__ (3); + +/* Return the DWARF register number used in FRAME to denote + the return address in FRAME's caller frame. The remaining + arguments can be non-null to fill in more information. + + Fill [*START, *END) with the PC range to which FRAME's information applies. + Fill in *SIGNALP to indicate whether this is a signal-handling frame. + If true, this is the implicit call frame that calls a signal handler. + This frame's "caller" is actually the interrupted state, not a call; + its return address is an exact PC, not a PC after a call instruction. */ +extern int dwarf_frame_info (Dwarf_Frame *frame, + Dwarf_Addr *start, Dwarf_Addr *end, bool *signalp); + +/* Return a DWARF expression that yields the Canonical Frame Address at + this frame state. Returns -1 for errors, or zero for success, with + *NOPS set to the number of operations stored at *OPS. That pointer + can be used only as long as FRAME is alive and unchanged. *NOPS is + zero if the CFA cannot be determined here. Note that if nonempty, + *OPS is a DWARF expression, not a location description--append + DW_OP_stack_value to a get a location description for the CFA. */ +extern int dwarf_frame_cfa (Dwarf_Frame *frame, Dwarf_Op **ops, size_t *nops) + __nonnull_attribute__ (2); + +/* Deliver a DWARF location description that yields the location or + value of DWARF register number REGNO in the state described by FRAME. + + Returns -1 for errors or zero for success, setting *NOPS to the + number of operations in the array stored at *OPS. Note the last + operation is DW_OP_stack_value if there is no mutable location but + only a computable value. + + *NOPS zero with *OPS set to OPS_MEM means CFI says the caller's + REGNO is "undefined", i.e. it's call-clobbered and cannot be recovered. + + *NOPS zero with *OPS set to a null pointer means CFI says the + caller's REGNO is "same_value", i.e. this frame did not change it; + ask the caller frame where to find it. + + For common simple expressions *OPS is OPS_MEM. For arbitrary DWARF + expressions in the CFI, *OPS is an internal pointer that can be used as + long as the Dwarf_CFI used to create FRAME remains alive. */ +extern int dwarf_frame_register (Dwarf_Frame *frame, int regno, + Dwarf_Op ops_mem[3], + Dwarf_Op **ops, size_t *nops) + __nonnull_attribute__ (3, 4, 5); + + +/* Return error code of last failing function call. This value is kept + separately for each thread. */ +extern int dwarf_errno (void); + +/* Return error string for ERROR. If ERROR is zero, return error string + for most recent error or NULL is none occurred. If ERROR is -1 the + behaviour is similar to the last case except that not NULL but a legal + string is returned. */ +extern const char *dwarf_errmsg (int err); + + +/* Register new Out-Of-Memory handler. The old handler is returned. */ +extern Dwarf_OOM dwarf_new_oom_handler (Dwarf *dbg, Dwarf_OOM handler); + + +/* Inline optimizations. */ +#ifdef __OPTIMIZE__ +/* Return attribute code of given attribute. */ +__libdw_extern_inline unsigned int +dwarf_whatattr (Dwarf_Attribute *attr) +{ + return attr == NULL ? 0 : attr->code; +} + +/* Return attribute code of given attribute. */ +__libdw_extern_inline unsigned int +dwarf_whatform (Dwarf_Attribute *attr) +{ + return attr == NULL ? 0 : attr->form; +} +#endif /* Optimize. */ + +#ifdef __cplusplus +} +#endif + +#endif /* libdw.h */ diff --git a/src/libdw/libdw.map b/src/libdw/libdw.map new file mode 100644 index 00000000..1f71d03b --- /dev/null +++ b/src/libdw/libdw.map @@ -0,0 +1,256 @@ +ELFUTILS_0 { }; +ELFUTILS_0.122 { + global: + dwarf_abbrevhaschildren; + dwarf_addrdie; + dwarf_arrayorder; + dwarf_attr; + dwarf_attr_integrate; + dwarf_begin; + dwarf_begin_elf; + dwarf_bitoffset; + dwarf_bitsize; + dwarf_bytesize; + dwarf_child; + dwarf_cuoffset; + dwarf_decl_column; + dwarf_decl_file; + dwarf_decl_line; + dwarf_diecu; + dwarf_diename; + dwarf_dieoffset; + dwarf_end; + dwarf_entry_breakpoints; + dwarf_entrypc; + dwarf_errmsg; + dwarf_errno; + dwarf_filesrc; + dwarf_formaddr; + dwarf_formblock; + dwarf_formflag; + dwarf_formref; + dwarf_formref_die; + dwarf_formsdata; + dwarf_formstring; + dwarf_formudata; + dwarf_func_inline; + dwarf_func_inline_instances; + dwarf_getabbrev; + dwarf_getabbrevattr; + dwarf_getabbrevcode; + dwarf_getabbrevtag; + dwarf_getarange_addr; + dwarf_getarangeinfo; + dwarf_getaranges; + dwarf_getattrcnt; + dwarf_getattrs; + dwarf_getfuncs; + dwarf_getlocation; + dwarf_getlocation_addr; + dwarf_getmacros; + dwarf_getpubnames; + dwarf_getscn_info; + dwarf_getscopes; + dwarf_getscopes_die; + dwarf_getscopevar; + dwarf_getsrc_die; + dwarf_getsrc_file; + dwarf_getsrcfiles; + dwarf_getsrclines; + dwarf_getstring; + dwarf_hasattr; + dwarf_hasattr_integrate; + dwarf_haschildren; + dwarf_hasform; + dwarf_haspc; + dwarf_highpc; + dwarf_lineaddr; + dwarf_linebeginstatement; + dwarf_lineblock; + dwarf_linecol; + dwarf_lineendsequence; + dwarf_lineepiloguebegin; + dwarf_lineno; + dwarf_lineprologueend; + dwarf_linesrc; + dwarf_lowpc; + dwarf_macro_opcode; + dwarf_macro_param1; + dwarf_macro_param2; + dwarf_new_oom_handler; + dwarf_nextcu; + dwarf_offabbrev; + dwarf_offdie; + dwarf_onearange; + dwarf_onesrcline; + dwarf_ranges; + dwarf_siblingof; + dwarf_srclang; + dwarf_tag; + dwarf_whatattr; + dwarf_whatform; + + # libdwfl_pic.a contributes these symbols. + dwfl_addrdie; + dwfl_addrdwarf; + dwfl_addrmodule; + dwfl_begin; + dwfl_cumodule; + dwfl_end; + dwfl_errmsg; + dwfl_errno; + dwfl_getdwarf; + dwfl_getmodules; + dwfl_getsrc; + dwfl_getsrclines; + dwfl_line_comp_dir; + dwfl_linecu; + dwfl_lineinfo; + dwfl_linemodule; + dwfl_linux_kernel_find_elf; + dwfl_linux_kernel_module_section_address; + dwfl_linux_kernel_report_kernel; + dwfl_linux_kernel_report_modules; + dwfl_linux_kernel_report_offline; + dwfl_linux_proc_find_elf; + dwfl_linux_proc_maps_report; + dwfl_linux_proc_report; + dwfl_module_addrdie; + dwfl_module_addrname; + dwfl_module_getdwarf; + dwfl_module_getelf; + dwfl_module_getsrc; + dwfl_module_getsrc_file; + dwfl_module_getsym; + dwfl_module_getsymtab; + dwfl_module_info; + dwfl_module_nextcu; + dwfl_module_register_names; + dwfl_module_relocate_address; + dwfl_module_relocation_info; + dwfl_module_relocations; + dwfl_module_return_value_location; + dwfl_nextcu; + dwfl_offline_section_address; + dwfl_onesrcline; + dwfl_report_begin; + dwfl_report_elf; + dwfl_report_end; + dwfl_report_module; + dwfl_report_offline; + dwfl_standard_argp; + dwfl_standard_find_debuginfo; + dwfl_version; + + local: + *; +} ELFUTILS_0; + +ELFUTILS_0.126 { + global: + dwarf_getelf; + + local: + *; +} ELFUTILS_0.122; + +ELFUTILS_0.127 { + global: + dwarf_getsrcdirs; + + dwfl_module_addrsym; + dwfl_report_begin_add; + dwfl_module_address_section; + + local: + *; +} ELFUTILS_0.126; + +ELFUTILS_0.130 { + global: + dwfl_build_id_find_elf; + dwfl_build_id_find_debuginfo; + dwfl_module_build_id; + dwfl_module_report_build_id; + + local: + *; +} ELFUTILS_0.127; + +ELFUTILS_0.136 { + global: + dwfl_addrsegment; + dwfl_report_segment; + + local: + *; +} ELFUTILS_0.130; + +ELFUTILS_0.138 { + global: + # Replaced ELFUTILS_0.130 version, which has bug-compatibility wrapper. + dwfl_module_build_id; + + local: + *; +} ELFUTILS_0.136; + +ELFUTILS_0.142 { + global: + dwarf_next_cfi; + dwarf_getcfi; + dwarf_getcfi_elf; + dwarf_cfi_addrframe; + dwarf_cfi_end; + dwarf_frame_cfa; + dwarf_frame_register; + dwarf_frame_info; + + dwfl_module_dwarf_cfi; + dwfl_module_eh_cfi; +} ELFUTILS_0.138; + +ELFUTILS_0.143 { + global: + dwarf_getlocation_implicit_value; + + # Replaced ELFUTILS_0.122 versions. Both versions point to the + # same implementation, but users of the new symbol version can + # presume that they use dwarf_attr_integrate properly. + dwarf_arrayorder; + dwarf_bitoffset; + dwarf_bitsize; + dwarf_bytesize; + dwarf_decl_column; + dwarf_decl_file; + dwarf_decl_line; + dwarf_srclang; + +} ELFUTILS_0.142; + +ELFUTILS_0.144 { + global: + dwarf_aggregate_size; +} ELFUTILS_0.143; + +ELFUTILS_0.146 { + global: + dwfl_core_file_report; +} ELFUTILS_0.144; + +ELFUTILS_0.148 { + global: + dwarf_lineisa; + dwarf_linediscriminator; + dwarf_lineop_index; + + dwarf_next_unit; + dwarf_offdie_types; +} ELFUTILS_0.146; + +ELFUTILS_0.149 { + global: + dwarf_getlocation_implicit_pointer; + + dwfl_dwarf_line; +} ELFUTILS_0.148; diff --git a/src/libdw/libdwP.h b/src/libdw/libdwP.h new file mode 100644 index 00000000..b84bf02c --- /dev/null +++ b/src/libdw/libdwP.h @@ -0,0 +1,677 @@ +/* Internal definitions for libdwarf. + Copyright (C) 2002-2011 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifndef _LIBDWP_H +#define _LIBDWP_H 1 + +#include <libintl.h> +#include <stdbool.h> + +#include <libdw.h> + + +/* gettext helper macros. */ +#define _(Str) dgettext ("elfutils", Str) + + +/* Known location expressions already decoded. */ +struct loc_s +{ + void *addr; + Dwarf_Op *loc; + size_t nloc; +}; + +/* Known DW_OP_implicit_value blocks already decoded. + This overlaps struct loc_s exactly, but only the + first member really has to match. */ +struct loc_block_s +{ + void *addr; + unsigned char *data; + size_t length; +}; + +/* Valid indeces for the section data. */ +enum + { + IDX_debug_info = 0, + IDX_debug_types, + IDX_debug_abbrev, + IDX_debug_aranges, + IDX_debug_line, + IDX_debug_frame, + IDX_debug_loc, + IDX_debug_pubnames, + IDX_debug_str, + IDX_debug_macinfo, + IDX_debug_ranges, + IDX_last + }; + + +/* Error values. */ +enum +{ + DWARF_E_NOERROR = 0, + DWARF_E_UNKNOWN_ERROR, + DWARF_E_INVALID_ACCESS, + DWARF_E_NO_REGFILE, + DWARF_E_IO_ERROR, + DWARF_E_INVALID_ELF, + DWARF_E_NO_DWARF, + DWARF_E_NOELF, + DWARF_E_GETEHDR_ERROR, + DWARF_E_NOMEM, + DWARF_E_UNIMPL, + DWARF_E_INVALID_CMD, + DWARF_E_INVALID_VERSION, + DWARF_E_INVALID_FILE, + DWARF_E_NO_ENTRY, + DWARF_E_INVALID_DWARF, + DWARF_E_NO_STRING, + DWARF_E_NO_ADDR, + DWARF_E_NO_CONSTANT, + DWARF_E_NO_REFERENCE, + DWARF_E_INVALID_REFERENCE, + DWARF_E_NO_DEBUG_LINE, + DWARF_E_INVALID_DEBUG_LINE, + DWARF_E_TOO_BIG, + DWARF_E_VERSION, + DWARF_E_INVALID_DIR_IDX, + DWARF_E_ADDR_OUTOFRANGE, + DWARF_E_NO_LOCLIST, + DWARF_E_NO_BLOCK, + DWARF_E_INVALID_LINE_IDX, + DWARF_E_INVALID_ARANGE_IDX, + DWARF_E_NO_MATCH, + DWARF_E_NO_FLAG, + DWARF_E_INVALID_OFFSET, + DWARF_E_NO_DEBUG_RANGES, + DWARF_E_INVALID_CFI, +}; + + +#include "dwarf_sig8_hash.h" + +/* This is the structure representing the debugging state. */ +struct Dwarf +{ + /* The underlying ELF file. */ + Elf *elf; + + /* The section data. */ + Elf_Data *sectiondata[IDX_last]; + +#if USE_ZLIB + /* The 1 << N bit is set if sectiondata[N] is malloc'd decompressed data. */ + unsigned int sectiondata_gzip_mask:IDX_last; +#endif + + /* True if the file has a byte order different from the host. */ + bool other_byte_order; + + /* If true, we allocated the ELF descriptor ourselves. */ + bool free_elf; + + /* Information for traversing the .debug_pubnames section. This is + an array and separately allocated with malloc. */ + struct pubnames_s + { + Dwarf_Off cu_offset; + Dwarf_Off set_start; + unsigned int cu_header_size; + int address_len; + } *pubnames_sets; + size_t pubnames_nsets; + + /* Search tree for the CUs. */ + void *cu_tree; + Dwarf_Off next_cu_offset; + + /* Search tree and sig8 hash table for .debug_types type units. */ + void *tu_tree; + Dwarf_Off next_tu_offset; + Dwarf_Sig8_Hash sig8_hash; + + /* Address ranges. */ + Dwarf_Aranges *aranges; + + /* Cached info from the CFI section. */ + struct Dwarf_CFI_s *cfi; + + /* Internal memory handling. This is basically a simplified + reimplementation of obstacks. Unfortunately the standard obstack + implementation is not usable in libraries. */ + struct libdw_memblock + { + size_t size; + size_t remaining; + struct libdw_memblock *prev; + char mem[0]; + } *mem_tail; + + /* Default size of allocated memory blocks. */ + size_t mem_default_size; + + /* Registered OOM handler. */ + Dwarf_OOM oom_handler; +}; + + +/* Abbreviation representation. */ +struct Dwarf_Abbrev +{ + Dwarf_Off offset; + unsigned char *attrp; + unsigned int attrcnt; + unsigned int code; + unsigned int tag; + bool has_children; +}; + +#include "dwarf_abbrev_hash.h" + + +/* Files in line information records. */ +struct Dwarf_Files_s + { + struct Dwarf_CU *cu; + unsigned int ndirs; + unsigned int nfiles; + struct Dwarf_Fileinfo_s + { + char *name; + Dwarf_Word mtime; + Dwarf_Word length; + } info[0]; + /* nfiles of those, followed by char *[ndirs]. */ + }; +typedef struct Dwarf_Fileinfo_s Dwarf_Fileinfo; + + +/* Representation of a row in the line table. */ + +struct Dwarf_Line_s +{ + Dwarf_Files *files; + + 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; + /* The remaining bit fields are not flags, but hold values presumed to be + small. All the flags and other bit fields should add up to 48 bits + to give the whole struct a nice round size. */ + unsigned int op_index:8; + unsigned int isa:8; + unsigned int discriminator:24; +}; + +struct Dwarf_Lines_s +{ + size_t nlines; + struct Dwarf_Line_s info[0]; +}; + +/* Representation of address ranges. */ +struct Dwarf_Aranges_s +{ + Dwarf *dbg; + size_t naranges; + + struct Dwarf_Arange_s + { + Dwarf_Addr addr; + Dwarf_Word length; + Dwarf_Off offset; + } info[0]; +}; + + +/* CU representation. */ +struct Dwarf_CU +{ + Dwarf *dbg; + Dwarf_Off start; + Dwarf_Off end; + uint8_t address_size; + uint8_t offset_size; + uint16_t version; + + /* Zero if this is a normal CU. Nonzero if it is a type unit. */ + size_t type_offset; + uint64_t type_sig8; + + /* Hash table for the abbreviations. */ + Dwarf_Abbrev_Hash abbrev_hash; + /* Offset of the first abbreviation. */ + size_t orig_abbrev_offset; + /* Offset past last read abbreviation. */ + size_t last_abbrev_offset; + + /* The srcline information. */ + Dwarf_Lines *lines; + + /* The source file information. */ + Dwarf_Files *files; + + /* Known location lists. */ + void *locs; +}; + +/* Compute the offset of a CU's first DIE from its offset. This + is either: + LEN VER OFFSET ADDR + 4-bytes + 2-bytes + 4-bytes + 1-byte for 32-bit dwarf + 12-bytes + 2-bytes + 8-bytes + 1-byte for 64-bit dwarf + or in .debug_types, SIGNATURE TYPE-OFFSET + 4-bytes + 2-bytes + 4-bytes + 1-byte + 8-bytes + 4-bytes for 32-bit + 12-bytes + 2-bytes + 8-bytes + 1-byte + 8-bytes + 8-bytes for 64-bit + + Note the trick in the computation. If the offset_size is 4 + the '- 4' term changes the '3 *' into a '2 *'. If the + offset_size is 8 it accounts for the 4-byte escape value + used at the start of the length. */ +#define DIE_OFFSET_FROM_CU_OFFSET(cu_offset, offset_size, type_unit) \ + ((type_unit) ? ((cu_offset) + 4 * (offset_size) - 4 + 3 + 8) \ + : ((cu_offset) + 3 * (offset_size) - 4 + 3)) + +#define CUDIE(fromcu) \ + ((Dwarf_Die) \ + { \ + .cu = (fromcu), \ + .addr = ((char *) cu_data (fromcu)->d_buf \ + + DIE_OFFSET_FROM_CU_OFFSET ((fromcu)->start, \ + (fromcu)->offset_size, \ + (fromcu)->type_offset != 0)) \ + }) \ + + +/* Macro information. */ +struct Dwarf_Macro_s +{ + unsigned int opcode; + Dwarf_Word param1; + union + { + Dwarf_Word u; + const char *s; + } param2; +}; + + +/* We have to include the file at this point because the inline + functions access internals of the Dwarf structure. */ +#include "memory-access.h" + + +/* Set error value. */ +extern void __libdw_seterrno (int value) internal_function; + + +/* Memory handling, the easy parts. This macro does not do any locking. */ +#define libdw_alloc(dbg, type, tsize, cnt) \ + ({ struct libdw_memblock *_tail = (dbg)->mem_tail; \ + size_t _required = (tsize) * (cnt); \ + type *_result = (type *) (_tail->mem + (_tail->size - _tail->remaining));\ + size_t _padding = ((__alignof (type) \ + - ((uintptr_t) _result & (__alignof (type) - 1))) \ + & (__alignof (type) - 1)); \ + if (unlikely (_tail->remaining < _required + _padding)) \ + _result = (type *) __libdw_allocate (dbg, _required, __alignof (type));\ + else \ + { \ + _required += _padding; \ + _result = (type *) ((char *) _result + _padding); \ + _tail->remaining -= _required; \ + } \ + _result; }) + +#define libdw_typed_alloc(dbg, type) \ + libdw_alloc (dbg, type, sizeof (type), 1) + +/* Callback to allocate more. */ +extern void *__libdw_allocate (Dwarf *dbg, size_t minsize, size_t align) + __attribute__ ((__malloc__)) __nonnull_attribute__ (1); + +/* Default OOM handler. */ +extern void __libdw_oom (void) __attribute ((noreturn, visibility ("hidden"))); + +#if USE_ZLIB +extern void __libdw_free_zdata (Dwarf *dwarf) internal_function; +#else +# define __libdw_free_zdata(dwarf) ((void) (dwarf)) +#endif + +/* Allocate the internal data for a unit not seen before. */ +extern struct Dwarf_CU *__libdw_intern_next_unit (Dwarf *dbg, bool debug_types) + __nonnull_attribute__ (1) internal_function; + +/* Find CU for given offset. */ +extern struct Dwarf_CU *__libdw_findcu (Dwarf *dbg, Dwarf_Off offset, bool tu) + __nonnull_attribute__ (1) internal_function; + +/* Return tag of given DIE. */ +extern Dwarf_Abbrev *__libdw_findabbrev (struct Dwarf_CU *cu, + unsigned int code) + __nonnull_attribute__ (1) internal_function; + +/* Get abbreviation at given offset. */ +extern Dwarf_Abbrev *__libdw_getabbrev (Dwarf *dbg, struct Dwarf_CU *cu, + Dwarf_Off offset, size_t *lengthp, + Dwarf_Abbrev *result) + __nonnull_attribute__ (1) internal_function; + +/* Helper functions for form handling. */ +extern size_t __libdw_form_val_len (Dwarf *dbg, struct Dwarf_CU *cu, + unsigned int form, + const unsigned char *valp) + __nonnull_attribute__ (1, 2, 4) internal_function; + +/* Helper function for DW_FORM_ref* handling. */ +extern int __libdw_formref (Dwarf_Attribute *attr, Dwarf_Off *return_offset) + __nonnull_attribute__ (1, 2) internal_function; + + +/* Helper function to locate attribute. */ +extern unsigned char *__libdw_find_attr (Dwarf_Die *die, + unsigned int search_name, + unsigned int *codep, + unsigned int *formp) + __nonnull_attribute__ (1) internal_function; + +/* Helper function to access integer attribute. */ +extern int __libdw_attr_intval (Dwarf_Die *die, int *valp, int attval) + __nonnull_attribute__ (1, 2) internal_function; + +/* Helper function to walk scopes. */ +struct Dwarf_Die_Chain +{ + Dwarf_Die die; + struct Dwarf_Die_Chain *parent; + bool prune; /* The PREVISIT function can set this. */ +}; +extern int __libdw_visit_scopes (unsigned int depth, + struct Dwarf_Die_Chain *root, + int (*previsit) (unsigned int depth, + struct Dwarf_Die_Chain *, + void *arg), + int (*postvisit) (unsigned int depth, + struct Dwarf_Die_Chain *, + void *arg), + void *arg) + __nonnull_attribute__ (2, 3) internal_function; + +/* Parse a DWARF Dwarf_Block into an array of Dwarf_Op's, + and cache the result (via tsearch). */ +extern int __libdw_intern_expression (Dwarf *dbg, + bool other_byte_order, + unsigned int address_size, + unsigned int ref_size, + void **cache, const Dwarf_Block *block, + bool cfap, bool valuep, + Dwarf_Op **llbuf, size_t *listlen, + int sec_index) + __nonnull_attribute__ (5, 6, 9, 10) internal_function; + +extern Dwarf_Die *__libdw_offdie (Dwarf *dbg, Dwarf_Off offset, + Dwarf_Die *result, bool debug_types) + internal_function; + + +/* Return error code of last failing function call. This value is kept + separately for each thread. */ +extern int __dwarf_errno_internal (void); + + +/* Reader hooks. */ + +/* Relocation hooks return -1 on error (in that case the error code + must already have been set), 0 if there is no relocation and 1 if a + relocation was present.*/ + +static inline int +__libdw_relocate_address (Dwarf *dbg __attribute__ ((unused)), + int sec_index __attribute__ ((unused)), + const void *addr __attribute__ ((unused)), + int width __attribute__ ((unused)), + Dwarf_Addr *val __attribute__ ((unused))) +{ + return 0; +} + +static inline int +__libdw_relocate_offset (Dwarf *dbg __attribute__ ((unused)), + int sec_index __attribute__ ((unused)), + const void *addr __attribute__ ((unused)), + int width __attribute__ ((unused)), + Dwarf_Off *val __attribute__ ((unused))) +{ + return 0; +} + +static inline Elf_Data * +__libdw_checked_get_data (Dwarf *dbg, int sec_index) +{ + Elf_Data *data = dbg->sectiondata[sec_index]; + if (unlikely (data == NULL) + || unlikely (data->d_buf == NULL)) + { + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return NULL; + } + return data; +} + +static inline int +__libdw_offset_in_section (Dwarf *dbg, int sec_index, + Dwarf_Off offset, size_t size) +{ + Elf_Data *data = __libdw_checked_get_data (dbg, sec_index); + if (data == NULL) + return -1; + if (unlikely (offset > data->d_size) + || unlikely (data->d_size - offset < size)) + { + __libdw_seterrno (DWARF_E_INVALID_OFFSET); + return -1; + } + + return 0; +} + +static inline bool +__libdw_in_section (Dwarf *dbg, int sec_index, + const void *addr, size_t size) +{ + Elf_Data *data = __libdw_checked_get_data (dbg, sec_index); + if (data == NULL) + return false; + if (unlikely (addr < data->d_buf) + || unlikely (data->d_size - (addr - data->d_buf) < size)) + { + __libdw_seterrno (DWARF_E_INVALID_OFFSET); + return false; + } + + return true; +} + +#define READ_AND_RELOCATE(RELOC_HOOK, VAL) \ + ({ \ + if (!__libdw_in_section (dbg, sec_index, addr, width)) \ + return -1; \ + \ + const unsigned char *orig_addr = addr; \ + if (width == 4) \ + VAL = read_4ubyte_unaligned_inc (dbg, addr); \ + else \ + VAL = read_8ubyte_unaligned_inc (dbg, addr); \ + \ + int status = RELOC_HOOK (dbg, sec_index, orig_addr, width, &VAL); \ + if (status < 0) \ + return status; \ + status > 0; \ + }) + +static inline int +__libdw_read_address_inc (Dwarf *dbg, + int sec_index, const unsigned char **addrp, + int width, Dwarf_Addr *ret) +{ + const unsigned char *addr = *addrp; + READ_AND_RELOCATE (__libdw_relocate_address, (*ret)); + *addrp = addr; + return 0; +} + +static inline int +__libdw_read_address (Dwarf *dbg, + int sec_index, const unsigned char *addr, + int width, Dwarf_Addr *ret) +{ + READ_AND_RELOCATE (__libdw_relocate_address, (*ret)); + return 0; +} + +static inline int +__libdw_read_offset_inc (Dwarf *dbg, + int sec_index, const unsigned char **addrp, + int width, Dwarf_Off *ret, int sec_ret, + size_t size) +{ + const unsigned char *addr = *addrp; + READ_AND_RELOCATE (__libdw_relocate_offset, (*ret)); + *addrp = addr; + return __libdw_offset_in_section (dbg, sec_ret, *ret, size); +} + +static inline int +__libdw_read_offset (Dwarf *dbg, + int sec_index, const unsigned char *addr, + int width, Dwarf_Off *ret, int sec_ret, + size_t size) +{ + READ_AND_RELOCATE (__libdw_relocate_offset, (*ret)); + return __libdw_offset_in_section (dbg, sec_ret, *ret, size); +} + +static inline size_t +cu_sec_idx (struct Dwarf_CU *cu) +{ + return cu->type_offset == 0 ? IDX_debug_info : IDX_debug_types; +} + +static inline Elf_Data * +cu_data (struct Dwarf_CU *cu) +{ + return cu->dbg->sectiondata[cu_sec_idx (cu)]; +} + +/* Read up begin/end pair and increment read pointer. + - If it's normal range record, set up *BEGINP and *ENDP and return 0. + - If it's base address selection record, set up *BASEP and return 1. + - If it's end of rangelist, don't set anything and return 2 + - If an error occurs, don't set anything and return <0. */ +int __libdw_read_begin_end_pair_inc (Dwarf *dbg, int sec_index, + unsigned char **addr, int width, + Dwarf_Addr *beginp, Dwarf_Addr *endp, + Dwarf_Addr *basep) + internal_function; + +unsigned char * __libdw_formptr (Dwarf_Attribute *attr, int sec_index, + int err_nodata, unsigned char **endpp, + Dwarf_Off *offsetp) + internal_function; + + + +/* Aliases to avoid PLTs. */ +INTDECL (dwarf_aggregate_size) +INTDECL (dwarf_attr) +INTDECL (dwarf_attr_integrate) +INTDECL (dwarf_begin_elf) +INTDECL (dwarf_child) +INTDECL (dwarf_dieoffset) +INTDECL (dwarf_diename) +INTDECL (dwarf_end) +INTDECL (dwarf_entrypc) +INTDECL (dwarf_errmsg) +INTDECL (dwarf_formaddr) +INTDECL (dwarf_formblock) +INTDECL (dwarf_formref_die) +INTDECL (dwarf_formsdata) +INTDECL (dwarf_formstring) +INTDECL (dwarf_formudata) +INTDECL (dwarf_getarange_addr) +INTDECL (dwarf_getarangeinfo) +INTDECL (dwarf_getaranges) +INTDECL (dwarf_getsrcfiles) +INTDECL (dwarf_getsrclines) +INTDECL (dwarf_hasattr) +INTDECL (dwarf_haschildren) +INTDECL (dwarf_haspc) +INTDECL (dwarf_highpc) +INTDECL (dwarf_lowpc) +INTDECL (dwarf_nextcu) +INTDECL (dwarf_next_unit) +INTDECL (dwarf_offdie) +INTDECL (dwarf_ranges) +INTDECL (dwarf_siblingof) +INTDECL (dwarf_srclang) +INTDECL (dwarf_tag) + +#endif /* libdwP.h */ diff --git a/src/libdw/libdw_alloc.c b/src/libdw/libdw_alloc.c new file mode 100644 index 00000000..917cb309 --- /dev/null +++ b/src/libdw/libdw_alloc.c @@ -0,0 +1,99 @@ +/* Memory handling for libdw. + Copyright (C) 2003, 2004, 2006 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2003. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <error.h> +#include <errno.h> +#include <stdlib.h> +#include <sys/param.h> +#include "libdwP.h" + + +void * +__libdw_allocate (Dwarf *dbg, size_t minsize, size_t align) +{ + size_t size = MAX (dbg->mem_default_size, + (align - 1 + + 2 * minsize + offsetof (struct libdw_memblock, mem))); + struct libdw_memblock *newp = malloc (size); + if (newp == NULL) + dbg->oom_handler (); + + uintptr_t result = ((uintptr_t) newp->mem + align - 1) & ~(align - 1); + + newp->size = size - offsetof (struct libdw_memblock, mem); + newp->remaining = (uintptr_t) newp + size - (result + minsize); + + newp->prev = dbg->mem_tail; + dbg->mem_tail = newp; + + return (void *) result; +} + + +Dwarf_OOM +dwarf_new_oom_handler (Dwarf *dbg, Dwarf_OOM handler) +{ + Dwarf_OOM old = dbg->oom_handler; + dbg->oom_handler = handler; + return old; +} + + +void +__attribute ((noreturn, visibility ("hidden"))) +__libdw_oom (void) +{ + while (1) + error (EXIT_FAILURE, ENOMEM, "libdw"); +} diff --git a/src/libdw/libdw_findcu.c b/src/libdw/libdw_findcu.c new file mode 100644 index 00000000..8e5f9e9b --- /dev/null +++ b/src/libdw/libdw_findcu.c @@ -0,0 +1,183 @@ +/* Find CU for given offset. + Copyright (C) 2003-2010 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2003. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <assert.h> +#include <search.h> +#include "libdwP.h" + + +struct Dwarf_CU * +internal_function +__libdw_intern_next_unit (dbg, debug_types) + Dwarf *dbg; + bool debug_types; +{ + Dwarf_Off *const offsetp + = debug_types ? &dbg->next_tu_offset : &dbg->next_cu_offset; + + Dwarf_Off oldoff = *offsetp; + uint16_t version; + uint8_t address_size; + uint8_t offset_size; + Dwarf_Off abbrev_offset; + uint64_t type_sig8 = 0; + Dwarf_Off type_offset = 0; + + if (INTUSE(dwarf_next_unit) (dbg, oldoff, offsetp, NULL, + &version, &abbrev_offset, + &address_size, &offset_size, + debug_types ? &type_sig8 : NULL, + debug_types ? &type_offset : NULL) != 0) + /* No more entries. */ + return NULL; + + /* We only know how to handle the DWARF version 2 through 4 formats. */ + if (unlikely (version < 2) || unlikely (version > 4)) + { + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return NULL; + } + + /* Create an entry for this CU. */ + struct Dwarf_CU *newp = libdw_typed_alloc (dbg, struct Dwarf_CU); + + newp->dbg = dbg; + newp->start = oldoff; + newp->end = *offsetp; + newp->address_size = address_size; + newp->offset_size = offset_size; + newp->version = version; + newp->type_sig8 = type_sig8; + newp->type_offset = type_offset; + Dwarf_Abbrev_Hash_init (&newp->abbrev_hash, 41); + newp->orig_abbrev_offset = newp->last_abbrev_offset = abbrev_offset; + newp->lines = NULL; + newp->locs = NULL; + + return newp; +} + + +static int +findcu_cb (const void *arg1, const void *arg2) +{ + struct Dwarf_CU *cu1 = (struct Dwarf_CU *) arg1; + struct Dwarf_CU *cu2 = (struct Dwarf_CU *) arg2; + + /* Find out which of the two arguments is the search value. It has + end offset 0. */ + if (cu1->end == 0) + { + if (cu1->start < cu2->start) + return -1; + if (cu1->start >= cu2->end) + return 1; + } + else + { + if (cu2->start < cu1->start) + return 1; + if (cu2->start >= cu1->end) + return -1; + } + + return 0; +} + +struct Dwarf_CU * +__libdw_findcu (dbg, start, debug_types) + Dwarf *dbg; + Dwarf_Off start; + bool debug_types; +{ + void **tree = debug_types ? &dbg->tu_tree : &dbg->cu_tree; + Dwarf_Off *next_offset + = debug_types ? &dbg->next_tu_offset : &dbg->next_cu_offset; + + /* Maybe we already know that CU. */ + struct Dwarf_CU fake = { .start = start, .end = 0 }; + struct Dwarf_CU **found = tfind (&fake, tree, findcu_cb); + if (found != NULL) + return *found; + + if (start < *next_offset) + { + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return NULL; + } + + /* No. Then read more CUs. */ + while (1) + { + Dwarf_Off oldoff = *next_offset; + struct Dwarf_CU *newp = __libdw_intern_next_unit (dbg, debug_types); + if (newp == NULL) + return NULL; + + /* Add the new entry to the search tree. */ + if (tsearch (newp, tree, findcu_cb) == NULL) + { + /* Something went wrong. Undo the operation. */ + *next_offset = oldoff; + __libdw_seterrno (DWARF_E_NOMEM); + return NULL; + } + + /* Is this the one we are looking for? */ + if (start < *next_offset) + // XXX Match exact offset. + return newp; + } + /* NOTREACHED */ +} diff --git a/src/libdw/libdw_form.c b/src/libdw/libdw_form.c new file mode 100644 index 00000000..219dd793 --- /dev/null +++ b/src/libdw/libdw_form.c @@ -0,0 +1,158 @@ +/* Helper functions for form handling. + Copyright (C) 2003-2009 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2003. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <dwarf.h> +#include <string.h> + +#include "libdwP.h" + + +size_t +internal_function +__libdw_form_val_len (Dwarf *dbg, struct Dwarf_CU *cu, unsigned int form, + const unsigned char *valp) +{ + const unsigned char *saved; + Dwarf_Word u128; + size_t result; + + switch (form) + { + case DW_FORM_addr: + result = cu->address_size; + break; + + case DW_FORM_ref_addr: + result = cu->version == 2 ? cu->address_size : cu->offset_size; + break; + + case DW_FORM_strp: + case DW_FORM_sec_offset: + result = cu->offset_size; + break; + + case DW_FORM_block1: + result = *valp + 1; + break; + + case DW_FORM_block2: + result = read_2ubyte_unaligned (dbg, valp) + 2; + break; + + case DW_FORM_block4: + result = read_4ubyte_unaligned (dbg, valp) + 4; + break; + + case DW_FORM_block: + case DW_FORM_exprloc: + saved = valp; + get_uleb128 (u128, valp); + result = u128 + (valp - saved); + break; + + case DW_FORM_flag_present: + result = 0; + break; + + case DW_FORM_ref1: + case DW_FORM_data1: + case DW_FORM_flag: + result = 1; + break; + + case DW_FORM_data2: + case DW_FORM_ref2: + result = 2; + break; + + case DW_FORM_data4: + case DW_FORM_ref4: + result = 4; + break; + + case DW_FORM_data8: + case DW_FORM_ref8: + case DW_FORM_ref_sig8: + result = 8; + break; + + case DW_FORM_string: + result = strlen ((char *) valp) + 1; + break; + + case DW_FORM_sdata: + case DW_FORM_udata: + case DW_FORM_ref_udata: + saved = valp; + get_uleb128 (u128, valp); + result = valp - saved; + break; + + case DW_FORM_indirect: + saved = valp; + get_uleb128 (u128, valp); + // XXX Is this really correct? + result = __libdw_form_val_len (dbg, cu, u128, valp); + if (result != (size_t) -1) + result += valp - saved; + break; + + default: + __libdw_seterrno (DWARF_E_INVALID_DWARF); + result = (size_t) -1l; + break; + } + + return result; +} diff --git a/src/libdw/libdw_visit_scopes.c b/src/libdw/libdw_visit_scopes.c new file mode 100644 index 00000000..9c7c3789 --- /dev/null +++ b/src/libdw/libdw_visit_scopes.c @@ -0,0 +1,177 @@ +/* Helper functions to descend DWARF scope trees. + Copyright (C) 2005,2006,2007 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under an Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) and to distribute linked + combinations including the two. Non-GPL Code permitted under this + exception must only link to the code of Red Hat elfutils through those + well defined interfaces identified in the file named EXCEPTION found in + the source code files (the "Approved Interfaces"). The files of Non-GPL + Code may instantiate templates or use macros or inline functions from + the Approved Interfaces without causing the resulting work to be covered + by the GNU General Public License. Only Red Hat, Inc. may make changes + or additions to the list of Approved Interfaces. Red Hat's grant of + this exception is conditioned upon your not adding any new exceptions. + If you wish to add a new Approved Interface or exception, please contact + Red Hat. You must obey the GNU General Public License in all respects + for all of the Red Hat elfutils code and other code used in conjunction + with Red Hat elfutils except the Non-GPL Code covered by this exception. + If you modify this file, you may extend this exception to your version + of the file, but you are not obligated to do so. If you do not wish to + provide this exception without modification, you must delete this + exception statement from your version and license this file solely under + the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "libdwP.h" +#include <dwarf.h> + +enum die_class { ignore, match, match_inline, walk, imported }; + +static enum die_class +classify_die (Dwarf_Die *die) +{ + switch (INTUSE(dwarf_tag) (die)) + { + /* DIEs with addresses we can try to match. */ + case DW_TAG_compile_unit: + case DW_TAG_module: + case DW_TAG_lexical_block: + case DW_TAG_with_stmt: + case DW_TAG_catch_block: + case DW_TAG_try_block: + case DW_TAG_entry_point: + return match; + case DW_TAG_inlined_subroutine: + return match_inline; + case DW_TAG_subprogram: + /* This might be a concrete out-of-line instance of an inline, in + which case it is not guaranteed to be owned by the right scope and + we will search for its origin as for DW_TAG_inlined_subroutine. */ + return (INTUSE(dwarf_hasattr) (die, DW_AT_abstract_origin) + ? match_inline : match); + + /* DIEs without addresses that can own DIEs with addresses. */ + case DW_TAG_namespace: + case DW_TAG_class_type: + case DW_TAG_structure_type: + return walk; + + /* Special indirection required. */ + case DW_TAG_imported_unit: + return imported; + + /* Other DIEs we have no reason to descend. */ + default: + break; + } + return ignore; +} + +int +__libdw_visit_scopes (depth, root, previsit, postvisit, arg) + unsigned int depth; + struct Dwarf_Die_Chain *root; + int (*previsit) (unsigned int depth, struct Dwarf_Die_Chain *, void *); + int (*postvisit) (unsigned int depth, struct Dwarf_Die_Chain *, void *); + void *arg; +{ + struct Dwarf_Die_Chain child; + + child.parent = root; + if (INTUSE(dwarf_child) (&root->die, &child.die) != 0) + return -1; + + inline int recurse (void) + { + return __libdw_visit_scopes (depth + 1, &child, + previsit, postvisit, arg); + } + + do + { + child.prune = false; + + if (previsit != NULL) + { + int result = (*previsit) (depth + 1, &child, arg); + if (result != DWARF_CB_OK) + return result; + } + + if (!child.prune) + switch (classify_die (&child.die)) + { + case match: + case match_inline: + case walk: + if (INTUSE(dwarf_haschildren) (&child.die)) + { + int result = recurse (); + if (result != DWARF_CB_OK) + return result; + } + break; + + case imported: + { + /* This imports another compilation unit to appear + as part of this one, inside the current scope. + Recurse to search the referenced unit, but without + recording it as an inner scoping level. */ + + Dwarf_Attribute attr_mem; + Dwarf_Attribute *attr = INTUSE(dwarf_attr) (&child.die, + DW_AT_import, + &attr_mem); + if (INTUSE(dwarf_formref_die) (attr, &child.die) != NULL) + { + int result = recurse (); + if (result != DWARF_CB_OK) + return result; + } + } + break; + + default: + break; + } + + if (postvisit != NULL) + { + int result = (*postvisit) (depth + 1, &child, arg); + if (result != DWARF_CB_OK) + return result; + } + } + while (INTUSE(dwarf_siblingof) (&child.die, &child.die) == 0); + + return 0; +} diff --git a/src/libdw/memory-access.c b/src/libdw/memory-access.c new file mode 100644 index 00000000..c9a0ca76 --- /dev/null +++ b/src/libdw/memory-access.c @@ -0,0 +1,71 @@ +/* Out of line functions for memory-access.h macros. + Copyright (C) 2005, 2006 Red Hat, Inc. + This file is part of Red Hat elfutils. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#include "libdwP.h" +#include "memory-access.h" + +uint64_t +internal_function +__libdw_get_uleb128 (uint64_t acc, unsigned int i, const unsigned char **addrp) +{ + unsigned char __b; + get_uleb128_rest_return (acc, i, addrp); +} + +int64_t +internal_function +__libdw_get_sleb128 (int64_t acc, unsigned int i, const unsigned char **addrp) +{ + unsigned char __b; + int64_t _v = acc; + get_sleb128_rest_return (acc, i, addrp); +} diff --git a/src/libdw/memory-access.h b/src/libdw/memory-access.h new file mode 100644 index 00000000..b7799e92 --- /dev/null +++ b/src/libdw/memory-access.h @@ -0,0 +1,315 @@ +/* Unaligned memory access functionality. + Copyright (C) 2000-2010 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper <drepper@redhat.com>, 2001. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + <http://www.openinventionnetwork.com>. */ + +#ifndef _MEMORY_ACCESS_H +#define _MEMORY_ACCESS_H 1 + +#include <byteswap.h> +#include <limits.h> +#include <stdint.h> + + +/* Number decoding macros. See 7.6 Variable Length Data. */ + +#define get_uleb128_step(var, addr, nth, break) \ + __b = *(addr)++; \ + var |= (uintmax_t) (__b & 0x7f) << (nth * 7); \ + if (likely ((__b & 0x80) == 0)) \ + break + +#define get_uleb128(var, addr) \ + do { \ + unsigned char __b; \ + var = 0; \ + get_uleb128_step (var, addr, 0, break); \ + var = __libdw_get_uleb128 (var, 1, &(addr)); \ + } while (0) + +#define get_uleb128_rest_return(var, i, addrp) \ + do { \ + for (; i < 10; ++i) \ + { \ + get_uleb128_step (var, *addrp, i, return var); \ + } \ + /* Other implementations set VALUE to UINT_MAX in this \ + case. So we better do this as well. */ \ + return UINT64_MAX; \ + } while (0) + +/* The signed case is similar, but we sign-extend the result. */ + +#define get_sleb128_step(var, addr, nth, break) \ + __b = *(addr)++; \ + _v |= (uint64_t) (__b & 0x7f) << (nth * 7); \ + if (likely ((__b & 0x80) == 0)) \ + { \ + var = (_v << (64 - (nth * 7) - 7)) >> (64 - (nth * 7) - 7); \ + break; \ + } \ + else do {} while (0) + +#define get_sleb128(var, addr) \ + do { \ + unsigned char __b; \ + int64_t _v = 0; \ + get_sleb128_step (var, addr, 0, break); \ + var = __libdw_get_sleb128 (_v, 1, &(addr)); \ + } while (0) + +#define get_sleb128_rest_return(var, i, addrp) \ + do { \ + for (; i < 9; ++i) \ + { \ + get_sleb128_step (var, *addrp, i, return var); \ + } \ + __b = *(*addrp)++; \ + if (likely ((__b & 0x80) == 0)) \ + return var | ((uint64_t) __b << 63); \ + else \ + /* Other implementations set VALUE to INT_MAX in this \ + case. So we better do this as well. */ \ + return INT64_MAX; \ + } while (0) + +#ifdef IS_LIBDW +extern uint64_t __libdw_get_uleb128 (uint64_t acc, unsigned int i, + const unsigned char **addrp) + internal_function attribute_hidden; +extern int64_t __libdw_get_sleb128 (int64_t acc, unsigned int i, + const unsigned char **addrp) + internal_function attribute_hidden; +#else +static inline uint64_t +__attribute__ ((unused)) +__libdw_get_uleb128 (uint64_t acc, unsigned int i, const unsigned char **addrp) +{ + unsigned char __b; + get_uleb128_rest_return (acc, i, addrp); +} +static inline int64_t +__attribute__ ((unused)) +__libdw_get_sleb128 (int64_t acc, unsigned int i, const unsigned char **addrp) +{ + unsigned char __b; + int64_t _v = acc; + get_sleb128_rest_return (acc, i, addrp); +} +#endif + + +/* 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) \ + (unlikely ((Dbg)->other_byte_order) \ + ? bswap_16 (*((const uint16_t *) (Addr))) \ + : *((const uint16_t *) (Addr))) +# define read_2sbyte_unaligned(Dbg, Addr) \ + (unlikely ((Dbg)->other_byte_order) \ + ? (int16_t) bswap_16 (*((const int16_t *) (Addr))) \ + : *((const int16_t *) (Addr))) + +# define read_4ubyte_unaligned_noncvt(Addr) \ + *((const uint32_t *) (Addr)) +# define read_4ubyte_unaligned(Dbg, Addr) \ + (unlikely ((Dbg)->other_byte_order) \ + ? bswap_32 (*((const uint32_t *) (Addr))) \ + : *((const uint32_t *) (Addr))) +# define read_4sbyte_unaligned(Dbg, Addr) \ + (unlikely ((Dbg)->other_byte_order) \ + ? (int32_t) bswap_32 (*((const int32_t *) (Addr))) \ + : *((const int32_t *) (Addr))) + +# define read_8ubyte_unaligned(Dbg, Addr) \ + (unlikely ((Dbg)->other_byte_order) \ + ? bswap_64 (*((const uint64_t *) (Addr))) \ + : *((const uint64_t *) (Addr))) +# define read_8sbyte_unaligned(Dbg, Addr) \ + (unlikely ((Dbg)->other_byte_order) \ + ? (int64_t) bswap_64 (*((const int64_t *) (Addr))) \ + : *((const int64_t *) (Addr))) + +#else + +union unaligned + { + void *p; + uint16_t u2; + uint32_t u4; + uint64_t u8; + int16_t s2; + int32_t s4; + int64_t s8; + } __attribute__ ((packed)); + +# define read_2ubyte_unaligned(Dbg, Addr) \ + read_2ubyte_unaligned_1 ((Dbg)->other_byte_order, (Addr)) +# define read_2sbyte_unaligned(Dbg, Addr) \ + read_2sbyte_unaligned_1 ((Dbg)->other_byte_order, (Addr)) +# define read_4ubyte_unaligned(Dbg, Addr) \ + read_4ubyte_unaligned_1 ((Dbg)->other_byte_order, (Addr)) +# define read_4sbyte_unaligned(Dbg, Addr) \ + read_4sbyte_unaligned_1 ((Dbg)->other_byte_order, (Addr)) +# define read_8ubyte_unaligned(Dbg, Addr) \ + read_8ubyte_unaligned_1 ((Dbg)->other_byte_order, (Addr)) +# define read_8sbyte_unaligned(Dbg, Addr) \ + read_8sbyte_unaligned_1 ((Dbg)->other_byte_order, (Addr)) + +static inline uint16_t +read_2ubyte_unaligned_1 (bool other_byte_order, const void *p) +{ + const union unaligned *up = p; + if (unlikely (other_byte_order)) + return bswap_16 (up->u2); + return up->u2; +} +static inline int16_t +read_2sbyte_unaligned_1 (bool other_byte_order, const void *p) +{ + const union unaligned *up = p; + if (unlikely (other_byte_order)) + return (int16_t) bswap_16 (up->u2); + return up->s2; +} + +static inline uint32_t +read_4ubyte_unaligned_noncvt (const void *p) +{ + const union unaligned *up = p; + return up->u4; +} +static inline uint32_t +read_4ubyte_unaligned_1 (bool other_byte_order, const void *p) +{ + const union unaligned *up = p; + if (unlikely (other_byte_order)) + return bswap_32 (up->u4); + return up->u4; +} +static inline int32_t +read_4sbyte_unaligned_1 (bool other_byte_order, const void *p) +{ + const union unaligned *up = p; + if (unlikely (other_byte_order)) + return (int32_t) bswap_32 (up->u4); + return up->s4; +} + +static inline uint64_t +read_8ubyte_unaligned_1 (bool other_byte_order, const void *p) +{ + const union unaligned *up = p; + if (unlikely (other_byte_order)) + return bswap_64 (up->u8); + return up->u8; +} +static inline int64_t +read_8sbyte_unaligned_1 (bool other_byte_order, const void *p) +{ + const union unaligned *up = p; + if (unlikely (other_byte_order)) + return (int64_t) bswap_64 (up->u8); + return up->s8; +} + +#endif /* allow unaligned */ + + +#define read_ubyte_unaligned(Nbytes, Dbg, Addr) \ + ((Nbytes) == 2 ? read_2ubyte_unaligned (Dbg, Addr) \ + : (Nbytes) == 4 ? read_4ubyte_unaligned (Dbg, Addr) \ + : read_8ubyte_unaligned (Dbg, Addr)) + +#define read_sbyte_unaligned(Nbytes, Dbg, Addr) \ + ((Nbytes) == 2 ? read_2sbyte_unaligned (Dbg, Addr) \ + : (Nbytes) == 4 ? read_4sbyte_unaligned (Dbg, Addr) \ + : read_8sbyte_unaligned (Dbg, Addr)) + + +#define read_2ubyte_unaligned_inc(Dbg, Addr) \ + ({ uint16_t t_ = read_2ubyte_unaligned (Dbg, Addr); \ + Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 2); \ + t_; }) +#define read_2sbyte_unaligned_inc(Dbg, Addr) \ + ({ int16_t t_ = read_2sbyte_unaligned (Dbg, Addr); \ + Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 2); \ + t_; }) + +#define read_4ubyte_unaligned_inc(Dbg, Addr) \ + ({ uint32_t t_ = read_4ubyte_unaligned (Dbg, Addr); \ + Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 4); \ + t_; }) +#define read_4sbyte_unaligned_inc(Dbg, Addr) \ + ({ int32_t t_ = read_4sbyte_unaligned (Dbg, Addr); \ + Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 4); \ + t_; }) + +#define read_8ubyte_unaligned_inc(Dbg, Addr) \ + ({ uint64_t t_ = read_8ubyte_unaligned (Dbg, Addr); \ + Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 8); \ + t_; }) +#define read_8sbyte_unaligned_inc(Dbg, Addr) \ + ({ int64_t t_ = read_8sbyte_unaligned (Dbg, Addr); \ + Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 8); \ + t_; }) + + +#define read_ubyte_unaligned_inc(Nbytes, Dbg, Addr) \ + ((Nbytes) == 2 ? read_2ubyte_unaligned_inc (Dbg, Addr) \ + : (Nbytes) == 4 ? read_4ubyte_unaligned_inc (Dbg, Addr) \ + : read_8ubyte_unaligned_inc (Dbg, Addr)) + +#define read_sbyte_unaligned_inc(Nbytes, Dbg, Addr) \ + ((Nbytes) == 2 ? read_2sbyte_unaligned_inc (Dbg, Addr) \ + : (Nbytes) == 4 ? read_4sbyte_unaligned_inc (Dbg, Addr) \ + : read_8sbyte_unaligned_inc (Dbg, Addr)) + +#endif /* memory-access.h */ |