diff options
Diffstat (limited to 'src/libdwfl')
74 files changed, 0 insertions, 20515 deletions
diff --git a/src/libdwfl/Android.mk b/src/libdwfl/Android.mk deleted file mode 100755 index 377b58a3..00000000 --- a/src/libdwfl/Android.mk +++ /dev/null @@ -1,167 +0,0 @@ -# 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) - -LIBDWFL_SRC_FILES := \ - core-file.c \ - cu.c \ - derelocate.c \ - dwfl_addrdie.c \ - dwfl_addrdwarf.c \ - dwfl_addrmodule.c \ - dwfl_begin.c \ - dwfl_build_id_find_debuginfo.c \ - dwfl_build_id_find_elf.c \ - dwfl_cumodule.c \ - dwfl_dwarf_line.c \ - dwfl_end.c \ - dwfl_error.c \ - dwfl_frame.c \ - dwfl_frame_pc.c \ - dwfl_frame_regs.c \ - dwfl_getdwarf.c \ - dwfl_getmodules.c \ - dwfl_getsrc.c \ - dwfl_getsrclines.c \ - dwfl_line_comp_dir.c \ - dwfl_linecu.c \ - dwfl_lineinfo.c \ - dwfl_linemodule.c \ - dwfl_module_addrdie.c \ - dwfl_module_addrname.c \ - dwfl_module_addrsym.c \ - dwfl_module_build_id.c \ - dwfl_module.c \ - dwfl_module_dwarf_cfi.c \ - dwfl_module_eh_cfi.c \ - dwfl_module_getdwarf.c \ - dwfl_module_getelf.c \ - dwfl_module_getsrc.c \ - dwfl_module_getsrc_file.c \ - dwfl_module_getsym.c \ - dwfl_module_info.c \ - dwfl_module_nextcu.c \ - dwfl_module_register_names.c \ - dwfl_module_report_build_id.c \ - dwfl_module_return_value_location.c \ - dwfl_nextcu.c \ - dwfl_onesrcline.c \ - dwfl_report_elf.c \ - dwfl_segment_report_module.c \ - dwfl_validate_address.c \ - dwfl_version.c \ - elf-from-memory.c \ - find-debuginfo.c \ - frame_unwind.c \ - gzip.c \ - image-header.c \ - libdwfl_crc32.c \ - libdwfl_crc32_file.c \ - lines.c \ - link_map.c \ - linux-core-attach.c \ - linux-kernel-modules.c \ - linux-pid-attach.c \ - linux-proc-maps.c \ - offline.c \ - open.c \ - relocate.c \ - segment.c \ - - -ifeq ($(HOST_OS),linux) - -# -# host libdwfl -# - -include $(CLEAR_VARS) - -# Clang has no nested functions. -LOCAL_CLANG := false - -LOCAL_SRC_FILES := $(LIBDWFL_SRC_FILES) - -LOCAL_C_INCLUDES := \ - $(LOCAL_PATH)/.. \ - $(LOCAL_PATH)/../lib \ - $(LOCAL_PATH)/../libdwelf \ - $(LOCAL_PATH)/../libdwfl \ - $(LOCAL_PATH)/../libebl \ - $(LOCAL_PATH)/../libdw \ - $(LOCAL_PATH)/../libelf - -LOCAL_CFLAGS += -DHAVE_CONFIG_H -std=gnu99 -D_GNU_SOURCE - -# to suppress the "pointer of type ‘void *’ used in arithmetic" warning -LOCAL_CFLAGS += -Wno-pointer-arith - -# Asserts are not compiled, so some debug variables appear unused. Rather than -# fix, we prefer to turn off the warning locally. -LOCAL_CFLAGS += -Wno-unused-but-set-variable - -# Similar to the above. To stay in line with upstream, ignore the warning. -LOCAL_CFLAGS += -Wno-unused-variable - -LOCAL_MODULE:= libdwfl - -LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH) - -LOCAL_STATIC_LIBRARIES := libz - -include $(BUILD_HOST_STATIC_LIBRARY) - -endif # linux - -# -# target libdwfl -# - -include $(CLEAR_VARS) - -# Clang has no nested functions. -LOCAL_CLANG := false - -LOCAL_SRC_FILES := $(LIBDWFL_SRC_FILES) - -LOCAL_C_INCLUDES := \ - $(LOCAL_PATH)/.. \ - $(LOCAL_PATH)/../lib \ - $(LOCAL_PATH)/../libdwelf \ - $(LOCAL_PATH)/../libdwfl \ - $(LOCAL_PATH)/../libebl \ - $(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 -D_GNU_SOURCE -Werror - -# to suppress the "pointer of type ‘void *’ used in arithmetic" warning -LOCAL_CFLAGS += -Wno-pointer-arith - -# See above. -LOCAL_CFLAGS += -Wno-unused-but-set-variable -LOCAL_CFLAGS += -Wno-unused-variable - -LOCAL_MODULE:= libdwfl - -LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH) - -LOCAL_STATIC_LIBRARIES := libz - -include $(BUILD_STATIC_LIBRARY) diff --git a/src/libdwfl/ChangeLog b/src/libdwfl/ChangeLog deleted file mode 100644 index 69e59a6f..00000000 --- a/src/libdwfl/ChangeLog +++ /dev/null @@ -1,2345 +0,0 @@ -2014-12-19 Mark Wielaard <mjw@redhat.com> - - * dwfl_module_getdwarf.c (find_symtab): Always try find_dynsym last. - -2014-12-19 Mark Wielaard <mjw@redhat.com> - - * elf-from-memory.c (handle_segment): Remove palign sanity check. - -2014-12-18 Mark Wielaard <mjw@redhat.com> - - * relocate.c (resolve_symbol): Make sure symstrdata->d_buf != NULL. - -2014-12-13 Mark Wielaard <mjw@redhat.com> - - * dwfl_module_getdwarf.c (find_dynsym): elf_getdata_rawchunk takes - a size_t, make sure it doesn't overflow. - -2014-12-13 Mark Wielaard <mjw@redhat.com> - - * cu.c (cudie_offset): Make sure Dwarf_Off difference doesn't - wrap around before returning as int. - -2014-12-11 Josh Stone <jistone@redhat.com> - - * dwfl_module_getsrc.c (dwfl_module_getsrc): Return the *last* line - record <= addr, rather than returning immediately on matches. - -2014-12-09 Mark Wielaard <mjw@redhat.com> - - * dwfl_segment_report_module.c (handle_file_note): Check count doesn't - overflow. - -2014-12-07 Mark Wielaard <mjw@redhat.com> - - * relocate.c (relocate_section): Sanity check section overlap against - actually used ehsize, shentsize and phentsize. - -2014-12-07 Mark Wielaard <mjw@redhat.com> - - * offline.c (dwfl_offline_section_address): Assert shndx is not zero. - * relocate.c (__libdwfl_relocate_value): Don't relocate against - section zero. - -2014-11-29 Mark Wielaard <mjw@redhat.com> - - * relocate.c (relocate_section): Check relocation section and target - section data don't overlap any of the ELF headers. - (relocate): Check for offset + size overflow. - -2014-11-22 Mark Wielaard <mjw@redhat.com> - - * link_map.c (consider_executable): Use elf_getphdrnum. - (dwfl_link_map_report): Likewise. - -2014-11-18 Mark Wielaard <mjw@redhat.com> - - * dwfl_module_getdwarf.c (find_symtab): Sanity check the data buffer, - number of symbols and first_global before use. - -2014-11-14 Mark Wielaard <mjw@redhat.com> - - * dwfl_module_getdwarf.c (load_symtab): Don't use tables which have - a zero sh_entsize. - -2014-11-10 Mark Wielaard <mjw@redhat.com> - - * dwfl_module_getdwarf.c (find_dynsym): New inner function - translate_offs that takes an adjust argument. Try finding - the symbol table with and without adjusting to main_bias. - -2014-09-26 Jan Kratochvil <jan.kratochvil@redhat.com> - - Support NT_FILE for locating files. - * core-file.c (dwfl_core_file_report): New variables note_file and - note_file_size, set them and pass them to dwfl_segment_report_module. - * dwfl_segment_report_module.c: Include common.h and fcntl.h. - (buf_has_data, buf_read_ulong, handle_file_note): New functions. - (invalid_elf): New function from code of dwfl_segment_report_module. - (dwfl_segment_report_module): Add parameters note_file and - note_file_size. New variables elf and fd, clean them up in finish. - Move some code to invalid_elf. Call handle_file_note, if it found - a name verify the file by invalid_elf. Protect elf and fd against - cleanup by finish if we found the file for new Dwfl_Module. - * libdwflP.h (dwfl_segment_report_module): Add parameters note_file and - note_file_size. - -2014-09-23 Mark Wielaard <mjw@redhat.com> - - * dwfl_segment_report_module.c (dwfl_segment_report_module): - Extract ei_class, ei_data and e_type early and use the result. - -2014-09-18 Jan Kratochvil <jan.kratochvil@redhat.com> - - * dwfl_build_id_find_elf.c (dwfl_build_id_find_elf): Use IS_EXECUTABLE. - * dwfl_segment_report_module.c (dwfl_segment_report_module): Set - IS_EXECUTABLE. - * libdwflP.h (struct Dwfl_Module): New field is_executable. - -2014-08-28 Jan Kratochvil <jan.kratochvil@redhat.com> - - * dwfl_module_getdwarf.c (find_offsets): Add parameter main_bias, use - it. - (find_dynsym): Pass the new parameter main_bias. - -2014-08-14 Mark Wielaard <mjw@redhat.com> - - * linux-kernel-modules.c (check-suffix): Also TRY .ko.xz. - -2014-07-24 Jan Kratochvil <jan.kratochvil@redhat.com> - - Fix report_r_debug for prelinked libraries. - * link_map.c (report_r_debug): Comment out variable l_addr. - Use instead new variable base recalculated from l_ld. - -2014-06-24 Kurt Roeckx <kurt@roeckx.be> - - * linux-pid-attach.c: Make it build on non linux hosts. - -2014-06-17 Mark Wielaard <mjw@redhat.com> - - * frame_unwind.c (handle_cfi): Use ebl_func_addr_mask. - * dwfl_module_getsym.c (__libdwfl_getsym): Likewise. - -2014-06-15 Mark Wielaard <mjw@redhat.com> - - * linux-core-attach.c (core_memory_read): Use libdw/memory-access.h - macros read_4ubyte_unaligned_noncvt and read_8ubyte_unaligned_noncvt - to read possibly unaligned data. - (core_next_thread): Likewise. - (core_set_initial_registers): Likewise. - (dwfl_core_file_attach): Likewise. - -2014-06-11 Mark Wielaard <mjw@redhat.com> - - * dwfl_frame.c (__libdwfl_process_free): Reset dwfl->attacherr. - (dwfl_attach_state): Set dwfl->attacherr. - (dwfl_pid): Check and return dwfl->attacherr if set. - (dwfl_getthreads): Likewise. - (getthread): Likewise. - * libdwflP.h: Add DWFL_E_NO_CORE_FILE. - (struct Dwfl): Add attacherr field. - * linux-core-attach.c (dwfl_core_file_attach): Set dwfl->attacherr. - Don't assert if ELF file is not ET_CORE, just return error. - * linux-pid-attach.c (dwfl_linux_proc_attach): Set dwfl->attacherr. - -2014-06-10 Mark Wielaard <mjw@redhat.com> - - * argp-std.c (parse_opt): Ignore errors from dwfl_core_file_attach - or dwfl_linux_proc_attach. - -2014-05-15 Mark Wielaard <mjw@redhat.com> - - * linux-proc-maps.c (grovel_auxv): Close fd on error. - -2014-05-02 Mark Wielaard <mjw@redhat.com> - - * dwfl_module_getdwarf: Remove ENABLE_DWZ ifdefs so find_debug_altlink - is always called. - -2014-05-01 Mark Wielaard <mjw@redhat.com> - - * libdwflP.h (struct Dwfl_Module): Add alt, alt_fd and alt_elf fields. - (__libdwfl_open_mod_by_build_id): Renamed __libdwfl_open_by_build_id. - (__libdwfl_open_by_build_id): New declaration that takes an explicit - build-id. - * dwfl_build_id_find_debuginfo.c (dwfl_build_id_find_debuginfo): If - we already have the Dwarf then look for the alt dwz multi file by - build-id. - * dwfl_build_id_find_elf.c (__libdwfl_open_by_build_id): Add the - build-id we are looking for as argument. - (__libdwfl_open_mod_by_build_id): New function, calls - __libdwfl_open_by_build_id. - (dwfl_build_id_find_elf): Call __libdwfl_open_mod_by_build_id. - * dwfl_module.c (__libdwfl_module_free): Release alt, alt_elf and - close alt_fd if necessary. - * dwfl_module_getdwarf.c (__check_build_id): Removed. - (try_debugaltlink): Removed. - (open_debugaltlink): Removed. - (open_elf_file): First half of open_elf that just opens the elf - file but doesn't setup the load address. - (open_elf): Call open_elf_file. - (find_debug_altlink): New function. - (load_dw): Remove loading of dwz multifile. - (find_dw): Call find_debug_altlink. - * find-debuginfo.c (validate): Handle alt debug case using - dwelf_dwarf_gnu_debugaltlink and mod->alt_elf. - (find_debuginfo_in_path): Handle alt debug files possibly in .dwz - subdirs. - * linux-kernel-modules.c (try_kernel_name): Use fakemod.debug.name - to store name to find by dwfl_standard_find_debuginfo instead of - allocating an extra variable on stack. - -2014-04-30 Mark Wielaard <mjw@redhat.com> - - * dwfl_module_build_id.c (__libdwfl_find_elf_build_id): Moved to - dwelf_elf_gnu_build_id.c. - (__libdwfl_find_build_id): Add assert to make sure mod is never NULL. - * dwfl_segment_report_module.c (dwfl_segment_report_module): Call - dwelf_elf_gnu_build_id directly instead of __libdwfl_find_build_id. - * dwfl_module_getdwarf.c (__check_build_id): Implement using - dwelf_elf_gnu_build_id. - -2014-04-15 Florian Weimer <fweimer@redhat.com> - - * dwfl_module_getdwarf.c (__check_build_id): Moved from libdw. - (try_debugaltlink): Likewise. - (open_debugaltlink): Likewise. - (load_dw): Locate alternate debug information using - dwelf_dwarf_gnu_debugaltlink and call open_debugaltlink. - -2014-04-11 Mark Wielaard <mjw@redhat.com> - - * Makefile.am (AM_CPPFLAGS): Add libdwelf. - * libdwflP.h: Include libdwelfP.h. - * dwfl_module_getdwarf.c (find_debuglink): Moved to libdwelf. - (find_debuginfo): Use dwelf_elf_gnu_debuglink. - -2014-04-22 Mark Wielaard <mjw@redhat.com> - - * frame_unwind.c (__libdwfl_frame_reg_get): Use uint64_t when - checking bits. - (__libdwfl_frame_reg_set): Likewise. - -2014-04-22 Kurt Roeckx <kurt@roeckx.be> - - * linux-pid-attach.c: Make linux only. - -2014-03-14 Mark Wielaard <mjw@redhat.com> - - * Makefile.am: Remove !MUDFLAP and MUDFLAP conditions. - Remove libelf and libdw definitions when MUDFLAP is defined. - * argp-std.c (__libdwfl_argp_mudflap_options): Removed. - -2014-03-03 Mark Wielaard <mjw@redhat.com> - - * elf-from-memory.c (elf_from_remote_memory): Keep track of - segments_end_mem. Pass memsz to first handle_segment pass. Only - extend contents_size and use shdrs if only file bits are in - segment. - -2014-03-11 Josh Stone <jistone@redhat.com> - - * dwfl_module_getdwarf.c (open_elf): Only explicitly set - mod->e_type when processing the main ELF file. - -2014-03-04 Mark Wielaard <mjw@redhat.com> - - * libdwflP.h (struct __libdwfl_pid_arg): Moved here and renamed from - linux-pid-attach.c (struct pid_arg). - (__libdwfl_get_pid_arg): New internal function declaration. - (__libdwfl_ptrace_attach): Likewise. - (__libdwfl_ptrace_detach): Likewise. - * dwfl_frame.c (dwfl_attach_state): Add "(deleted)" files to the - special exception modules that cannot be checked at this point. - * linux-pid-attach.c (struct pid_arg): Moved to libdwflP.h - (ptrace_attach): Renamed to... - (__libdwfl_ptrace_attach): New internal function. - (__libdwfl_ptrace_detach): Likewise. Extracted from ... - (pid_thread_detach): Call __libdwfl_ptrace_detach now. - (__libdwfl_get_pid_arg): New internal function. - * linux-proc-maps.c (dwfl_linux_proc_find_elf): Check if special - module name contains "(deleted)" and dwfl_pid gives an attached - pid. If pid is set and try to (re)use ptrace attach state of - process before reading memory. - -2014-03-03 Mark Wielaard <mjw@redhat.com> - - * elf-from-memory.c (elf_from_remote_memory): Take pagesize as - argument. Free buffer when detecting bad elf. Check PT_LOAD - alignment requirements on first handle_segment pass. Calculate - loadbase, start and end of segment using pagesize, not p_align. - * linux-proc-maps.c (dwfl_linux_proc_find_elf): Provide pagesize - to elf_from_remote_memory. - -2014-02-26 Mark Wielaard <mjw@redhat.com> - - * linux-proc-maps.c (proc_maps_report): Don't assert on bad input. - -2014-02-26 Mark Wielaard <mjw@redhat.com> - - * elf-from-memory.c (elf_from_remote_memory): Check against p64 - p_type in case ELFCLASS64, not against p32 p_type. - -2014-01-17 Petr Machata <pmachata@redhat.com> - - * relocate.c (relocate_section): Use gelf_fsize instead of relying - on shdr->sh_entsize. - -2014-01-05 Mark Wielaard <mjw@redhat.com> - - * frame_unwind.c (handle_cfi): Only skip resetting return register - if the regno is not the actual CIE return address register. - -2014-01-02 Mark Wielaard <mjw@redhat.com> - - * linux-pid-attach.c (dwfl_linux_proc_attach): Use strtol, not atoi. - -2013-12-30 Mark Wielaard <mjw@redhat.com> - - * argp-std.c (parse_opt): Call dwfl_linux_proc_attach and - dwfl_core_file_attach explicitly. - * core-file.c (dwfl_core_file_report): Don't call - __libdwfl_attach_state_for_core implicitly. - * dwfl_begin.c (dwfl_begin): Remove setting of process_attach_error. - * dwfl_frame.c (dwfl_pid): Set errno to DWFL_E_NO_ATTACH_STATE, not - process_attach_error. - (dwfl_getthreads): Likewise. - (getthread): Likewise. - * libdwfl.h (dwfl_core_file_report): Update documentation. - (dwfl_linux_proc_report): Likewise. - (dwfl_core_file_attach): New function declaration. - (dwfl_linux_proc_attach): Likewise. - * libdwflP.h (struct Dwfl): Remove process_attach_error. - (__libdwfl_attach_state_for_pid): Removed declaration. - (__libdwfl_attach_state_for_core): Likewise. - (dwfl_core_file_attach): New internal declaration. - (dwfl_linux_proc_attach): Likewise. - (attach_state_for_core): Renamed to... - (dwfl_core_file_attach): ...this. Change return type. - (__libdwfl_attach_state_for_core): Removed. - * linux-pid-attach.c (struct pid_arg): Add assume_ptrace_stopped. - (pid_set_initial_registers): Check assume_ptrace_stopped before - calling ptrace. - (pid_thread_detach): Likewise. - (__libdwfl_attach_state_for_pid): Renamed to... - (dwfl_linux_proc_attach): ...this. Adjust return type. - * linux-proc-maps.c (dwfl_linux_proc_report): Don't call - __libdwfl_attach_state_for_pid implicitly. - -2013-12-28 Mark Wielaard <mjw@redhat.com> - - * linux-proc-maps.c (dwfl_linux_proc_find_elf): Don't return special - character device files, only regular files. - -2013-12-24 Mark Wielaard <mjw@redhat.com> - - * linux-core-attach.c (core_next_thread): Check whether thread_argp - is NULL. Reset core_arg->thread_note_offset and malloc a thread_arg - in that case. Free thread_arg if there are no more threads. - -2013-12-23 Mark Wielaard <mjw@redhat.com> - - * dwfl_segment_report_module.c (dwfl_segment_report_module): Free - build_id before returning early. - -2013-12-23 Mark Wielaard <mjw@redhat.com> - - * linux-pid-attach.c (__libdwfl_attach_state_for_pid): Report actual - pid (thread group leader) to dwfl_attach_state. - -2013-12-21 Mark Wielaard <mjw@redhat.com> - - * frame_unwind.c (handle_cfi): Track whether the return register - has been set and only allow it to be set once. - -2013-12-20 Mark Wielaard <mjw@redhat.com> - - * dwfl_frame.c (one_arg): New struct. - (get_one_thread_cb): New function. - (dwfl_getthread): Likewise. - (one_thread): New struct. - (get_one_thread_frames_cb): New function. - (dwfl_getthread_frames): Likewise. - * libdwfl.h (Dwfl_Thread_Callbacks): Add get_thread function. - (dwfl_getthread_frames): Likewise. - * libdwflP.h (dwfl_getthread_frames): New internal function declaration. - * linux-core-attach.c (core_thread_callbacks): Initialize get_thread - to NULL. - * linux-pid-attach.c (pid_getthread): New function. - (pid_thread_callbacks): Initialize get_thread to pid_getthread. - -2013-12-20 Mark Wielaard <mjw@redhat.com> - - * linux-kernel-modules.c (report_kernel_archive): Correct nested - asprintf result check for debug.a. - -2013-12-18 Mark Wielaard <mjw@redhat.com> - - * derelocate.c (__libdwfl_find_section_ndx): New internal function. - * dwfl_module_addrname.c (dwfl_module_addrname): Use - dwfl_module_addrinfo. - * dwfl_module_addrsym.c (dwfl_module_addrsym_elf): Replace with... - (__libdwfl_addrsym): ...this. Use __libdwfl_getsym, use value - for comparisons, not st_value. Fill in off. Search for both value - and the (adjusted) sym.st_value when different. - (dwfl_module_addrsym): Implement using __libdwfl_addrsym. - (dwfl_module_addrinfo): New function. - * dwfl_module_getsym.c (dwfl_module_getsym_elf): Replace with... - (__libdwfl_getsym): ...this. Use ebl_resolve_sym_value if requested - and possible. Adjust sym->st_value only when requested. Fill in addr - if available. - (dwfl_module_getsym_info): New function. - (dwfl_module_getsym): Use __libdwfl_getsym. - * libdwfl.h (dwfl_module_getsym_elf): Removed. - (dwfl_module_getsym_info): New function declaration. - (dwfl_module_addrinfo): Likewise. - (dwfl_module_addrsym): Add documentation describing differences - with addrinfo variants. - (dwfl_module_addrsym_elf): Removed. - * libdwflP.h (__libdwfl_getsym): New internal function declaration. - (__libdwfl_addrsym): Likewise. - (__libdwfl_find_section_ndx): Likewise. - (dwfl_module_addrinfo): New internal declaration. - (dwfl_module_getsym_info): Likewise. - (dwfl_module_addrsym_elf): Removed. - (dwfl_module_getsym_elf): Likewise. - -2013-12-18 Jan Kratochvil <jan.kratochvil@redhat.com> - - * argp-std.c (offline_find_elf): Remove. - (offline_callbacks): Use dwfl_build_id_find_elf instead. - * dwfl_build_id_find_elf.c (dwfl_build_id_find_elf): Move here the code - removed above. - -2013-12-18 Jan Kratochvil <jan.kratochvil@redhat.com> - - unwinder: s390 and s390x - * dwfl_frame_pc.c (dwfl_frame_pc): Call ebl_normalize_pc. - * frame_unwind.c (new_unwound): New function from ... - (handle_cfi): ... here. Call it. - (setfunc, getfunc, readfunc): New functions. - (__libdwfl_frame_unwind): Call ebl_unwind with those functions. - * linux-core-attach.c (core_set_initial_registers): Always iterate - through the Ebl_Register_Location loop. Call - dwfl_thread_state_register_pc there. - -2013-12-17 Jan Kratochvil <jan.kratochvil@redhat.com> - - * frame_unwind.c (handle_cfi): Call ebl_dwarf_to_regno for RA. - -2013-12-17 Mark Wielaard <mjw@redhat.com> - - * linux-pid-attach.c (pid_next_thread): Call rewinddir on first - traversal. - -2013-12-16 Mark Wielaard <mjw@redhat.com> - - * libdwfl.h (dwfl_module_getsymtab_first_global): New function - definition. - * dwfl_module_getdwarf.c (dwfl_module_getsymtab_first_global): New - function. - * libdwflP.h (dwfl_module_getsymtab_first_global): New internal - function definition. - * dwfl_module_addrsym.c (dwfl_module_addrsym_elf): Use new function. - -2013-12-14 Mark Wielaard <mjw@redhat.com> - - * dwfl_module.c (__libdwfl_module_free): Free mod->reloc_info if - allocated. Call dwarf_cfi_end on mod->eh_cfi if necessary. - * frame_unwind.c (handle_cfi): Free frame result from - dwarf_cfi_addrframe when done. - -2013-12-15 Jan Kratochvil <jan.kratochvil@redhat.com> - - unwinder: ppc and ppc64 - * frame_unwind.c (__libdwfl_frame_reg_get, __libdwfl_frame_reg_set): - Call ebl_dwarf_to_regno. - * linux-core-attach.c (core_set_initial_registers): Implement - pc_register support. - * linux-pid-attach.c (pid_thread_state_registers_cb): Implement - FIRSTREG -1. - -2013-11-30 Jan Kratochvil <jan.kratochvil@redhat.com> - - Introduce process_attach_error. - * dwfl_begin.c (dwfl_begin): Initialize process_attach_error. - * dwfl_frame.c (dwfl_pid, dwfl_getthreads): Use PROCESS_ATTACH_ERROR if - PROCESS is NULL. - * libdwflP.h (struct Dwfl): New field process_attach_error. - * linux-core-attach.c (__libdwfl_attach_state_for_core): Rename to ... - (attach_state_for_core): ... here, make it static, change return type, - no longer use __libdwfl_seterrno. - (__libdwfl_attach_state_for_core): New wrapper for it. - -2013-11-27 Mark Wielaard <mjw@redhat.com> - - * dwfl_module_addrsym.c (dwfl_module_addrsym): Rename to and call... - (dwfl_module_addrsym_elf): this. Add elfp and biasp arguments, - keep track of symelf, addr_symelf, closest_elf and sizeless_elf - instead of tracking dwfl_files. - * dwfl_module_getsym.c (__libdwfl_module_getsym): Renamed to... - (dwfl_module_getsym_elf): ...this. Remove dwfl_file argument, add - new elfp and biasp arguments. Track elf instead of file. - (dwfl_module_getsym): Call dwfl_module_getsym_elf. - dwfl_module_info.c (dwfl_module_info): Pass elf to - dwfl_adjusted_st_value. - * libdwfl.h (dwfl_module_getsym): Document limitations of shndx. - (dwfl_module_getsym_elf): New function declaration. - (dwfl_module_addrsym_elf): Likewise. - * libdwflP.h (dwfl_module_addrsym_elf): INTDECL. - (dwfl_module_getsym_elf): Likewise. - (dwfl_adjusted_st_value): Take and check elf not dwfl_file. - (dwfl_deadjust_st_value): Likewise. - (__libdwfl_module_getsym): Removed. - * relocate.c (resolve_symbol): Pass elf to dwfl_adjusted_st_value. - -2013-11-21 Jan Kratochvil <jan.kratochvil@redhat.com> - - Fix non-build-id core files on build-id system. - * link_map.c (report_r_debug): Remove valid clearing if build-id cannot - be read from memory. - -2013-11-21 Jan Kratochvil <jan.kratochvil@redhat.com> - - * dwfl_segment_report_module.c (dwfl_segment_report_module): New - variable close_elf. Call __libdwfl_find_elf_build_id and compare the - content, if possible. - -2013-11-21 Jan Kratochvil <jan.kratochvil@redhat.com> - - link_map: Use proper bias, not l_addr. - * core-file.c (dynamic_vaddr_get): Rename to ... - (__libdwfl_dynamic_vaddr_get): ... here, make it global, - internal_function. - (dwfl_core_file_report): Update name in the caller. - * libdwflP.h (__libdwfl_dynamic_vaddr_get): New declaration. - * link_map.c (report_r_debug): New variable elf_dynamic_vaddr. Call - __libdwfl_dynamic_vaddr_get for it. Remove L_ADDR FIXME comment. - Use ELF_DYNAMIC_VADDR instead of L_ADDR. - -2013-11-19 Jan Kratochvil <jan.kratochvil@redhat.com> - - Compatibility with older kernels such as RHEL-6. - * linux-pid-attach.c (struct pid_arg): New field tid_was_stopped. - (ptrace_attach): New parameter tid_was_stoppedp. Set it. - (pid_set_initial_registers): Pass tid_was_stopped. - (pid_thread_detach): Use tid_was_stopped. - -2013-11-18 Josh Stone <jistone@redhat.com> - - * dwfl_module_getdwarf.c (find_aux_address_sync): New function. - (find_aux_sym): Use it. - -2013-11-14 Jan Kratochvil <jan.kratochvil@redhat.com> - - Code cleanup: Remove const in prototype - * dwfl_frame_regs.c (dwfl_thread_state_registers): Remove const from - firstreg. - * libdwfl.h (dwfl_thread_state_registers): Likewise. - * linux-pid-attach.c (pid_thread_state_registers_cb): Likewise. - -2013-11-14 Jan Kratochvil <jan.kratochvil@redhat.com> - - Fix dwfl_attach_state machine->elf. - * dwfl_frame.c (dwfl_attach_state): Change parameter machine to elf. - Call ebl_openbackend instead of ebl_openbackend_machine. - * libdwfl.h (dwfl_attach_state): Change parameter machine to elf. - Update the function description. - * linux-core-attach.c (__libdwfl_attach_state_for_core): Pass CORE to - dwfl_attach_state. - * linux-pid-attach.c (__libdwfl_attach_state_for_pid): Pass NULL to - dwfl_attach_state. - -2013-11-06 Jan Kratochvil <jan.kratochvil@redhat.com> - - Provide __libdwfl_module_getsym to get dwfl_file *. - * dwfl_module_addrsym.c (dwfl_module_addrsym) (i_to_symfile): Remove. - (dwfl_module_addrsym) (search_table): New variable file. Use - __libdwfl_module_getsym. Use file. - * dwfl_module_getsym.c (dwfl_module_getsym): Rename to ... - (__libdwfl_module_getsym): ... here. Add parameter filep. Set it. - (dwfl_module_getsym): New wrapper. - * libdwflP.h (__libdwfl_module_getsym): New declaration. - -2013-11-13 Jan Kratochvil <jan.kratochvil@redhat.com> - - Fix dwfl_module_addrsym for minidebuginfo. - * dwfl_module_addrsym.c (dwfl_module_addrsym): New variable - addr_symfile. - (dwfl_module_addrsym) (same_section): Use it. - (dwfl_module_addrsym) (i_to_symfile): New function. - (dwfl_module_addrsym) (search_table): Use it. - -2013-11-07 Jan Kratochvil <jan.kratochvil@redhat.com> - Mark Wielaard <mjw@redhat.com> - - * Makefile.am (libdwfl_a_SOURCES): Add dwfl_frame.c, frame_unwind.c, - dwfl_frame_pc.c, linux-pid-attach.c, linux-core-attach.c and - dwfl_frame_regs.c. - * core-file.c (dwfl_core_file_report): Call - __libdwfl_attach_state_for_core. - * dwfl_end.c (dwfl_end): Call __libdwfl_process_free. - * dwfl_frame.c: New file. - * frame_unwind.c: New file. - * dwfl_frame_pc.c: New file. - * linux-pid-attach.c: New file. - * linux-core-attach.c: New file. - * dwfl_frame_regs.c: New file. - * libdwfl.h (Dwfl_Thread, Dwfl_Frame): New typedefs. - (dwfl_core_file_report, dwfl_linux_proc_report): Extend comments. - (Dwfl_Thread_Callbacks): New definition. - (struct ebl, dwfl_attach_state, dwfl_pid, dwfl_thread_dwfl) - (dwfl_thread_tid, dwfl_frame_thread, dwfl_thread_state_registers) - (dwfl_thread_state_register_pc, dwfl_getthreads, dwfl_thread_getframes) - (dwfl_frame_pc): New declarations. - * libdwflP.h (Dwfl_Process): New typedef. - (LIBEBL_BAD, CORE_MISSING, INVALID_REGISTER, PROCESS_MEMORY_READ) - (PROCESS_NO_ARCH, PARSE_PROC, INVALID_DWARF, UNSUPPORTED_DWARF) - (NEXT_THREAD_FAIL, ATTACH_STATE_CONFLICT, NO_ATTACH_STATE, NO_UNWIND) - (INVALID_ARGUMENT): New DWFL_ERROR entries. - (struct Dwfl): New entry process. - (struct Dwfl_Process, struct Dwfl_Thread, struct Dwfl_Frame) - (__libdwfl_frame_reg_get, __libdwfl_frame_reg_set) - (__libdwfl_process_free, __libdwfl_frame_unwind) - (__libdwfl_attach_state_for_pid, __libdwfl_attach_state_for_core) - (__libdwfl_segment_start, __libdwfl_segment_end): New declarations. - (dwfl_attach_state, dwfl_pid, dwfl_thread_dwfl, dwfl_thread_tid) - (dwfl_frame_thread, dwfl_thread_state_registers) - (dwfl_thread_state_register_pc, dwfl_getthreads, dwfl_thread_getframes) - (dwfl_frame_pc): New INTDECL entries. - * linux-proc-maps.c (dwfl_linux_proc_report): Call - __libdwfl_attach_state_for_pid. - * segment.c (segment_start): Rename to ... - (__libdwfl_segment_start): ... here and make it internal_function. - (segment_end): Rename to ... - (__libdwfl_segment_end): ... here and make it internal_function. - (reify_segments, dwfl_report_segment): Rename them at the callers. - -2013-11-07 Jan Kratochvil <jan.kratochvil@redhat.com> - - * core-file.c (dwfl_core_file_report): Remove the use of MAX. - -2013-11-07 Jan Kratochvil <jan.kratochvil@redhat.com> - - * core-file.c (dwfl_core_file_report): Replaced variable sniffed by - retval. Fix one forgotten LISTED increase. - -2013-11-07 Jan Kratochvil <jan.kratochvil@redhat.com> - - Fix core files for re-prelink-ed files. - * core-file.c (dynamic_vaddr_get): New function. - (dwfl_core_file_report): New variable file_dynamic_vaddr. Call - dynamic_vaddr_get instead of using L_ADDR. - * libdwflP.h (struct r_debug_info_module): Remove field l_addr. - * link_map.c (report_r_debug): Do not initialize l_addr. - -2013-11-07 Jan Kratochvil <jan.kratochvil@redhat.com> - - Code cleanup. - * core-file.c (dwfl_core_file_report): Reindent block of code by - continue keyword. - -2013-10-30 Jan Kratochvil <jan.kratochvil@redhat.com> - - * argp-std.c (parse_opt): Use executable parameter of - dwfl_core_file_report. - * core-file.c (dwfl_core_file_report): Add parameter executable. Set - it to DWFL. Add NEW_VERSION for it. - (_compat_without_executable_dwfl_core_file_report): New. Twice. - * libdwfl.h (dwfl_core_file_report): Add parameter executable, update - the function comment. - -2013-10-15 Mark Wielaard <mjw@redhat.com> - - * linux-proc-maps.c (proc_maps_report): Ignore non-absolute file - mappings. - (dwfl_linux_proc_find_elf): Don't abort, just return failure. - -2013-09-12 Mark Wielaard <mjw@redhat.com> - - * cu.c (intern_cu): If dwarf_offdie fails free cu. - -2013-09-12 Mark Wielaard <mjw@redhat.com> - - * linux-proc-maps.c (proc_maps_report): Don't fclose FILE in - bad_report. - -2013-09-12 Mark Wielaard <mjw@redhat.com> - - * dwfl_module_getdwarf.c (find_symtab): Call elf_getdata with - aux_xndxscn, not xndxscn, for aux_symxndxdata. - -2013-08-25 Mark Wielaard <mjw@redhat.com> - - * linux-kernel-modules.c (report_kernel): Pass add_p_vaddr as true - to dwfl_report_elf. - -2013-07-25 Jan Kratochvil <jan.kratochvil@redhat.com> - - * dwfl_segment_report_module.c (dwfl_segment_report_module): Check for - conflicts all the modules, not just the first one. Compare L_LD if it - is equal, not if it is in a module address range. - -2013-07-23 Jan Kratochvil <jan.kratochvil@redhat.com> - - * libdwflP.h (__libdwfl_elf_address_range): Add internal_function. - -2013-07-23 Jan Kratochvil <jan.kratochvil@redhat.com> - - * core-file.c (clear_r_debug_info): Close also ELF and FD. - (dwfl_core_file_report): Call __libdwfl_report_elf for - R_DEBUG_INFO.MODULE. - * dwfl_report_elf.c (__libdwfl_elf_address_range): New function from - code of ... - (__libdwfl_report_elf): ... this function. Call it. - * dwfl_segment_report_module.c: Include unistd.h. - (dwfl_segment_report_module): Use basename for MODULE->NAME. - Clear MODULE if it has no build-id and we have segment with build-id. - Ignore this segment only if MODULE still contains valid ELF. - * libdwflP.h (__libdwfl_elf_address_range): New declaration. - (struct r_debug_info_module): New fields fd, elf, l_addr, start, end - and disk_file_has_build_id. - (dwfl_link_map_report): Extend the comment. - * link_map.c (report_r_debug): Extend the comment. Always fill in new - r_debug_info_module. Initialize also the new r_debug_info_module - fields. Remove one FIXME comment. Call __libdwfl_elf_address_range - instead of __libdwfl_report_elf when R_DEBUG_INFO is not NULL. - -2013-07-19 Jan Kratochvil <jan.kratochvil@redhat.com> - - * libdwflP.h (__libdwfl_find_elf_build_id): Add internal_function. - -2013-07-02 Mark Wielaard <mjw@redhat.com> - - * relocate.c (__libdwfl_relocate_value): Remove mod->e_type assert. - -2013-06-05 Mark Wielaard <mjw@redhat.com> - - * link_map.c (report_r_debug): Always call release_buffer after - memory_callback succeeded reading build_id. - -2013-05-30 Jan Kratochvil <jan.kratochvil@redhat.com> - - * argp-std.c (parse_opt) <ARGP_KEY_SUCCESS> <opt->core> <opt->e>: Set - executable_for_core before calling dwfl_core_file_report. - * core-file.c (clear_r_debug_info): New function. - (dwfl_core_file_report): Move raw segments reporting lower. New - variable r_debug_info, pass it to dwfl_segment_report_module. Call - clear_r_debug_info in the end. Return sum of LISTED and SNIFFED. - * dwfl_module_build_id.c (check_notes): Move into - __libdwfl_find_elf_build_id. - (__libdwfl_find_build_id): Rename to ... - (__libdwfl_find_elf_build_id): ... here. Add parameters build_id_bits, - build_id_elfaddr and build_id_len. Verify MOD vs. ELF. - (__libdwfl_find_elf_build_id) (check_notes): Remove parameters mod and - set, rename data_vaddr to data_elfaddr. Do not call found_build_id. - (__libdwfl_find_elf_build_id): Update the check_notes caller, do not - adjust its data_elfaddr parameter. - (__libdwfl_find_build_id): New wrapper of __libdwfl_find_elf_build_id. - * dwfl_segment_report_module.c (dwfl_segment_report_module): New - parameter r_debug_info. New variable name_is_final. Adjust addresses - according to R_DEBUG_INFO->MODULE. Check conflicts against DWFL. - Do not overwrite NAME by SONAME if NAME_IS_FINAL. - * libdwflP.h (__libdwfl_find_elf_build_id): New declaration. - (struct r_debug_info_module, struct r_debug_info): New definitions. - (dwfl_segment_report_module, dwfl_link_map_report): Add parameter - r_debug_info. - * link_map.c: Include fcntl.h. - (report_r_debug): Add parameter r_debug_info, describe it in the - function comment. Delete dwfl_addrmodule call and its dependent code. - Verify build-id before calling dwfl_report_elf, also supply - executable_for_core to it. Store r_debug_info->module info when - appropriate. - (dwfl_link_map_report): Add parameter r_debug_info. New variable - in_ok. Try to read IN from EXECUTABLE_FOR_CORE. Update report_r_debug - caller parameters. - -2013-04-30 Jan Kratochvil <jan.kratochvil@redhat.com> - - * dwfl_report_elf.c (__libdwfl_report_elf): Add parameter add_p_vaddr. - Set it to true for ET_EXEC and ET_CORE. Provide alternative - setup of START and BIAS if !ADD_P_VADDR. Set END from BIAS, not BASE. - (dwfl_report_elf): Add parameter add_p_vaddr. Pass it down. Add - NEW_VERSION. - (_compat_without_add_p_vaddr_dwfl_report_elf) <SHARED>: New, with - COMPAT_VERSION. - * libdwfl.h (dwfl_report_elf): Add parameter add_p_vaddr. Describe it. - * libdwflP.h (__libdwfl_report_elf): Add parameter add_p_vaddr. - * link_map.c (report_r_debug): Use true add_p_vaddr for dwfl_report_elf. - * linux-kernel-modules.c (report_kernel): Use false add_p_vaddr for - dwfl_report_elf. - * offline.c (process_elf): Use true add_p_vaddr for dwfl_report_elf. - -2013-04-27 Mark Wielaard <mjw@redhat.com> - - * link_map.c: #include system.h. - -2013-04-26 Jan Kratochvil <jan.kratochvil@redhat.com> - - * link_map.c (BE32, BE64, LE32, LE64): Delete the definitions, move - them to lib/system.h. - -2013-04-24 Mark Wielaard <mjw@redhat.com> - - * Makefile.am: Use AM_CPPFLAGS instead of INCLUDES. - -2013-03-20 Jan Kratochvil <jan.kratochvil@redhat.com> - - * dwfl_report_elf.c (__libdwfl_report_elf): Remove BASE aligning. - -2013-03-12 Mark Wielaard <mjw@redhat.com> - - * dwfl_getsrclines.c (dwfl_getsrclines): Return 0 on success. - -2013-02-22 Mark Wielaard <mjw@redhat.com> - - * open.c (__libdw_gunzip,__libdw_bunzip2,__libdw_unlzma): Define - as DWFL_E_BADELF when not used. - -2013-02-10 Mark Wielaard <mjw@redhat.com> - - * argp-std.c (parse_opt): Use opt->core and opt->e explicitly in - failure messages When handling ARGP_KEY_SUCCESS because arg will - not have been set. - -2013-01-30 Jan Kratochvil <jan.kratochvil@redhat.com> - - * linux-proc-maps.c: Include system.h. - (PROCEXEFMT, get_pid_class): New. - (grovel_auxv): Detect 32-bit vs. 64-bit auxv, possibly call - get_pid_class. - -2013-01-23 Mark Wielaard <mjw@redhat.com> - - * dwfl_module_getdwarf.c (find_aux_sym): Don't substract one - from aux_syments by default. - (find_symtab): Also succeed when only aux_symdata is found. - When no symtab is found always try to load auxiliary table. - (dwfl_module_getsymtab): Substract one from result when both - tables have symbols. - * dwfl_module_getsym.c (dwfl_module_getsym): Only skip auxiliary - zero entry when both tables have symbols. - * dwfl_module_addrsym.c (dwfl_module_addrsym): Only substract - one from first_global when both tables have symbols. - -2013-01-16 Mark Wielaard <mjw@redhat.com> - - * libdwflP.h (struct Dwfl_Module): Add aux_sym, aux_symdata, - aux_syments, aux_symstrdata, aux_symxndxdata and aux_first_global. - (dwfl_adjusted_aux_sym_addr): New function. - (dwfl_deadjust_aux_sym_addr): Likewise. - (dwfl_adjusted_st_value): Take and check symfile argument. - (dwfl_deadjust_st_value): Likewise. - * dwfl_module_getdwarf.c (find_prelink_address_sync): Take and - use dwfl_file as argument to set address_sync. - (find_debuginfo): Call find_prelink_address_sync with debug file. - (find_aux_sym): New function. - (find_symtab): Use find_aux_sym if all we have is the dynsym table - and fill in aux DwflModule fields. - (dwfl_module_getsymtab): Return syments plus aux_syments. - (load_symtab): Always set first_global. - * dwfl_module_addrsym.c (dwfl_module_addrsym): Check symfile - when using same_section. Calculate first_global based on both - mod->first_global and mod->aux_first_global. - * dwfl_module.c (__libdwfl_module_free): Free aux_sym. - * dwfl_module_getsym.c (dwfl_module_getsym): Use auxsym table - to retrieve symbol and name if necessary, making sure all locals - from any table come before any globals. - * dwfl_module_info.c (dwfl_module_info): Call dwfl_adjusted_st_value - with symfile. - * relocate.c (resolve_symbol): Likewise. - -2013-01-07 Roland McGrath <roland@hack.frob.com> - - * link_map.c (auxv_format_probe): Handle unaligned 64-bit data, but - still assume the data is at least 32-bit aligned anyway. - (dwfl_link_map_report): Handle unaligned auxv data. - -2012-12-11 Mark Wielaard <mjw@redhat.com> - - * linux-kernel-modules.c (report_kernel): Only free fname if - find_kernel_elf succeeds and allocates it. - (report_kernel_archive): Fix brackets around unlikely expression. - -2012-11-29 Jan Kratochvil <jan.kratochvil@redhat.com> - - * argp-std.c: Update Copyright year. - (offline_find_elf): New function. - (offline_callbacks): Use it for find_elf. - (struct parse_opt): New. - (parse_opt): New key ARGP_KEY_INIT. In other make hook struct - parse_opt pointer from former Dwfl pointer. Delay 'e and OPT_COREFILE - processing till ARGP_KEY_SUCCESS. Initialize state->input already from - ARGP_KEY_SUCCESS. Modify the cleanup in ARGP_KEY_ERROR. Make the - final state->input initialization optional. - * dwfl_end.c: Update Copyright year. - (dwfl_end): Free executable_for_core. - * libdwflP.h: Update Copyright year. - (struct Dwfl): New field executable_for_core. - -2012-11-20 Jan Kratochvil <jan.kratochvil@redhat.com> - - * dwfl_report_elf.c (__libdwfl_report_elf): Simplify START and BIAS - calculation. - -2012-10-17 Jan Kratochvil <jan.kratochvil@redhat.com> - - * dwfl_module_getdwarf.c (mod_verify_build_id): New function with code - from ... - (__libdwfl_getelf): ... here. Call it. - -2012-10-17 Jan Kratochvil <jan.kratochvil@redhat.com> - - * libdwfl.h (dwfl_module_getelf): Add __nonnull_attribute__. - -2012-10-10 Jan Kratochvil <jan.kratochvil@redhat.com> - - * dwfl_segment_report_module.c (dwfl_segment_report_module): - Initialize mod->MAIN_BIAS. - -2012-10-10 Jan Kratochvil <jan.kratochvil@redhat.com> - - * dwfl_module_addrsym.c (dwfl_module_addrsym): New function - binding_value. Use it for both zero and non-zero size symbols - comparisons. - -2012-10-01 Mark Wielaard <mjw@redhat.com> - - * cu.c (cudie_offset): Don't use type_sig8, it might not be - initialized and these are always real CUs, never TUs. - -2012-10-01 Mark Wielaard <mjw@redhat.com> - - * derelocate.c (find_section): Check next section exists before - accessing it. - -2012-08-01 Petr Machata <pmachata@redhat.com> - - * offline.c (process_archive_member): Ignore entry "/SYM64/". - -2012-03-28 Roland McGrath <roland@hack.frob.com> - - * dwfl_segment_report_module.c - (dwfl_segment_report_module: read_portion): Don't use existing buffer - when FILESZ is zero (string mode) and available portion doesn't hold - a terminated string. - -2011-12-02 Roland McGrath <roland@hack.frob.com> - - * elf-from-memory.c (elf_from_remote_memory): Fix ELFCLASS64 case - to use elf64_xlatetom and PHDRS.p64. - Reported by Serge Pavlov <serge.pavlov.at.gnu@gmail.com>. - -2011-11-31 Mark Wielaard <mjw@redhat.com> - - * dwfl_module_addrsym.c (dwfl_module_addrsym): First search all - global symbols. Then only when that doesn't provide a match search - all local symbols too. - * dwfl_module_getdwarf.c (load_symtab): Take first_global int arg - and fill it in. - (find_symtab): Initialize mod->first_global and pass it to load_symtab. - * libdwfl/libdwflP.h (Dwfl_Module): Add first_global field. - -2011-11-31 Mark Wielaard <mjw@redhat.com> - - * dwfl_module_addrsym.c (dwfl_module_addrsym): Only update - sizeless_sym if needed and closer to desired addr. - -2011-10-20 Mark Wielaard <mjw@redhat.com> - - * derelocate.c (cache_sections): Intern mod->reloc_info check. - (dwfl_module_relocations): Don't check mod->reloc_info. - (dwfl_module_relocation_info): Likewise. - (find_section): Likewise. - -2011-07-09 Roland McGrath <roland@hack.frob.com> - - * image-header.c (LE32): Macro removed (now in lib/system.h). - -2011-04-11 Mark Wielaard <mjw@redhat.com> - - * linux-kernel-modules.c (vmlinux_suffixes): Guard definition - by check for zlib, bzlib or lzma defines to check it isn't empty. - (try_kernel_name): Use same guard for use of vmlinux_suffixes. - -2011-03-08 Roland McGrath <roland@redhat.com> - - * dwfl_module_getdwarf.c (open_elf): Clear errno before CBFAIL. - Reported by Kurt Roeckx <kurt@roeckx.be>. - -2011-02-11 Roland McGrath <roland@redhat.com> - - * linux-kernel-modules.c (try_kernel_name): Try .gz, .bz2, .xz - suffixes if corresponding decompression support is enabled. - -2011-02-01 Roland McGrath <roland@redhat.com> - - * dwfl_module_getdwarf.c (find_prelink_address_sync): Use the - section-end address as the synchronization point, rather than sh_addr. - - * dwfl_module_getdwarf.c (find_prelink_address_sync): Discover - PT_INTERP p_vaddr separately from main phdrs and undo phdrs. - - * dwfl_module_getdwarf.c (find_prelink_address_sync): Fix pasto in - last change, so we recognize PT_INTERP in ELFCLASS64 correctly. - -2011-01-11 Roland McGrath <roland@redhat.com> - - * dwfl_module_getdwarf.c (open_elf): Remove section-based - address_sync fixup from here. - (find_prelink_address_sync): New function. - (find_debuginfo): Call it. - * libdwflP.h (DWFL_ERRORS): Add BAD_PRELINK error. - -2011-01-04 Roland McGrath <roland@redhat.com> - - * dwfl_module_getdwarf.c (open_elf): Enhance address_sync calculation - logic to consider section addresses, the better to survive all the - possible prelink machinations. - * libdwflP.h (struct dwfl_file): Comment change. - -2010-11-30 Roland McGrath <roland@redhat.com> - - * derelocate.c (dwfl_module_relocations): Remove over-eager assert. - -2010-11-12 Roland McGrath <roland@redhat.com> - - * libdwflP.h (struct Dwfl_Module): New member main_bias. - (dwfl_adjusted_address, dwfl_deadjust_address): Use it. - * dwfl_module_getdwarf.c (__libdwfl_getelf): Initialize it. - - * libdwflP.h (dwfl_deadjust_address): New function. - (dwfl_deadjust_dwarf_addr, dwfl_deadjust_st_value): New functions. - * cu.c (addrarange): Use dwfl_deadjust_dwarf_addr. - * dwfl_module_addrsym.c: Use dwfl_deadjust_st_value. - -2010-11-11 Roland McGrath <roland@redhat.com> - - * libdwflP.h (struct dwfl_file): Remove bias member. - Add vaddr and address_sync members instead. - (dwfl_adjusted_address): Calculate using vaddr. - (dwfl_adjusted_dwarf_addr): Calculate using address_sync and call that. - (dwfl_adjusted_st_value): Use one of those calls. - * dwfl_module_getdwarf.c (open_elf): Initialize vaddr and address_sync. - * dwfl_segment_report_module.c (dwfl_segment_report_module): Likewise. - * derelocate.c (dwfl_module_relocations): Update ET_EXEC assertions. - * link_map.c (consider_executable): Adjust only MOD->low_addr for - detected PIE bias change. - - * libdwflP.h (dwfl_adjusted_dwarf_addr): New function. - * dwfl_module_info.c: Use it. - * cu.c (addrarange): Likewise. - * dwfl_dwarf_line.c: Likewise. - * dwfl_module_dwarf_cfi.c: Likewise. - * dwfl_lineinfo.c: Likewise. - * dwfl_nextcu.c: Likewise. - * dwfl_module_getdwarf.c (dwfl_module_getdwarf): Likewise. - - * libdwflP.h (dwfl_adjusted_st_value): New function. - * relocate.c (resolve_symbol): Use it. - * dwfl_module_getsym.c: Likewise. - * dwfl_module_addrsym.c: Likewise. - * dwfl_module_info.c: Likewise. - - * libdwflP.h (dwfl_adjusted_address): New function. - * dwfl_module_build_id.c (__libdwfl_find_build_id): Use it. - * relocate.c (__libdwfl_relocate_value): Likewise. - * derelocate.c (cache_sections): Likewise. - (dwfl_module_address_section): Likewise. - * dwfl_module_getelf.c: Likewise. - * dwfl_module_eh_cfi.c: Likewise. - * link_map.c (consider_executable): Likewise. - -2010-08-24 Roland McGrath <roland@redhat.com> - - * dwfl_dwarf_line.c: New file. - * Makefile.am (libdwfl_a_SOURCES): Add it. - -2010-08-18 Roland McGrath <roland@redhat.com> - - * link_map.c (report_r_debug): Use found name if we have no name, - even if we already have an Elf handle. - -2010-06-30 Roland McGrath <roland@redhat.com> - - * linux-kernel-modules.c (dwfl_linux_kernel_find_elf): Don't be - confused by -1 return from dwfl_build_id_find_elf after it opened - the Elf handle. - * find-debuginfo.c (dwfl_standard_find_debuginfo): Likewise for - dwfl_build_id_find_debuginfo. - -2010-06-16 Roland McGrath <roland@redhat.com> - - * cu.c (cudie_offset): Use DIE_OFFSET_FROM_CU_OFFSET macro. - -2010-06-14 Roland McGrath <roland@redhat.com> - - * find-debuginfo.c (try_open): Take new arg MAIN_STAT. Compare - candidate file to that st_dev/st_ino and pretend it didn't exist - if they match. - (find_debuginfo_in_path): Update caller, pass main file's info. - -2010-05-20 Roland McGrath <roland@redhat.com> - - * linux-proc-maps.c (find_sysinfo_ehdr): Renamed to ... - (grovel_auxv): ... this. Take DWFL argument. - (dwfl_linux_proc_report): Update caller. - - * dwfl_module_getdwarf.c (open_elf): Calculate alignment for bias - based on dwfl->segment_align or manifest alignment of MOD->low_addr. - -2010-05-19 Roland McGrath <roland@redhat.com> - - * linux-kernel-modules.c (intuit_kernel_bounds): Rewritten. - -2010-05-06 Roland McGrath <roland@redhat.com> - - * segment.c (insert): Clear inserted elements of DWFL->lookup_module. - - * libdwflP.h (DWFL_ERRORS): Add WRONG_ID_ELF. - * dwfl_build_id_find_elf.c: Set MOD->main.valid when there is a build - ID but we didn't find a file. - * dwfl_module_getdwarf.c (__libdwfl_getelf): When that's set, check - and refuse any fallback file-by-name if it lacks the matching ID. - - * dwfl_error.c (dwfl_errno): Add INTDEF. - * libdwflP.h: Add INTDECL. - - * dwfl_module_getdwarf.c (open_elf): Do elf_end and clear FILE->elf in - failure cases. - -2010-05-04 Roland McGrath <roland@redhat.com> - - * dwfl_segment_report_module.c: Use "[pie]" rather than "[dso]" for an - ET_DYN that has a DT_DEBUG. - - * dwfl_segment_report_module.c: Fix jump-start of NDX-finding loop. - - * segment.c (insert): Fix moving of values following insertion. - (reify_segments): Fix up MOD->segment backpointer indices after - later insertions in the main loop invalidate them. - - * link_map.c (dwfl_link_map_report): Detect bias of embedded phdrs and - apply it to PT_DYNAMIC p_vaddr so we handle a PIE correctly. - - * core-file.c (dwfl_core_file_report): Return any nonzero count of - modules reported, even if link_map grovelling failed and only sniffing - found anything. - -2010-04-26 Roland McGrath <roland@redhat.com> - - * relocate.c (relocate_section): Treat R_*_NONE reloc as no reloc. - Works around probably-wrong ld -r behavior for case of a DWARF address - constant that refers to a discarded SHF_ALLOC section. - -2010-04-14 Roland McGrath <roland@redhat.com> - - * link_map.c (report_r_debug): Limit iterations on the l_next chain to - an upper bound on sane possible number of elements. - -2010-03-11 Roland McGrath <roland@redhat.com> - - * link_map.c (auxv_format_probe): Fix scanning loop, so we really scan - the second half for 32-bit matches. - -2010-03-10 Roland McGrath <roland@redhat.com> - - * core-file.c (dwfl_core_file_report): Punt EHDR argument. - * argp-std.c (parse_opt): Update caller. - * libdwfl.h: Declare dwfl_core_file_report. - * libdwflP.h: Don't. - -2010-02-17 Roland McGrath <roland@redhat.com> - - * dwfl_segment_report_module.c (addr_segndx): Take new flag argument. - If set, find the first index not below ADDR. - (dwfl_segment_report_module): Update callers. - Pass true when calculating return value. - -2010-02-15 Roland McGrath <roland@redhat.com> - - * Makefile.am: Use config/eu.am for common stuff. - - * find-debuginfo.c (find_debuginfo_in_path): Fix uninitialized - variable in failure path. - -2010-02-02 Mark Wielaard <mjw@redhat.com> - - * dwfl_module_dwarf_cfi.c (dwfl_module_dwarf_cfi): Always set bias. - * dwfl_module_eh_cfi.c (dwfl_module_eh_cfi): Likewise - -2010-01-07 Roland McGrath <roland@redhat.com> - - * core-file.c (dwfl_core_file_report): Use elf_getphdrnum. - * dwfl_module_build_id.c (__libdwfl_find_build_id): Likewise. - * dwfl_module_getdwarf.c (open_elf, find_dynsym): Likewise. - * dwfl_report_elf.c (__libdwfl_report_elf): Likewise. - -2010-01-06 Roland McGrath <roland@redhat.com> - - * relocate.c (relocate_getsym): For SHN_COMMON, zero st_value. - (relocate_section): Let unresolved SHN_COMMON symbol stay 0. - -2009-11-16 Roland McGrath <roland@redhat.com> - - * relocate.c (relocate_section): Skip SHT_NOBITS or empty target scn. - -2009-11-12 Petr Machata <pmachata@redhat.com> - - * core-file.c (dwfl_elf_phdr_memory_callback): Only load ahead if - the chunk is both offset-contiguous and vaddr-contiguous. - -2009-11-05 Roland McGrath <roland@redhat.com> - - * link_map.c (report_r_debug): Skip entries with l_ld==0. - Use dwfl_addrmodule for l_ld lookup, don't bail on lookup failure. - -2009-09-04 Roland McGrath <roland@redhat.com> - - * image-header.c (__libdw_image_header): Fix tranposed comparison. - -2009-08-27 Roland McGrath <roland@redhat.com> - - * image-header.c: New file. - * Makefile.am (libdwfl_a_SOURCES): Add it. - * libdwflP.h: Declare __libdw_image_header. - * open.c (decompress): Don't consume ELF on failure. - (what_kind): New function, broken out of ... - (__libdw_open_file): ... here. Call it. - If it fails, try __libdw_image_header and then try what_kind again. - - * gzip.c (unzip): Reuse *WHOLE as first INPUT_BUFFER, - leave it behind for next decompressor. - * open.c (decompress): Free BUFFER on failure. - -2009-08-26 Roland McGrath <roland@redhat.com> - - * gzip.c (find_zImage_payload): New function, broken out of ... - (mapped_zImage): ... here. Call it. - (find_zImage_payload) [LZMA]: Match LZMA-compressed kernels with - stupid method of just trying the decoder. - - * open.c [USE_LZMA]: Try __libdw_unlzma. - * libdwflP.h: Declare it. - (DWFL_ERRORS): Add DWFL_E_LZMA. - * gzip.c [LZMA]: Implement liblzma version for XZ file format. - * lzma.c: New file. - * Makefile.am [LZMA] (libdwfl_a_SOURCES): Add it. - - * gzip.c (mapped_zImage): Limit scan to 32kb. - Make this unconditional, support bzip2 kernel images too. - (unzip): Use direct inflate method for non-mmap case too. - Only zlib uses the stream method. - -2009-08-09 Roland McGrath <roland@redhat.com> - - * dwfl_module_build_id.c: Use new macros for versioned definitions. - -2009-07-08 Roland McGrath <roland@redhat.com> - - * dwfl_module_dwarf_cfi.c: New file. - * dwfl_module_eh_cfi.c: New file. - * Makefile.am (libdwfl_a_SOURCES): Add them. - * libdwflP.h (struct Dwfl_Module): New members `dwarf_cfi', `eh_cfi. - Add INTDECL for dwfl_module_eh_cfi, dwfl_module_dwarf_cfi. - -2009-07-08 Roland McGrath <roland@redhat.com> - - * libdwflP.h (struct Dwfl_Module): Reorder members to pack better. - -2009-06-18 Mark Wielaard <mjw@redhat.com> - - * dwfl_report_elf.c (__libdwfl_report_elf): Return NULL on overlap. - -2009-06-13 Ulrich Drepper <drepper@redhat.com> - - * derelocate.c: Don't use deprecated libelf functions. - * dwfl_module_getdwarf.c: Likewise. - * relocate.c: Likewise. - -2009-04-23 Ulrich Drepper <drepper@redhat.com> - - * dwfl_module_build_id.c: Define versioned symbols only if SHARED is - defined. Otherwise just define the latest version. - -2009-04-22 Roland McGrath <roland@redhat.com> - - * relocate.c (resolve_symbol): Apply correct bias to st_value found in - a non-ET_REL module. - - * dwfl_module_build_id.c (__libdwfl_find_build_id): Fix last change to - adjust properly for non-ET_REL. - -2009-04-21 Roland McGrath <roland@redhat.com> - - * dwfl_module_getsym.c: Apply non-ET_REL bias only if SHF_ALLOC. - - * relocate.c (__libdwfl_relocate_value): Assert that MOD is ET_REL. - * derelocate.c (cache_sections): Call __libdwfl_relocate_value only - for ET_REL. - * dwfl_module_build_id.c (__libdwfl_find_build_id): Likewise. - -2009-04-20 Roland McGrath <roland@redhat.com> - - * dwfl_module_getdwarf.c (__libdwfl_getelf): Add internal_function. - -2009-04-19 Roland McGrath <roland@redhat.com> - - * dwfl_module_getdwarf.c (find_file): Renamed to ... - (__libdwfl_getelf): ... this. Make it global. - (find_symtab, find_dw): Update callers. - (dwfl_module_getelf): Functions moved ... - * dwfl_module_getelf.c: ... here, new file. - * Makefile.am (libdwfl_a_SOURCES): Add it. - * libdwflP.h: Declare __libdwfl_getelf. - -2009-04-14 Roland McGrath <roland@redhat.com> - - * dwfl_segment_report_module.c: Handle DT_STRTAB value being either - absolute (already adjusted in place) or needing load bias adjustment. - - * core-file.c (dwfl_elf_phdr_memory_callback): Fix return value for - gelf_getphdr failure. Fix file size limit checks. - - * dwfl_segment_report_module.c: Fix underflow in DYNSTRSZ check. - -2009-04-08 Roland McGrath <roland@redhat.com> - - * dwfl_module_getsym.c: Don't adjust for bias again after - __libdwfl_relocate_value. - - * relocate.c (__libdwfl_relocate_value): Don't adjust a value from - a non-SHF_ALLOC section. - (relocate_getsym): Test st_shndx for SHN_* values, not *SHNDX. - * dwfl_module_getsym.c (dwfl_module_getsym): Likewise. - -2009-03-09 Roland McGrath <roland@redhat.com> - - * dwfl_module_build_id.c (__libdwfl_find_build_id): Move SHSTRNDX - variable to outer scope, so we cache it for the loop. - - * relocate.c (__libdwfl_relocate_value): Add MOD->main.bias to sh_addr. - -2009-02-12 Roland McGrath <roland@redhat.com> - - * dwfl_module_build_id.c (__libdwfl_find_build_id): Use - __libdwfl_relocate_value to find correct sh_addr value. - -2009-02-10 Roland McGrath <roland@redhat.com> - - * dwfl_report_elf.c (__libdwfl_report_elf): Take new arg SANITY. - If false, don't fail for NO_PHDR. - (dwfl_report_elf): Update caller. - * libdwflP.h: Update decl. - * offline.c (process_elf): Call it with false, so we don't refuse - dubiously-formed objects here. - - * link_map.c (consider_executable): Don't assert dwfl_addrsegment - finds our module. We shouldn't crash when we confuse some guesses. - -2009-02-10 Ulrich Drepper <drepper@redhat.com> - - * open.c (decompress): Avoid crash with empty input file. - -2009-01-27 Roland McGrath <roland@redhat.com> - - * dwfl_report_elf.c (__libdwfl_report_elf): Ignore trailing PT_LOAD - with zero vaddr and memsz. - -2009-01-22 Roland McGrath <roland@redhat.com> - - * open.c (decompress): Move BUFFER, SIZE decls outside #if. - - * dwfl_segment_report_module.c (addr_segndx): Remove bogus adjustments - after address-matching loop. - - * segment.c (lookup): Fix fencepost in checking for HINT match. - -2009-01-14 Roland McGrath <roland@redhat.com> - - * gzip.c [!BZLIB] (mapped_zImage): New function. - (unzip) [!BZLIB]: Grok Linux kernel zImage format. - -2009-01-10 Ulrich Drepper <drepper@redhat.com> - - * dwfl_error.c: Always use __thread. Remove all !USE_TLS code. - -2009-01-08 Roland McGrath <roland@redhat.com> - - * linux-kernel-modules.c (dwfl_linux_kernel_report_offline): - Skip subdirectory named "source". - (dwfl_linux_kernel_find_elf): Likewise. - -2009-01-06 Roland McGrath <roland@redhat.com> - - * linux-kernel-modules.c (check_suffix): New function. - Match ".ko", ".ko.gz", and ".ko.bz2" suffixes. - (dwfl_linux_kernel_report_offline): Use it. - (dwfl_linux_kernel_find_elf): Likewise. - -2009-01-05 Roland McGrath <roland@redhat.com> - - * argp-std.c (parse_opt): Use __libdw_open_file for core file. - * dwfl_build_id_find_debuginfo.c: Use it to open the file. - * dwfl_build_id_find_elf.c: Likewise. - * dwfl_module_getdwarf.c (open_elf): Likewise. - * dwfl_report_elf.c: Likewise. - * find-debuginfo.c (validate): Likewise. - * offline.c (__libdwfl_report_offline): Likewise. - - * libdwflP.h: Declare __libdw_open_file. - * open.c: New file. - * Makefile.am (libdwfl_a_SOURCES): Add it. - - * gzip.c: New file. - * Makefile.am [ZLIB] (libdwfl_a_SOURCES): Add it. - * bzip2.c: New file. - * Makefile.am [BZLIB] (libdwfl_a_SOURCES): Add it. - * libdwflP.h: Declare __libdw_gunzip, __libdw_bunzip2. - -2008-12-16 Roland McGrath <roland@redhat.com> - - * dwfl_module_build_id.c (dwfl_module_build_id): Define with alias and - symver magic to bind to ELFUTILS_0.138. - (_BUG_COMPAT_dwfl_module_build_id): New function, bug compatible - wrapper for ELFUTILS_0.130 version set. - -2008-12-18 Roland McGrath <roland@redhat.com> - - * derelocate.c (dwfl_module_relocate_address): Fix last fix: ET_DYN - addresses are taken as relative to MOD->low_addr. - -2008-12-15 Roland McGrath <roland@redhat.com> - - * derelocate.c (dwfl_module_relocate_address): Apply main.bias, not - debug.bias. - -2008-12-11 Roland McGrath <roland@redhat.com> - - * offline.c (process_archive): Don't call elf_end and close if - returning NULL. Check first elf_begin call and set error code - specially for empty archive. - Fixes RHBZ#465878. - -2008-12-02 Roland McGrath <roland@redhat.com> - - * dwfl_getmodules.c (dwfl_getmodules): Typo fix in last change. - -2008-11-26 Roland McGrath <roland@redhat.com> - - * dwfl_getmodules.c (dwfl_getmodules): Encode iteration style in - return value, and interpret encoded OFFSET argument. - -2008-10-07 Roland McGrath <roland@redhat.com> - - * dwfl_module_build_id.c (check_notes): Fix typo in vaddr calculation. - -2008-09-29 Roland McGrath <roland@redhat.com> - - * segment.c (insert): Must realloc DWFL->lookup_module here too. - (dwfl_report_segment): Clear DWFL->lookup_module before insert calls. - -2008-08-28 Roland McGrath <roland@redhat.com> - - * segment.c (reify_segments): Fix last change. - -2008-08-27 Roland McGrath <roland@redhat.com> - - * linux-proc-maps.c (read_proc_memory): Return 0 for EINVAL or EPERM - failure from pread64. - -2008-08-26 Roland McGrath <roland@redhat.com> - - * segment.c (reify_segments): Insert a trailing segment for a module - end that is above the highest current segment. - -2008-08-25 Roland McGrath <roland@redhat.com> - - * dwfl_module_getdwarf.c (open_elf): Extract elf_errno () for - coded return value, not plain DWFL_E_LIBELF. Return DWFL_E_BADELF - if FILE->elf is not ELF_K_ELF. - - * dwfl_segment_report_module.c: Add a cast. - -2008-08-21 Denys Vlasenko <dvlasenk@redhat.com> - - * dwfl_module_addrsym.c (dwfl_module_addrsym): Improve logic - which decides which symbol is "closest" to a given address. - -2008-08-15 Roland McGrath <roland@redhat.com> - - * argp-std.c (offline_callbacks): Use dwfl_build_id_find_elf. - (options, parse_opt): Handle --core. - - * core-file.c: New file. - * Makefile.am (libdwfl_a_SOURCES): Add it. - * libdwflP.h (dwfl_core_file_report): Declare it. - - * link_map.c: New file. - * Makefile.am (libdwfl_a_SOURCES): Add it. - * libdwflP.h (dwfl_link_map_report): Declare it. - - * libdwflP.h (MIN, MAX): New macros. - (Dwfl_Memory_Callback): New typedef. - (Dwfl_Module_Callback): New typedef. - (dwfl_segment_report_module): Declare it. - * dwfl_segment_report_module.c: New file. - * Makefile.am (libdwfl_a_SOURCES): Add it. - - * derelocate.c (dwfl_module_address_section): Add INTDEF. - * libdwflP.h: Add INTDECL. - - * segment.c: New file. - * Makefile.am (libdwfl_a_SOURCES): Add it. - * libdwfl.h: Declare dwfl_addrsegment, dwfl_report_segment. - * libdwflP.h (struct Dwfl): New members lookup_elts, lookup_alloc, - lookup_addr, lookup_module, lookup_segndx, replace removed members - modules, nmodules. - (struct Dwfl_Module): New member segment. - * dwfl_end.c (dwfl_end): Free the new ones. Iterate via modulelist - to each free module. - * dwfl_module.c (dwfl_report_begin_add): Do nothing. - (dwfl_report_begin): Don't call it. Truncate the segment table instead. - (dwfl_report_module): Don't touch DWFL->nmodules. - (dwfl_report_end): Don't touch DWFL->modules and DWFL->nmodules. - (compare_modules): Function removed. - * dwfl_getmodules.c: Rewritten. - Add INTDEF. - * libdwflP.h: Add INTDECLs. - * dwfl_getdwarf.c: Rewritten to call dwfl_getmodules. - * dwfl_addrmodule.c: Rewritten to just call dwfl_addrsegment. - -2008-08-03 Roland McGrath <roland@redhat.com> - - * linux-kernel-modules.c: Include <fts.h> before <config.h>. - -2008-07-17 Roland McGrath <roland@redhat.com> - - * dwfl_build_id_find_elf.c (__libdwfl_open_by_build_id): Set errno to - zero if the failure was only ENOENT. - -2008-06-03 Roland McGrath <roland@redhat.com> - - * dwfl_module_addrsym.c (dwfl_module_addrsym): Exclude undefined - symbols. - -2008-05-22 Petr Machata <pmachata@redhat.com> - - * dwfl_module_getdwarf.c (open_elf): Bias of ET_EXEC files is always 0. - -2008-05-06 Roland McGrath <roland@frob.com> - - * linux-kernel-modules.c (dwfl_linux_kernel_report_offline): Use - FTS_LOGICAL here too. - (dwfl_linux_kernel_find_elf): Likewise. - -2008-04-29 Roland McGrath <roland@redhat.com> - - * find-debuginfo.c (dwfl_standard_find_debuginfo): Try path search - based on canonicalize_file_name if it differs from the supplied name. - - * linux-kernel-modules.c (check_module_notes): Use FTS_LOGICAL so - we accept symlinks. - -2008-04-27 Roland McGrath <roland@redhat.com> - - * linux-kernel-modules.c (report_kernel): Fix crash when - dwfl_report_elf fails. - -2008-04-05 Roland McGrath <roland@redhat.com> - - * linux-proc-maps.c (proc_maps_report): Don't leak LAST_FILE. - - * dwfl_module_getdwarf.c (find_file): Always free build_id_bits. - Clear it after freeing. - * dwfl_module_report_build_id.c (dwfl_module_report_build_id): Likewise. - -2008-03-26 Roland McGrath <roland@redhat.com> - - * dwfl_module_getdwarf.c (load_symtab): Don't return success for - SHT_DYNSYM, just set *SYMSCN like the comment says. - - * dwfl_end.c (dwfl_end): Iterate on modulelist chain, not modules array. - - * argp-std.c (parse_opt): On failure, call dwfl_end before argp_failure. - -2008-03-19 Roland McGrath <roland@redhat.com> - - * dwfl_module_getsrc.c: Adjust address for module bias before search. - -2008-03-01 Roland McGrath <roland@redhat.com> - - * libdwflP.h (__libdwfl_seterrno): Remove parameter name from - prototype to avoid older compiler's complaint about reuse of the name. - (__libdwfl_canon_error): Likewise. - -2008-02-19 Roland McGrath <roland@redhat.com> - - * relocate.c (relocate_section): Check for an unhandled relocation - type before resolving a reloc's symbol. Lift DWFL_E_BADRELTYPE -> - DWFL_E_UNKNOWN_MACHINE check out of loops. - - * dwfl_module_getdwarf.c (load_dw): Skip relocation if - DEBUGFILE->relocated is already set. - -2008-01-26 Roland McGrath <roland@redhat.com> - - * dwfl_module_getdwarf.c (open_elf): Open FILE->name if it's non-null. - - * dwfl_build_id_find_elf.c (__libdwfl_open_by_build_id): Don't clear - incoming *FILE_NAME at the start. - -2008-01-08 Roland McGrath <roland@redhat.com> - - * Makefile.am (euinclude): Variable removed. - (pkginclude_HEADERS): Set this instead of euinclude_HEADERS. - -2007-10-23 Roland McGrath <roland@redhat.com> - - * linux-kernel-modules.c (report_kernel_archive): Reorder the kernel - module to appear first. - -2007-10-20 Roland McGrath <roland@redhat.com> - - * offline.c (process_archive_member): Take FD argument, pass it down - to process_file. Return Elf_Cmd, not bool. - Call elf_next here, always before elf_end. - (process_archive): Update caller. Don't close FD here unless there - are no member refs. - - * dwfl_module.c (free_file): Close fd only when elf_end returns zero. - - * libdwflP.h (struct dwfl_file): New bool member `relocated'. - * dwfl_module_getdwarf.c (dwfl_module_getelf): For ET_REL, apply - partial relocation to one or both files. - (dwfl_module_getdwarf): For ET_REL, make sure extra sections' - relocations have been applied to the debug file if dwfl_module_getelf - has been used before. - - * relocate.c (resolve_symbol): New function. - (relocate_section): Call it. - - * relocate.c (relocate_getsym): Handle null MOD->symfile. - (relocate_section): Take new bool arg, PARTIAL. If true, - no error for BADRELTYPE/RELUNDEF, instead just skip them - and leave only those skipped relocs behind the reloc section. - (__libdwfl_relocate_section): Take new arg, pass it down. - (__libdwfl_relocate): Take new bool arg, DEBUG. If false, - do partial relocation on all sections. - * dwfl_module_getdwarf.c (load_dw): Update caller. - * libdwflP.h: Update decls. - * derelocate.c (dwfl_module_address_section): Pass new argument - to __libdwfl_relocate_section, true. - - * derelocate.c (cache_sections): Don't cache reloc sections when - section_address callback is null. - -2007-10-19 Roland McGrath <roland@redhat.com> - - * relocate.c (relocate_section): Fix fencepost error in r_offset check. - - * derelocate.c (struct dwfl_relocation): Add member `relocs'. - (struct secref): Likewise. - (cache_sections): Cache the relocation section referring to each - section we cache, if any. - (dwfl_module_address_section): Use __libdwfl_relocate_section as - necessary. - - * relocate.c (struct reloc_symtab_cache): New type. - (relocate_getsym): Use it instead of four arguments. - (__libdwfl_relocate): Update caller. - (relocate_section): New function, broken out of ... - (__libdwfl_relocate): ... here. - (__libdwfl_relocate_section): New function. - * libdwflP.h: Declare it. - -2007-10-17 Roland McGrath <roland@redhat.com> - - * dwfl_module_getsym.c (dwfl_module_getsym): Apply MOD->symfile->bias - to relocated st_value. - - * dwfl_report_elf.c (__libdwfl_report_elf): Align initial BASE for - ET_REL to 0x100. - -2007-10-16 Roland McGrath <roland@redhat.com> - - * dwfl_report_elf.c (__libdwfl_report_elf): Readjust BASE when a later - section has larger alignment requirements not met by the original BASE, - rather than padding more between sections. - - * dwfl_report_elf.c (__libdwfl_report_elf): Fix bias calculation. - - * dwfl_module_build_id.c (__libdwfl_find_build_id): Apply module bias - to sh_addr value. - - * dwfl_report_elf.c (__libdwfl_report_elf): Don't be confused by BASE - at zero in ET_REL case. Adjust BASE to necessary alignment. - - * dwfl_module_build_id.c (check_notes): Take -1, not 0, as stub value - for DATA_VADDR. - (__libdwfl_find_build_id): Update caller. - - * relocate.c (__libdwfl_relocate_value): Don't use sh_offset. - * dwfl_report_elf.c (__libdwfl_report_elf): Likewise. - * offline.c (dwfl_offline_section_address): Bail early if there is - separate debug file. - - * relocate.c (__libdwfl_relocate): Don't return DWFL_E_NO_DWARF. - -2007-10-09 Roland McGrath <roland@redhat.com> - - * dwfl_report_elf.c (__libdwfl_report_elf): Clear SHDR->sh_offset when - caching SHDR->sh_addr = 0. - * offline.c (dwfl_offline_section_address): Never called for sh_addr - really at 0, don't check for it. Use MOD->debug directly, not symfile. - - * dwfl_module_getdwarf.c (load_symtab): Return success properly when - we've found SHT_SYMTAB. - - * relocate.c (relocate_getsym): New function. - (__libdwfl_relocate): Use it. - (__libdwfl_relocate_value): Take new Elf * argument. Make SYMSHSTRNDX - be a pointer instead of value; cache getshstrndx result there. - * libdwflP.h: Update decl. - * derelocate.c (cache_sections): Update caller. - Always work on the main file, not the symfile. - (dwfl_module_address_section): Likewise. - * dwfl_module_getsym.c (dwfl_module_getsym): Update caller. - -2007-10-07 Roland McGrath <roland@redhat.com> - - * offline.c (process_archive): Initialize MOD. - - * linux-kernel-modules.c (get_release): New function, broken out of ... - (report_kernel): ... here. Call it. - (try_kernel_name): Take new arg TRY_DEBUG, only try ".debug" if set. - (find_kernel_elf): Update caller. - (report_kernel_archive): New function. - (dwfl_linux_kernel_report_offline): Call it. - - * offline.c (process_file): Take new arg PREDICATE, pass it down. - (process_archive): Likewise. - (process_archive_member): Likewise. When nonnull, let the predicate - decide whether to use this member. - (__libdwfl_report_offline): New function, broken out of ... - (dwfl_report_offline): ... here. Call it. - * libdwflP.h: Declare it. - - * offline.c (process_archive, process_archive_member): New functions. - (process_elf, process_file): New functions, broken out of ... - (dwfl_report_offline): ... here. Call process_file, which recurses on - ELF_K_AR files. - - * dwfl_report_elf.c (__libdwfl_report_elf): New, broken out of ... - (dwfl_report_elf): ... here. Call it. - * libdwflP.h: Declare it. - -2007-10-06 Roland McGrath <roland@redhat.com> - - * derelocate.c (dwfl_module_relocations): Don't call - dwfl_module_getdwarf. - - * derelocate.c (find_section): Use __libdwfl_seterrno, not - __libdw_seterrno. - - * relocate.c (__libdwfl_relocate_value): Abuse sh_offset, not - SHF_ALLOC, to cache sh_addr resolved to 0. - - * dwfl_report_elf.c (dwfl_report_elf): When an ET_REL file has sh_addr - values nonzero already, just use its existing layout. - - * relocate.c (__libdwfl_relocate): Clear size of reloc section in its - in-core shdr after applying it. - -2007-10-04 Ulrich Drepper <drepper@redhat.com> - - * linux-kernel-modules.c (dwfl_linux_kernel_report_kernel): Fake - initialization of notes variable. - -2007-10-04 Roland McGrath <roland@redhat.com> - - * linux-kernel-modules.c (intuit_kernel_bounds): Take new arg NOTES, - fill in with vaddr of "__start_notes" symbol if found. - (check_notes): New function. - (check_kernel_notes): New function. - (dwfl_linux_kernel_report_kernel): Call it. - (check_module_notes): New function. - (dwfl_linux_kernel_report_modules): Call it. - - * linux-kernel-modules.c (dwfl_linux_kernel_find_elf): - Try dwfl_build_id_find_elf first. - - * linux-kernel-modules.c (report_kernel): Don't leak FD if !REPORT. - Set kernel module e_type to ET_DYN. - -2007-10-03 Roland McGrath <roland@redhat.com> - - * find-debuginfo.c (validate): New function, broken out of ... - (find_debuginfo_in_path): ... here. New function, broken out of ... - (dwfl_standard_find_debuginfo): ... here. Call it, after trying - dwfl_build_id_find_debuginfo first. - - * dwfl_build_id_find_elf.c: New file. - * dwfl_build_id_find_debuginfo.c: New file. - * Makefile.am (libdwfl_a_SOURCES): Add them. - * libdwfl.h: Declare them. - * libdwflP.h: Add INTDECLs. - - * dwfl_module_build_id.c: New file. - * dwfl_module_report_build_id.c: New file. - * Makefile.am (libdwfl_a_SOURCES): Add them. - * libdwfl.h: Declare them. - * libdwflP.h (struct Dwfl_Module): New members build_id_bits, - build_id_len, build_id_vaddr. Declare __libdwfl_find_build_id. - * dwfl_module.c (__libdwfl_module_free): Free MOD->build_id_bits. - - * dwfl_module_getdwarf.c (find_offsets): New function. - (find_dynsym): New function, calls that. - (find_symtab): Call it. - -2007-09-11 Roland McGrath <roland@redhat.com> - - * dwfl_module_addrsym.c: Prefer a later global symbol at the same - address if its st_size is smaller. - -2007-08-13 Roland McGrath <roland@redhat.com> - - * dwfl_module_addrsym.c: Add dead initializer for stupid compiler. - -2007-08-12 Roland McGrath <roland@redhat.com> - - * linux-kernel-modules.c (dwfl_linux_kernel_report_offline): Don't use - FTS_LOGICAL. - - * elf-from-memory.c (elf_from_remote_memory): Don't reset LOADBASE on - a second phdr if it happens to match EHDR_VMA exactly. - -2007-08-08 Roland McGrath <roland@redhat.com> - - * dwfl_module_addrsym.c: Don't use STT_SECTION, STT_FILE symbols and - those with no names. Rewrite best symbol algorithm not to assume a - sorted table and to be smarter handling sizeless symbols. - -2007-07-16 Roland McGrath <roland@redhat.com> - - * dwfl_module.c (dwfl_report_module): Increment DWFL->nmodules when - reviving an existing module. - -2007-06-08 Roland McGrath <roland@redhat.com> - - * libdwflP.h: Fix #ifndef for config.h to use PACKAGE_NAME. - -2007-05-17 Roland McGrath <roland@redhat.com> - - * linux-kernel-modules.c (dwfl_linux_kernel_report_offline): Look at - whole /lib/modules/VERSION tree, not just /lib/modules/VERSION/kernel. - (dwfl_linux_kernel_find_elf): Likewise. - - * linux-kernel-modules.c (dwfl_linux_kernel_report_modules): Use - getline and sscanf instead of fscanf. - -2007-05-08 Roland McGrath <roland@redhat.com> - - * offline.c (dwfl_offline_section_address): Don't assume section - numbers match between stripped and debuginfo files. Instead, assume - only that the ordering among SHF_ALLOC sections matches. - - * linux-kernel-modules.c (report_kernel): Change RELEASE argument to - pointer to string. - (dwfl_linux_kernel_report_offline): Update caller. - (dwfl_linux_kernel_report_kernel): Likewise. - -2007-04-23 Roland McGrath <roland@redhat.com> - - * argp-std.c (options): Fix group title string. - - * argp-std.c (parse_opt): Handle ARGP_KEY_ERROR, free the Dwfl. - Update via STATE->input every time we set STATE->hook, not only at - ARGP_KEY_SUCCESS. - - * dwfl_module.c (free_file): Free FILE->name. - -2007-04-16 Roland McGrath <roland@redhat.com> - - * derelocate.c (cache_sections): Apply bias to sh_addr. - (compare_secrefs): Fix address comparison to avoid signed overflow. - (find_section): New function, broken out of ... - (dwfl_module_relocate_address): ... here, call it. - (check_module): New function, broken out of ... - (dwfl_module_relocate_address): ... here, call it. - (dwfl_module_address_section): New function. - * libdwfl.h: Declare it. - -2007-03-26 Roland McGrath <roland@redhat.com> - - * dwfl_module.c (__libdwfl_module_free): Free MOD itself. - -2007-03-18 Roland McGrath <roland@redhat.com> - - * dwfl_module_getdwarf.c (find_debuglink): New function, broken out of - (find_debuginfo): ... here. Call it. - Don't return error for libelf errors finding .gnu_debuglink section. - -2007-03-12 Roland McGrath <roland@redhat.com> - - * dwfl_module.c (dwfl_report_begin_add): New function broken out of ... - (dwfl_report_begin): ... here. Call it. - * libdwfl.h: Declare it. - * libdwflP.h: Add INTDECL. - - * elf-from-memory.c (elf_from_remote_memory): Fix 32/64 typo. - - * offline.c: Comment typo fix. - -2007-03-04 Roland McGrath <roland@redhat.com> - - * linux-kernel-modules.c (KERNEL_MODNAME): New macro for "kernel". - (find_kernel_elf): New function, broken out of ... - (report_kernel): ... here. Call it. - (dwfl_linux_kernel_find_elf): Use it for module named KERNEL_MODNAME. - (intuit_kernel_bounds): New function, grovel /proc/kallsyms to guess - virtual address bounds of kernel from symbols rounded to page size. - (dwfl_linux_kernel_report_kernel): Use that if it works, before - resorting to report_kernel. - - * dwfl_module_getdwarf.c (open_elf): Set MOD->e_type to ET_DYN for an - ET_EXEC file with nonzero bias. - - * dwfl_module_addrname.c (dwfl_module_addrname): Just call - dwfl_module_addrsym. Guts moved to ... - * dwfl_module_addrsym.c: ... here; new file. - * Makefile.am (libdwfl_a_SOURCES): Add it. - * libdwfl.h: Declare dwfl_module_addrsym. - * libdwflP.h: Add INTDECL. - -2007-03-03 Roland McGrath <roland@redhat.com> - - * dwfl_module.c (free_file): New function, broken out of ... - (__libdwfl_module_free): ... here. In it, close fd after elf_end. - - * dwfl_module_getdwarf.c (open_elf): Close fd and reset to -1 - on libelf failure. - -2007-03-02 Roland McGrath <roland@redhat.com> - - * linux-kernel-modules.c: Fix bogus error test for asprintf call. - -2007-02-02 Roland McGrath <roland@redhat.com> - - * dwfl_addrmodule.c (dwfl_addrmodule): Match a module's high boundary - address exactly if it's no other module's low boundary. - - * dwfl_module_addrname.c (dwfl_module_addrname): If no symbol's value - and size cover the address, select the closest symbol with st_size==0 - that lies in the same section. - -2007-01-29 Roland McGrath <roland@redhat.com> - - * dwfl_version.c (dwfl_version): Return PACKAGE_VERSION, - not PACKAGE_STRING. - -2007-01-20 Roland McGrath <roland@redhat.com> - - * relocate.c (__libdwfl_relocate_value): Treat section_address of -1 - as omitted, not 0. - * libdwfl.h (Dwfl_Callbacks): Update comment. - * derelocate.c (cache_sections): Don't ignore sh_addr == 0 sections. - * linux-kernel-modules.c (dwfl_linux_kernel_module_section_address): - For ignored missing section, use -1 instead of 0. - * offline.c (dwfl_offline_section_address): Expect a call for 0. - -2007-01-19 Roland McGrath <roland@redhat.com> - - * argp-std.c (parse_opt): For -e, reset DWFL->offline_next_address to - zero so a lone -e foo.so is shown without address bias. - -2007-01-10 Roland McGrath <roland@redhat.com> - - * linux-kernel-modules.c (report_kernel): Check asprintf return value - directly instead of via side effect, to silence warn_unused_result. - (dwfl_linux_kernel_report_offline): Likewise. - (dwfl_linux_kernel_find_elf): Likewise. - (dwfl_linux_kernel_module_section_address): Likewise. - * find-debuginfo.c (try_open): Likewise. - * linux-proc-maps.c (find_sysinfo_ehdr): Likewise. - (dwfl_linux_proc_report): Likewise. - - * libdwfl.h (dwfl_begin): Require nonnull argument. - -2006-12-27 Roland McGrath <roland@redhat.com> - - * dwfl_module.c (compare_modules): Fix address comparison to avoid - signed overflow. Patch by Frank Ch. Eigler <fche@redhat.com>. - -2006-10-30 Roland McGrath <roland@redhat.com> - - * dwfl_module.c (dwfl_report_module): Comment typo fix. - -2006-09-05 Roland McGrath <roland@redhat.com> - - * derelocate.c (cache_sections): Use alloca instead of variable-sized - auto array, in function already using alloca. - -2006-08-14 Roland McGrath <roland@redhat.com> - - * linux-kernel-modules.c (try_kernel_name): If the call to - dwfl_standard_find_debuginfo produces no results, try it again - with NULL as DEBUGLINK_FILE to try *FNAME with .debug suffix. - - * find-debuginfo.c (DEFAULT_DEBUGINFO_PATH): Macro moved ... - * libdwflP.h: ... to here. - * linux-kernel-modules.c (try_kernel_name): Skip manual open if it - repeats the first thing dwfl_standard_find_debuginfo will try. - - * linux-kernel-modules.c (MODULE_SECT_NAME_LEN): New macro. - (dwfl_linux_kernel_module_section_address): If a /sys file is missing - and the section name is >= MODULE_SECT_NAME_LEN, try truncating the - section name. - -2006-07-12 Ulrich Drepper <drepper@redhat.com> - - * cu.c: Adjust for internal_function_def removal. - * dwfl_error.c: Likewise. - * dwfl_module.c: Likewise. - * dwfl_module_getdwarf.c: Likewise. - * lines.c: Likewise. - * relocate.c: Likewise. - -2006-07-11 Ulrich Drepper <drepper@redhat.com> - - * dwfl_module.c (compare_modules): Don't return GElf_Sxword value, - it can overflow the return value type. - Patch by Tim Moore <timoore@redhat.com>. - -2006-06-28 Roland McGrath <roland@redhat.com> - - * libdwfl.h: Cosmetic changes. - - * dwfl_line_comp_dir.c: New file. - * Makefile.am (libdwfl_a_SOURCES): Add it. - * libdwfl.h: Declare dwfl_line_comp_dir. - - * dwfl_lineinfo.c (dwfl_lineinfo): Remove stray extern in defn. - - * dwfl_linecu.c: New file. - * Makefile.am (libdwfl_a_SOURCES): Add it. - * libdwfl.h: Declare dwfl_linecu. - - * libdwflP.h (dwfl_linecu_inline): Function renamed from dwfl_linecu. - (dwfl_linecu): Define as macro. - - * relocate.c (__libdwfl_relocate): Use dwfl_module_getsym. - - * dwfl_module_getdwarf.c (dwfl_module_getsymtab): New function. - (dwfl_module_addrname): Function moved ... - * dwfl_module_addrname.c: ... here, new file. - * dwfl_module_getsym.c: New file. - * Makefile.am (libdwfl_a_SOURCES): Add them. - * libdwfl.h: Declare dwfl_module_getsymtab, dwfl_module_getsym. - * libdwflP.h: Add INTDECLs. - -2006-06-27 Roland McGrath <roland@redhat.com> - - * dwfl_module.c (dwfl_report_end): Whitespace fix. - -2006-06-13 Roland McGrath <roland@redhat.com> - - * elf-from-memory.c (elf_from_remote_memory): Fix 32/64 typo. - Use __libdwfl_seterrno for elf_memory failure. - -2006-05-22 Roland McGrath <roland@redhat.com> - - * dwfl_module_return_value_location.c - (dwfl_module_return_value_location): Use __libdwfl_module_getebl. - -2006-05-27 Ulrich Drepper <drepper@redhat.com> - - * libdwfl.h: Add extern "C". - -2006-05-22 Ulrich Drepper <drepper@redhat.com> - - * cu.c (addrarange): Handle files without aranges information. - -2006-05-16 Ulrich Drepper <drepper@redhat.com> - - * dwfl_addrmodule.c (dwfl_addrmodule): Also return NULL of - ->modules is NULL. - -2006-02-26 Roland McGrath <roland@redhat.com> - - * dwfl_version.c: New file. - * Makefile.am (libdwfl_a_SOURCES): Add it. - * libdwfl.h: Declare dwfl_version. - - * offline.c (dwfl_report_offline): Account for dwfl_report_elf having - aligned up from DWFL->offline_next_address when checking for overlap. - -2005-12-22 Roland McGrath <roland@redhat.com> - - * argp-std.c (parse_opt): Call dwfl_end in failure cases. - - * linux-proc-maps.c (proc_maps_report): New function, broken out of ... - (dwfl_linux_proc_report): ... here. Call it. - (dwfl_linux_proc_maps_report): New function. - * libdwfl.h: Declare it. - * libdwflP.h: Add INTDECL. - * argp-std.c (options, parse_opt): Grok -M/--linux-process-map. - - * dwfl_nextcu.c (dwfl_nextcu): Don't fail when dwfl_module_getdwarf - failed with DWFL_E_NO_DWARF. - -2005-11-26 Roland McGrath <roland@redhat.com> - - * dwfl_end.c (dwfl_end): Free the DWFL itself. - -2005-11-25 Roland McGrath <roland@redhat.com> - - * dwfl_module_getdwarf.c (__libdwfl_module_getebl): New function. - (load_dw): Use it. - * dwfl_module_register_names.c (dwfl_module_register_names): Likewise. - * libdwflP.h: Declare it. - - * dwfl_module_register_names.c: New file. - * Makefile.am (libdwfl_a_SOURCES): Add it. - * libdwfl.h: Declare dwfl_module_register_names. - -2005-11-21 Roland McGrath <roland@redhat.com> - - * linux-kernel-modules.c (dwfl_linux_kernel_module_section_address): - Don't leak malloc'd file name. - If a /sys/.../sections file is missing and starts with ".init", - try the variant with "_init" too; catches PPC64 kernel braindamage. - -2005-11-15 Roland McGrath <roland@redhat.com> - - * libdwfl.h: Comment fixes. - - * dwfl_module_return_value_location.c: Add unlikely for error case. - -2005-11-13 Roland McGrath <roland@redhat.com> - - * dwfl_return_value_location.c: New file. - * Makefile.am (libdwfl_a_SOURCES): Add it. - * libdwfl.h: Declare dwfl_module_return_value_location. - * libdwflP.h (DWFL_ERRORS): Add DWFL_E_WEIRD_TYPE. - -2005-10-20 Roland McGrath <roland@redhat.com> - - * libdwflP.h (DWFL_ERRORS): New error UNKNOWN_MACHINE. - * relocate.c (__libdwfl_relocate): Return DWFL_E_UNKNOWN_MACHINE - instead of DWFL_E_BADRELTYPE if ebl_get_elfmachine yields EM_NONE. - -2005-10-01 Roland McGrath <roland@redhat.com> - - * linux-kernel-modules.c (report_kernel): Return ENOENT if we fail - with errno 0. - -2005-09-19 Roland McGrath <roland@redhat.com> - - * linux-kernel-modules.c (dwfl_linux_kernel_report_modules): Use - PRIx64 instead of PRIi64, lest addresses with high bits set overflow - the signed integer reading; they will just have to be in hexadecimal. - (dwfl_linux_kernel_module_section_address): Likewise. - -2005-08-28 Ulrich Drepper <drepper@redhat.com> - - * Makefile.am (%.os): Use COMPILE.os. - (COMPILE.os): Filter out gconv options. - -2005-08-25 Roland McGrath <roland@redhat.com> - - * cu.c (__libdwfl_nextcu): Return success when dwarf_nextcu hits end. - * dwfl_nextcu.c (dwfl_nextcu): Skip modules with no dwarf info. - -2005-08-24 Roland McGrath <roland@redhat.com> - - * dwfl_lineinfo.c (dwfl_lineinfo): Add bias, don't subtract it. - - * argp-std.c [_MUDFLAP] (__libdwfl_argp_mudflap_options): New function, - magic initializer to set -heur-stack-bound option. - -2005-08-22 Roland McGrath <roland@redhat.com> - - * dwfl_validate_address.c: New file. - * Makefile.am (libdwfl_a_SOURCES): Add it. - * libdwfl.h: Declare dwfl_validate_address. - - * derelocate.c (dwfl_module_relocate_address): Add INTDEF. - * libdwflP.h: Add INTDECL. - - * dwfl_module_getdwarf.c (find_symtab): Use elf_getdata instead of - elf_rawdata for symbol-related sections. - - * offline.c (dwfl_report_offline): Move offline_next_address outside - module's range, in case it's an ET_EXEC using fixed segment locations. - * libdwfl.h: Update comment. - - * dwfl_report_elf.c (dwfl_report_elf): Align BASE to first segment's - required alignment. - -2005-08-20 Roland McGrath <roland@redhat.com> - - * linux-kernel-modules.c (report_kernel): Take new argument PREDICATE, - function to choose whether to report. - (dwfl_linux_kernel_report_offline): Likewise. - * libdwfl.h: Update decl. - * argp-std.c (parse_opt): Update caller. - - * dwfl_getsrclines.c: New file. - * dwfl_onesrcline.c: New file. - * Makefile.am (libdwfl_a_SOURCES): Add them. - * libdwfl.h: Declare dwfl_getsrclines, dwfl_onesrcline. - - * linux-kernel-modules.c (dwfl_linux_kernel_find_elf): Don't leak - MODULESDIR[0]. Call fts_close on failure. - - * dwfl_module_getdwarf.c (load_dw): Take dwfl_file * instead of Elf *. - Close ET_REL file descriptors after relocation. - (find_dw): Update caller. - * offline.c (dwfl_report_offline): Get the file into memory and close - the file descriptor. - - * dwfl_module_getdwarf.c (find_debuginfo): Do nothing when - MOD->debug.elf is already set. - - * find-debuginfo.c (try_open): Use TEMP_FAILURE_RETRY. - (dwfl_standard_find_debuginfo): Fail on errors not ENOENT or ENOTDIR. - - * argp-std.c (options, parse_opt): Grok -K/--offline-kernel, use - dwfl_linux_kernel_report_offline with offline_callbacks. - - * linux-kernel-modules.c (report_kernel): New function, broken out of - ... - (dwfl_linux_kernel_report_kernel): ... here. Use it. - (dwfl_linux_kernel_report_offline): New function. - * libdwfl.h: Declare it. - * libdwflP.h: Add INTDECL. - -2005-08-19 Roland McGrath <roland@redhat.com> - - Use standard debuginfo search path to look for vmlinux. - * find-debuginfo.c (dwfl_standard_find_debuginfo): Don't check CRC if - passed zero. - * linux-kernel-modules.c (try_kernel_name): New function, broken out - of ... - (dwfl_linux_kernel_report_kernel): ... here. Use it. - - * argp-std.c (offline_callbacks): New variable. - (parse_opt): Use it for -e. Allow multiple -e options. - - * offline.c: New file. - * Makefile.am (libdwfl_a_SOURCES): Add it. - * libdwfl.h: Declare dwfl_offline_section_address, dwfl_report_offline. - * libdwflP.h: Add INTDECLs. - (OFFLINE_REDZONE): New macro. - (struct Dwfl): New member `offline_next_address'. - * dwfl_begin.c (dwfl_begin): Initialize it. - * dwfl_module.c (dwfl_report_begin): Likewise. - - * dwfl_report_elf.c (dwfl_report_elf): Accept all types. When ET_REL, - do a nominal absolute section layout starting at BASE. - * libdwfl.h: Update comment. - -2005-08-18 Roland McGrath <roland@redhat.com> - - * dwfl_module_getsrc_file.c (dwfl_module_getsrc_file): Do - dwfl_module_getdwarf if necessary. - - * dwfl_report_elf.c (dwfl_report_elf): Permit ET_REL with BASE==0. - * libdwfl.h: Update comment. - - * derelocate.c: New file. - * Makefile.am (libdwfl_a_SOURCES): Add it. - - * libdwflP.h (struct Dwfl_Module): isrel -> e_type. - * dwfl_report_elf.c (dwfl_report_elf): Initialize it. - * dwfl_module_getdwarf.c (open_elf): Update initialization. - (load_dw, dwfl_module_addrname): Update uses. - * relocate.c (__libdwfl_relocate): Likewise. - -2005-08-04 Roland McGrath <roland@redhat.com> - - * libdwfl.h (Dwfl_Callbacks.section_address): Take additional - arguments SHNDX, SHDR. - (dwfl_linux_kernel_module_section_address): Update prototype. - * relocate.c (__libdwfl_relocate_value): Update caller. - * linux-kernel-modules.c (dwfl_linux_kernel_module_section_address): - Take the new arguments. - -2005-08-10 Roland McGrath <roland@redhat.com> - - * relocate.c (__libdwfl_relocate): Take argument DEBUGFILE, - use it instead of MOD->debug.file. - * libdwflP.h: Update decl. - * dwfl_module_getdwarf.c (load_dw): Update caller. - Fixes bug #165598. - -2005-08-09 Roland McGrath <roland@redhat.com> - - * libdwflP.h: Include ../libdw/libdwP.h for its INTDECLs. - * cu.c: Use INTUSE on dwarf_* calls. - * dwfl_error.c: Likewise. - * dwfl_module.c: Likewise. - * dwfl_module_getdwarf.c: Likewise. - * dwfl_module_getsrc_file.c: Likewise. - * lines.c: Likewise. - -2005-08-07 Roland McGrath <roland@redhat.com> - - * linux-kernel-modules.c (dwfl_linux_kernel_find_elf): When module - names contain '_' or '-', look for files named either "foo-bar.ko" - or "foo_bar.ko". - -2005-07-29 Roland McGrath <roland@redhat.com> - - * loc2c.c: File removed. - * loc2c.h: File removed. - * loc2c-runtime.h: File removed. - * test2.c: File removed. - * Makefile.am (EXTRA_DIST): Variable removed. - (noinst_HEADERS): Remove loc2c.h from here. - -2005-07-28 Ulrich Drepper <drepper@redhat.com> - - * libdwfl.h: Add a few missing extern for function prototypes. - - * libdwfl_crc32.c: New file. - * libdwfl_crc32_file.c: New file. - * libdwflP.h: Declare the new functions. - * Makefile.am (libdwfl_a_SOURCES): Add libdwfl_crc32.c and - libdwfl_crc32_file.c. - * libdwfl/find-debuginfo.c (check_crc): Use __libdwfl_crc32_file - instead of crc32_file. - -2005-07-28 Roland McGrath <roland@redhat.com> - - * ptest.c: Moved to ../tests/dwflmodtest.c. - - * Makefile.am (noinst_PROGRAMS): Variable removed. - (libdwfl_so_SOURCES, libdwfl_LIBS, libdwfl_so_LDADD): Likewise. - (EXTRA_DIST, ptest_LDADD, test2_LDADD): Likewise. - (libdwfl): Don't use libdwfl.so any more. - (libdwfl.so, install, uninstall): Targets removed. - (test2_SOURCES): Define EXTRA_DIST instead of this. - * libdwfl.map: File removed. - - * libdwfl.h: Use "" for libdw.h #include. - -2005-07-27 Roland McGrath <roland@redhat.com> - - * libdwfl.map: Add dwfl_getmodules. - -2005-07-23 Ulrich Drepper <drepper@redhat.com> - - * Makefile.am: Fix rules to allow building with mudflap. - -2005-07-21 Roland McGrath <roland@redhat.com> - - * Makefile.am (noinst_HEADERS): Add loc2c.c. - - * test2.c (main): Check sscanf result to quiet warning. - -2005-07-20 Roland McGrath <roland@redhat.com> - - * libdwfl-branch merged, creating this direcotry. diff --git a/src/libdwfl/Makefile b/src/libdwfl/Makefile deleted file mode 100644 index 48180b24..00000000 --- a/src/libdwfl/Makefile +++ /dev/null @@ -1,801 +0,0 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. -# libdwfl/Makefile. Generated from Makefile.in by configure. - -# Copyright (C) 1994-2013 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. - - - - - -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' -am__make_running_with_option = \ - case $${target_option-} in \ - ?) ;; \ - *) echo "am__make_running_with_option: internal error: invalid" \ - "target option '$${target_option-}' specified" >&2; \ - exit 1;; \ - esac; \ - has_opt=no; \ - sane_makeflags=$$MAKEFLAGS; \ - if $(am__is_gnu_make); then \ - sane_makeflags=$$MFLAGS; \ - else \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - bs=\\; \ - sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ - | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ - esac; \ - fi; \ - skip_next=no; \ - strip_trailopt () \ - { \ - flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ - }; \ - for flg in $$sane_makeflags; do \ - test $$skip_next = yes && { skip_next=no; continue; }; \ - case $$flg in \ - *=*|--*) continue;; \ - -*I) strip_trailopt 'I'; skip_next=yes;; \ - -*I?*) strip_trailopt 'I';; \ - -*O) strip_trailopt 'O'; skip_next=yes;; \ - -*O?*) strip_trailopt 'O';; \ - -*l) strip_trailopt 'l'; skip_next=yes;; \ - -*l?*) strip_trailopt 'l';; \ - -[dEDm]) skip_next=yes;; \ - -[JT]) skip_next=yes;; \ - esac; \ - case $$flg in \ - *$$target_option*) has_opt=yes; break;; \ - esac; \ - done; \ - test $$has_opt = yes -am__make_dryrun = (target_option=n; $(am__make_running_with_option)) -am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) -pkgdatadir = $(datadir)/elfutils -pkgincludedir = $(includedir)/elfutils -pkglibdir = $(libdir)/elfutils -pkglibexecdir = $(libexecdir)/elfutils -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 = x86_64-unknown-linux-gnu -host_triplet = x86_64-unknown-linux-gnu -DIST_COMMON = $(top_srcdir)/config/eu.am $(srcdir)/Makefile.in \ - $(srcdir)/Makefile.am $(top_srcdir)/config/depcomp \ - $(noinst_HEADERS) $(pkginclude_HEADERS) ChangeLog -am__append_1 = gzip.c -#am__append_2 = bzip2.c -#am__append_3 = lzma.c -subdir = libdwfl -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/biarch.m4 \ - $(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 = -LIBRARIES = $(noinst_LIBRARIES) -ARFLAGS = cru -AM_V_AR = $(am__v_AR_$(V)) -am__v_AR_ = $(am__v_AR_$(AM_DEFAULT_VERBOSITY)) -am__v_AR_0 = @echo " AR " $@; -am__v_AR_1 = -libdwfl_a_AR = $(AR) $(ARFLAGS) -libdwfl_a_LIBADD = -am__libdwfl_a_SOURCES_DIST = dwfl_begin.c dwfl_end.c dwfl_error.c \ - dwfl_version.c dwfl_module.c dwfl_report_elf.c relocate.c \ - dwfl_module_build_id.c dwfl_module_report_build_id.c \ - derelocate.c offline.c segment.c dwfl_module_info.c \ - dwfl_getmodules.c dwfl_getdwarf.c dwfl_module_getdwarf.c \ - dwfl_module_getelf.c dwfl_validate_address.c argp-std.c \ - find-debuginfo.c dwfl_build_id_find_elf.c \ - dwfl_build_id_find_debuginfo.c linux-kernel-modules.c \ - linux-proc-maps.c dwfl_addrmodule.c dwfl_addrdwarf.c cu.c \ - dwfl_module_nextcu.c dwfl_nextcu.c dwfl_cumodule.c \ - dwfl_module_addrdie.c dwfl_addrdie.c lines.c dwfl_lineinfo.c \ - dwfl_line_comp_dir.c dwfl_linemodule.c dwfl_linecu.c \ - dwfl_dwarf_line.c dwfl_getsrclines.c dwfl_onesrcline.c \ - dwfl_module_getsrc.c dwfl_getsrc.c dwfl_module_getsrc_file.c \ - libdwfl_crc32.c libdwfl_crc32_file.c elf-from-memory.c \ - dwfl_module_dwarf_cfi.c dwfl_module_eh_cfi.c \ - dwfl_module_getsym.c dwfl_module_addrname.c \ - dwfl_module_addrsym.c dwfl_module_return_value_location.c \ - dwfl_module_register_names.c dwfl_segment_report_module.c \ - link_map.c core-file.c open.c image-header.c dwfl_frame.c \ - frame_unwind.c dwfl_frame_pc.c linux-pid-attach.c \ - linux-core-attach.c dwfl_frame_regs.c gzip.c bzip2.c lzma.c -am__objects_1 = gzip.$(OBJEXT) -#am__objects_2 = bzip2.$(OBJEXT) -#am__objects_3 = lzma.$(OBJEXT) -am_libdwfl_a_OBJECTS = dwfl_begin.$(OBJEXT) dwfl_end.$(OBJEXT) \ - dwfl_error.$(OBJEXT) dwfl_version.$(OBJEXT) \ - dwfl_module.$(OBJEXT) dwfl_report_elf.$(OBJEXT) \ - relocate.$(OBJEXT) dwfl_module_build_id.$(OBJEXT) \ - dwfl_module_report_build_id.$(OBJEXT) derelocate.$(OBJEXT) \ - offline.$(OBJEXT) segment.$(OBJEXT) dwfl_module_info.$(OBJEXT) \ - dwfl_getmodules.$(OBJEXT) dwfl_getdwarf.$(OBJEXT) \ - dwfl_module_getdwarf.$(OBJEXT) dwfl_module_getelf.$(OBJEXT) \ - dwfl_validate_address.$(OBJEXT) argp-std.$(OBJEXT) \ - find-debuginfo.$(OBJEXT) dwfl_build_id_find_elf.$(OBJEXT) \ - dwfl_build_id_find_debuginfo.$(OBJEXT) \ - linux-kernel-modules.$(OBJEXT) linux-proc-maps.$(OBJEXT) \ - dwfl_addrmodule.$(OBJEXT) dwfl_addrdwarf.$(OBJEXT) \ - cu.$(OBJEXT) dwfl_module_nextcu.$(OBJEXT) \ - dwfl_nextcu.$(OBJEXT) dwfl_cumodule.$(OBJEXT) \ - dwfl_module_addrdie.$(OBJEXT) dwfl_addrdie.$(OBJEXT) \ - lines.$(OBJEXT) dwfl_lineinfo.$(OBJEXT) \ - dwfl_line_comp_dir.$(OBJEXT) dwfl_linemodule.$(OBJEXT) \ - dwfl_linecu.$(OBJEXT) dwfl_dwarf_line.$(OBJEXT) \ - dwfl_getsrclines.$(OBJEXT) dwfl_onesrcline.$(OBJEXT) \ - dwfl_module_getsrc.$(OBJEXT) dwfl_getsrc.$(OBJEXT) \ - dwfl_module_getsrc_file.$(OBJEXT) libdwfl_crc32.$(OBJEXT) \ - libdwfl_crc32_file.$(OBJEXT) elf-from-memory.$(OBJEXT) \ - dwfl_module_dwarf_cfi.$(OBJEXT) dwfl_module_eh_cfi.$(OBJEXT) \ - dwfl_module_getsym.$(OBJEXT) dwfl_module_addrname.$(OBJEXT) \ - dwfl_module_addrsym.$(OBJEXT) \ - dwfl_module_return_value_location.$(OBJEXT) \ - dwfl_module_register_names.$(OBJEXT) \ - dwfl_segment_report_module.$(OBJEXT) link_map.$(OBJEXT) \ - core-file.$(OBJEXT) open.$(OBJEXT) image-header.$(OBJEXT) \ - dwfl_frame.$(OBJEXT) frame_unwind.$(OBJEXT) \ - dwfl_frame_pc.$(OBJEXT) linux-pid-attach.$(OBJEXT) \ - linux-core-attach.$(OBJEXT) dwfl_frame_regs.$(OBJEXT) \ - $(am__objects_1) $(am__objects_2) $(am__objects_3) -libdwfl_a_OBJECTS = $(am_libdwfl_a_OBJECTS) -libdwfl_pic_a_AR = $(AR) $(ARFLAGS) -libdwfl_pic_a_LIBADD = -libdwfl_pic_a_OBJECTS = $(am_libdwfl_pic_a_OBJECTS) -AM_V_P = $(am__v_P_$(V)) -am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY)) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_$(V)) -am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_$(V)) -am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) -am__v_at_0 = @ -am__v_at_1 = -DEFAULT_INCLUDES = -I. -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) -AM_V_CC = $(am__v_CC_$(V)) -am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY)) -am__v_CC_0 = @echo " CC " $@; -am__v_CC_1 = -CCLD = $(CC) -LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CCLD = $(am__v_CCLD_$(V)) -am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY)) -am__v_CCLD_0 = @echo " CCLD " $@; -am__v_CCLD_1 = -SOURCES = $(libdwfl_a_SOURCES) $(libdwfl_pic_a_SOURCES) -DIST_SOURCES = $(am__libdwfl_a_SOURCES_DIST) $(libdwfl_pic_a_SOURCES) -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -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__uninstall_files_from_dir = { \ - test -z "$$files" \ - || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ - || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ - $(am__cd) "$$dir" && rm -f $$files; }; \ - } -am__installdirs = "$(DESTDIR)$(pkgincludedir)" -HEADERS = $(noinst_HEADERS) $(pkginclude_HEADERS) -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -# Read a list of newline-separated strings from the standard input, -# and print each of them once, without duplicates. Input order is -# *not* preserved. -am__uniquify_input = $(AWK) '\ - BEGIN { nonempty = 0; } \ - { items[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in items) print i; }; } \ -' -# Make sure the list of sources is unique. This is necessary because, -# e.g., the same source file might be shared among _SOURCES variables -# for different programs/libraries. -am__define_uniq_tagged_files = \ - list='$(am__tagged_files)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | $(am__uniquify_input)` -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = ${SHELL} /huge-ssd/aosp-arm64/external/elfutils/src/config/missing aclocal-1.14 -AMTAR = $${TAR-tar} -AM_DEFAULT_VERBOSITY = 1 -AR = ar -AUTOCONF = ${SHELL} /huge-ssd/aosp-arm64/external/elfutils/src/config/missing autoconf -AUTOHEADER = ${SHELL} /huge-ssd/aosp-arm64/external/elfutils/src/config/missing autoheader -AUTOMAKE = ${SHELL} /huge-ssd/aosp-arm64/external/elfutils/src/config/missing automake-1.14 -AWK = gawk -CC = gcc -CCDEPMODE = depmode=gcc3 -CC_BIARCH = gcc -m32 -CFLAGS = -g -O2 -CPP = gcc -E -CPPFLAGS = -CYGPATH_W = echo -DEBUGPRED = 0 -DEFS = -D_GNU_SOURCE -DHAVE_CONFIG_H -DLOCALEDIR='"${localedir}"' -DEPDIR = .deps -ECHO_C = -ECHO_N = -n -ECHO_T = -EGREP = /bin/grep -E -EXEEXT = -GETTEXT_MACRO_VERSION = 0.18 -GMSGFMT = /usr/bin/msgfmt -GMSGFMT_015 = /usr/bin/msgfmt -GREP = /bin/grep -HAVE_VALGRIND = -INSTALL = /usr/bin/install -c -INSTALL_DATA = ${INSTALL} -m 644 -INSTALL_PROGRAM = ${INSTALL} -INSTALL_SCRIPT = ${INSTALL} -INSTALL_STRIP_PROGRAM = $(install_sh) -c -s -LDFLAGS = -LEX = flex -LEXLIB = -lfl -LEX_OUTPUT_ROOT = lex.yy -LIBEBL_SUBDIR = elfutils -LIBOBJS = -LIBS = -LTLIBOBJS = -MAINT = # -MAKEINFO = ${SHELL} /huge-ssd/aosp-arm64/external/elfutils/src/config/missing makeinfo -MKDIR_P = /bin/mkdir -p -MODVERSION = Build on enh.mtv.corp.google.com 2015-02-18T19:32:04-0800 -MSGFMT = /usr/bin/msgfmt -MSGFMT_015 = /usr/bin/msgfmt -MSGMERGE = /usr/bin/msgmerge -NM = nm -OBJEXT = o -PACKAGE = elfutils -PACKAGE_BUGREPORT = https://bugzilla.redhat.com/ -PACKAGE_NAME = elfutils -PACKAGE_STRING = elfutils 0.161 -PACKAGE_TARNAME = elfutils -PACKAGE_URL = -PACKAGE_VERSION = 0.161 -PATH_SEPARATOR = : -RANLIB = ranlib -READELF = readelf -SET_MAKE = -SHELL = /bin/sh -STRIP = -USE_NLS = yes -VERSION = 1 -XGETTEXT = /usr/bin/xgettext -XGETTEXT_015 = /usr/bin/xgettext -XGETTEXT_EXTRA_OPTIONS = -YACC = bison -y -YFLAGS = -abs_builddir = /huge-ssd/aosp-arm64/external/elfutils/src/libdwfl -abs_srcdir = /huge-ssd/aosp-arm64/external/elfutils/src/libdwfl -abs_top_builddir = /huge-ssd/aosp-arm64/external/elfutils/src -abs_top_srcdir = /huge-ssd/aosp-arm64/external/elfutils/src -ac_ct_AR = ar -ac_ct_CC = gcc -am__include = include -am__leading_dot = . -am__quote = -am__tar = $${TAR-tar} chof - "$$tardir" -am__untar = $${TAR-tar} xf - -base_cpu = none -bindir = ${exec_prefix}/bin -build = x86_64-unknown-linux-gnu -build_alias = -build_cpu = x86_64 -build_os = linux-gnu -build_vendor = unknown -builddir = . -datadir = ${datarootdir} -datarootdir = ${prefix}/share -docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} -dvidir = ${docdir} -eu_version = 161 -exec_prefix = ${prefix} -host = x86_64-unknown-linux-gnu -host_alias = -host_cpu = x86_64 -host_os = linux-gnu -host_vendor = unknown -htmldir = ${docdir} -includedir = ${prefix}/include -infodir = ${datarootdir}/info -install_sh = ${SHELL} /huge-ssd/aosp-arm64/external/elfutils/src/config/install-sh -libdir = ${exec_prefix}/lib -libexecdir = ${exec_prefix}/libexec -localedir = ${datarootdir}/locale -localstatedir = ${prefix}/var -mandir = ${datarootdir}/man -mkdir_p = $(MKDIR_P) -oldincludedir = /usr/include -pdfdir = ${docdir} -prefix = /usr/local -program_transform_name = s,x,x, -psdir = ${docdir} -sbindir = ${exec_prefix}/sbin -sharedstatedir = ${prefix}/com -srcdir = . -sysconfdir = ${prefix}/etc -target_alias = -top_build_prefix = ../ -top_builddir = .. -top_srcdir = .. -zip_LIBS = -lz -AM_CPPFLAGS = -I. -I$(srcdir) -I$(top_srcdir)/lib -I.. -I$(srcdir) \ - -I$(srcdir)/../libelf -I$(srcdir)/../libebl \ - -I$(srcdir)/../libdw -I$(srcdir)/../libdwelf -AM_CFLAGS = -std=gnu99 -Wall -Wshadow -Wformat=2 \ - $(if $($(*F)_no_Werror),,-Werror) \ - $(if $($(*F)_no_Wunused),,-Wunused -Wextra) \ - $($(*F)_CFLAGS) - -COMPILE.os = $(filter-out -fprofile-arcs -ftest-coverage, $(COMPILE)) -CLEANFILES = *.gcno *.gcda $(am_libdwfl_pic_a_OBJECTS) -textrel_msg = echo "WARNING: TEXTREL found in '$@'" -#textrel_found = $(textrel_msg) -textrel_found = $(textrel_msg); exit 1 -textrel_check = if $(READELF) -d $@ | fgrep -q TEXTREL; then $(textrel_found); fi -noinst_LIBRARIES = libdwfl.a libdwfl_pic.a -pkginclude_HEADERS = libdwfl.h -libdwfl_a_SOURCES = dwfl_begin.c dwfl_end.c dwfl_error.c \ - dwfl_version.c dwfl_module.c dwfl_report_elf.c relocate.c \ - dwfl_module_build_id.c dwfl_module_report_build_id.c \ - derelocate.c offline.c segment.c dwfl_module_info.c \ - dwfl_getmodules.c dwfl_getdwarf.c dwfl_module_getdwarf.c \ - dwfl_module_getelf.c dwfl_validate_address.c argp-std.c \ - find-debuginfo.c dwfl_build_id_find_elf.c \ - dwfl_build_id_find_debuginfo.c linux-kernel-modules.c \ - linux-proc-maps.c dwfl_addrmodule.c dwfl_addrdwarf.c cu.c \ - dwfl_module_nextcu.c dwfl_nextcu.c dwfl_cumodule.c \ - dwfl_module_addrdie.c dwfl_addrdie.c lines.c dwfl_lineinfo.c \ - dwfl_line_comp_dir.c dwfl_linemodule.c dwfl_linecu.c \ - dwfl_dwarf_line.c dwfl_getsrclines.c dwfl_onesrcline.c \ - dwfl_module_getsrc.c dwfl_getsrc.c dwfl_module_getsrc_file.c \ - libdwfl_crc32.c libdwfl_crc32_file.c elf-from-memory.c \ - dwfl_module_dwarf_cfi.c dwfl_module_eh_cfi.c \ - dwfl_module_getsym.c dwfl_module_addrname.c \ - dwfl_module_addrsym.c dwfl_module_return_value_location.c \ - dwfl_module_register_names.c dwfl_segment_report_module.c \ - link_map.c core-file.c open.c image-header.c dwfl_frame.c \ - frame_unwind.c dwfl_frame_pc.c linux-pid-attach.c \ - linux-core-attach.c dwfl_frame_regs.c $(am__append_1) \ - $(am__append_2) $(am__append_3) -libdwfl = $(libdw) -libdw = ../libdw/libdw.so -libelf = ../libelf/libelf.so -libebl = ../libebl/libebl.a -libeu = ../lib/libeu.a -libdwfl_pic_a_SOURCES = -am_libdwfl_pic_a_OBJECTS = $(libdwfl_a_SOURCES:.c=.os) -noinst_HEADERS = libdwflP.h -all: all-am - -.SUFFIXES: -.SUFFIXES: .c .o .obj -$(srcdir)/Makefile.in: # $(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 libdwfl/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnits libdwfl/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_srcdir)/config/eu.am: - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: # $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): # $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): - -clean-noinstLIBRARIES: - -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) - -libdwfl.a: $(libdwfl_a_OBJECTS) $(libdwfl_a_DEPENDENCIES) $(EXTRA_libdwfl_a_DEPENDENCIES) - $(AM_V_at)-rm -f libdwfl.a - $(AM_V_AR)$(libdwfl_a_AR) libdwfl.a $(libdwfl_a_OBJECTS) $(libdwfl_a_LIBADD) - $(AM_V_at)$(RANLIB) libdwfl.a - -libdwfl_pic.a: $(libdwfl_pic_a_OBJECTS) $(libdwfl_pic_a_DEPENDENCIES) $(EXTRA_libdwfl_pic_a_DEPENDENCIES) - $(AM_V_at)-rm -f libdwfl_pic.a - $(AM_V_AR)$(libdwfl_pic_a_AR) libdwfl_pic.a $(libdwfl_pic_a_OBJECTS) $(libdwfl_pic_a_LIBADD) - $(AM_V_at)$(RANLIB) libdwfl_pic.a - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -include ./$(DEPDIR)/argp-std.Po -include ./$(DEPDIR)/bzip2.Po -include ./$(DEPDIR)/core-file.Po -include ./$(DEPDIR)/cu.Po -include ./$(DEPDIR)/derelocate.Po -include ./$(DEPDIR)/dwfl_addrdie.Po -include ./$(DEPDIR)/dwfl_addrdwarf.Po -include ./$(DEPDIR)/dwfl_addrmodule.Po -include ./$(DEPDIR)/dwfl_begin.Po -include ./$(DEPDIR)/dwfl_build_id_find_debuginfo.Po -include ./$(DEPDIR)/dwfl_build_id_find_elf.Po -include ./$(DEPDIR)/dwfl_cumodule.Po -include ./$(DEPDIR)/dwfl_dwarf_line.Po -include ./$(DEPDIR)/dwfl_end.Po -include ./$(DEPDIR)/dwfl_error.Po -include ./$(DEPDIR)/dwfl_frame.Po -include ./$(DEPDIR)/dwfl_frame_pc.Po -include ./$(DEPDIR)/dwfl_frame_regs.Po -include ./$(DEPDIR)/dwfl_getdwarf.Po -include ./$(DEPDIR)/dwfl_getmodules.Po -include ./$(DEPDIR)/dwfl_getsrc.Po -include ./$(DEPDIR)/dwfl_getsrclines.Po -include ./$(DEPDIR)/dwfl_line_comp_dir.Po -include ./$(DEPDIR)/dwfl_linecu.Po -include ./$(DEPDIR)/dwfl_lineinfo.Po -include ./$(DEPDIR)/dwfl_linemodule.Po -include ./$(DEPDIR)/dwfl_module.Po -include ./$(DEPDIR)/dwfl_module_addrdie.Po -include ./$(DEPDIR)/dwfl_module_addrname.Po -include ./$(DEPDIR)/dwfl_module_addrsym.Po -include ./$(DEPDIR)/dwfl_module_build_id.Po -include ./$(DEPDIR)/dwfl_module_dwarf_cfi.Po -include ./$(DEPDIR)/dwfl_module_eh_cfi.Po -include ./$(DEPDIR)/dwfl_module_getdwarf.Po -include ./$(DEPDIR)/dwfl_module_getelf.Po -include ./$(DEPDIR)/dwfl_module_getsrc.Po -include ./$(DEPDIR)/dwfl_module_getsrc_file.Po -include ./$(DEPDIR)/dwfl_module_getsym.Po -include ./$(DEPDIR)/dwfl_module_info.Po -include ./$(DEPDIR)/dwfl_module_nextcu.Po -include ./$(DEPDIR)/dwfl_module_register_names.Po -include ./$(DEPDIR)/dwfl_module_report_build_id.Po -include ./$(DEPDIR)/dwfl_module_return_value_location.Po -include ./$(DEPDIR)/dwfl_nextcu.Po -include ./$(DEPDIR)/dwfl_onesrcline.Po -include ./$(DEPDIR)/dwfl_report_elf.Po -include ./$(DEPDIR)/dwfl_segment_report_module.Po -include ./$(DEPDIR)/dwfl_validate_address.Po -include ./$(DEPDIR)/dwfl_version.Po -include ./$(DEPDIR)/elf-from-memory.Po -include ./$(DEPDIR)/find-debuginfo.Po -include ./$(DEPDIR)/frame_unwind.Po -include ./$(DEPDIR)/gzip.Po -include ./$(DEPDIR)/image-header.Po -include ./$(DEPDIR)/libdwfl_crc32.Po -include ./$(DEPDIR)/libdwfl_crc32_file.Po -include ./$(DEPDIR)/lines.Po -include ./$(DEPDIR)/link_map.Po -include ./$(DEPDIR)/linux-core-attach.Po -include ./$(DEPDIR)/linux-kernel-modules.Po -include ./$(DEPDIR)/linux-pid-attach.Po -include ./$(DEPDIR)/linux-proc-maps.Po -include ./$(DEPDIR)/lzma.Po -include ./$(DEPDIR)/offline.Po -include ./$(DEPDIR)/open.Po -include ./$(DEPDIR)/relocate.Po -include ./$(DEPDIR)/segment.Po - -.c.o: - $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< - $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -# $(AM_V_CC)source='$<' object='$@' libtool=no \ -# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ -# $(AM_V_CC_no)$(COMPILE) -c -o $@ $< - -.c.obj: - $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` - $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -# $(AM_V_CC)source='$<' object='$@' libtool=no \ -# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ -# $(AM_V_CC_no)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` -install-pkgincludeHEADERS: $(pkginclude_HEADERS) - @$(NORMAL_INSTALL) - @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ - if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(pkgincludedir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)" || exit 1; \ - fi; \ - 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|^.*/||'`; \ - dir='$(DESTDIR)$(pkgincludedir)'; $(am__uninstall_files_from_dir) - -ID: $(am__tagged_files) - $(am__define_uniq_tagged_files); mkid -fID $$unique -tags: tags-am -TAGS: tags - -tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - set x; \ - here=`pwd`; \ - $(am__define_uniq_tagged_files); \ - 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-am - -CTAGS: ctags -ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - $(am__define_uniq_tagged_files); \ - 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" -cscopelist: cscopelist-am - -cscopelist-am: $(am__tagged_files) - list='$(am__tagged_files)'; \ - case "$(srcdir)" in \ - [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ - *) sdir=$(subdir)/$(srcdir) ;; \ - esac; \ - for i in $$list; do \ - if test -f "$$i"; then \ - echo "$(subdir)/$$i"; \ - else \ - echo "$$sdir/$$i"; \ - fi; \ - done >> $(top_builddir)/cscope.files - -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: check-am -all-am: Makefile $(LIBRARIES) $(HEADERS) -installdirs: - for dir in "$(DESTDIR)$(pkgincludedir)"; do \ - test -z "$$dir" || $(MKDIR_P) "$$dir"; \ - done -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -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." -clean: clean-am - -clean-am: clean-generic clean-noinstLIBRARIES 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-pkgincludeHEADERS - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: - -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-pkgincludeHEADERS - -.MAKE: install-am install-strip - -.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ - clean-noinstLIBRARIES cscopelist-am ctags ctags-am 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-info install-info-am 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 tags-am uninstall uninstall-am \ - uninstall-pkgincludeHEADERS - - -%.os: %.c %.o - if $(COMPILE.os) -c -o $@ -fpic -DPIC -DSHARED -MT $@ -MD -MP \ - -MF "$(DEPDIR)/$*.Tpo" `test -f '$<' || echo '$(srcdir)/'`$<; \ - then cat "$(DEPDIR)/$*.Tpo" >> "$(DEPDIR)/$*.Po"; \ - rm -f "$(DEPDIR)/$*.Tpo"; \ - else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ - fi -# $(COMPILE.os) -c -o $@ -fpic -DPIC -DSHARED $< - -# 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/libdwfl/Makefile.am b/src/libdwfl/Makefile.am deleted file mode 100644 index 72c980bf..00000000 --- a/src/libdwfl/Makefile.am +++ /dev/null @@ -1,94 +0,0 @@ -## Makefile.am for libdwfl library subdirectory in elfutils. -## -## Process this file with automake to create Makefile.in -## -## Copyright (C) 2005-2010, 2013 Red Hat, Inc. -## This file is part of elfutils. -## -## This file is free software; you can redistribute it and/or modify -## it under the terms of either -## -## * the GNU Lesser General Public License as published by the Free -## Software Foundation; either version 3 of the License, or (at -## your option) any later version -## -## or -## -## * the GNU General Public License as published by the Free -## Software Foundation; either version 2 of the License, or (at -## your option) any later version -## -## or both in parallel, as here. -## -## 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 copies of the GNU General Public License and -## the GNU Lesser General Public License along with this program. If -## not, see <http://www.gnu.org/licenses/>. -## -include $(top_srcdir)/config/eu.am -AM_CPPFLAGS += -I$(srcdir) -I$(srcdir)/../libelf -I$(srcdir)/../libebl \ - -I$(srcdir)/../libdw -I$(srcdir)/../libdwelf -VERSION = 1 - -noinst_LIBRARIES = libdwfl.a -noinst_LIBRARIES += libdwfl_pic.a - -pkginclude_HEADERS = libdwfl.h - -libdwfl_a_SOURCES = dwfl_begin.c dwfl_end.c dwfl_error.c dwfl_version.c \ - dwfl_module.c dwfl_report_elf.c relocate.c \ - dwfl_module_build_id.c dwfl_module_report_build_id.c \ - derelocate.c offline.c segment.c \ - dwfl_module_info.c dwfl_getmodules.c dwfl_getdwarf.c \ - dwfl_module_getdwarf.c dwfl_module_getelf.c \ - dwfl_validate_address.c \ - argp-std.c find-debuginfo.c \ - dwfl_build_id_find_elf.c \ - dwfl_build_id_find_debuginfo.c \ - linux-kernel-modules.c linux-proc-maps.c \ - dwfl_addrmodule.c dwfl_addrdwarf.c \ - cu.c dwfl_module_nextcu.c dwfl_nextcu.c dwfl_cumodule.c \ - dwfl_module_addrdie.c dwfl_addrdie.c \ - lines.c dwfl_lineinfo.c dwfl_line_comp_dir.c \ - dwfl_linemodule.c dwfl_linecu.c dwfl_dwarf_line.c \ - dwfl_getsrclines.c dwfl_onesrcline.c \ - dwfl_module_getsrc.c dwfl_getsrc.c \ - dwfl_module_getsrc_file.c \ - libdwfl_crc32.c libdwfl_crc32_file.c \ - elf-from-memory.c \ - dwfl_module_dwarf_cfi.c dwfl_module_eh_cfi.c \ - dwfl_module_getsym.c \ - dwfl_module_addrname.c dwfl_module_addrsym.c \ - dwfl_module_return_value_location.c \ - dwfl_module_register_names.c \ - dwfl_segment_report_module.c \ - link_map.c core-file.c open.c image-header.c \ - dwfl_frame.c frame_unwind.c dwfl_frame_pc.c \ - linux-pid-attach.c linux-core-attach.c dwfl_frame_regs.c - -if ZLIB -libdwfl_a_SOURCES += gzip.c -endif -if BZLIB -libdwfl_a_SOURCES += bzip2.c -endif -if LZMA -libdwfl_a_SOURCES += lzma.c -endif - -libdwfl = $(libdw) -libdw = ../libdw/libdw.so -libelf = ../libelf/libelf.so -libebl = ../libebl/libebl.a -libeu = ../lib/libeu.a - -libdwfl_pic_a_SOURCES = -am_libdwfl_pic_a_OBJECTS = $(libdwfl_a_SOURCES:.c=.os) - -noinst_HEADERS = libdwflP.h - -CLEANFILES += $(am_libdwfl_pic_a_OBJECTS) diff --git a/src/libdwfl/Makefile.in b/src/libdwfl/Makefile.in deleted file mode 100644 index f00e79e4..00000000 --- a/src/libdwfl/Makefile.in +++ /dev/null @@ -1,801 +0,0 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994-2013 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@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' -am__make_running_with_option = \ - case $${target_option-} in \ - ?) ;; \ - *) echo "am__make_running_with_option: internal error: invalid" \ - "target option '$${target_option-}' specified" >&2; \ - exit 1;; \ - esac; \ - has_opt=no; \ - sane_makeflags=$$MAKEFLAGS; \ - if $(am__is_gnu_make); then \ - sane_makeflags=$$MFLAGS; \ - else \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - bs=\\; \ - sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ - | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ - esac; \ - fi; \ - skip_next=no; \ - strip_trailopt () \ - { \ - flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ - }; \ - for flg in $$sane_makeflags; do \ - test $$skip_next = yes && { skip_next=no; continue; }; \ - case $$flg in \ - *=*|--*) continue;; \ - -*I) strip_trailopt 'I'; skip_next=yes;; \ - -*I?*) strip_trailopt 'I';; \ - -*O) strip_trailopt 'O'; skip_next=yes;; \ - -*O?*) strip_trailopt 'O';; \ - -*l) strip_trailopt 'l'; skip_next=yes;; \ - -*l?*) strip_trailopt 'l';; \ - -[dEDm]) skip_next=yes;; \ - -[JT]) skip_next=yes;; \ - esac; \ - case $$flg in \ - *$$target_option*) has_opt=yes; break;; \ - esac; \ - done; \ - test $$has_opt = yes -am__make_dryrun = (target_option=n; $(am__make_running_with_option)) -am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) -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 = $(top_srcdir)/config/eu.am $(srcdir)/Makefile.in \ - $(srcdir)/Makefile.am $(top_srcdir)/config/depcomp \ - $(noinst_HEADERS) $(pkginclude_HEADERS) ChangeLog -@ZLIB_TRUE@am__append_1 = gzip.c -@BZLIB_TRUE@am__append_2 = bzip2.c -@LZMA_TRUE@am__append_3 = lzma.c -subdir = libdwfl -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/biarch.m4 \ - $(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 = -LIBRARIES = $(noinst_LIBRARIES) -ARFLAGS = cru -AM_V_AR = $(am__v_AR_@AM_V@) -am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@) -am__v_AR_0 = @echo " AR " $@; -am__v_AR_1 = -libdwfl_a_AR = $(AR) $(ARFLAGS) -libdwfl_a_LIBADD = -am__libdwfl_a_SOURCES_DIST = dwfl_begin.c dwfl_end.c dwfl_error.c \ - dwfl_version.c dwfl_module.c dwfl_report_elf.c relocate.c \ - dwfl_module_build_id.c dwfl_module_report_build_id.c \ - derelocate.c offline.c segment.c dwfl_module_info.c \ - dwfl_getmodules.c dwfl_getdwarf.c dwfl_module_getdwarf.c \ - dwfl_module_getelf.c dwfl_validate_address.c argp-std.c \ - find-debuginfo.c dwfl_build_id_find_elf.c \ - dwfl_build_id_find_debuginfo.c linux-kernel-modules.c \ - linux-proc-maps.c dwfl_addrmodule.c dwfl_addrdwarf.c cu.c \ - dwfl_module_nextcu.c dwfl_nextcu.c dwfl_cumodule.c \ - dwfl_module_addrdie.c dwfl_addrdie.c lines.c dwfl_lineinfo.c \ - dwfl_line_comp_dir.c dwfl_linemodule.c dwfl_linecu.c \ - dwfl_dwarf_line.c dwfl_getsrclines.c dwfl_onesrcline.c \ - dwfl_module_getsrc.c dwfl_getsrc.c dwfl_module_getsrc_file.c \ - libdwfl_crc32.c libdwfl_crc32_file.c elf-from-memory.c \ - dwfl_module_dwarf_cfi.c dwfl_module_eh_cfi.c \ - dwfl_module_getsym.c dwfl_module_addrname.c \ - dwfl_module_addrsym.c dwfl_module_return_value_location.c \ - dwfl_module_register_names.c dwfl_segment_report_module.c \ - link_map.c core-file.c open.c image-header.c dwfl_frame.c \ - frame_unwind.c dwfl_frame_pc.c linux-pid-attach.c \ - linux-core-attach.c dwfl_frame_regs.c gzip.c bzip2.c lzma.c -@ZLIB_TRUE@am__objects_1 = gzip.$(OBJEXT) -@BZLIB_TRUE@am__objects_2 = bzip2.$(OBJEXT) -@LZMA_TRUE@am__objects_3 = lzma.$(OBJEXT) -am_libdwfl_a_OBJECTS = dwfl_begin.$(OBJEXT) dwfl_end.$(OBJEXT) \ - dwfl_error.$(OBJEXT) dwfl_version.$(OBJEXT) \ - dwfl_module.$(OBJEXT) dwfl_report_elf.$(OBJEXT) \ - relocate.$(OBJEXT) dwfl_module_build_id.$(OBJEXT) \ - dwfl_module_report_build_id.$(OBJEXT) derelocate.$(OBJEXT) \ - offline.$(OBJEXT) segment.$(OBJEXT) dwfl_module_info.$(OBJEXT) \ - dwfl_getmodules.$(OBJEXT) dwfl_getdwarf.$(OBJEXT) \ - dwfl_module_getdwarf.$(OBJEXT) dwfl_module_getelf.$(OBJEXT) \ - dwfl_validate_address.$(OBJEXT) argp-std.$(OBJEXT) \ - find-debuginfo.$(OBJEXT) dwfl_build_id_find_elf.$(OBJEXT) \ - dwfl_build_id_find_debuginfo.$(OBJEXT) \ - linux-kernel-modules.$(OBJEXT) linux-proc-maps.$(OBJEXT) \ - dwfl_addrmodule.$(OBJEXT) dwfl_addrdwarf.$(OBJEXT) \ - cu.$(OBJEXT) dwfl_module_nextcu.$(OBJEXT) \ - dwfl_nextcu.$(OBJEXT) dwfl_cumodule.$(OBJEXT) \ - dwfl_module_addrdie.$(OBJEXT) dwfl_addrdie.$(OBJEXT) \ - lines.$(OBJEXT) dwfl_lineinfo.$(OBJEXT) \ - dwfl_line_comp_dir.$(OBJEXT) dwfl_linemodule.$(OBJEXT) \ - dwfl_linecu.$(OBJEXT) dwfl_dwarf_line.$(OBJEXT) \ - dwfl_getsrclines.$(OBJEXT) dwfl_onesrcline.$(OBJEXT) \ - dwfl_module_getsrc.$(OBJEXT) dwfl_getsrc.$(OBJEXT) \ - dwfl_module_getsrc_file.$(OBJEXT) libdwfl_crc32.$(OBJEXT) \ - libdwfl_crc32_file.$(OBJEXT) elf-from-memory.$(OBJEXT) \ - dwfl_module_dwarf_cfi.$(OBJEXT) dwfl_module_eh_cfi.$(OBJEXT) \ - dwfl_module_getsym.$(OBJEXT) dwfl_module_addrname.$(OBJEXT) \ - dwfl_module_addrsym.$(OBJEXT) \ - dwfl_module_return_value_location.$(OBJEXT) \ - dwfl_module_register_names.$(OBJEXT) \ - dwfl_segment_report_module.$(OBJEXT) link_map.$(OBJEXT) \ - core-file.$(OBJEXT) open.$(OBJEXT) image-header.$(OBJEXT) \ - dwfl_frame.$(OBJEXT) frame_unwind.$(OBJEXT) \ - dwfl_frame_pc.$(OBJEXT) linux-pid-attach.$(OBJEXT) \ - linux-core-attach.$(OBJEXT) dwfl_frame_regs.$(OBJEXT) \ - $(am__objects_1) $(am__objects_2) $(am__objects_3) -libdwfl_a_OBJECTS = $(am_libdwfl_a_OBJECTS) -libdwfl_pic_a_AR = $(AR) $(ARFLAGS) -libdwfl_pic_a_LIBADD = -libdwfl_pic_a_OBJECTS = $(am_libdwfl_pic_a_OBJECTS) -AM_V_P = $(am__v_P_@AM_V@) -am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -am__v_at_1 = -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) -AM_V_CC = $(am__v_CC_@AM_V@) -am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) -am__v_CC_0 = @echo " CC " $@; -am__v_CC_1 = -CCLD = $(CC) -LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CCLD = $(am__v_CCLD_@AM_V@) -am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) -am__v_CCLD_0 = @echo " CCLD " $@; -am__v_CCLD_1 = -SOURCES = $(libdwfl_a_SOURCES) $(libdwfl_pic_a_SOURCES) -DIST_SOURCES = $(am__libdwfl_a_SOURCES_DIST) $(libdwfl_pic_a_SOURCES) -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -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__uninstall_files_from_dir = { \ - test -z "$$files" \ - || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ - || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ - $(am__cd) "$$dir" && rm -f $$files; }; \ - } -am__installdirs = "$(DESTDIR)$(pkgincludedir)" -HEADERS = $(noinst_HEADERS) $(pkginclude_HEADERS) -am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -# Read a list of newline-separated strings from the standard input, -# and print each of them once, without duplicates. Input order is -# *not* preserved. -am__uniquify_input = $(AWK) '\ - BEGIN { nonempty = 0; } \ - { items[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in items) print i; }; } \ -' -# Make sure the list of sources is unique. This is necessary because, -# e.g., the same source file might be shared among _SOURCES variables -# for different programs/libraries. -am__define_uniq_tagged_files = \ - list='$(am__tagged_files)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | $(am__uniquify_input)` -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CC_BIARCH = @CC_BIARCH@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEBUGPRED = @DEBUGPRED@ -DEFS = -D_GNU_SOURCE -DHAVE_CONFIG_H -DLOCALEDIR='"${localedir}"' -DEPDIR = @DEPDIR@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ -GMSGFMT = @GMSGFMT@ -GMSGFMT_015 = @GMSGFMT_015@ -GREP = @GREP@ -HAVE_VALGRIND = @HAVE_VALGRIND@ -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@ -NM = @NM@ -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@ -READELF = @READELF@ -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_AR = @ac_ct_AR@ -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@ -AM_CPPFLAGS = -I. -I$(srcdir) -I$(top_srcdir)/lib -I.. -I$(srcdir) \ - -I$(srcdir)/../libelf -I$(srcdir)/../libebl \ - -I$(srcdir)/../libdw -I$(srcdir)/../libdwelf -AM_CFLAGS = -std=gnu99 -Wall -Wshadow -Wformat=2 \ - $(if $($(*F)_no_Werror),,-Werror) \ - $(if $($(*F)_no_Wunused),,-Wunused -Wextra) \ - $($(*F)_CFLAGS) - -COMPILE.os = $(filter-out -fprofile-arcs -ftest-coverage, $(COMPILE)) -CLEANFILES = *.gcno *.gcda $(am_libdwfl_pic_a_OBJECTS) -textrel_msg = echo "WARNING: TEXTREL found in '$@'" -@FATAL_TEXTREL_FALSE@textrel_found = $(textrel_msg) -@FATAL_TEXTREL_TRUE@textrel_found = $(textrel_msg); exit 1 -textrel_check = if $(READELF) -d $@ | fgrep -q TEXTREL; then $(textrel_found); fi -noinst_LIBRARIES = libdwfl.a libdwfl_pic.a -pkginclude_HEADERS = libdwfl.h -libdwfl_a_SOURCES = dwfl_begin.c dwfl_end.c dwfl_error.c \ - dwfl_version.c dwfl_module.c dwfl_report_elf.c relocate.c \ - dwfl_module_build_id.c dwfl_module_report_build_id.c \ - derelocate.c offline.c segment.c dwfl_module_info.c \ - dwfl_getmodules.c dwfl_getdwarf.c dwfl_module_getdwarf.c \ - dwfl_module_getelf.c dwfl_validate_address.c argp-std.c \ - find-debuginfo.c dwfl_build_id_find_elf.c \ - dwfl_build_id_find_debuginfo.c linux-kernel-modules.c \ - linux-proc-maps.c dwfl_addrmodule.c dwfl_addrdwarf.c cu.c \ - dwfl_module_nextcu.c dwfl_nextcu.c dwfl_cumodule.c \ - dwfl_module_addrdie.c dwfl_addrdie.c lines.c dwfl_lineinfo.c \ - dwfl_line_comp_dir.c dwfl_linemodule.c dwfl_linecu.c \ - dwfl_dwarf_line.c dwfl_getsrclines.c dwfl_onesrcline.c \ - dwfl_module_getsrc.c dwfl_getsrc.c dwfl_module_getsrc_file.c \ - libdwfl_crc32.c libdwfl_crc32_file.c elf-from-memory.c \ - dwfl_module_dwarf_cfi.c dwfl_module_eh_cfi.c \ - dwfl_module_getsym.c dwfl_module_addrname.c \ - dwfl_module_addrsym.c dwfl_module_return_value_location.c \ - dwfl_module_register_names.c dwfl_segment_report_module.c \ - link_map.c core-file.c open.c image-header.c dwfl_frame.c \ - frame_unwind.c dwfl_frame_pc.c linux-pid-attach.c \ - linux-core-attach.c dwfl_frame_regs.c $(am__append_1) \ - $(am__append_2) $(am__append_3) -libdwfl = $(libdw) -libdw = ../libdw/libdw.so -libelf = ../libelf/libelf.so -libebl = ../libebl/libebl.a -libeu = ../lib/libeu.a -libdwfl_pic_a_SOURCES = -am_libdwfl_pic_a_OBJECTS = $(libdwfl_a_SOURCES:.c=.os) -noinst_HEADERS = libdwflP.h -all: 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 libdwfl/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnits libdwfl/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_srcdir)/config/eu.am: - -$(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): - -clean-noinstLIBRARIES: - -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) - -libdwfl.a: $(libdwfl_a_OBJECTS) $(libdwfl_a_DEPENDENCIES) $(EXTRA_libdwfl_a_DEPENDENCIES) - $(AM_V_at)-rm -f libdwfl.a - $(AM_V_AR)$(libdwfl_a_AR) libdwfl.a $(libdwfl_a_OBJECTS) $(libdwfl_a_LIBADD) - $(AM_V_at)$(RANLIB) libdwfl.a - -libdwfl_pic.a: $(libdwfl_pic_a_OBJECTS) $(libdwfl_pic_a_DEPENDENCIES) $(EXTRA_libdwfl_pic_a_DEPENDENCIES) - $(AM_V_at)-rm -f libdwfl_pic.a - $(AM_V_AR)$(libdwfl_pic_a_AR) libdwfl_pic.a $(libdwfl_pic_a_OBJECTS) $(libdwfl_pic_a_LIBADD) - $(AM_V_at)$(RANLIB) libdwfl_pic.a - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/argp-std.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bzip2.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core-file.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cu.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/derelocate.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_addrdie.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_addrdwarf.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_addrmodule.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_begin.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_build_id_find_debuginfo.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_build_id_find_elf.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_cumodule.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_dwarf_line.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_end.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_error.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_frame.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_frame_pc.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_frame_regs.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_getdwarf.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_getmodules.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_getsrc.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_getsrclines.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_line_comp_dir.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_linecu.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_lineinfo.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_linemodule.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_module.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_module_addrdie.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_module_addrname.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_module_addrsym.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_module_build_id.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_module_dwarf_cfi.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_module_eh_cfi.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_module_getdwarf.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_module_getelf.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_module_getsrc.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_module_getsrc_file.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_module_getsym.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_module_info.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_module_nextcu.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_module_register_names.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_module_report_build_id.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_module_return_value_location.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_nextcu.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_onesrcline.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_report_elf.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_segment_report_module.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_validate_address.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwfl_version.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf-from-memory.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/find-debuginfo.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/frame_unwind.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gzip.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/image-header.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdwfl_crc32.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdwfl_crc32_file.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lines.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/link_map.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/linux-core-attach.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/linux-kernel-modules.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/linux-pid-attach.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/linux-proc-maps.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lzma.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/offline.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/open.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/relocate.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/segment.Po@am__quote@ - -.c.o: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< - -.c.obj: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` -install-pkgincludeHEADERS: $(pkginclude_HEADERS) - @$(NORMAL_INSTALL) - @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ - if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(pkgincludedir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)" || exit 1; \ - fi; \ - 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|^.*/||'`; \ - dir='$(DESTDIR)$(pkgincludedir)'; $(am__uninstall_files_from_dir) - -ID: $(am__tagged_files) - $(am__define_uniq_tagged_files); mkid -fID $$unique -tags: tags-am -TAGS: tags - -tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - set x; \ - here=`pwd`; \ - $(am__define_uniq_tagged_files); \ - 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-am - -CTAGS: ctags -ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) - $(am__define_uniq_tagged_files); \ - 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" -cscopelist: cscopelist-am - -cscopelist-am: $(am__tagged_files) - list='$(am__tagged_files)'; \ - case "$(srcdir)" in \ - [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ - *) sdir=$(subdir)/$(srcdir) ;; \ - esac; \ - for i in $$list; do \ - if test -f "$$i"; then \ - echo "$(subdir)/$$i"; \ - else \ - echo "$$sdir/$$i"; \ - fi; \ - done >> $(top_builddir)/cscope.files - -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: check-am -all-am: Makefile $(LIBRARIES) $(HEADERS) -installdirs: - for dir in "$(DESTDIR)$(pkgincludedir)"; do \ - test -z "$$dir" || $(MKDIR_P) "$$dir"; \ - done -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -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." -clean: clean-am - -clean-am: clean-generic clean-noinstLIBRARIES 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-pkgincludeHEADERS - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: - -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-pkgincludeHEADERS - -.MAKE: install-am install-strip - -.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ - clean-noinstLIBRARIES cscopelist-am ctags ctags-am 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-info install-info-am 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 tags-am uninstall uninstall-am \ - 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 $< - -# 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/libdwfl/argp-std.c b/src/libdwfl/argp-std.c deleted file mode 100644 index 42b7e783..00000000 --- a/src/libdwfl/argp-std.c +++ /dev/null @@ -1,364 +0,0 @@ -/* Standard argp argument parsers for tools using libdwfl. - Copyright (C) 2005-2010, 2012 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" -#include <argp.h> -#include <stdlib.h> -#include <assert.h> -#include <libintl.h> -#include <fcntl.h> -#include <unistd.h> - -/* gettext helper macros. */ -#define _(Str) dgettext ("elfutils", Str) - - -#define OPT_DEBUGINFO 0x100 -#define OPT_COREFILE 0x101 - -static const struct argp_option options[] = -{ - { NULL, 0, NULL, 0, N_("Input selection options:"), 0 }, - { "executable", 'e', "FILE", 0, N_("Find addresses in FILE"), 0 }, - { "core", OPT_COREFILE, "COREFILE", 0, - N_("Find addresses from signatures found in COREFILE"), 0 }, - { "pid", 'p', "PID", 0, - N_("Find addresses in files mapped into process PID"), 0 }, - { "linux-process-map", 'M', "FILE", 0, - N_("Find addresses in files mapped as read from FILE" - " in Linux /proc/PID/maps format"), 0 }, - { "kernel", 'k', NULL, 0, N_("Find addresses in the running kernel"), 0 }, - { "offline-kernel", 'K', "RELEASE", OPTION_ARG_OPTIONAL, - N_("Kernel with all modules"), 0 }, - { "debuginfo-path", OPT_DEBUGINFO, "PATH", 0, - N_("Search path for separate debuginfo files"), 0 }, - { NULL, 0, NULL, 0, NULL, 0 } -}; - -static char *debuginfo_path; - -static const Dwfl_Callbacks offline_callbacks = - { - .find_debuginfo = INTUSE(dwfl_standard_find_debuginfo), - .debuginfo_path = &debuginfo_path, - - .section_address = INTUSE(dwfl_offline_section_address), - - /* We use this table for core files too. */ - .find_elf = INTUSE(dwfl_build_id_find_elf), - }; - -static const Dwfl_Callbacks proc_callbacks = - { - .find_debuginfo = INTUSE(dwfl_standard_find_debuginfo), - .debuginfo_path = &debuginfo_path, - - .find_elf = INTUSE(dwfl_linux_proc_find_elf), - }; - -static const Dwfl_Callbacks kernel_callbacks = - { - .find_debuginfo = INTUSE(dwfl_standard_find_debuginfo), - .debuginfo_path = &debuginfo_path, - - .find_elf = INTUSE(dwfl_linux_kernel_find_elf), - .section_address = INTUSE(dwfl_linux_kernel_module_section_address), - }; - -/* Structure held at state->HOOK. */ -struct parse_opt -{ - Dwfl *dwfl; - /* The -e|--executable parameter. */ - const char *e; - /* The --core parameter. */ - const char *core; -}; - -static error_t -parse_opt (int key, char *arg, struct argp_state *state) -{ - inline void failure (Dwfl *dwfl, int errnum, const char *msg) - { - if (dwfl != NULL) - dwfl_end (dwfl); - if (errnum == -1) - argp_failure (state, EXIT_FAILURE, 0, "%s: %s", - msg, INTUSE(dwfl_errmsg) (-1)); - else - argp_failure (state, EXIT_FAILURE, errnum, "%s", msg); - } - inline error_t fail (Dwfl *dwfl, int errnum, const char *msg) - { - failure (dwfl, errnum, msg); - return errnum == -1 ? EIO : errnum; - } - - switch (key) - { - case ARGP_KEY_INIT: - { - assert (state->hook == NULL); - struct parse_opt *opt = calloc (1, sizeof (*opt)); - if (opt == NULL) - failure (NULL, DWFL_E_ERRNO, "calloc"); - state->hook = opt; - } - break; - - case OPT_DEBUGINFO: - debuginfo_path = arg; - break; - - case 'e': - { - struct parse_opt *opt = state->hook; - Dwfl *dwfl = opt->dwfl; - if (dwfl == NULL) - { - dwfl = INTUSE(dwfl_begin) (&offline_callbacks); - if (dwfl == NULL) - return fail (dwfl, -1, arg); - opt->dwfl = dwfl; - - /* Start at zero so if there is just one -e foo.so, - the DSO is shown without address bias. */ - dwfl->offline_next_address = 0; - } - if (dwfl->callbacks != &offline_callbacks) - { - toomany: - argp_error (state, "%s", - _("only one of -e, -p, -k, -K, or --core allowed")); - return EINVAL; - } - opt->e = arg; - } - break; - - case 'p': - { - struct parse_opt *opt = state->hook; - if (opt->dwfl == NULL) - { - Dwfl *dwfl = INTUSE(dwfl_begin) (&proc_callbacks); - int result = INTUSE(dwfl_linux_proc_report) (dwfl, atoi (arg)); - if (result != 0) - return fail (dwfl, result, arg); - - /* Non-fatal to not be able to attach to process, ignore error. */ - INTUSE(dwfl_linux_proc_attach) (dwfl, atoi (arg), false); - - opt->dwfl = dwfl; - } - else - goto toomany; - } - break; - - case 'M': - { - struct parse_opt *opt = state->hook; - if (opt->dwfl == NULL) - { - FILE *f = fopen (arg, "r"); - if (f == NULL) - { - int code = errno; - argp_failure (state, EXIT_FAILURE, code, - "cannot open '%s'", arg); - return code; - } - Dwfl *dwfl = INTUSE(dwfl_begin) (&proc_callbacks); - int result = INTUSE(dwfl_linux_proc_maps_report) (dwfl, f); - fclose (f); - if (result != 0) - return fail (dwfl, result, arg); - opt->dwfl = dwfl; - } - else - goto toomany; - } - break; - - case OPT_COREFILE: - { - struct parse_opt *opt = state->hook; - Dwfl *dwfl = opt->dwfl; - if (dwfl == NULL) - opt->dwfl = dwfl = INTUSE(dwfl_begin) (&offline_callbacks); - /* Permit -e and --core together. */ - else if (dwfl->callbacks != &offline_callbacks) - goto toomany; - opt->core = arg; - } - break; - - case 'k': - { - struct parse_opt *opt = state->hook; - if (opt->dwfl == NULL) - { - Dwfl *dwfl = INTUSE(dwfl_begin) (&kernel_callbacks); - int result = INTUSE(dwfl_linux_kernel_report_kernel) (dwfl); - if (result != 0) - return fail (dwfl, result, _("cannot load kernel symbols")); - result = INTUSE(dwfl_linux_kernel_report_modules) (dwfl); - if (result != 0) - /* Non-fatal to have no modules since we do have the kernel. */ - failure (dwfl, result, _("cannot find kernel modules")); - opt->dwfl = dwfl; - } - else - goto toomany; - } - break; - - case 'K': - { - struct parse_opt *opt = state->hook; - if (opt->dwfl == NULL) - { - Dwfl *dwfl = INTUSE(dwfl_begin) (&offline_callbacks); - int result = INTUSE(dwfl_linux_kernel_report_offline) (dwfl, arg, - NULL); - if (result != 0) - return fail (dwfl, result, _("cannot find kernel or modules")); - opt->dwfl = dwfl; - } - else - goto toomany; - } - break; - - case ARGP_KEY_SUCCESS: - { - struct parse_opt *opt = state->hook; - Dwfl *dwfl = opt->dwfl; - - if (dwfl == NULL) - { - /* Default if no -e, -p, or -k, is "-e a.out". */ - arg = "a.out"; - dwfl = INTUSE(dwfl_begin) (&offline_callbacks); - if (INTUSE(dwfl_report_offline) (dwfl, "", arg, -1) == NULL) - return fail (dwfl, -1, arg); - opt->dwfl = dwfl; - } - - if (opt->core) - { - int fd = open64 (opt->core, O_RDONLY); - if (fd < 0) - { - int code = errno; - argp_failure (state, EXIT_FAILURE, code, - "cannot open '%s'", opt->core); - return code; - } - - Elf *core; - Dwfl_Error error = __libdw_open_file (&fd, &core, true, false); - if (error != DWFL_E_NOERROR) - { - argp_failure (state, EXIT_FAILURE, 0, - _("cannot read ELF core file: %s"), - INTUSE(dwfl_errmsg) (error)); - return error == DWFL_E_ERRNO ? errno : EIO; - } - - int result = INTUSE(dwfl_core_file_report) (dwfl, core, opt->e); - if (result < 0) - { - elf_end (core); - close (fd); - return fail (dwfl, result, opt->core); - } - - /* Non-fatal to not be able to attach to core, ignore error. */ - INTUSE(dwfl_core_file_attach) (dwfl, core); - - /* From now we leak FD and CORE. */ - - if (result == 0) - { - argp_failure (state, EXIT_FAILURE, 0, - _("No modules recognized in core file")); - return ENOENT; - } - } - else if (opt->e) - { - if (INTUSE(dwfl_report_offline) (dwfl, "", opt->e, -1) == NULL) - return fail (dwfl, -1, opt->e); - } - - /* One of the three flavors has done dwfl_begin and some reporting - if we got here. Tie up the Dwfl and return it to the caller of - argp_parse. */ - - int result = INTUSE(dwfl_report_end) (dwfl, NULL, NULL); - assert (result == 0); - - /* Update the input all along, so a parent parser can see it. - As we free OPT the update below will be no longer active. */ - *(Dwfl **) state->input = dwfl; - free (opt); - state->hook = NULL; - } - break; - - case ARGP_KEY_ERROR: - { - struct parse_opt *opt = state->hook; - dwfl_end (opt->dwfl); - free (opt); - state->hook = NULL; - } - break; - - default: - return ARGP_ERR_UNKNOWN; - } - - /* Update the input all along, so a parent parser can see it. */ - struct parse_opt *opt = state->hook; - if (opt) - *(Dwfl **) state->input = opt->dwfl; - - return 0; -} - -static const struct argp libdwfl_argp = - { .options = options, .parser = parse_opt }; - -const struct argp * -dwfl_standard_argp (void) -{ - return &libdwfl_argp; -} diff --git a/src/libdwfl/bzip2.c b/src/libdwfl/bzip2.c deleted file mode 100644 index 8ad4ee5a..00000000 --- a/src/libdwfl/bzip2.c +++ /dev/null @@ -1,4 +0,0 @@ -/* bzlib is almost just like zlib. */ - -#define BZLIB -#include "gzip.c" diff --git a/src/libdwfl/core-file.c b/src/libdwfl/core-file.c deleted file mode 100644 index 50031aed..00000000 --- a/src/libdwfl/core-file.c +++ /dev/null @@ -1,589 +0,0 @@ -/* Core file handling. - Copyright (C) 2008-2010, 2013 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include <config.h> -#include "../libelf/libelfP.h" /* For NOTE_ALIGN. */ -#undef _ -#include "libdwflP.h" -#include <gelf.h> - -#include <sys/param.h> -#include <unistd.h> -#include <endian.h> -#include <byteswap.h> -#include "system.h" - - -/* This is a prototype of what a new libelf interface might be. - This implementation is pessimal for non-mmap cases and should - be replaced by more diddling inside libelf internals. */ -static Elf * -elf_begin_rand (Elf *parent, loff_t offset, loff_t size, loff_t *next) -{ - if (parent == NULL) - return NULL; - - /* On failure return, we update *NEXT to point back at OFFSET. */ - inline Elf *fail (int error) - { - if (next != NULL) - *next = offset; - //__libelf_seterrno (error); - __libdwfl_seterrno (DWFL_E (LIBELF, error)); - return NULL; - } - - loff_t min = (parent->kind == ELF_K_ELF ? - (parent->class == ELFCLASS32 - ? sizeof (Elf32_Ehdr) : sizeof (Elf64_Ehdr)) - : parent->kind == ELF_K_AR ? SARMAG - : 0); - - if (unlikely (offset < min) - || unlikely (offset >= (loff_t) parent->maximum_size)) - return fail (ELF_E_RANGE); - - /* For an archive, fetch just the size field - from the archive header to override SIZE. */ - if (parent->kind == ELF_K_AR) - { - struct ar_hdr h = { .ar_size = "" }; - - if (unlikely (parent->maximum_size - offset < sizeof h)) - return fail (ELF_E_RANGE); - - if (parent->map_address != NULL) - memcpy (h.ar_size, parent->map_address + parent->start_offset + offset, - sizeof h.ar_size); - else if (unlikely (pread_retry (parent->fildes, - h.ar_size, sizeof (h.ar_size), - parent->start_offset + offset - + offsetof (struct ar_hdr, ar_size)) - != sizeof (h.ar_size))) - return fail (ELF_E_READ_ERROR); - - offset += sizeof h; - - char *endp; - size = strtoll (h.ar_size, &endp, 10); - if (unlikely (endp == h.ar_size) - || unlikely ((loff_t) parent->maximum_size - offset < size)) - return fail (ELF_E_INVALID_ARCHIVE); - } - - if (unlikely ((loff_t) parent->maximum_size - offset < size)) - return fail (ELF_E_RANGE); - - /* Even if we fail at this point, update *NEXT to point past the file. */ - if (next != NULL) - *next = offset + size; - - if (unlikely (offset == 0) - && unlikely (size == (loff_t) parent->maximum_size)) - return elf_clone (parent, parent->cmd); - - /* Note the image is guaranteed live only as long as PARENT - lives. Using elf_memory is quite suboptimal if the whole - file is not mmap'd. We really should have something like - a generalization of the archive support. */ - Elf_Data *data = elf_getdata_rawchunk (parent, offset, size, ELF_T_BYTE); - if (data == NULL) - return NULL; - assert ((loff_t) data->d_size == size); - return elf_memory (data->d_buf, size); -} - - -int -dwfl_report_core_segments (Dwfl *dwfl, Elf *elf, size_t phnum, GElf_Phdr *notes) -{ - if (unlikely (dwfl == NULL)) - return -1; - - int result = 0; - - if (notes != NULL) - notes->p_type = PT_NULL; - - for (size_t ndx = 0; result >= 0 && ndx < phnum; ++ndx) - { - GElf_Phdr phdr_mem; - GElf_Phdr *phdr = gelf_getphdr (elf, ndx, &phdr_mem); - if (unlikely (phdr == NULL)) - { - __libdwfl_seterrno (DWFL_E_LIBELF); - return -1; - } - switch (phdr->p_type) - { - case PT_LOAD: - result = dwfl_report_segment (dwfl, ndx, phdr, 0, NULL); - break; - - case PT_NOTE: - if (notes != NULL) - { - *notes = *phdr; - notes = NULL; - } - break; - } - } - - return result; -} - -/* Never read more than this much without mmap. */ -#define MAX_EAGER_COST 8192 - -static bool -core_file_read_eagerly (Dwfl_Module *mod, - void **userdata __attribute__ ((unused)), - const char *name __attribute__ ((unused)), - Dwarf_Addr start __attribute__ ((unused)), - void **buffer, size_t *buffer_available, - GElf_Off cost, GElf_Off worthwhile, - GElf_Off whole, - GElf_Off contiguous __attribute__ ((unused)), - void *arg, Elf **elfp) -{ - Elf *core = arg; - - if (whole <= *buffer_available) - { - /* All there ever was, we already have on hand. */ - - if (core->map_address == NULL) - { - /* We already malloc'd the buffer. */ - *elfp = elf_memory (*buffer, whole); - if (unlikely (*elfp == NULL)) - return false; - - (*elfp)->flags |= ELF_F_MALLOCED; - *buffer = NULL; - *buffer_available = 0; - return true; - } - - /* We can use the image inside the core file directly. */ - *elfp = elf_begin_rand (core, *buffer - core->map_address, whole, NULL); - *buffer = NULL; - *buffer_available = 0; - return *elfp != NULL; - } - - /* We don't have the whole file. - Figure out if this is better than nothing. */ - - if (worthwhile == 0) - /* Caller doesn't think so. */ - return false; - - /* - XXX would like to fall back to partial file via memory - when build id find_elf fails - also, link_map name may give file name from disk better than partial here - requires find_elf hook re-doing the magic to fall back if no file found - */ - - if (mod->build_id_len > 0) - /* There is a build ID that could help us find the whole file, - which might be more useful than what we have. - We'll just rely on that. */ - return false; - - if (core->map_address != NULL) - /* It's cheap to get, so get it. */ - return true; - - /* Only use it if there isn't too much to be read. */ - return cost <= MAX_EAGER_COST; -} - -bool -dwfl_elf_phdr_memory_callback (Dwfl *dwfl, int ndx, - void **buffer, size_t *buffer_available, - GElf_Addr vaddr, - size_t minread, - void *arg) -{ - Elf *elf = arg; - - if (ndx == -1) - { - /* Called for cleanup. */ - if (elf->map_address == NULL) - free (*buffer); - *buffer = NULL; - *buffer_available = 0; - return false; - } - - const GElf_Off align = dwfl->segment_align ?: 1; - GElf_Phdr phdr; - - do - if (unlikely (gelf_getphdr (elf, ndx++, &phdr) == NULL)) - return false; - while (phdr.p_type != PT_LOAD - || ((phdr.p_vaddr + phdr.p_memsz + align - 1) & -align) <= vaddr); - - GElf_Off start = vaddr - phdr.p_vaddr + phdr.p_offset; - GElf_Off end; - GElf_Addr end_vaddr; - - inline void update_end () - { - end = (phdr.p_offset + phdr.p_filesz + align - 1) & -align; - end_vaddr = (phdr.p_vaddr + phdr.p_memsz + align - 1) & -align; - } - - update_end (); - - /* Use following contiguous segments to get towards SIZE. */ - inline bool more (size_t size) - { - while (end <= start || end - start < size) - { - if (phdr.p_filesz < phdr.p_memsz) - /* This segment is truncated, so no following one helps us. */ - return false; - - if (unlikely (gelf_getphdr (elf, ndx++, &phdr) == NULL)) - return false; - - if (phdr.p_type == PT_LOAD) - { - if (phdr.p_offset > end - || phdr.p_vaddr > end_vaddr) - /* It's discontiguous! */ - return false; - - update_end (); - } - } - return true; - } - - /* We need at least this much. */ - if (! more (minread)) - return false; - - /* See how much more we can get of what the caller wants. */ - (void) more (*buffer_available); - - /* If it's already on hand anyway, use as much as there is. */ - if (elf->map_address != NULL) - (void) more (elf->maximum_size - start); - - /* Make sure we don't look past the end of the actual file, - even if the headers tell us to. */ - if (unlikely (end > elf->maximum_size)) - end = elf->maximum_size; - - /* If the file is too small, there is nothing at all to get. */ - if (unlikely (start >= end)) - return false; - - if (elf->map_address != NULL) - { - void *contents = elf->map_address + elf->start_offset + start; - size_t size = end - start; - - if (minread == 0) /* String mode. */ - { - const void *eos = memchr (contents, '\0', size); - if (unlikely (eos == NULL) || unlikely (eos == contents)) - return false; - size = eos + 1 - contents; - } - - if (*buffer == NULL) - { - *buffer = contents; - *buffer_available = size; - } - else - { - *buffer_available = MIN (size, *buffer_available); - memcpy (*buffer, contents, *buffer_available); - } - } - else - { - void *into = *buffer; - if (*buffer == NULL) - { - *buffer_available = MIN (minread ?: 512, - MAX (4096, MIN (end - start, - *buffer_available))); - into = malloc (*buffer_available); - if (unlikely (into == NULL)) - { - __libdwfl_seterrno (DWFL_E_NOMEM); - return false; - } - } - - ssize_t nread = pread_retry (elf->fildes, into, *buffer_available, start); - if (nread < (ssize_t) minread) - { - if (into != *buffer) - free (into); - if (nread < 0) - __libdwfl_seterrno (DWFL_E_ERRNO); - return false; - } - - if (minread == 0) /* String mode. */ - { - const void *eos = memchr (into, '\0', nread); - if (unlikely (eos == NULL) || unlikely (eos == into)) - { - if (*buffer == NULL) - free (into); - return false; - } - nread = eos + 1 - into; - } - - if (*buffer == NULL) - *buffer = into; - *buffer_available = nread; - } - - return true; -} - -/* Free the contents of R_DEBUG_INFO without the R_DEBUG_INFO memory itself. */ - -static void -clear_r_debug_info (struct r_debug_info *r_debug_info) -{ - while (r_debug_info->module != NULL) - { - struct r_debug_info_module *module = r_debug_info->module; - r_debug_info->module = module->next; - elf_end (module->elf); - if (module->fd != -1) - close (module->fd); - free (module); - } -} - -bool -internal_function -__libdwfl_dynamic_vaddr_get (Elf *elf, GElf_Addr *vaddrp) -{ - size_t phnum; - if (unlikely (elf_getphdrnum (elf, &phnum) != 0)) - return false; - 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 false; - if (phdr->p_type == PT_DYNAMIC) - { - *vaddrp = phdr->p_vaddr; - return true; - } - } - return false; -} - -int -dwfl_core_file_report (Dwfl *dwfl, Elf *elf, const char *executable) -{ - size_t phnum; - if (unlikely (elf_getphdrnum (elf, &phnum) != 0)) - { - __libdwfl_seterrno (DWFL_E_LIBELF); - return -1; - } - - free (dwfl->executable_for_core); - if (executable == NULL) - dwfl->executable_for_core = NULL; - else - { - dwfl->executable_for_core = strdup (executable); - if (dwfl->executable_for_core == NULL) - { - __libdwfl_seterrno (DWFL_E_NOMEM); - return -1; - } - } - - /* First report each PT_LOAD segment. */ - GElf_Phdr notes_phdr; - int ndx = dwfl_report_core_segments (dwfl, elf, phnum, ¬es_phdr); - if (unlikely (ndx <= 0)) - return ndx; - - /* Next, we should follow the chain from DT_DEBUG. */ - - const void *auxv = NULL; - const void *note_file = NULL; - size_t auxv_size = 0; - size_t note_file_size = 0; - if (likely (notes_phdr.p_type == PT_NOTE)) - { - /* PT_NOTE -> NT_AUXV -> AT_PHDR -> PT_DYNAMIC -> DT_DEBUG */ - - Elf_Data *notes = elf_getdata_rawchunk (elf, - notes_phdr.p_offset, - notes_phdr.p_filesz, - ELF_T_NHDR); - if (likely (notes != NULL)) - { - size_t pos = 0; - GElf_Nhdr nhdr; - size_t name_pos; - size_t desc_pos; - while ((pos = gelf_getnote (notes, pos, &nhdr, - &name_pos, &desc_pos)) > 0) - if (nhdr.n_namesz == sizeof "CORE" - && !memcmp (notes->d_buf + name_pos, "CORE", sizeof "CORE")) - { - if (nhdr.n_type == NT_AUXV) - { - auxv = notes->d_buf + desc_pos; - auxv_size = nhdr.n_descsz; - } - if (nhdr.n_type == NT_FILE) - { - note_file = notes->d_buf + desc_pos; - note_file_size = nhdr.n_descsz; - } - } - } - } - - /* Now we have NT_AUXV contents. From here on this processing could be - used for a live process with auxv read from /proc. */ - - struct r_debug_info r_debug_info; - memset (&r_debug_info, 0, sizeof r_debug_info); - int retval = dwfl_link_map_report (dwfl, auxv, auxv_size, - dwfl_elf_phdr_memory_callback, elf, - &r_debug_info); - int listed = retval > 0 ? retval : 0; - - /* Now sniff segment contents for modules hinted by information gathered - from DT_DEBUG. */ - - ndx = 0; - do - { - int seg = dwfl_segment_report_module (dwfl, ndx, NULL, - &dwfl_elf_phdr_memory_callback, elf, - core_file_read_eagerly, elf, - note_file, note_file_size, - &r_debug_info); - if (unlikely (seg < 0)) - { - clear_r_debug_info (&r_debug_info); - return seg; - } - if (seg > ndx) - { - ndx = seg; - ++listed; - } - else - ++ndx; - } - while (ndx < (int) phnum); - - /* Now report the modules from dwfl_link_map_report which were not filtered - out by dwfl_segment_report_module. */ - - Dwfl_Module **lastmodp = &dwfl->modulelist; - while (*lastmodp != NULL) - lastmodp = &(*lastmodp)->next; - for (struct r_debug_info_module *module = r_debug_info.module; - module != NULL; module = module->next) - { - if (module->elf == NULL) - continue; - GElf_Addr file_dynamic_vaddr; - if (! __libdwfl_dynamic_vaddr_get (module->elf, &file_dynamic_vaddr)) - continue; - Dwfl_Module *mod; - mod = __libdwfl_report_elf (dwfl, basename (module->name), module->name, - module->fd, module->elf, - module->l_ld - file_dynamic_vaddr, - true, true); - if (mod == NULL) - continue; - ++listed; - module->elf = NULL; - module->fd = -1; - /* Move this module to the end of the list, so that we end - up with a list in the same order as the link_map chain. */ - if (mod->next != NULL) - { - if (*lastmodp != mod) - { - lastmodp = &dwfl->modulelist; - while (*lastmodp != mod) - lastmodp = &(*lastmodp)->next; - } - *lastmodp = mod->next; - mod->next = NULL; - while (*lastmodp != NULL) - lastmodp = &(*lastmodp)->next; - *lastmodp = mod; - } - lastmodp = &mod->next; - } - - clear_r_debug_info (&r_debug_info); - - /* We return the number of modules we found if we found any. - If we found none, we return -1 instead of 0 if there was an - error rather than just nothing found. */ - return listed > 0 ? listed : retval; -} -INTDEF (dwfl_core_file_report) -NEW_VERSION (dwfl_core_file_report, ELFUTILS_0.158) - -#ifdef SHARED -int _compat_without_executable_dwfl_core_file_report (Dwfl *dwfl, Elf *elf); -COMPAT_VERSION_NEWPROTO (dwfl_core_file_report, ELFUTILS_0.146, - without_executable) - -int -_compat_without_executable_dwfl_core_file_report (Dwfl *dwfl, Elf *elf) -{ - return dwfl_core_file_report (dwfl, elf, NULL); -} -#endif diff --git a/src/libdwfl/cu.c b/src/libdwfl/cu.c deleted file mode 100644 index 5ce531bd..00000000 --- a/src/libdwfl/cu.c +++ /dev/null @@ -1,312 +0,0 @@ -/* Keeping track of DWARF compilation units in libdwfl. - Copyright (C) 2005-2010 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" -#include "../libdw/libdwP.h" -#include "../libdw/memory-access.h" -#include <search.h> - - -static inline Dwarf_Arange * -dwar (Dwfl_Module *mod, unsigned int idx) -{ - return &mod->dw->aranges->info[mod->aranges[idx].arange]; -} - - -static Dwfl_Error -addrarange (Dwfl_Module *mod, Dwarf_Addr addr, struct dwfl_arange **arange) -{ - if (mod->aranges == NULL) - { - struct dwfl_arange *aranges = NULL; - Dwarf_Aranges *dwaranges = NULL; - size_t naranges; - if (INTUSE(dwarf_getaranges) (mod->dw, &dwaranges, &naranges) != 0) - return DWFL_E_LIBDW; - - /* If the module has no aranges (when no code is included) we - allocate nothing. */ - if (naranges != 0) - { - aranges = malloc (naranges * sizeof *aranges); - if (unlikely (aranges == NULL)) - return DWFL_E_NOMEM; - - /* libdw has sorted its list by address, which is how we want it. - But the sorted list is full of not-quite-contiguous runs pointing - to the same CU. We don't care about the little gaps inside the - module, we'll consider them part of the surrounding CU anyway. - Collect our own array with just one record for each run of ranges - pointing to one CU. */ - - naranges = 0; - Dwarf_Off lastcu = 0; - for (size_t i = 0; i < dwaranges->naranges; ++i) - if (i == 0 || dwaranges->info[i].offset != lastcu) - { - aranges[naranges].arange = i; - aranges[naranges].cu = NULL; - ++naranges; - lastcu = dwaranges->info[i].offset; - } - } - - /* Store the final array, which is probably much smaller than before. */ - mod->naranges = naranges; - mod->aranges = (realloc (aranges, naranges * sizeof aranges[0]) - ?: aranges); - mod->lazycu += naranges; - } - - /* The address must be inside the module to begin with. */ - addr = dwfl_deadjust_dwarf_addr (mod, addr); - - /* The ranges are sorted by address, so we can use binary search. */ - size_t l = 0, u = mod->naranges; - while (l < u) - { - size_t idx = (l + u) / 2; - Dwarf_Addr start = dwar (mod, idx)->addr; - if (addr < start) - { - u = idx; - continue; - } - else if (addr > start) - { - if (idx + 1 < mod->naranges) - { - if (addr >= dwar (mod, idx + 1)->addr) - { - l = idx + 1; - continue; - } - } - else - { - /* It might be in the last range. */ - const Dwarf_Arange *last - = &mod->dw->aranges->info[mod->dw->aranges->naranges - 1]; - if (addr > last->addr + last->length) - break; - } - } - - *arange = &mod->aranges[idx]; - return DWFL_E_NOERROR; - } - - return DWFL_E_ADDR_OUTOFRANGE; -} - - -static void -nofree (void *arg) -{ - struct dwfl_cu *cu = arg; - if (cu == (void *) -1l) - return; - - assert (cu->mod->lazycu == 0); -} - -/* One reason fewer to keep the lazy lookup table for CUs. */ -static inline void -less_lazy (Dwfl_Module *mod) -{ - if (--mod->lazycu > 0) - return; - - /* We know about all the CUs now, we don't need this table. */ - tdestroy (mod->lazy_cu_root, nofree); - mod->lazy_cu_root = NULL; -} - -static inline Dwarf_Off -cudie_offset (const struct dwfl_cu *cu) -{ - /* These are real CUs, so there never is a type_sig8. Note - initialization of dwkey.start and offset_size in intern_cu () - to see why this calculates the same value for both key and - die.cu search items. */ - return DIE_OFFSET_FROM_CU_OFFSET (cu->die.cu->start, cu->die.cu->offset_size, - 0); -} - -static int -compare_cukey (const void *a, const void *b) -{ - Dwarf_Off a_off = cudie_offset (a); - Dwarf_Off b_off = cudie_offset (b); - return (a_off < b_off) ? -1 : ((a_off > b_off) ? 1 : 0); -} - -/* Intern the CU if necessary. */ -static Dwfl_Error -intern_cu (Dwfl_Module *mod, Dwarf_Off cuoff, struct dwfl_cu **result) -{ - struct Dwarf_CU dwkey; - struct dwfl_cu key; - key.die.cu = &dwkey; - dwkey.offset_size = 0; - dwkey.start = cuoff - (3 * 0 - 4 + 3); - struct dwfl_cu **found = tsearch (&key, &mod->lazy_cu_root, &compare_cukey); - if (unlikely (found == NULL)) - return DWFL_E_NOMEM; - - if (*found == &key || *found == NULL) - { - if (unlikely (cuoff + 4 >= mod->dw->sectiondata[IDX_debug_info]->d_size)) - { - /* This is the EOF marker. Now we have interned all the CUs. - One increment in MOD->lazycu counts not having hit EOF yet. */ - *found = (void *) -1l; - less_lazy (mod); - } - else - { - /* This is a new entry, meaning we haven't looked at this CU. */ - - *found = NULL; - - struct dwfl_cu *cu = malloc (sizeof *cu); - if (unlikely (cu == NULL)) - return DWFL_E_NOMEM; - - cu->mod = mod; - cu->next = NULL; - cu->lines = NULL; - - /* XXX use non-searching lookup */ - Dwarf_Die *die = INTUSE(dwarf_offdie) (mod->dw, cuoff, &cu->die); - if (die == NULL) - { - free (cu); - return DWFL_E_LIBDW; - } - assert (die == &cu->die); - - struct dwfl_cu **newvec = realloc (mod->cu, ((mod->ncu + 1) - * sizeof (mod->cu[0]))); - if (newvec == NULL) - { - free (cu); - return DWFL_E_NOMEM; - } - mod->cu = newvec; - - mod->cu[mod->ncu++] = cu; - if (cu->die.cu->start == 0) - mod->first_cu = cu; - - *found = cu; - } - } - - *result = *found; - return DWFL_E_NOERROR; -} - - -/* Traverse all the CUs in the module. */ - -Dwfl_Error -internal_function -__libdwfl_nextcu (Dwfl_Module *mod, struct dwfl_cu *lastcu, - struct dwfl_cu **cu) -{ - Dwarf_Off cuoff; - struct dwfl_cu **nextp; - - if (lastcu == NULL) - { - /* Start the traversal. */ - cuoff = 0; - nextp = &mod->first_cu; - } - else - { - /* Continue following LASTCU. */ - cuoff = lastcu->die.cu->end; - nextp = &lastcu->next; - } - - if (*nextp == NULL) - { - size_t cuhdrsz; - Dwarf_Off nextoff; - int end = INTUSE(dwarf_nextcu) (mod->dw, cuoff, &nextoff, &cuhdrsz, - NULL, NULL, NULL); - if (end < 0) - return DWFL_E_LIBDW; - if (end > 0) - { - *cu = NULL; - return DWFL_E_NOERROR; - } - - Dwfl_Error result = intern_cu (mod, cuoff + cuhdrsz, nextp); - if (result != DWFL_E_NOERROR) - return result; - - if ((*nextp)->next == NULL && nextoff == (Dwarf_Off) -1l) - (*nextp)->next = (void *) -1l; - } - - *cu = *nextp == (void *) -1l ? NULL : *nextp; - return DWFL_E_NOERROR; -} - - -/* Intern the CU arange points to, if necessary. */ - -static Dwfl_Error -arangecu (Dwfl_Module *mod, struct dwfl_arange *arange, struct dwfl_cu **cu) -{ - if (arange->cu == NULL) - { - const Dwarf_Arange *dwarange = &mod->dw->aranges->info[arange->arange]; - Dwfl_Error result = intern_cu (mod, dwarange->offset, &arange->cu); - if (result != DWFL_E_NOERROR) - return result; - assert (arange->cu != NULL && arange->cu != (void *) -1l); - less_lazy (mod); /* Each arange with null ->cu counts once. */ - } - - *cu = arange->cu; - return DWFL_E_NOERROR; -} - -Dwfl_Error -internal_function -__libdwfl_addrcu (Dwfl_Module *mod, Dwarf_Addr addr, struct dwfl_cu **cu) -{ - struct dwfl_arange *arange; - return addrarange (mod, addr, &arange) ?: arangecu (mod, arange, cu); -} diff --git a/src/libdwfl/derelocate.c b/src/libdwfl/derelocate.c deleted file mode 100644 index da679089..00000000 --- a/src/libdwfl/derelocate.c +++ /dev/null @@ -1,401 +0,0 @@ -/* Recover relocatibility for addresses computed from debug information. - Copyright (C) 2005-2010, 2013 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" - -struct dwfl_relocation -{ - size_t count; - struct - { - Elf_Scn *scn; - Elf_Scn *relocs; - const char *name; - GElf_Addr start, end; - } refs[0]; -}; - - -struct secref -{ - struct secref *next; - Elf_Scn *scn; - Elf_Scn *relocs; - const char *name; - GElf_Addr start, end; -}; - -static int -compare_secrefs (const void *a, const void *b) -{ - struct secref *const *p1 = a; - struct secref *const *p2 = b; - - /* No signed difference calculation is correct here, since the - terms are unsigned and could be more than INT64_MAX apart. */ - if ((*p1)->start < (*p2)->start) - return -1; - if ((*p1)->start > (*p2)->start) - return 1; - - return 0; -} - -static int -cache_sections (Dwfl_Module *mod) -{ - if (likely (mod->reloc_info != NULL)) - return mod->reloc_info->count; - - struct secref *refs = NULL; - size_t nrefs = 0; - - size_t shstrndx; - if (unlikely (elf_getshdrstrndx (mod->main.elf, &shstrndx) < 0)) - { - elf_error: - __libdwfl_seterrno (DWFL_E_LIBELF); - return -1; - } - - bool check_reloc_sections = false; - Elf_Scn *scn = NULL; - while ((scn = elf_nextscn (mod->main.elf, scn)) != NULL) - { - GElf_Shdr shdr_mem; - GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); - if (shdr == NULL) - goto elf_error; - - if ((shdr->sh_flags & SHF_ALLOC) && shdr->sh_addr == 0 - && mod->e_type == ET_REL) - { - /* This section might not yet have been looked at. */ - if (__libdwfl_relocate_value (mod, mod->main.elf, &shstrndx, - elf_ndxscn (scn), - &shdr->sh_addr) != DWFL_E_NOERROR) - continue; - shdr = gelf_getshdr (scn, &shdr_mem); - if (unlikely (shdr == NULL)) - goto elf_error; - } - - if (shdr->sh_flags & SHF_ALLOC) - { - const char *name = elf_strptr (mod->main.elf, shstrndx, - shdr->sh_name); - if (unlikely (name == NULL)) - goto elf_error; - - struct secref *newref = alloca (sizeof *newref); - newref->scn = scn; - newref->relocs = NULL; - newref->name = name; - newref->start = dwfl_adjusted_address (mod, shdr->sh_addr); - newref->end = newref->start + shdr->sh_size; - newref->next = refs; - refs = newref; - ++nrefs; - } - - if (mod->e_type == ET_REL - && shdr->sh_size != 0 - && (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA) - && mod->dwfl->callbacks->section_address != NULL) - { - if (shdr->sh_info < elf_ndxscn (scn)) - { - /* We've already looked at the section these relocs apply to. */ - Elf_Scn *tscn = elf_getscn (mod->main.elf, shdr->sh_info); - if (likely (tscn != NULL)) - for (struct secref *sec = refs; sec != NULL; sec = sec->next) - if (sec->scn == tscn) - { - sec->relocs = scn; - break; - } - } - else - /* We'll have to do a second pass. */ - check_reloc_sections = true; - } - } - - mod->reloc_info = malloc (offsetof (struct dwfl_relocation, refs[nrefs])); - if (mod->reloc_info == NULL) - { - __libdwfl_seterrno (DWFL_E_NOMEM); - return -1; - } - - struct secref **sortrefs = alloca (nrefs * sizeof sortrefs[0]); - for (size_t i = nrefs; i-- > 0; refs = refs->next) - sortrefs[i] = refs; - assert (refs == NULL); - - qsort (sortrefs, nrefs, sizeof sortrefs[0], &compare_secrefs); - - mod->reloc_info->count = nrefs; - for (size_t i = 0; i < nrefs; ++i) - { - mod->reloc_info->refs[i].name = sortrefs[i]->name; - mod->reloc_info->refs[i].scn = sortrefs[i]->scn; - mod->reloc_info->refs[i].relocs = sortrefs[i]->relocs; - mod->reloc_info->refs[i].start = sortrefs[i]->start; - mod->reloc_info->refs[i].end = sortrefs[i]->end; - } - - if (unlikely (check_reloc_sections)) - { - /* There was a reloc section that preceded its target section. - So we have to scan again now that we have cached all the - possible target sections we care about. */ - - scn = NULL; - while ((scn = elf_nextscn (mod->main.elf, scn)) != NULL) - { - GElf_Shdr shdr_mem; - GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); - if (shdr == NULL) - goto elf_error; - - if (shdr->sh_size != 0 - && (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)) - { - Elf_Scn *tscn = elf_getscn (mod->main.elf, shdr->sh_info); - if (likely (tscn != NULL)) - for (size_t i = 0; i < nrefs; ++i) - if (mod->reloc_info->refs[i].scn == tscn) - { - mod->reloc_info->refs[i].relocs = scn; - break; - } - } - } - } - - return nrefs; -} - - -int -dwfl_module_relocations (Dwfl_Module *mod) -{ - if (mod == NULL) - return -1; - - switch (mod->e_type) - { - case ET_REL: - return cache_sections (mod); - - case ET_DYN: - return 1; - - case ET_EXEC: - assert (mod->main.vaddr == mod->low_addr); - break; - } - - return 0; -} - -const char * -dwfl_module_relocation_info (Dwfl_Module *mod, unsigned int idx, - Elf32_Word *shndxp) -{ - if (mod == NULL) - return NULL; - - switch (mod->e_type) - { - case ET_REL: - break; - - case ET_DYN: - if (idx != 0) - return NULL; - if (shndxp) - *shndxp = SHN_ABS; - return ""; - - default: - return NULL; - } - - if (cache_sections (mod) < 0) - return NULL; - - struct dwfl_relocation *sections = mod->reloc_info; - - if (idx >= sections->count) - return NULL; - - if (shndxp) - *shndxp = elf_ndxscn (sections->refs[idx].scn); - - return sections->refs[idx].name; -} - -/* Check that MOD is valid and make sure its relocation has been done. */ -static bool -check_module (Dwfl_Module *mod) -{ - if (INTUSE(dwfl_module_getsymtab) (mod) < 0) - { - Dwfl_Error error = dwfl_errno (); - if (error != DWFL_E_NO_SYMTAB) - { - __libdwfl_seterrno (error); - return true; - } - } - - if (mod->dw == NULL) - { - Dwarf_Addr bias; - if (INTUSE(dwfl_module_getdwarf) (mod, &bias) == NULL) - { - Dwfl_Error error = dwfl_errno (); - if (error != DWFL_E_NO_DWARF) - { - __libdwfl_seterrno (error); - return true; - } - } - } - - return false; -} - -/* Find the index in MOD->reloc_info.refs containing *ADDR. */ -static int -find_section (Dwfl_Module *mod, Dwarf_Addr *addr) -{ - if (cache_sections (mod) < 0) - return -1; - - struct dwfl_relocation *sections = mod->reloc_info; - - /* The sections are sorted by address, so we can use binary search. */ - size_t l = 0, u = sections->count; - while (l < u) - { - size_t idx = (l + u) / 2; - if (*addr < sections->refs[idx].start) - u = idx; - else if (*addr > sections->refs[idx].end) - l = idx + 1; - else - { - /* Consider the limit of a section to be inside it, unless it's - inside the next one. A section limit address can appear in - line records. */ - if (*addr == sections->refs[idx].end - && idx + 1 < sections->count - && *addr == sections->refs[idx + 1].start) - ++idx; - - *addr -= sections->refs[idx].start; - return idx; - } - } - - __libdwfl_seterrno (DWFL_E (LIBDW, DWARF_E_NO_MATCH)); - return -1; -} - -size_t -internal_function -__libdwfl_find_section_ndx (Dwfl_Module *mod, Dwarf_Addr *addr) -{ - int idx = find_section (mod, addr); - if (unlikely (idx == -1)) - return SHN_UNDEF; - - return elf_ndxscn (mod->reloc_info->refs[idx].scn); -} - -int -dwfl_module_relocate_address (Dwfl_Module *mod, Dwarf_Addr *addr) -{ - if (unlikely (check_module (mod))) - return -1; - - switch (mod->e_type) - { - case ET_REL: - return find_section (mod, addr); - - case ET_DYN: - /* All relative to first and only relocation base: module start. */ - *addr -= mod->low_addr; - break; - - default: - /* Already absolute, dwfl_module_relocations returned zero. We - shouldn't really have been called, but it's a harmless no-op. */ - break; - } - - return 0; -} -INTDEF (dwfl_module_relocate_address) - -Elf_Scn * -dwfl_module_address_section (Dwfl_Module *mod, Dwarf_Addr *address, - Dwarf_Addr *bias) -{ - if (check_module (mod)) - return NULL; - - int idx = find_section (mod, address); - if (idx < 0) - return NULL; - - if (mod->reloc_info->refs[idx].relocs != NULL) - { - assert (mod->e_type == ET_REL); - - Elf_Scn *tscn = mod->reloc_info->refs[idx].scn; - Elf_Scn *relocscn = mod->reloc_info->refs[idx].relocs; - Dwfl_Error result = __libdwfl_relocate_section (mod, mod->main.elf, - relocscn, tscn, true); - if (likely (result == DWFL_E_NOERROR)) - mod->reloc_info->refs[idx].relocs = NULL; - else - { - __libdwfl_seterrno (result); - return NULL; - } - } - - *bias = dwfl_adjusted_address (mod, 0); - return mod->reloc_info->refs[idx].scn; -} -INTDEF (dwfl_module_address_section) diff --git a/src/libdwfl/dwfl_addrdie.c b/src/libdwfl/dwfl_addrdie.c deleted file mode 100644 index 1e9b3ab6..00000000 --- a/src/libdwfl/dwfl_addrdie.c +++ /dev/null @@ -1,36 +0,0 @@ -/* Fetch CU DIE from address. - Copyright (C) 2005 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" - -Dwarf_Die * -dwfl_addrdie (Dwfl *dwfl, Dwarf_Addr addr, Dwarf_Addr *bias) -{ - return INTUSE(dwfl_module_addrdie) (INTUSE(dwfl_addrmodule) (dwfl, addr), - addr, bias); -} diff --git a/src/libdwfl/dwfl_addrdwarf.c b/src/libdwfl/dwfl_addrdwarf.c deleted file mode 100644 index ba412eca..00000000 --- a/src/libdwfl/dwfl_addrdwarf.c +++ /dev/null @@ -1,37 +0,0 @@ -/* Fetch libdw handle from address. - Copyright (C) 2005 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" - -Dwarf * -dwfl_addrdwarf (Dwfl *dwfl, Dwarf_Addr address, Dwarf_Addr *bias) -{ - return INTUSE(dwfl_module_getdwarf) (INTUSE(dwfl_addrmodule) (dwfl, address), - bias); -} -INTDEF (dwfl_addrdwarf) diff --git a/src/libdwfl/dwfl_addrmodule.c b/src/libdwfl/dwfl_addrmodule.c deleted file mode 100644 index 9234eb71..00000000 --- a/src/libdwfl/dwfl_addrmodule.c +++ /dev/null @@ -1,38 +0,0 @@ -/* Find module containing address. - Copyright (C) 2005, 2006, 2007, 2008 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" - -Dwfl_Module * -dwfl_addrmodule (Dwfl *dwfl, Dwarf_Addr address) -{ - Dwfl_Module *mod; - (void) INTUSE(dwfl_addrsegment) (dwfl, address, &mod); - return mod; -} -INTDEF (dwfl_addrmodule) diff --git a/src/libdwfl/dwfl_begin.c b/src/libdwfl/dwfl_begin.c deleted file mode 100644 index 44c16a92..00000000 --- a/src/libdwfl/dwfl_begin.c +++ /dev/null @@ -1,51 +0,0 @@ -/* Set up a session using libdwfl. - Copyright (C) 2005 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" - -Dwfl * -dwfl_begin (const Dwfl_Callbacks *callbacks) -{ - if (elf_version (EV_CURRENT) == EV_NONE) - { - __libdwfl_seterrno (DWFL_E_LIBELF); - return NULL; - } - - Dwfl *dwfl = calloc (1, sizeof *dwfl); - if (dwfl == NULL) - __libdwfl_seterrno (DWFL_E_NOMEM); - else - { - dwfl->callbacks = callbacks; - dwfl->offline_next_address = OFFLINE_REDZONE; - } - - return dwfl; -} -INTDEF (dwfl_begin) diff --git a/src/libdwfl/dwfl_build_id_find_debuginfo.c b/src/libdwfl/dwfl_build_id_find_debuginfo.c deleted file mode 100644 index f1c64bcd..00000000 --- a/src/libdwfl/dwfl_build_id_find_debuginfo.c +++ /dev/null @@ -1,128 +0,0 @@ -/* Find the debuginfo file for a module from its build ID. - Copyright (C) 2007, 2009, 2014 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" -#include <unistd.h> - - -int -dwfl_build_id_find_debuginfo (Dwfl_Module *mod, - void **userdata __attribute__ ((unused)), - const char *modname __attribute__ ((unused)), - Dwarf_Addr base __attribute__ ((unused)), - const char *file __attribute__ ((unused)), - const char *debuglink __attribute__ ((unused)), - GElf_Word crc __attribute__ ((unused)), - char **debuginfo_file_name) -{ - int fd = -1; - - /* Are we looking for a separate debug file for the main file or for - an alternate (dwz multi) debug file? Alternatively we could check - whether the dwbias == -1. */ - if (mod->dw != NULL) - { - const void *build_id; - const char *altname; - ssize_t build_id_len = INTUSE(dwelf_dwarf_gnu_debugaltlink) (mod->dw, - &altname, - &build_id); - if (build_id_len > 0) - fd = __libdwfl_open_by_build_id (mod, true, debuginfo_file_name, - build_id_len, build_id); - - if (fd >= 0) - { - /* We need to open an Elf handle on the file so we can check its - build ID note for validation. Backdoor the handle into the - module data structure since we had to open it early anyway. */ - Dwfl_Error error = __libdw_open_file (&fd, &mod->alt_elf, - true, false); - if (error != DWFL_E_NOERROR) - __libdwfl_seterrno (error); - else - { - const void *alt_build_id; - ssize_t alt_len = INTUSE(dwelf_elf_gnu_build_id) (mod->alt_elf, - &alt_build_id); - if (alt_len > 0 && alt_len == build_id_len - && memcmp (build_id, alt_build_id, alt_len) == 0) - return fd; - else - { - /* A mismatch! */ - elf_end (mod->alt_elf); - mod->alt_elf = NULL; - close (fd); - fd = -1; - } - free (*debuginfo_file_name); - *debuginfo_file_name = NULL; - errno = 0; - } - } - return fd; - } - - /* We don't even have the Dwarf yet and it isn't in the main file. - Try to find separate debug file now using the module build id. */ - const unsigned char *bits; - GElf_Addr vaddr; - - if (INTUSE(dwfl_module_build_id) (mod, &bits, &vaddr) > 0) - fd = __libdwfl_open_mod_by_build_id (mod, true, debuginfo_file_name); - if (fd >= 0) - { - /* We need to open an Elf handle on the file so we can check its - build ID note for validation. Backdoor the handle into the - module data structure since we had to open it early anyway. */ - Dwfl_Error error = __libdw_open_file (&fd, &mod->debug.elf, true, false); - if (error != DWFL_E_NOERROR) - __libdwfl_seterrno (error); - else if (likely (__libdwfl_find_build_id (mod, false, - mod->debug.elf) == 2)) - { - /* Also backdoor the gratuitous flag. */ - mod->debug.valid = true; - return fd; - } - else - { - /* A mismatch! */ - elf_end (mod->debug.elf); - mod->debug.elf = NULL; - close (fd); - fd = -1; - } - free (*debuginfo_file_name); - *debuginfo_file_name = NULL; - errno = 0; - } - return fd; -} -INTDEF (dwfl_build_id_find_debuginfo) diff --git a/src/libdwfl/dwfl_build_id_find_elf.c b/src/libdwfl/dwfl_build_id_find_elf.c deleted file mode 100644 index 062aad1f..00000000 --- a/src/libdwfl/dwfl_build_id_find_elf.c +++ /dev/null @@ -1,174 +0,0 @@ -/* Find an ELF file for a module from its build ID. - Copyright (C) 2007-2010, 2014 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" -#include <inttypes.h> -#include <fcntl.h> -#include <unistd.h> - - -int -internal_function -__libdwfl_open_by_build_id (Dwfl_Module *mod, bool debug, char **file_name, - const size_t id_len, const uint8_t *id) -{ - /* Search debuginfo_path directories' .build-id/ subdirectories. */ - - char id_name[sizeof "/.build-id/" + 1 + id_len * 2 + sizeof ".debug" - 1]; - strcpy (id_name, "/.build-id/"); - int n = snprintf (&id_name[sizeof "/.build-id/" - 1], - 4, "%02" PRIx8 "/", (uint8_t) id[0]); - assert (n == 3); - for (size_t i = 1; i < id_len; ++i) - { - n = snprintf (&id_name[sizeof "/.build-id/" - 1 + 3 + (i - 1) * 2], - 3, "%02" PRIx8, (uint8_t) id[i]); - assert (n == 2); - } - if (debug) - strcpy (&id_name[sizeof "/.build-id/" - 1 + 3 + (id_len - 1) * 2], - ".debug"); - - const Dwfl_Callbacks *const cb = mod->dwfl->callbacks; - char *path = strdupa ((cb->debuginfo_path ? *cb->debuginfo_path : NULL) - ?: DEFAULT_DEBUGINFO_PATH); - - int fd = -1; - char *dir; - while (fd < 0 && (dir = strsep (&path, ":")) != NULL) - { - if (dir[0] == '+' || dir[0] == '-') - ++dir; - - /* Only absolute directory names are useful to us. */ - if (dir[0] != '/') - continue; - - size_t dirlen = strlen (dir); - char *name = malloc (dirlen + sizeof id_name); - if (unlikely (name == NULL)) - break; - memcpy (mempcpy (name, dir, dirlen), id_name, sizeof id_name); - - fd = TEMP_FAILURE_RETRY (open64 (name, O_RDONLY)); - if (fd >= 0) - { - if (*file_name != NULL) - free (*file_name); - *file_name = canonicalize_file_name (name); - if (*file_name == NULL) - { - *file_name = name; - name = NULL; - } - } - free (name); - } - - /* If we simply found nothing, clear errno. If we had some other error - with the file, report that. Possibly this should treat other errors - like ENOENT too. But ignoring all errors could mask some that should - be reported. */ - if (fd < 0 && errno == ENOENT) - errno = 0; - - return fd; -} - -int -internal_function -__libdwfl_open_mod_by_build_id (Dwfl_Module *mod, bool debug, char **file_name) -{ - /* If *FILE_NAME was primed into the module, leave it there - as the fallback when we have nothing to offer. */ - errno = 0; - if (mod->build_id_len <= 0) - return -1; - - const size_t id_len = mod->build_id_len; - const uint8_t *id = mod->build_id_bits; - - return __libdwfl_open_by_build_id (mod, debug, file_name, id_len, id); -} - -int -dwfl_build_id_find_elf (Dwfl_Module *mod, - void **userdata __attribute__ ((unused)), - const char *modname __attribute__ ((unused)), - Dwarf_Addr base __attribute__ ((unused)), - char **file_name, Elf **elfp) -{ - *elfp = NULL; - if (mod->is_executable && mod->dwfl->executable_for_core != NULL) - { - /* When dwfl_core_file_report was called with a non-NULL executable file - name this callback will replace the Dwfl_Module main.name with the - recorded executable file when MOD was identified as main executable - (which then triggers opening and reporting of the executable). */ - int fd = open64 (mod->dwfl->executable_for_core, O_RDONLY); - if (fd >= 0) - { - *file_name = strdup (mod->dwfl->executable_for_core); - if (*file_name != NULL) - return fd; - else - close (fd); - } - } - int fd = __libdwfl_open_mod_by_build_id (mod, false, file_name); - if (fd >= 0) - { - Dwfl_Error error = __libdw_open_file (&fd, elfp, true, false); - if (error != DWFL_E_NOERROR) - __libdwfl_seterrno (error); - else if (__libdwfl_find_build_id (mod, false, *elfp) == 2) - { - /* This is a backdoor signal to short-circuit the ID refresh. */ - mod->main.valid = true; - return fd; - } - else - { - /* This file does not contain the ID it should! */ - elf_end (*elfp); - *elfp = NULL; - close (fd); - fd = -1; - } - free (*file_name); - *file_name = NULL; - } - else if (errno == 0 && mod->build_id_len > 0) - /* Setting this with no file yet loaded is a marker that - the build ID is authoritative even if we also know a - putative *FILE_NAME. */ - mod->main.valid = true; - - return fd; -} -INTDEF (dwfl_build_id_find_elf) diff --git a/src/libdwfl/dwfl_cumodule.c b/src/libdwfl/dwfl_cumodule.c deleted file mode 100644 index c5cf004d..00000000 --- a/src/libdwfl/dwfl_cumodule.c +++ /dev/null @@ -1,36 +0,0 @@ -/* Find the module for a CU DIE previously returned by libdwfl. - Copyright (C) 2005 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" - -Dwfl_Module * -dwfl_cumodule (Dwarf_Die *cudie) -{ - struct dwfl_cu *cu = (struct dwfl_cu *) cudie; - return cu->mod; -} diff --git a/src/libdwfl/dwfl_dwarf_line.c b/src/libdwfl/dwfl_dwarf_line.c deleted file mode 100644 index e96f859a..00000000 --- a/src/libdwfl/dwfl_dwarf_line.c +++ /dev/null @@ -1,43 +0,0 @@ -/* Get information from a source line record returned by libdwfl. - Copyright (C) 2010 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" -#include "../libdw/libdwP.h" - -Dwarf_Line * -dwfl_dwarf_line (Dwfl_Line *line, Dwarf_Addr *bias) -{ - if (line == NULL) - return NULL; - - struct dwfl_cu *cu = dwfl_linecu (line); - const Dwarf_Line *info = &cu->die.cu->lines->info[line->idx]; - - *bias = dwfl_adjusted_dwarf_addr (cu->mod, 0); - return (Dwarf_Line *) info; -} diff --git a/src/libdwfl/dwfl_end.c b/src/libdwfl/dwfl_end.c deleted file mode 100644 index 33cae48c..00000000 --- a/src/libdwfl/dwfl_end.c +++ /dev/null @@ -1,54 +0,0 @@ -/* Finish a session using libdwfl. - Copyright (C) 2005, 2008, 2012-2013 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" - -void -dwfl_end (Dwfl *dwfl) -{ - if (dwfl == NULL) - return; - - if (dwfl->process) - __libdwfl_process_free (dwfl->process); - - free (dwfl->lookup_addr); - free (dwfl->lookup_module); - free (dwfl->lookup_segndx); - - Dwfl_Module *next = dwfl->modulelist; - while (next != NULL) - { - Dwfl_Module *dead = next; - next = dead->next; - __libdwfl_module_free (dead); - } - - free (dwfl->executable_for_core); - free (dwfl); -} diff --git a/src/libdwfl/dwfl_error.c b/src/libdwfl/dwfl_error.c deleted file mode 100644 index d9ca9e7e..00000000 --- a/src/libdwfl/dwfl_error.c +++ /dev/null @@ -1,159 +0,0 @@ -/* Error handling in libdwfl. - Copyright (C) 2005-2010 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - -#include <assert.h> -#include <libintl.h> -#include <stdbool.h> -#include <stdint.h> -#include <stdlib.h> -#include <errno.h> - -#include "libdwflP.h" - - -/* The error number. */ -static __thread int global_error; - - -int -dwfl_errno (void) -{ - int result = global_error; - global_error = DWFL_E_NOERROR; - return result; -} -INTDEF (dwfl_errno) - - -static const struct msgtable -{ -#define DWFL_ERROR(name, text) char msg_##name[sizeof text]; - DWFL_ERRORS -#undef DWFL_ERROR -} msgtable = - { -#define DWFL_ERROR(name, text) text, - DWFL_ERRORS -#undef DWFL_ERROR - }; -#define msgstr (&msgtable.msg_NOERROR[0]) - -static const uint_fast16_t msgidx[] = -{ -#define DWFL_ERROR(name, text) \ - [DWFL_E_##name] = offsetof (struct msgtable, msg_##name), - DWFL_ERRORS -#undef DWFL_ERROR -}; -#define nmsgidx (sizeof msgidx / sizeof msgidx[0]) - - -static inline int -canonicalize (Dwfl_Error error) -{ - unsigned int value; - - switch (error) - { - default: - value = error; - if ((value &~ 0xffff) != 0) - break; - assert (value < nmsgidx); - break; - case DWFL_E_ERRNO: - value = DWFL_E (ERRNO, errno); - break; - case DWFL_E_LIBELF: - value = DWFL_E (LIBELF, elf_errno ()); - break; - case DWFL_E_LIBDW: - value = DWFL_E (LIBDW, INTUSE(dwarf_errno) ()); - break; -#if 0 - DWFL_E_LIBEBL: - value = DWFL_E (LIBEBL, ebl_errno ()); - break; -#endif - } - - return value; -} - -int -internal_function -__libdwfl_canon_error (Dwfl_Error error) -{ - return canonicalize (error); -} - -void -internal_function -__libdwfl_seterrno (Dwfl_Error error) -{ - global_error = canonicalize (error); -} - - -const char * -dwfl_errmsg (error) - int error; -{ - if (error == 0 || error == -1) - { - int last_error = global_error; - - if (error == 0 && last_error == 0) - return NULL; - - error = last_error; - global_error = DWFL_E_NOERROR; - } - - switch (error &~ 0xffff) - { - case OTHER_ERROR (ERRNO): - return strerror_r (error & 0xffff, "bad", 0); - case OTHER_ERROR (LIBELF): - return elf_errmsg (error & 0xffff); - case OTHER_ERROR (LIBDW): - return INTUSE(dwarf_errmsg) (error & 0xffff); -#if 0 - case OTHER_ERROR (LIBEBL): - return ebl_errmsg (error & 0xffff); -#endif - } - - return _(&msgstr[msgidx[(unsigned int) error < nmsgidx - ? error : DWFL_E_UNKNOWN_ERROR]]); -} -INTDEF (dwfl_errmsg) diff --git a/src/libdwfl/dwfl_frame.c b/src/libdwfl/dwfl_frame.c deleted file mode 100644 index f6f86c0d..00000000 --- a/src/libdwfl/dwfl_frame.c +++ /dev/null @@ -1,474 +0,0 @@ -/* Get Dwarf Frame state for target PID or core file. - Copyright (C) 2013, 2014 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" -#include <sys/ptrace.h> -#include <unistd.h> - -/* Set STATE->pc_set from STATE->regs according to the backend. Return true on - success, false on error. */ -static bool -state_fetch_pc (Dwfl_Frame *state) -{ - switch (state->pc_state) - { - case DWFL_FRAME_STATE_PC_SET: - return true; - case DWFL_FRAME_STATE_PC_UNDEFINED: - abort (); - case DWFL_FRAME_STATE_ERROR: - { - Ebl *ebl = state->thread->process->ebl; - Dwarf_CIE abi_info; - if (ebl_abi_cfi (ebl, &abi_info) != 0) - { - __libdwfl_seterrno (DWFL_E_LIBEBL); - return false; - } - unsigned ra = abi_info.return_address_register; - /* dwarf_frame_state_reg_is_set is not applied here. */ - if (ra >= ebl_frame_nregs (ebl)) - { - __libdwfl_seterrno (DWFL_E_LIBEBL_BAD); - return false; - } - state->pc = state->regs[ra]; - state->pc_state = DWFL_FRAME_STATE_PC_SET; - } - return true; - } - abort (); -} - -/* Do not call it on your own, to be used by thread_* functions only. */ - -static void -state_free (Dwfl_Frame *state) -{ - Dwfl_Thread *thread = state->thread; - assert (thread->unwound == state); - thread->unwound = state->unwound; - free (state); -} - -static void -thread_free_all_states (Dwfl_Thread *thread) -{ - while (thread->unwound) - state_free (thread->unwound); -} - -static Dwfl_Frame * -state_alloc (Dwfl_Thread *thread) -{ - assert (thread->unwound == NULL); - Ebl *ebl = thread->process->ebl; - size_t nregs = ebl_frame_nregs (ebl); - if (nregs == 0) - return NULL; - assert (nregs < sizeof (((Dwfl_Frame *) NULL)->regs_set) * 8); - Dwfl_Frame *state = malloc (sizeof (*state) + sizeof (*state->regs) * nregs); - if (state == NULL) - return NULL; - state->thread = thread; - state->signal_frame = false; - state->initial_frame = true; - state->pc_state = DWFL_FRAME_STATE_ERROR; - memset (state->regs_set, 0, sizeof (state->regs_set)); - thread->unwound = state; - state->unwound = NULL; - return state; -} - -void -internal_function -__libdwfl_process_free (Dwfl_Process *process) -{ - Dwfl *dwfl = process->dwfl; - if (process->callbacks->detach != NULL) - process->callbacks->detach (dwfl, process->callbacks_arg); - assert (dwfl->process == process); - dwfl->process = NULL; - if (process->ebl_close) - ebl_closebackend (process->ebl); - free (process); - dwfl->attacherr = DWFL_E_NOERROR; -} - -/* Allocate new Dwfl_Process for DWFL. */ -static void -process_alloc (Dwfl *dwfl) -{ - Dwfl_Process *process = malloc (sizeof (*process)); - if (process == NULL) - return; - process->dwfl = dwfl; - dwfl->process = process; -} - -bool -dwfl_attach_state (Dwfl *dwfl, Elf *elf, pid_t pid, - const Dwfl_Thread_Callbacks *thread_callbacks, void *arg) -{ - if (dwfl->process != NULL) - { - __libdwfl_seterrno (DWFL_E_ATTACH_STATE_CONFLICT); - return false; - } - - /* Reset any previous error, we are just going to try again. */ - dwfl->attacherr = DWFL_E_NOERROR; - if (thread_callbacks == NULL || thread_callbacks->next_thread == NULL - || thread_callbacks->set_initial_registers == NULL) - { - dwfl->attacherr = DWFL_E_INVALID_ARGUMENT; - fail: - dwfl->attacherr = __libdwfl_canon_error (dwfl->attacherr); - __libdwfl_seterrno (dwfl->attacherr); - return false; - } - - Ebl *ebl; - bool ebl_close; - if (elf != NULL) - { - ebl = ebl_openbackend (elf); - ebl_close = true; - } - else - { - ebl = NULL; - for (Dwfl_Module *mod = dwfl->modulelist; mod != NULL; mod = mod->next) - { - /* Reading of the vDSO or (deleted) modules may fail as - /proc/PID/mem is unreadable without PTRACE_ATTACH and - we may not be PTRACE_ATTACH-ed now. MOD would not be - re-read later to unwind it when we are already - PTRACE_ATTACH-ed to PID. This happens when this function - is called from dwfl_linux_proc_attach with elf == NULL. - __libdwfl_module_getebl will call __libdwfl_getelf which - will call the find_elf callback. */ - if (strncmp (mod->name, "[vdso: ", 7) == 0 - || strcmp (strrchr (mod->name, ' ') ?: "", - " (deleted)") == 0) - continue; - Dwfl_Error error = __libdwfl_module_getebl (mod); - if (error != DWFL_E_NOERROR) - continue; - ebl = mod->ebl; - break; - } - ebl_close = false; - } - if (ebl == NULL) - { - /* Not identified EBL from any of the modules. */ - dwfl->attacherr = DWFL_E_PROCESS_NO_ARCH; - goto fail; - } - process_alloc (dwfl); - Dwfl_Process *process = dwfl->process; - if (process == NULL) - { - if (ebl_close) - ebl_closebackend (ebl); - dwfl->attacherr = DWFL_E_NOMEM; - goto fail; - } - process->ebl = ebl; - process->ebl_close = ebl_close; - process->pid = pid; - process->callbacks = thread_callbacks; - process->callbacks_arg = arg; - return true; -} -INTDEF(dwfl_attach_state) - -pid_t -dwfl_pid (Dwfl *dwfl) -{ - if (dwfl->attacherr != DWFL_E_NOERROR) - { - __libdwfl_seterrno (dwfl->attacherr); - return -1; - } - - if (dwfl->process == NULL) - { - __libdwfl_seterrno (DWFL_E_NO_ATTACH_STATE); - return -1; - } - return dwfl->process->pid; -} -INTDEF(dwfl_pid) - -Dwfl * -dwfl_thread_dwfl (Dwfl_Thread *thread) -{ - return thread->process->dwfl; -} -INTDEF(dwfl_thread_dwfl) - -pid_t -dwfl_thread_tid (Dwfl_Thread *thread) -{ - return thread->tid; -} -INTDEF(dwfl_thread_tid) - -Dwfl_Thread * -dwfl_frame_thread (Dwfl_Frame *state) -{ - return state->thread; -} -INTDEF(dwfl_frame_thread) - -int -dwfl_getthreads (Dwfl *dwfl, int (*callback) (Dwfl_Thread *thread, void *arg), - void *arg) -{ - if (dwfl->attacherr != DWFL_E_NOERROR) - { - __libdwfl_seterrno (dwfl->attacherr); - return -1; - } - - Dwfl_Process *process = dwfl->process; - if (process == NULL) - { - __libdwfl_seterrno (DWFL_E_NO_ATTACH_STATE); - return -1; - } - - Dwfl_Thread thread; - thread.process = process; - thread.unwound = NULL; - thread.callbacks_arg = NULL; - for (;;) - { - thread.tid = process->callbacks->next_thread (dwfl, - process->callbacks_arg, - &thread.callbacks_arg); - if (thread.tid < 0) - { - Dwfl_Error saved_errno = dwfl_errno (); - thread_free_all_states (&thread); - __libdwfl_seterrno (saved_errno); - return -1; - } - if (thread.tid == 0) - { - thread_free_all_states (&thread); - __libdwfl_seterrno (DWFL_E_NOERROR); - return 0; - } - int err = callback (&thread, arg); - if (err != DWARF_CB_OK) - { - thread_free_all_states (&thread); - return err; - } - assert (thread.unwound == NULL); - } - /* NOTREACHED */ -} -INTDEF(dwfl_getthreads) - -struct one_arg -{ - pid_t tid; - bool seen; - int (*callback) (Dwfl_Thread *thread, void *arg); - void *arg; - int ret; -}; - -static int -get_one_thread_cb (Dwfl_Thread *thread, void *arg) -{ - struct one_arg *oa = (struct one_arg *) arg; - if (! oa->seen && INTUSE(dwfl_thread_tid) (thread) == oa->tid) - { - oa->seen = true; - oa->ret = oa->callback (thread, oa->arg); - return DWARF_CB_ABORT; - } - - return DWARF_CB_OK; -} - -/* Note not currently exported, will be when there are more Dwfl_Thread - properties to query. Use dwfl_getthread_frames for now directly. */ -static int -getthread (Dwfl *dwfl, pid_t tid, - int (*callback) (Dwfl_Thread *thread, void *arg), - void *arg) -{ - if (dwfl->attacherr != DWFL_E_NOERROR) - { - __libdwfl_seterrno (dwfl->attacherr); - return -1; - } - - Dwfl_Process *process = dwfl->process; - if (process == NULL) - { - __libdwfl_seterrno (DWFL_E_NO_ATTACH_STATE); - return -1; - } - - if (process->callbacks->get_thread != NULL) - { - Dwfl_Thread thread; - thread.process = process; - thread.unwound = NULL; - thread.callbacks_arg = NULL; - - if (process->callbacks->get_thread (dwfl, tid, process->callbacks_arg, - &thread.callbacks_arg)) - { - int err; - thread.tid = tid; - err = callback (&thread, arg); - thread_free_all_states (&thread); - return err; - } - - return -1; - } - - struct one_arg oa = { .tid = tid, .callback = callback, - .arg = arg, .seen = false }; - int err = INTUSE(dwfl_getthreads) (dwfl, get_one_thread_cb, &oa); - - if (err == DWARF_CB_ABORT && oa.seen) - return oa.ret; - - if (err == DWARF_CB_OK && ! oa.seen) - { - errno = ESRCH; - __libdwfl_seterrno (DWFL_E_ERRNO); - return -1; - } - - return err; -} - -struct one_thread -{ - int (*callback) (Dwfl_Frame *frame, void *arg); - void *arg; -}; - -static int -get_one_thread_frames_cb (Dwfl_Thread *thread, void *arg) -{ - struct one_thread *ot = (struct one_thread *) arg; - return INTUSE(dwfl_thread_getframes) (thread, ot->callback, ot->arg); -} - -int -dwfl_getthread_frames (Dwfl *dwfl, pid_t tid, - int (*callback) (Dwfl_Frame *frame, void *arg), - void *arg) -{ - struct one_thread ot = { .callback = callback, .arg = arg }; - return getthread (dwfl, tid, get_one_thread_frames_cb, &ot); -} -INTDEF(dwfl_getthread_frames) - -int -dwfl_thread_getframes (Dwfl_Thread *thread, - int (*callback) (Dwfl_Frame *state, void *arg), - void *arg) -{ - if (thread->unwound != NULL) - { - /* We had to be called from inside CALLBACK. */ - __libdwfl_seterrno (DWFL_E_ATTACH_STATE_CONFLICT); - return -1; - } - Ebl *ebl = thread->process->ebl; - if (ebl_frame_nregs (ebl) == 0) - { - __libdwfl_seterrno (DWFL_E_NO_UNWIND); - return -1; - } - if (state_alloc (thread) == NULL) - { - __libdwfl_seterrno (DWFL_E_NOMEM); - return -1; - } - Dwfl_Process *process = thread->process; - if (! process->callbacks->set_initial_registers (thread, - thread->callbacks_arg)) - { - thread_free_all_states (thread); - return -1; - } - if (! state_fetch_pc (thread->unwound)) - { - if (process->callbacks->thread_detach) - process->callbacks->thread_detach (thread, thread->callbacks_arg); - thread_free_all_states (thread); - return -1; - } - - Dwfl_Frame *state; - do - { - state = thread->unwound; - int err = callback (state, arg); - if (err != DWARF_CB_OK) - { - if (process->callbacks->thread_detach) - process->callbacks->thread_detach (thread, thread->callbacks_arg); - thread_free_all_states (thread); - return err; - } - __libdwfl_frame_unwind (state); - /* The old frame is no longer needed. */ - state_free (thread->unwound); - state = thread->unwound; - } - while (state && state->pc_state == DWFL_FRAME_STATE_PC_SET); - - Dwfl_Error err = dwfl_errno (); - if (process->callbacks->thread_detach) - process->callbacks->thread_detach (thread, thread->callbacks_arg); - if (state == NULL || state->pc_state == DWFL_FRAME_STATE_ERROR) - { - thread_free_all_states (thread); - __libdwfl_seterrno (err); - return -1; - } - assert (state->pc_state == DWFL_FRAME_STATE_PC_UNDEFINED); - thread_free_all_states (thread); - return 0; -} -INTDEF(dwfl_thread_getframes) diff --git a/src/libdwfl/dwfl_frame_pc.c b/src/libdwfl/dwfl_frame_pc.c deleted file mode 100644 index 296c815b..00000000 --- a/src/libdwfl/dwfl_frame_pc.c +++ /dev/null @@ -1,64 +0,0 @@ -/* Get return address register value for frame. - Copyright (C) 2013 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - -#include "libdwflP.h" - -bool -dwfl_frame_pc (Dwfl_Frame *state, Dwarf_Addr *pc, bool *isactivation) -{ - assert (state->pc_state == DWFL_FRAME_STATE_PC_SET); - *pc = state->pc; - ebl_normalize_pc (state->thread->process->ebl, pc); - if (isactivation) - { - /* Bottom frame? */ - if (state->initial_frame) - *isactivation = true; - /* *ISACTIVATION is logical union of whether current or previous frame - state is SIGNAL_FRAME. */ - else if (state->signal_frame) - *isactivation = true; - else - { - /* If the previous frame has unwound unsuccessfully just silently do - not consider it could be a SIGNAL_FRAME. */ - __libdwfl_frame_unwind (state); - if (state->unwound == NULL - || state->unwound->pc_state != DWFL_FRAME_STATE_PC_SET) - *isactivation = false; - else - *isactivation = state->unwound->signal_frame; - } - } - return true; -} -INTDEF (dwfl_frame_pc) diff --git a/src/libdwfl/dwfl_frame_regs.c b/src/libdwfl/dwfl_frame_regs.c deleted file mode 100644 index 10803fe7..00000000 --- a/src/libdwfl/dwfl_frame_regs.c +++ /dev/null @@ -1,57 +0,0 @@ -/* Get Dwarf Frame state from modules present in DWFL. - Copyright (C) 2013 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" - -bool -dwfl_thread_state_registers (Dwfl_Thread *thread, int firstreg, - unsigned nregs, const Dwarf_Word *regs) -{ - Dwfl_Frame *state = thread->unwound; - assert (state && state->unwound == NULL); - assert (state->initial_frame); - for (unsigned regno = firstreg; regno < firstreg + nregs; regno++) - if (! __libdwfl_frame_reg_set (state, regno, regs[regno - firstreg])) - { - __libdwfl_seterrno (DWFL_E_INVALID_REGISTER); - return false; - } - return true; -} -INTDEF(dwfl_thread_state_registers) - -void -dwfl_thread_state_register_pc (Dwfl_Thread *thread, Dwarf_Word pc) -{ - Dwfl_Frame *state = thread->unwound; - assert (state && state->unwound == NULL); - assert (state->initial_frame); - state->pc = pc; - state->pc_state = DWFL_FRAME_STATE_PC_SET; -} -INTDEF(dwfl_thread_state_register_pc) diff --git a/src/libdwfl/dwfl_getdwarf.c b/src/libdwfl/dwfl_getdwarf.c deleted file mode 100644 index 8d1d9ba7..00000000 --- a/src/libdwfl/dwfl_getdwarf.c +++ /dev/null @@ -1,59 +0,0 @@ -/* Iterate through modules to fetch Dwarf information. - Copyright (C) 2005, 2008 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" - -struct module_callback_info -{ - int (*callback) (Dwfl_Module *, void **, - const char *, Dwarf_Addr, - Dwarf *, Dwarf_Addr, void *); - void *arg; -}; - -static int -module_callback (Dwfl_Module *mod, void **userdata, - const char *name, Dwarf_Addr start, void *arg) -{ - const struct module_callback_info *info = arg; - Dwarf_Addr bias = 0; - Dwarf *dw = INTUSE(dwfl_module_getdwarf) (mod, &bias); - return (*info->callback) (mod, userdata, name, start, dw, bias, info->arg); -} - -ptrdiff_t -dwfl_getdwarf (Dwfl *dwfl, - int (*callback) (Dwfl_Module *, void **, - const char *, Dwarf_Addr, - Dwarf *, Dwarf_Addr, void *), - void *arg, - ptrdiff_t offset) -{ - struct module_callback_info info = { callback, arg }; - return INTUSE(dwfl_getmodules) (dwfl, &module_callback, &info, offset); -} diff --git a/src/libdwfl/dwfl_getmodules.c b/src/libdwfl/dwfl_getmodules.c deleted file mode 100644 index eed9b4ff..00000000 --- a/src/libdwfl/dwfl_getmodules.c +++ /dev/null @@ -1,92 +0,0 @@ -/* Iterate through modules. - Copyright (C) 2005, 2008 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" - -ptrdiff_t -dwfl_getmodules (Dwfl *dwfl, - int (*callback) (Dwfl_Module *, void **, - const char *, Dwarf_Addr, void *), - void *arg, - ptrdiff_t offset) -{ - if (dwfl == NULL) - return -1; - - /* We iterate through the linked list when it's all we have. - But continuing from an offset is slow that way. So when - DWFL->lookup_module is populated, we can instead keep our - place by jumping directly into the array. Since the actions - of a callback could cause it to get populated, we must - choose the style of place-holder when we return an offset, - and we encode the choice in the low bits of that value. */ - - Dwfl_Module *m = dwfl->modulelist; - - if ((offset & 3) == 1) - { - offset >>= 2; - for (ptrdiff_t pos = 0; pos < offset; ++pos) - if (m == NULL) - return -1; - else - m = m->next; - } - else if (((offset & 3) == 2) && likely (dwfl->lookup_module != NULL)) - { - offset >>= 2; - - if ((size_t) offset - 1 == dwfl->lookup_elts) - return 0; - - if (unlikely ((size_t) offset - 1 > dwfl->lookup_elts)) - return -1; - - m = dwfl->lookup_module[offset - 1]; - if (unlikely (m == NULL)) - return -1; - } - else if (offset != 0) - { - __libdwfl_seterrno (DWFL_E_BADSTROFF); - return -1; - } - - while (m != NULL) - { - int ok = (*callback) (MODCB_ARGS (m), arg); - ++offset; - m = m->next; - if (ok != DWARF_CB_OK) - return ((dwfl->lookup_module == NULL) ? ((offset << 2) | 1) - : (((m == NULL ? (ptrdiff_t) dwfl->lookup_elts + 1 - : m->segment + 1) << 2) | 2)); - } - return 0; -} -INTDEF (dwfl_getmodules) diff --git a/src/libdwfl/dwfl_getsrc.c b/src/libdwfl/dwfl_getsrc.c deleted file mode 100644 index 8d4ae022..00000000 --- a/src/libdwfl/dwfl_getsrc.c +++ /dev/null @@ -1,36 +0,0 @@ -/* Find source location for PC address. - Copyright (C) 2005 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" - -Dwfl_Line * -dwfl_getsrc (Dwfl *dwfl, Dwarf_Addr addr) -{ - return INTUSE(dwfl_module_getsrc) (INTUSE(dwfl_addrmodule) (dwfl, addr), - addr); -} diff --git a/src/libdwfl/dwfl_getsrclines.c b/src/libdwfl/dwfl_getsrclines.c deleted file mode 100644 index bdfcf5c6..00000000 --- a/src/libdwfl/dwfl_getsrclines.c +++ /dev/null @@ -1,48 +0,0 @@ -/* Fetch source line information for CU. - Copyright (C) 2005, 2013 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" - -int -dwfl_getsrclines (Dwarf_Die *cudie, size_t *nlines) -{ - struct dwfl_cu *cu = (struct dwfl_cu *) cudie; - - if (cu->lines == NULL) - { - Dwfl_Error error = __libdwfl_cu_getsrclines (cu); - if (error != DWFL_E_NOERROR) - { - __libdwfl_seterrno (error); - return -1; - } - } - - *nlines = cu->die.cu->lines->nlines; - return 0; -} diff --git a/src/libdwfl/dwfl_line_comp_dir.c b/src/libdwfl/dwfl_line_comp_dir.c deleted file mode 100644 index bda09c46..00000000 --- a/src/libdwfl/dwfl_line_comp_dir.c +++ /dev/null @@ -1,43 +0,0 @@ -/* Get information from a source line record returned by libdwfl. - Copyright (C) 2005, 2006 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" -#include <dwarf.h> - -const char * -dwfl_line_comp_dir (Dwfl_Line *line) -{ - if (line == NULL) - return NULL; - - struct dwfl_cu *cu = dwfl_linecu (line); - Dwarf_Attribute attr_mem; - return INTUSE(dwarf_formstring) (INTUSE(dwarf_attr) (&cu->die, - DW_AT_comp_dir, - &attr_mem)); -} diff --git a/src/libdwfl/dwfl_linecu.c b/src/libdwfl/dwfl_linecu.c deleted file mode 100644 index ce78d297..00000000 --- a/src/libdwfl/dwfl_linecu.c +++ /dev/null @@ -1,41 +0,0 @@ -/* Fetch the module containing a source line record returned by libdwfl. - Copyright (C) 2006 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" - -#undef dwfl_linecu - -Dwarf_Die * -dwfl_linecu (Dwfl_Line *line) -{ - if (line == NULL) - return NULL; - - struct dwfl_cu *cu = dwfl_linecu_inline (line); - return &cu->die; -} diff --git a/src/libdwfl/dwfl_lineinfo.c b/src/libdwfl/dwfl_lineinfo.c deleted file mode 100644 index dfb27d82..00000000 --- a/src/libdwfl/dwfl_lineinfo.c +++ /dev/null @@ -1,55 +0,0 @@ -/* Get information from a source line record returned by libdwfl. - Copyright (C) 2005-2010 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" -#include "../libdw/libdwP.h" - -const char * -dwfl_lineinfo (Dwfl_Line *line, Dwarf_Addr *addr, int *linep, int *colp, - Dwarf_Word *mtime, Dwarf_Word *length) -{ - if (line == NULL) - return NULL; - - struct dwfl_cu *cu = dwfl_linecu (line); - const Dwarf_Line *info = &cu->die.cu->lines->info[line->idx]; - - if (addr != NULL) - *addr = dwfl_adjusted_dwarf_addr (cu->mod, info->addr); - if (linep != NULL) - *linep = info->line; - if (colp != NULL) - *colp = info->column; - - struct Dwarf_Fileinfo_s *file = &info->files->info[info->file]; - if (mtime != NULL) - *mtime = file->mtime; - if (length != NULL) - *length = file->length; - return file->name; -} diff --git a/src/libdwfl/dwfl_linemodule.c b/src/libdwfl/dwfl_linemodule.c deleted file mode 100644 index e4a35e09..00000000 --- a/src/libdwfl/dwfl_linemodule.c +++ /dev/null @@ -1,38 +0,0 @@ -/* Fetch the module containing a source line record returned by libdwfl. - Copyright (C) 2005 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" - -Dwfl_Module * -dwfl_linemodule (Dwfl_Line *line) -{ - if (line == NULL) - return NULL; - - return dwfl_linecu (line)->mod; -} diff --git a/src/libdwfl/dwfl_module.c b/src/libdwfl/dwfl_module.c deleted file mode 100644 index 8efcfaa5..00000000 --- a/src/libdwfl/dwfl_module.c +++ /dev/null @@ -1,222 +0,0 @@ -/* Maintenance of module list in libdwfl. - Copyright (C) 2005, 2006, 2007, 2008, 2014 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" -#include <search.h> -#include <unistd.h> - -static void -free_cu (struct dwfl_cu *cu) -{ - if (cu->lines != NULL) - free (cu->lines); - free (cu); -} - -static void -nofree (void *arg __attribute__ ((unused))) -{ -} - -static void -free_file (struct dwfl_file *file) -{ - free (file->name); - - /* Close the fd only on the last reference. */ - if (file->elf != NULL && elf_end (file->elf) == 0 && file->fd != -1) - close (file->fd); -} - -void -internal_function -__libdwfl_module_free (Dwfl_Module *mod) -{ - if (mod->lazy_cu_root != NULL) - tdestroy (mod->lazy_cu_root, nofree); - - if (mod->aranges != NULL) - free (mod->aranges); - - if (mod->cu != NULL) - { - for (size_t i = 0; i < mod->ncu; ++i) - free_cu (mod->cu[i]); - free (mod->cu); - } - - if (mod->dw != NULL) - { - INTUSE(dwarf_end) (mod->dw); - if (mod->alt != NULL) - { - INTUSE(dwarf_end) (mod->alt); - if (mod->alt_elf != NULL) - elf_end (mod->alt_elf); - if (mod->alt_fd != -1) - close (mod->alt_fd); - } - } - - if (mod->ebl != NULL) - ebl_closebackend (mod->ebl); - - if (mod->debug.elf != mod->main.elf) - free_file (&mod->debug); - free_file (&mod->main); - free_file (&mod->aux_sym); - - if (mod->build_id_bits != NULL) - free (mod->build_id_bits); - - if (mod->reloc_info != NULL) - free (mod->reloc_info); - - if (mod->eh_cfi != NULL) - dwarf_cfi_end (mod->eh_cfi); - - free (mod->name); - free (mod); -} - -void -dwfl_report_begin_add (Dwfl *dwfl __attribute__ ((unused))) -{ - /* The lookup table will be cleared on demand, there is nothing we need - to do here. */ -} -INTDEF (dwfl_report_begin_add) - -void -dwfl_report_begin (Dwfl *dwfl) -{ - /* Clear the segment lookup table. */ - dwfl->lookup_elts = 0; - - for (Dwfl_Module *m = dwfl->modulelist; m != NULL; m = m->next) - m->gc = true; - - dwfl->offline_next_address = OFFLINE_REDZONE; -} -INTDEF (dwfl_report_begin) - -/* Report that a module called NAME spans addresses [START, END). - Returns the module handle, either existing or newly allocated, - or returns a null pointer for an allocation error. */ -Dwfl_Module * -dwfl_report_module (Dwfl *dwfl, const char *name, - GElf_Addr start, GElf_Addr end) -{ - Dwfl_Module **tailp = &dwfl->modulelist, **prevp = tailp; - - inline Dwfl_Module *use (Dwfl_Module *mod) - { - mod->next = *tailp; - *tailp = mod; - - if (unlikely (dwfl->lookup_module != NULL)) - { - free (dwfl->lookup_module); - dwfl->lookup_module = NULL; - } - - return mod; - } - - for (Dwfl_Module *m = *prevp; m != NULL; m = *(prevp = &m->next)) - { - if (m->low_addr == start && m->high_addr == end - && !strcmp (m->name, name)) - { - /* This module is still here. Move it to the place in the list - after the last module already reported. */ - *prevp = m->next; - m->gc = false; - return use (m); - } - - if (! m->gc) - tailp = &m->next; - } - - Dwfl_Module *mod = calloc (1, sizeof *mod); - if (mod == NULL) - goto nomem; - - mod->name = strdup (name); - if (mod->name == NULL) - { - free (mod); - nomem: - __libdwfl_seterrno (DWFL_E_NOMEM); - return NULL; - } - - mod->low_addr = start; - mod->high_addr = end; - mod->dwfl = dwfl; - - return use (mod); -} -INTDEF (dwfl_report_module) - - -/* Finish reporting the current set of modules to the library. - If REMOVED is not null, it's called for each module that - existed before but was not included in the current report. - Returns a nonzero return value from the callback. - DWFL cannot be used until this function has returned zero. */ -int -dwfl_report_end (Dwfl *dwfl, - int (*removed) (Dwfl_Module *, void *, - const char *, Dwarf_Addr, - void *arg), - void *arg) -{ - Dwfl_Module **tailp = &dwfl->modulelist; - while (*tailp != NULL) - { - Dwfl_Module *m = *tailp; - if (m->gc && removed != NULL) - { - int result = (*removed) (MODCB_ARGS (m), arg); - if (result != 0) - return result; - } - if (m->gc) - { - *tailp = m->next; - __libdwfl_module_free (m); - } - else - tailp = &m->next; - } - - return 0; -} -INTDEF (dwfl_report_end) diff --git a/src/libdwfl/dwfl_module_addrdie.c b/src/libdwfl/dwfl_module_addrdie.c deleted file mode 100644 index 20d2842a..00000000 --- a/src/libdwfl/dwfl_module_addrdie.c +++ /dev/null @@ -1,45 +0,0 @@ -/* Fetch the CU DIE for a PC address in a given module. - Copyright (C) 2005 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" - -Dwarf_Die * -dwfl_module_addrdie (Dwfl_Module *mod, Dwarf_Addr addr, Dwarf_Addr *bias) -{ - if (INTUSE(dwfl_module_getdwarf) (mod, bias) == NULL) - return NULL; - - struct dwfl_cu *cu; - Dwfl_Error error = __libdwfl_addrcu (mod, addr, &cu); - if (likely (error == DWFL_E_NOERROR)) - return &cu->die; - - __libdwfl_seterrno (error); - return NULL; -} -INTDEF (dwfl_module_addrdie) diff --git a/src/libdwfl/dwfl_module_addrname.c b/src/libdwfl/dwfl_module_addrname.c deleted file mode 100644 index 88a8139d..00000000 --- a/src/libdwfl/dwfl_module_addrname.c +++ /dev/null @@ -1,38 +0,0 @@ -/* Find debugging and symbol information for a module in libdwfl. - Copyright (C) 2005, 2006, 2007, 2013 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" - -const char * -dwfl_module_addrname (Dwfl_Module *mod, GElf_Addr addr) -{ - GElf_Off off; - GElf_Sym sym; - return INTUSE(dwfl_module_addrinfo) (mod, addr, &off, &sym, - NULL, NULL, NULL); -} diff --git a/src/libdwfl/dwfl_module_addrsym.c b/src/libdwfl/dwfl_module_addrsym.c deleted file mode 100644 index d205832c..00000000 --- a/src/libdwfl/dwfl_module_addrsym.c +++ /dev/null @@ -1,289 +0,0 @@ -/* Find debugging and symbol information for a module in libdwfl. - Copyright (C) 2005-2013 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" - -/* Returns the name of the symbol "closest" to ADDR. - Never returns symbols at addresses above ADDR. */ - -const char * -internal_function -__libdwfl_addrsym (Dwfl_Module *mod, GElf_Addr addr, GElf_Off *off, - GElf_Sym *closest_sym, GElf_Word *shndxp, - Elf **elfp, Dwarf_Addr *biasp, bool adjust_st_value) -{ - int syments = INTUSE(dwfl_module_getsymtab) (mod); - if (syments < 0) - return NULL; - - /* Return true iff we consider ADDR to lie in the same section as SYM. */ - GElf_Word addr_shndx = SHN_UNDEF; - Elf *addr_symelf = NULL; - inline bool same_section (GElf_Addr value, Elf *symelf, GElf_Word shndx) - { - /* For absolute symbols and the like, only match exactly. */ - if (shndx >= SHN_LORESERVE) - return value == addr; - - /* If value might not be st_value, the shndx of the symbol might - not match the section of the value. Explicitly look both up. */ - if (! adjust_st_value) - { - Dwarf_Addr v; - if (addr_shndx == SHN_UNDEF) - { - v = addr; - addr_shndx = __libdwfl_find_section_ndx (mod, &v); - } - - v = value; - return addr_shndx == __libdwfl_find_section_ndx (mod, &v); - } - - /* Figure out what section ADDR lies in. */ - if (addr_shndx == SHN_UNDEF || addr_symelf != symelf) - { - GElf_Addr mod_addr = dwfl_deadjust_st_value (mod, symelf, addr); - Elf_Scn *scn = NULL; - addr_shndx = SHN_ABS; - addr_symelf = symelf; - while ((scn = elf_nextscn (symelf, scn)) != NULL) - { - GElf_Shdr shdr_mem; - GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); - if (likely (shdr != NULL) - && mod_addr >= shdr->sh_addr - && mod_addr < shdr->sh_addr + shdr->sh_size) - { - addr_shndx = elf_ndxscn (scn); - break; - } - } - } - - return shndx == addr_shndx && addr_symelf == symelf; - } - - /* Keep track of the closest symbol we have seen so far. - Here we store only symbols with nonzero st_size. */ - const char *closest_name = NULL; - GElf_Addr closest_value = 0; - GElf_Word closest_shndx = SHN_UNDEF; - Elf *closest_elf = NULL; - - /* Keep track of an eligible symbol with st_size == 0 as a fallback. */ - const char *sizeless_name = NULL; - GElf_Sym sizeless_sym = { 0, 0, 0, 0, 0, SHN_UNDEF }; - GElf_Addr sizeless_value = 0; - GElf_Word sizeless_shndx = SHN_UNDEF; - Elf *sizeless_elf = NULL; - - /* Keep track of the lowest address a relevant sizeless symbol could have. */ - GElf_Addr min_label = 0; - - /* Try one symbol and associated value from the search table. */ - inline void try_sym_value (GElf_Addr value, GElf_Sym *sym, - const char *name, GElf_Word shndx, - Elf *elf, bool resolved) - { - /* Even if we don't choose this symbol, its existence excludes - any sizeless symbol (assembly label) that is below its upper - bound. */ - if (value + sym->st_size > min_label) - min_label = value + sym->st_size; - - if (sym->st_size == 0 || addr - value < sym->st_size) - { - /* Return GELF_ST_BIND as higher-is-better integer. */ - inline int binding_value (const GElf_Sym *symp) - { - switch (GELF_ST_BIND (symp->st_info)) - { - case STB_GLOBAL: - return 3; - case STB_WEAK: - return 2; - case STB_LOCAL: - return 1; - default: - return 0; - } - } - - /* This symbol is a better candidate than the current one - if it's closer to ADDR or is global when it was local. */ - if (closest_name == NULL - || closest_value < value - || binding_value (closest_sym) < binding_value (sym)) - { - if (sym->st_size != 0) - { - *closest_sym = *sym; - closest_value = value; - closest_shndx = shndx; - closest_elf = elf; - closest_name = name; - } - else if (closest_name == NULL - && value >= min_label - && same_section (value, - resolved ? mod->main.elf : elf, shndx)) - { - /* Handwritten assembly symbols sometimes have no - st_size. If no symbol with proper size includes - the address, we'll use the closest one that is in - the same section as ADDR. */ - sizeless_sym = *sym; - sizeless_value = value; - sizeless_shndx = shndx; - sizeless_elf = elf; - sizeless_name = name; - } - } - /* When the beginning of its range is no closer, - the end of its range might be. Otherwise follow - GELF_ST_BIND preference. If all are equal prefer - the first symbol found. */ - else if (sym->st_size != 0 - && closest_value == value - && ((closest_sym->st_size > sym->st_size - && (binding_value (closest_sym) - <= binding_value (sym))) - || (closest_sym->st_size >= sym->st_size - && (binding_value (closest_sym) - < binding_value (sym))))) - { - *closest_sym = *sym; - closest_value = value; - closest_shndx = shndx; - closest_elf = elf; - closest_name = name; - } - } - } - - /* Look through the symbol table for a matching symbol. */ - inline void search_table (int start, int end) - { - for (int i = start; i < end; ++i) - { - GElf_Sym sym; - GElf_Addr value; - GElf_Word shndx; - Elf *elf; - bool resolved; - const char *name = __libdwfl_getsym (mod, i, &sym, &value, - &shndx, &elf, NULL, - &resolved, adjust_st_value); - if (name != NULL && name[0] != '\0' - && sym.st_shndx != SHN_UNDEF - && value <= addr - && GELF_ST_TYPE (sym.st_info) != STT_SECTION - && GELF_ST_TYPE (sym.st_info) != STT_FILE - && GELF_ST_TYPE (sym.st_info) != STT_TLS) - { - try_sym_value (value, &sym, name, shndx, elf, resolved); - - /* If this is an addrinfo variant and the value could be - resolved then also try matching the (adjusted) st_value. */ - if (resolved && mod->e_type != ET_REL) - { - GElf_Addr adjusted_st_value; - adjusted_st_value = dwfl_adjusted_st_value (mod, elf, - sym.st_value); - if (value != adjusted_st_value && adjusted_st_value <= addr) - try_sym_value (adjusted_st_value, &sym, name, shndx, - elf, false); - } - } - } - } - - /* First go through global symbols. mod->first_global and - mod->aux_first_global are setup by dwfl_module_getsymtab to the - index of the first global symbol in those symbol tables. Both - are non-zero when the table exist, except when there is only a - dynsym table loaded through phdrs, then first_global is zero and - there will be no auxiliary table. All symbols with local binding - come first in the symbol table, then all globals. The zeroth, - null entry, in the auxiliary table is skipped if there is a main - table. */ - int first_global = INTUSE (dwfl_module_getsymtab_first_global) (mod); - if (first_global < 0) - return NULL; - search_table (first_global == 0 ? 1 : first_global, syments); - - /* If we found nothing searching the global symbols, then try the locals. - Unless we have a global sizeless symbol that matches exactly. */ - if (closest_name == NULL && first_global > 1 - && (sizeless_name == NULL || sizeless_value != addr)) - search_table (1, first_global); - - /* If we found no proper sized symbol to use, fall back to the best - candidate sizeless symbol we found, if any. */ - if (closest_name == NULL - && sizeless_name != NULL && sizeless_value >= min_label) - { - *closest_sym = sizeless_sym; - closest_value = sizeless_value; - closest_shndx = sizeless_shndx; - closest_elf = sizeless_elf; - closest_name = sizeless_name; - } - - *off = addr - closest_value; - - if (shndxp != NULL) - *shndxp = closest_shndx; - if (elfp != NULL) - *elfp = closest_elf; - if (biasp != NULL) - *biasp = dwfl_adjusted_st_value (mod, closest_elf, 0); - return closest_name; -} - - -const char * -dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr addr, - GElf_Sym *closest_sym, GElf_Word *shndxp) -{ - GElf_Off off; - return __libdwfl_addrsym (mod, addr, &off, closest_sym, shndxp, - NULL, NULL, true); -} -INTDEF (dwfl_module_addrsym) - -const char -*dwfl_module_addrinfo (Dwfl_Module *mod, GElf_Addr address, - GElf_Off *offset, GElf_Sym *sym, - GElf_Word *shndxp, Elf **elfp, Dwarf_Addr *bias) -{ - return __libdwfl_addrsym (mod, address, offset, sym, shndxp, elfp, bias, - false); -} -INTDEF (dwfl_module_addrinfo) diff --git a/src/libdwfl/dwfl_module_build_id.c b/src/libdwfl/dwfl_module_build_id.c deleted file mode 100644 index 350bbf83..00000000 --- a/src/libdwfl/dwfl_module_build_id.c +++ /dev/null @@ -1,117 +0,0 @@ -/* Return build ID information for a module. - Copyright (C) 2007-2010, 2014 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" - -static int -found_build_id (Dwfl_Module *mod, bool set, - const void *bits, int len, GElf_Addr vaddr) -{ - if (!set) - /* When checking bits, we do not compare VADDR because the - address found in a debuginfo file may not match the main - file as modified by prelink. */ - return 1 + (mod->build_id_len == len - && !memcmp (bits, mod->build_id_bits, len)); - - void *copy = malloc (len); - if (unlikely (copy == NULL)) - { - __libdwfl_seterrno (DWFL_E_NOMEM); - return -1; - } - - mod->build_id_bits = memcpy (copy, bits, len); - mod->build_id_vaddr = vaddr; - mod->build_id_len = len; - return len; -} - -int -internal_function -__libdwfl_find_build_id (Dwfl_Module *mod, bool set, Elf *elf) -{ - const void *build_id_bits; - GElf_Addr build_id_elfaddr; - int build_id_len; - - /* For mod == NULL use dwelf_elf_gnu_build_id directly. */ - assert (mod != NULL); - - int result = __libdwfl_find_elf_build_id (mod, elf, &build_id_bits, - &build_id_elfaddr, &build_id_len); - if (result <= 0) - return result; - - GElf_Addr build_id_vaddr = build_id_elfaddr + (build_id_elfaddr != 0 - ? mod->main_bias : 0); - return found_build_id (mod, set, build_id_bits, build_id_len, build_id_vaddr); -} - -int -dwfl_module_build_id (Dwfl_Module *mod, - const unsigned char **bits, GElf_Addr *vaddr) -{ - if (mod == NULL) - return -1; - - if (mod->build_id_len == 0 && mod->main.elf != NULL) - { - /* We have the file, but have not examined it yet. */ - int result = __libdwfl_find_build_id (mod, true, mod->main.elf); - if (result <= 0) - { - mod->build_id_len = -1; /* Cache negative result. */ - return result; - } - } - - if (mod->build_id_len <= 0) - return 0; - - *bits = mod->build_id_bits; - *vaddr = mod->build_id_vaddr; - return mod->build_id_len; -} -INTDEF (dwfl_module_build_id) -NEW_VERSION (dwfl_module_build_id, ELFUTILS_0.138) - -#ifdef SHARED -COMPAT_VERSION (dwfl_module_build_id, ELFUTILS_0.130, vaddr_at_end) - -int -_compat_vaddr_at_end_dwfl_module_build_id (Dwfl_Module *mod, - const unsigned char **bits, - GElf_Addr *vaddr) -{ - int result = INTUSE(dwfl_module_build_id) (mod, bits, vaddr); - if (result > 0) - *vaddr += (result + 3) & -4; - return result; -} -#endif diff --git a/src/libdwfl/dwfl_module_dwarf_cfi.c b/src/libdwfl/dwfl_module_dwarf_cfi.c deleted file mode 100644 index 5182d6a0..00000000 --- a/src/libdwfl/dwfl_module_dwarf_cfi.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Find DWARF CFI for a module in libdwfl. - Copyright (C) 2009-2010 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" -#include "../libdw/cfi.h" - -Dwarf_CFI * -internal_function -__libdwfl_set_cfi (Dwfl_Module *mod, Dwarf_CFI **slot, Dwarf_CFI *cfi) -{ - if (cfi != NULL && cfi->ebl == NULL) - { - Dwfl_Error error = __libdwfl_module_getebl (mod); - if (error == DWFL_E_NOERROR) - cfi->ebl = mod->ebl; - else - { - if (slot == &mod->eh_cfi) - INTUSE(dwarf_cfi_end) (cfi); - __libdwfl_seterrno (error); - return NULL; - } - } - - return *slot = cfi; -} - -Dwarf_CFI * -dwfl_module_dwarf_cfi (mod, bias) - Dwfl_Module *mod; - Dwarf_Addr *bias; -{ - if (mod == NULL) - return NULL; - - if (mod->dwarf_cfi != NULL) - { - *bias = dwfl_adjusted_dwarf_addr (mod, 0); - return mod->dwarf_cfi; - } - - return __libdwfl_set_cfi (mod, &mod->dwarf_cfi, - INTUSE(dwarf_getcfi) - (INTUSE(dwfl_module_getdwarf) (mod, bias))); -} -INTDEF (dwfl_module_dwarf_cfi) diff --git a/src/libdwfl/dwfl_module_eh_cfi.c b/src/libdwfl/dwfl_module_eh_cfi.c deleted file mode 100644 index da10d9fb..00000000 --- a/src/libdwfl/dwfl_module_eh_cfi.c +++ /dev/null @@ -1,57 +0,0 @@ -/* Find EH CFI for a module in libdwfl. - Copyright (C) 2009-2010 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" -#include "../libdw/cfi.h" - -Dwarf_CFI * -dwfl_module_eh_cfi (mod, bias) - Dwfl_Module *mod; - Dwarf_Addr *bias; -{ - if (mod == NULL) - return NULL; - - if (mod->eh_cfi != NULL) - { - *bias = dwfl_adjusted_address (mod, 0); - return mod->eh_cfi; - } - - __libdwfl_getelf (mod); - if (mod->elferr != DWFL_E_NOERROR) - { - __libdwfl_seterrno (mod->elferr); - return NULL; - } - - *bias = dwfl_adjusted_address (mod, 0); - return __libdwfl_set_cfi (mod, &mod->eh_cfi, - INTUSE(dwarf_getcfi_elf) (mod->main.elf)); -} -INTDEF (dwfl_module_eh_cfi) diff --git a/src/libdwfl/dwfl_module_getdwarf.c b/src/libdwfl/dwfl_module_getdwarf.c deleted file mode 100644 index 494407dd..00000000 --- a/src/libdwfl/dwfl_module_getdwarf.c +++ /dev/null @@ -1,1358 +0,0 @@ -/* Find debugging and symbol information for a module in libdwfl. - Copyright (C) 2005-2012, 2014 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" -#include <inttypes.h> -#include <fcntl.h> -#include <string.h> -#include <unistd.h> -#include "../libdw/libdwP.h" /* DWARF_E_* values are here. */ -#include "../libelf/libelfP.h" - -static inline Dwfl_Error -open_elf_file (Elf **elf, int *fd, char **name) -{ - if (*elf == NULL) - { - /* CBFAIL uses errno if it's set, so clear it first in case we don't - set it with an open failure below. */ - errno = 0; - - /* If there was a pre-primed file name left that the callback left - behind, try to open that file name. */ - if (*fd < 0 && *name != NULL) - *fd = TEMP_FAILURE_RETRY (open64 (*name, O_RDONLY)); - - if (*fd < 0) - return CBFAIL; - - return __libdw_open_file (fd, elf, true, false); - } - else if (unlikely (elf_kind (*elf) != ELF_K_ELF)) - { - elf_end (*elf); - *elf = NULL; - close (*fd); - *fd = -1; - return DWFL_E_BADELF; - } - - /* Elf file already open and looks fine. */ - return DWFL_E_NOERROR; -} - -/* Open libelf FILE->fd and compute the load base of ELF as loaded in MOD. - When we return success, FILE->elf and FILE->vaddr are set up. */ -static inline Dwfl_Error -open_elf (Dwfl_Module *mod, struct dwfl_file *file) -{ - Dwfl_Error error = open_elf_file (&file->elf, &file->fd, &file->name); - if (error != DWFL_E_NOERROR) - return error; - - GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (file->elf, &ehdr_mem); - if (ehdr == NULL) - { - elf_error: - elf_end (file->elf); - file->elf = NULL; - close (file->fd); - file->fd = -1; - return DWFL_E (LIBELF, elf_errno ()); - } - - if (ehdr->e_type != ET_REL) - { - /* In any non-ET_REL file, we compute the "synchronization address". - - We start with the address at the end of the first PT_LOAD - segment. When prelink converts REL to RELA in an ET_DYN - file, it expands the space between the beginning of the - segment and the actual code/data addresses. Since that - change wasn't made in the debug file, the distance from - p_vaddr to an address of interest (in an st_value or DWARF - data) now differs between the main and debug files. The - distance from address_sync to an address of interest remains - consistent. - - If there are no section headers at all (full stripping), then - the end of the first segment is a valid synchronization address. - This cannot happen in a prelinked file, since prelink itself - relies on section headers for prelinking and for undoing it. - (If you do full stripping on a prelinked file, then you get what - you deserve--you can neither undo the prelinking, nor expect to - line it up with a debug file separated before prelinking.) - - However, when prelink processes an ET_EXEC file, it can do - something different. There it juggles the "special" sections - (SHT_DYNSYM et al) to make space for the additional prelink - special sections. Sometimes it will do this by moving a special - section like .dynstr after the real program sections in the first - PT_LOAD segment--i.e. to the end. That changes the end address of - the segment, so it no longer lines up correctly and is not a valid - synchronization address to use. Because of this, we need to apply - a different prelink-savvy means to discover the synchronization - address when there is a separate debug file and a prelinked main - file. That is done in find_debuginfo, below. */ - - size_t phnum; - if (unlikely (elf_getphdrnum (file->elf, &phnum) != 0)) - goto elf_error; - - file->vaddr = file->address_sync = 0; - for (size_t i = 0; i < phnum; ++i) - { - GElf_Phdr ph_mem; - GElf_Phdr *ph = gelf_getphdr (file->elf, i, &ph_mem); - if (unlikely (ph == NULL)) - goto elf_error; - if (ph->p_type == PT_LOAD) - { - file->vaddr = ph->p_vaddr & -ph->p_align; - file->address_sync = ph->p_vaddr + ph->p_memsz; - break; - } - } - } - - /* We only want to set the module e_type explictly once, derived from - the main ELF file. (It might be changed for the kernel, because - that is special - see below.) open_elf is always called first for - the main ELF file, because both find_dw and find_symtab call - __libdwfl_getelf first to open the main file. So don't let debug - or aux files override the module e_type. The kernel heuristic - below could otherwise trigger for non-kernel/non-main files, since - their phdrs might not match the actual load addresses. */ - if (file == &mod->main) - { - mod->e_type = ehdr->e_type; - - /* Relocatable Linux kernels are ET_EXEC but act like ET_DYN. */ - if (mod->e_type == ET_EXEC && file->vaddr != mod->low_addr) - mod->e_type = ET_DYN; - } - else - assert (mod->main.elf != NULL); - - return DWFL_E_NOERROR; -} - -/* We have an authoritative build ID for this module MOD, so don't use - a file by name that doesn't match that ID. */ -static void -mod_verify_build_id (Dwfl_Module *mod) -{ - assert (mod->build_id_len > 0); - - switch (__builtin_expect (__libdwfl_find_build_id (mod, false, - mod->main.elf), 2)) - { - case 2: - /* Build ID matches as it should. */ - return; - - case -1: /* ELF error. */ - mod->elferr = INTUSE(dwfl_errno) (); - break; - - case 0: /* File has no build ID note. */ - case 1: /* FIle has a build ID that does not match. */ - mod->elferr = DWFL_E_WRONG_ID_ELF; - break; - - default: - abort (); - } - - /* We get here when it was the right ELF file. Clear it out. */ - elf_end (mod->main.elf); - mod->main.elf = NULL; - if (mod->main.fd >= 0) - { - close (mod->main.fd); - mod->main.fd = -1; - } -} - -/* Find the main ELF file for this module and open libelf on it. - When we return success, MOD->main.elf and MOD->main.bias are set up. */ -void -internal_function -__libdwfl_getelf (Dwfl_Module *mod) -{ - if (mod->main.elf != NULL /* Already done. */ - || mod->elferr != DWFL_E_NOERROR) /* Cached failure. */ - return; - - mod->main.fd = (*mod->dwfl->callbacks->find_elf) (MODCB_ARGS (mod), - &mod->main.name, - &mod->main.elf); - const bool fallback = mod->main.elf == NULL && mod->main.fd < 0; - mod->elferr = open_elf (mod, &mod->main); - if (mod->elferr != DWFL_E_NOERROR) - return; - - if (!mod->main.valid) - { - /* Clear any explicitly reported build ID, just in case it was wrong. - We'll fetch it from the file when asked. */ - free (mod->build_id_bits); - mod->build_id_bits = NULL; - mod->build_id_len = 0; - } - else if (fallback) - mod_verify_build_id (mod); - - mod->main_bias = mod->e_type == ET_REL ? 0 : mod->low_addr - mod->main.vaddr; -} - -/* If the main file might have been prelinked, then we need to - discover the correct synchronization address between the main and - debug files. Because of prelink's section juggling, we cannot rely - on the address_sync computed from PT_LOAD segments (see open_elf). - - We will attempt to discover a synchronization address based on the - section headers instead. But finding a section address that is - safe to use requires identifying which sections are SHT_PROGBITS. - We can do that in the main file, but in the debug file all the - allocated sections have been transformed into SHT_NOBITS so we have - lost the means to match them up correctly. - - The only method left to us is to decode the .gnu.prelink_undo - section in the prelinked main file. This shows what the sections - looked like before prelink juggled them--when they still had a - direct correspondence to the debug file. */ -static Dwfl_Error -find_prelink_address_sync (Dwfl_Module *mod, struct dwfl_file *file) -{ - /* The magic section is only identified by name. */ - size_t shstrndx; - if (elf_getshdrstrndx (mod->main.elf, &shstrndx) < 0) - return DWFL_E_LIBELF; - - Elf_Scn *scn = NULL; - while ((scn = elf_nextscn (mod->main.elf, scn)) != NULL) - { - GElf_Shdr shdr_mem; - GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); - if (unlikely (shdr == NULL)) - return DWFL_E_LIBELF; - if (shdr->sh_type == SHT_PROGBITS - && !(shdr->sh_flags & SHF_ALLOC) - && shdr->sh_name != 0) - { - const char *secname = elf_strptr (mod->main.elf, shstrndx, - shdr->sh_name); - if (unlikely (secname == NULL)) - return DWFL_E_LIBELF; - if (!strcmp (secname, ".gnu.prelink_undo")) - break; - } - } - - if (scn == NULL) - /* There was no .gnu.prelink_undo section. */ - return DWFL_E_NOERROR; - - Elf_Data *undodata = elf_rawdata (scn, NULL); - if (unlikely (undodata == NULL)) - return DWFL_E_LIBELF; - - /* Decode the section. It consists of the original ehdr, phdrs, - and shdrs (but omits section 0). */ - - union - { - Elf32_Ehdr e32; - Elf64_Ehdr e64; - } ehdr; - Elf_Data dst = - { - .d_buf = &ehdr, - .d_size = sizeof ehdr, - .d_type = ELF_T_EHDR, - .d_version = EV_CURRENT - }; - Elf_Data src = *undodata; - src.d_size = gelf_fsize (mod->main.elf, ELF_T_EHDR, 1, EV_CURRENT); - src.d_type = ELF_T_EHDR; - if (unlikely (gelf_xlatetom (mod->main.elf, &dst, &src, - elf_getident (mod->main.elf, NULL)[EI_DATA]) - == NULL)) - return DWFL_E_LIBELF; - - size_t shentsize = gelf_fsize (mod->main.elf, ELF_T_SHDR, 1, EV_CURRENT); - size_t phentsize = gelf_fsize (mod->main.elf, ELF_T_PHDR, 1, EV_CURRENT); - - uint_fast16_t phnum; - uint_fast16_t shnum; - if (ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32) - { - if (ehdr.e32.e_shentsize != shentsize - || ehdr.e32.e_phentsize != phentsize) - return DWFL_E_BAD_PRELINK; - phnum = ehdr.e32.e_phnum; - shnum = ehdr.e32.e_shnum; - } - else - { - if (ehdr.e64.e_shentsize != shentsize - || ehdr.e64.e_phentsize != phentsize) - return DWFL_E_BAD_PRELINK; - phnum = ehdr.e64.e_phnum; - shnum = ehdr.e64.e_shnum; - } - - /* Since prelink does not store the zeroth section header in the undo - section, it cannot support SHN_XINDEX encoding. */ - if (unlikely (shnum >= SHN_LORESERVE) - || unlikely (undodata->d_size != (src.d_size - + phnum * phentsize - + (shnum - 1) * shentsize))) - return DWFL_E_BAD_PRELINK; - - /* We look at the allocated SHT_PROGBITS (or SHT_NOBITS) sections. (Most - every file will have some SHT_PROGBITS sections, but it's possible to - have one with nothing but .bss, i.e. SHT_NOBITS.) The special sections - that can be moved around have different sh_type values--except for - .interp, the section that became the PT_INTERP segment. So we exclude - the SHT_PROGBITS section whose address matches the PT_INTERP p_vaddr. - For this reason, we must examine the phdrs first to find PT_INTERP. */ - - GElf_Addr main_interp = 0; - { - size_t main_phnum; - if (unlikely (elf_getphdrnum (mod->main.elf, &main_phnum))) - return DWFL_E_LIBELF; - for (size_t i = 0; i < main_phnum; ++i) - { - GElf_Phdr phdr; - if (unlikely (gelf_getphdr (mod->main.elf, i, &phdr) == NULL)) - return DWFL_E_LIBELF; - if (phdr.p_type == PT_INTERP) - { - main_interp = phdr.p_vaddr; - break; - } - } - } - - src.d_buf += src.d_size; - src.d_type = ELF_T_PHDR; - src.d_size = phnum * phentsize; - - GElf_Addr undo_interp = 0; - { - union - { - Elf32_Phdr p32[phnum]; - Elf64_Phdr p64[phnum]; - } phdr; - dst.d_buf = &phdr; - dst.d_size = sizeof phdr; - if (unlikely (gelf_xlatetom (mod->main.elf, &dst, &src, - ehdr.e32.e_ident[EI_DATA]) == NULL)) - return DWFL_E_LIBELF; - if (ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32) - { - for (uint_fast16_t i = 0; i < phnum; ++i) - if (phdr.p32[i].p_type == PT_INTERP) - { - undo_interp = phdr.p32[i].p_vaddr; - break; - } - } - else - { - for (uint_fast16_t i = 0; i < phnum; ++i) - if (phdr.p64[i].p_type == PT_INTERP) - { - undo_interp = phdr.p64[i].p_vaddr; - break; - } - } - } - - if (unlikely ((main_interp == 0) != (undo_interp == 0))) - return DWFL_E_BAD_PRELINK; - - src.d_buf += src.d_size; - src.d_type = ELF_T_SHDR; - src.d_size = gelf_fsize (mod->main.elf, ELF_T_SHDR, shnum - 1, EV_CURRENT); - - union - { - Elf32_Shdr s32[shnum - 1]; - Elf64_Shdr s64[shnum - 1]; - } shdr; - dst.d_buf = &shdr; - dst.d_size = sizeof shdr; - if (unlikely (gelf_xlatetom (mod->main.elf, &dst, &src, - ehdr.e32.e_ident[EI_DATA]) == NULL)) - return DWFL_E_LIBELF; - - /* Now we can look at the original section headers of the main file - before it was prelinked. First we'll apply our method to the main - file sections as they are after prelinking, to calculate the - synchronization address of the main file. Then we'll apply that - same method to the saved section headers, to calculate the matching - synchronization address of the debug file. - - The method is to consider SHF_ALLOC sections that are either - SHT_PROGBITS or SHT_NOBITS, excluding the section whose sh_addr - matches the PT_INTERP p_vaddr. The special sections that can be - moved by prelink have other types, except for .interp (which - becomes PT_INTERP). The "real" sections cannot move as such, but - .bss can be split into .dynbss and .bss, with the total memory - image remaining the same but being spread across the two sections. - So we consider the highest section end, which still matches up. */ - - GElf_Addr highest; - - inline void consider_shdr (GElf_Addr interp, - GElf_Word sh_type, - GElf_Xword sh_flags, - GElf_Addr sh_addr, - GElf_Xword sh_size) - { - if ((sh_flags & SHF_ALLOC) - && ((sh_type == SHT_PROGBITS && sh_addr != interp) - || sh_type == SHT_NOBITS)) - { - const GElf_Addr sh_end = sh_addr + sh_size; - if (sh_end > highest) - highest = sh_end; - } - } - - highest = 0; - scn = NULL; - while ((scn = elf_nextscn (mod->main.elf, scn)) != NULL) - { - GElf_Shdr sh_mem; - GElf_Shdr *sh = gelf_getshdr (scn, &sh_mem); - if (unlikely (sh == NULL)) - return DWFL_E_LIBELF; - consider_shdr (main_interp, sh->sh_type, sh->sh_flags, - sh->sh_addr, sh->sh_size); - } - if (highest > mod->main.vaddr) - { - mod->main.address_sync = highest; - - highest = 0; - if (ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32) - for (size_t i = 0; i < shnum - 1; ++i) - consider_shdr (undo_interp, shdr.s32[i].sh_type, shdr.s32[i].sh_flags, - shdr.s32[i].sh_addr, shdr.s32[i].sh_size); - else - for (size_t i = 0; i < shnum - 1; ++i) - consider_shdr (undo_interp, shdr.s64[i].sh_type, shdr.s64[i].sh_flags, - shdr.s64[i].sh_addr, shdr.s64[i].sh_size); - - if (highest > file->vaddr) - file->address_sync = highest; - else - return DWFL_E_BAD_PRELINK; - } - - return DWFL_E_NOERROR; -} - -/* Find the separate debuginfo file for this module and open libelf on it. - When we return success, MOD->debug is set up. */ -static Dwfl_Error -find_debuginfo (Dwfl_Module *mod) -{ - if (mod->debug.elf != NULL) - return DWFL_E_NOERROR; - - GElf_Word debuglink_crc = 0; - const char *debuglink_file; - debuglink_file = INTUSE(dwelf_elf_gnu_debuglink) (mod->main.elf, - &debuglink_crc); - - mod->debug.fd = (*mod->dwfl->callbacks->find_debuginfo) (MODCB_ARGS (mod), - mod->main.name, - debuglink_file, - debuglink_crc, - &mod->debug.name); - Dwfl_Error result = open_elf (mod, &mod->debug); - if (result == DWFL_E_NOERROR && mod->debug.address_sync != 0) - result = find_prelink_address_sync (mod, &mod->debug); - return result; -} - -/* Try to find the alternative debug link for the given DWARF and set - it if found. Only called when mod->dw is already setup but still - might need an alternative (dwz multi) debug file. filename is either - the main or debug name from which the Dwarf was created. */ -static void -find_debug_altlink (Dwfl_Module *mod, const char *filename) -{ - assert (mod->dw != NULL); - - const char *altname; - const void *build_id; - ssize_t build_id_len = INTUSE(dwelf_dwarf_gnu_debugaltlink) (mod->dw, - &altname, - &build_id); - - if (build_id_len > 0) - { - /* We could store altfile in the module, but don't really need it. */ - char *altfile = NULL; - mod->alt_fd = (*mod->dwfl->callbacks->find_debuginfo) (MODCB_ARGS (mod), - filename, - altname, - 0, - &altfile); - - /* The (internal) callbacks might just set mod->alt_elf directly - because they open the Elf anyway for sanity checking. - Otherwise open either the given file name or use the fd - returned. */ - Dwfl_Error error = open_elf_file (&mod->alt_elf, &mod->alt_fd, - &altfile); - if (error == DWFL_E_NOERROR) - { - mod->alt = INTUSE(dwarf_begin_elf) (mod->alt_elf, - DWARF_C_READ, NULL); - if (mod->alt == NULL) - { - elf_end (mod->alt_elf); - mod->alt_elf = NULL; - close (mod->alt_fd); - mod->alt_fd = -1; - } - else - dwarf_setalt (mod->dw, mod->alt); - } - - free (altfile); /* See above, we don't really need it. */ - } -} - -/* Try to find a symbol table in FILE. - Returns DWFL_E_NOERROR if a proper one is found. - Returns DWFL_E_NO_SYMTAB if not, but still sets results for SHT_DYNSYM. */ -static Dwfl_Error -load_symtab (struct dwfl_file *file, struct dwfl_file **symfile, - Elf_Scn **symscn, Elf_Scn **xndxscn, - size_t *syments, int *first_global, GElf_Word *strshndx) -{ - bool symtab = false; - Elf_Scn *scn = NULL; - while ((scn = elf_nextscn (file->elf, scn)) != NULL) - { - GElf_Shdr shdr_mem, *shdr = gelf_getshdr (scn, &shdr_mem); - if (shdr != NULL) - switch (shdr->sh_type) - { - case SHT_SYMTAB: - if (shdr->sh_entsize == 0) - break; - symtab = true; - *symscn = scn; - *symfile = file; - *strshndx = shdr->sh_link; - *syments = shdr->sh_size / shdr->sh_entsize; - *first_global = shdr->sh_info; - if (*xndxscn != NULL) - return DWFL_E_NOERROR; - break; - - case SHT_DYNSYM: - if (symtab) - break; - /* Use this if need be, but keep looking for SHT_SYMTAB. */ - if (shdr->sh_entsize == 0) - break; - *symscn = scn; - *symfile = file; - *strshndx = shdr->sh_link; - *syments = shdr->sh_size / shdr->sh_entsize; - *first_global = shdr->sh_info; - break; - - case SHT_SYMTAB_SHNDX: - *xndxscn = scn; - if (symtab) - return DWFL_E_NOERROR; - break; - - default: - break; - } - } - - if (symtab) - /* We found one, though no SHT_SYMTAB_SHNDX to go with it. */ - return DWFL_E_NOERROR; - - /* We found no SHT_SYMTAB, so any SHT_SYMTAB_SHNDX was bogus. - We might have found an SHT_DYNSYM and set *SYMSCN et al though. */ - *xndxscn = NULL; - return DWFL_E_NO_SYMTAB; -} - - -/* Translate addresses into file offsets. - OFFS[*] start out zero and remain zero if unresolved. */ -static void -find_offsets (Elf *elf, GElf_Addr main_bias, size_t phnum, size_t n, - GElf_Addr addrs[n], GElf_Off offs[n]) -{ - size_t unsolved = n; - for (size_t i = 0; i < phnum; ++i) - { - GElf_Phdr phdr_mem; - GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem); - if (phdr != NULL && phdr->p_type == PT_LOAD && phdr->p_memsz > 0) - for (size_t j = 0; j < n; ++j) - if (offs[j] == 0 - && addrs[j] >= phdr->p_vaddr + main_bias - && addrs[j] - (phdr->p_vaddr + main_bias) < phdr->p_filesz) - { - offs[j] = addrs[j] - (phdr->p_vaddr + main_bias) + phdr->p_offset; - if (--unsolved == 0) - break; - } - } -} - -/* Try to find a dynamic symbol table via phdrs. */ -static void -find_dynsym (Dwfl_Module *mod) -{ - GElf_Ehdr ehdr_mem; - GElf_Ehdr *ehdr = gelf_getehdr (mod->main.elf, &ehdr_mem); - - size_t phnum; - if (unlikely (elf_getphdrnum (mod->main.elf, &phnum) != 0)) - return; - - for (size_t i = 0; i < phnum; ++i) - { - GElf_Phdr phdr_mem; - GElf_Phdr *phdr = gelf_getphdr (mod->main.elf, i, &phdr_mem); - if (phdr == NULL) - break; - - if (phdr->p_type == PT_DYNAMIC) - { - /* Examine the dynamic section for the pointers we need. */ - - Elf_Data *data = elf_getdata_rawchunk (mod->main.elf, - phdr->p_offset, phdr->p_filesz, - ELF_T_DYN); - if (data == NULL) - continue; - - enum - { - i_symtab, - i_strtab, - i_hash, - i_gnu_hash, - i_max - }; - GElf_Addr addrs[i_max] = { 0, }; - GElf_Xword strsz = 0; - size_t n = data->d_size / gelf_fsize (mod->main.elf, - ELF_T_DYN, 1, EV_CURRENT); - for (size_t j = 0; j < n; ++j) - { - GElf_Dyn dyn_mem; - GElf_Dyn *dyn = gelf_getdyn (data, j, &dyn_mem); - if (dyn != NULL) - switch (dyn->d_tag) - { - case DT_SYMTAB: - addrs[i_symtab] = dyn->d_un.d_ptr; - continue; - - case DT_HASH: - addrs[i_hash] = dyn->d_un.d_ptr; - continue; - - case DT_GNU_HASH: - addrs[i_gnu_hash] = dyn->d_un.d_ptr; - continue; - - case DT_STRTAB: - addrs[i_strtab] = dyn->d_un.d_ptr; - continue; - - case DT_STRSZ: - strsz = dyn->d_un.d_val; - continue; - - default: - continue; - - case DT_NULL: - break; - } - break; - } - - /* Translate pointers into file offsets. ADJUST is either zero - in case the dynamic segment wasn't adjusted or mod->main_bias. */ - void translate_offs (GElf_Addr adjust) - { - GElf_Off offs[i_max] = { 0, }; - find_offsets (mod->main.elf, adjust, phnum, i_max, addrs, offs); - - /* Figure out the size of the symbol table. */ - if (offs[i_hash] != 0) - { - /* In the original format, .hash says the size of .dynsym. */ - - size_t entsz = SH_ENTSIZE_HASH (ehdr); - data = elf_getdata_rawchunk (mod->main.elf, - offs[i_hash] + entsz, entsz, - entsz == 4 ? ELF_T_WORD - : ELF_T_XWORD); - if (data != NULL) - mod->syments = (entsz == 4 - ? *(const GElf_Word *) data->d_buf - : *(const GElf_Xword *) data->d_buf); - } - if (offs[i_gnu_hash] != 0 && mod->syments == 0) - { - /* In the new format, we can derive it with some work. */ - - const struct - { - Elf32_Word nbuckets; - Elf32_Word symndx; - Elf32_Word maskwords; - Elf32_Word shift2; - } *header; - - data = elf_getdata_rawchunk (mod->main.elf, offs[i_gnu_hash], - sizeof *header, ELF_T_WORD); - if (data != NULL) - { - header = data->d_buf; - Elf32_Word nbuckets = header->nbuckets; - Elf32_Word symndx = header->symndx; - GElf_Off buckets_at = (offs[i_gnu_hash] + sizeof *header - + (gelf_getclass (mod->main.elf) - * sizeof (Elf32_Word) - * header->maskwords)); - - // elf_getdata_rawchunk takes a size_t, make sure it - // doesn't overflow. -#if SIZE_MAX <= UINT32_MAX - if (nbuckets > SIZE_MAX / sizeof (Elf32_Word)) - data = NULL; - else -#endif - data - = elf_getdata_rawchunk (mod->main.elf, buckets_at, - nbuckets * sizeof (Elf32_Word), - ELF_T_WORD); - if (data != NULL && symndx < nbuckets) - { - const Elf32_Word *const buckets = data->d_buf; - Elf32_Word maxndx = symndx; - for (Elf32_Word bucket = 0; bucket < nbuckets; ++bucket) - if (buckets[bucket] > maxndx) - maxndx = buckets[bucket]; - - GElf_Off hasharr_at = (buckets_at - + nbuckets * sizeof (Elf32_Word)); - hasharr_at += (maxndx - symndx) * sizeof (Elf32_Word); - do - { - data = elf_getdata_rawchunk (mod->main.elf, - hasharr_at, - sizeof (Elf32_Word), - ELF_T_WORD); - if (data != NULL - && (*(const Elf32_Word *) data->d_buf & 1u)) - { - mod->syments = maxndx + 1; - break; - } - ++maxndx; - hasharr_at += sizeof (Elf32_Word); - } while (data != NULL); - } - } - } - if (offs[i_strtab] > offs[i_symtab] && mod->syments == 0) - mod->syments = ((offs[i_strtab] - offs[i_symtab]) - / gelf_fsize (mod->main.elf, - ELF_T_SYM, 1, EV_CURRENT)); - - if (mod->syments > 0) - { - mod->symdata = elf_getdata_rawchunk (mod->main.elf, - offs[i_symtab], - gelf_fsize (mod->main.elf, - ELF_T_SYM, - mod->syments, - EV_CURRENT), - ELF_T_SYM); - if (mod->symdata != NULL) - { - mod->symstrdata = elf_getdata_rawchunk (mod->main.elf, - offs[i_strtab], - strsz, - ELF_T_BYTE); - if (mod->symstrdata == NULL) - mod->symdata = NULL; - } - if (mod->symdata == NULL) - mod->symerr = DWFL_E (LIBELF, elf_errno ()); - else - { - mod->symfile = &mod->main; - mod->symerr = DWFL_E_NOERROR; - } - } - } - - /* First try unadjusted, like ELF files from disk, vdso. - Then try for already adjusted dynamic section, like ELF - from remote memory. */ - translate_offs (0); - if (mod->symfile == NULL) - translate_offs (mod->main_bias); - - return; - } - } -} - - -#if USE_LZMA -/* Try to find the offset between the main file and .gnu_debugdata. */ -static bool -find_aux_address_sync (Dwfl_Module *mod) -{ - /* Don't trust the phdrs in the minisymtab elf file to be setup correctly. - The address_sync is equal to the main file it is embedded in at first. */ - mod->aux_sym.address_sync = mod->main.address_sync; - - /* Adjust address_sync for the difference in entry addresses, attempting to - account for ELF relocation changes after aux was split. */ - GElf_Ehdr ehdr_main, ehdr_aux; - if (unlikely (gelf_getehdr (mod->main.elf, &ehdr_main) == NULL) - || unlikely (gelf_getehdr (mod->aux_sym.elf, &ehdr_aux) == NULL)) - return false; - mod->aux_sym.address_sync += ehdr_aux.e_entry - ehdr_main.e_entry; - - /* The shdrs are setup OK to make find_prelink_address_sync () do the right - thing, which is possibly more reliable, but it needs .gnu.prelink_undo. */ - if (mod->aux_sym.address_sync != 0) - return find_prelink_address_sync (mod, &mod->aux_sym) == DWFL_E_NOERROR; - - return true; -} -#endif - -/* Try to find the auxiliary symbol table embedded in the main elf file - section .gnu_debugdata. Only matters if the symbol information comes - from the main file dynsym. No harm done if not found. */ -static void -find_aux_sym (Dwfl_Module *mod __attribute__ ((unused)), - Elf_Scn **aux_symscn __attribute__ ((unused)), - Elf_Scn **aux_xndxscn __attribute__ ((unused)), - GElf_Word *aux_strshndx __attribute__ ((unused))) -{ - /* Since a .gnu_debugdata section is compressed using lzma don't do - anything unless we have support for that. */ -#if USE_LZMA - Elf *elf = mod->main.elf; - - size_t shstrndx; - if (elf_getshdrstrndx (elf, &shstrndx) < 0) - return; - - 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) - return; - - const char *name = elf_strptr (elf, shstrndx, shdr->sh_name); - if (name == NULL) - return; - - if (!strcmp (name, ".gnu_debugdata")) - break; - } - - if (scn == NULL) - return; - - /* Found the .gnu_debugdata section. Uncompress the lzma image and - turn it into an ELF image. */ - Elf_Data *rawdata = elf_rawdata (scn, NULL); - if (rawdata == NULL) - return; - - Dwfl_Error error; - void *buffer = NULL; - size_t size = 0; - error = __libdw_unlzma (-1, 0, rawdata->d_buf, rawdata->d_size, - &buffer, &size); - if (error == DWFL_E_NOERROR) - { - if (unlikely (size == 0)) - free (buffer); - else - { - mod->aux_sym.elf = elf_memory (buffer, size); - if (mod->aux_sym.elf == NULL) - free (buffer); - else - { - mod->aux_sym.fd = -1; - mod->aux_sym.elf->flags |= ELF_F_MALLOCED; - if (open_elf (mod, &mod->aux_sym) != DWFL_E_NOERROR) - return; - if (! find_aux_address_sync (mod)) - { - elf_end (mod->aux_sym.elf); - mod->aux_sym.elf = NULL; - return; - } - - /* So far, so good. Get minisymtab table data and cache it. */ - bool minisymtab = false; - scn = NULL; - while ((scn = elf_nextscn (mod->aux_sym.elf, scn)) != NULL) - { - GElf_Shdr shdr_mem, *shdr = gelf_getshdr (scn, &shdr_mem); - if (shdr != NULL) - switch (shdr->sh_type) - { - case SHT_SYMTAB: - minisymtab = true; - *aux_symscn = scn; - *aux_strshndx = shdr->sh_link; - mod->aux_syments = shdr->sh_size / shdr->sh_entsize; - mod->aux_first_global = shdr->sh_info; - if (*aux_xndxscn != NULL) - return; - break; - - case SHT_SYMTAB_SHNDX: - *aux_xndxscn = scn; - if (minisymtab) - return; - break; - - default: - break; - } - } - - if (minisymtab) - /* We found one, though no SHT_SYMTAB_SHNDX to go with it. */ - return; - - /* We found no SHT_SYMTAB, so everything else is bogus. */ - *aux_xndxscn = NULL; - *aux_strshndx = 0; - mod->aux_syments = 0; - elf_end (mod->aux_sym.elf); - mod->aux_sym.elf = NULL; - return; - } - } - } - else - free (buffer); -#endif -} - -/* Try to find a symbol table in either MOD->main.elf or MOD->debug.elf. */ -static void -find_symtab (Dwfl_Module *mod) -{ - if (mod->symdata != NULL || mod->aux_symdata != NULL /* Already done. */ - || mod->symerr != DWFL_E_NOERROR) /* Cached previous failure. */ - return; - - __libdwfl_getelf (mod); - mod->symerr = mod->elferr; - if (mod->symerr != DWFL_E_NOERROR) - return; - - /* First see if the main ELF file has the debugging information. */ - Elf_Scn *symscn = NULL, *xndxscn = NULL; - Elf_Scn *aux_symscn = NULL, *aux_xndxscn = NULL; - GElf_Word strshndx, aux_strshndx = 0; - mod->symerr = load_symtab (&mod->main, &mod->symfile, &symscn, - &xndxscn, &mod->syments, &mod->first_global, - &strshndx); - switch (mod->symerr) - { - default: - return; - - case DWFL_E_NOERROR: - break; - - case DWFL_E_NO_SYMTAB: - /* Now we have to look for a separate debuginfo file. */ - mod->symerr = find_debuginfo (mod); - switch (mod->symerr) - { - default: - return; - - case DWFL_E_NOERROR: - mod->symerr = load_symtab (&mod->debug, &mod->symfile, &symscn, - &xndxscn, &mod->syments, - &mod->first_global, &strshndx); - break; - - case DWFL_E_CB: /* The find_debuginfo hook failed. */ - mod->symerr = DWFL_E_NO_SYMTAB; - break; - } - - switch (mod->symerr) - { - default: - return; - - case DWFL_E_NOERROR: - break; - - case DWFL_E_NO_SYMTAB: - /* There might be an auxiliary table. */ - find_aux_sym (mod, &aux_symscn, &aux_xndxscn, &aux_strshndx); - - if (symscn != NULL) - { - /* We still have the dynamic symbol table. */ - mod->symerr = DWFL_E_NOERROR; - break; - } - - if (aux_symscn != NULL) - { - /* We still have the auxiliary symbol table. */ - mod->symerr = DWFL_E_NOERROR; - goto aux_cache; - } - - /* Last ditch, look for dynamic symbols without section headers. */ - find_dynsym (mod); - return; - } - break; - } - - /* This does some sanity checks on the string table section. */ - if (elf_strptr (mod->symfile->elf, strshndx, 0) == NULL) - { - elferr: - mod->symerr = DWFL_E (LIBELF, elf_errno ()); - goto aux_cleanup; /* This cleans up some more and tries find_dynsym. */ - } - - /* Cache the data; MOD->syments and MOD->first_global were set above. */ - - mod->symstrdata = elf_getdata (elf_getscn (mod->symfile->elf, strshndx), - NULL); - if (mod->symstrdata == NULL || mod->symstrdata->d_buf == NULL) - goto elferr; - - if (xndxscn == NULL) - mod->symxndxdata = NULL; - else - { - mod->symxndxdata = elf_getdata (xndxscn, NULL); - if (mod->symxndxdata == NULL || mod->symxndxdata->d_buf == NULL) - goto elferr; - } - - mod->symdata = elf_getdata (symscn, NULL); - if (mod->symdata == NULL || mod->symdata->d_buf == NULL) - goto elferr; - - // Sanity check number of symbols. - GElf_Shdr shdr_mem, *shdr = gelf_getshdr (symscn, &shdr_mem); - if (mod->syments > mod->symdata->d_size / shdr->sh_entsize - || (size_t) mod->first_global > mod->syments) - goto elferr; - - /* Cache any auxiliary symbol info, when it fails, just ignore aux_sym. */ - if (aux_symscn != NULL) - { - aux_cache: - /* This does some sanity checks on the string table section. */ - if (elf_strptr (mod->aux_sym.elf, aux_strshndx, 0) == NULL) - { - aux_cleanup: - mod->aux_syments = 0; - elf_end (mod->aux_sym.elf); - mod->aux_sym.elf = NULL; - /* We thought we had something through shdrs, but it failed... - Last ditch, look for dynamic symbols without section headers. */ - find_dynsym (mod); - return; - } - - mod->aux_symstrdata = elf_getdata (elf_getscn (mod->aux_sym.elf, - aux_strshndx), - NULL); - if (mod->aux_symstrdata == NULL || mod->aux_symstrdata->d_buf == NULL) - goto aux_cleanup; - - if (aux_xndxscn == NULL) - mod->aux_symxndxdata = NULL; - else - { - mod->aux_symxndxdata = elf_getdata (aux_xndxscn, NULL); - if (mod->aux_symxndxdata == NULL - || mod->aux_symxndxdata->d_buf == NULL) - goto aux_cleanup; - } - - mod->aux_symdata = elf_getdata (aux_symscn, NULL); - if (mod->aux_symdata == NULL || mod->aux_symdata->d_buf == NULL) - goto aux_cleanup; - - // Sanity check number of aux symbols. - shdr = gelf_getshdr (aux_symscn, &shdr_mem); - if (mod->aux_syments > mod->aux_symdata->d_size / shdr->sh_entsize - || (size_t) mod->aux_first_global > mod->aux_syments) - goto aux_cleanup; - } -} - - -/* Try to open a libebl backend for MOD. */ -Dwfl_Error -internal_function -__libdwfl_module_getebl (Dwfl_Module *mod) -{ - if (mod->ebl == NULL) - { - __libdwfl_getelf (mod); - if (mod->elferr != DWFL_E_NOERROR) - return mod->elferr; - - mod->ebl = ebl_openbackend (mod->main.elf); - if (mod->ebl == NULL) - return DWFL_E_LIBEBL; - } - return DWFL_E_NOERROR; -} - -/* Try to start up libdw on DEBUGFILE. */ -static Dwfl_Error -load_dw (Dwfl_Module *mod, struct dwfl_file *debugfile) -{ - if (mod->e_type == ET_REL && !debugfile->relocated) - { - const Dwfl_Callbacks *const cb = mod->dwfl->callbacks; - - /* The debugging sections have to be relocated. */ - if (cb->section_address == NULL) - return DWFL_E_NOREL; - - Dwfl_Error error = __libdwfl_module_getebl (mod); - if (error != DWFL_E_NOERROR) - return error; - - find_symtab (mod); - Dwfl_Error result = mod->symerr; - if (result == DWFL_E_NOERROR) - result = __libdwfl_relocate (mod, debugfile->elf, true); - if (result != DWFL_E_NOERROR) - return result; - - /* Don't keep the file descriptors around. */ - if (mod->main.fd != -1 && elf_cntl (mod->main.elf, ELF_C_FDREAD) == 0) - { - close (mod->main.fd); - mod->main.fd = -1; - } - if (debugfile->fd != -1 && elf_cntl (debugfile->elf, ELF_C_FDREAD) == 0) - { - close (debugfile->fd); - debugfile->fd = -1; - } - } - - mod->dw = INTUSE(dwarf_begin_elf) (debugfile->elf, DWARF_C_READ, NULL); - if (mod->dw == NULL) - { - int err = INTUSE(dwarf_errno) (); - return err == DWARF_E_NO_DWARF ? DWFL_E_NO_DWARF : DWFL_E (LIBDW, err); - } - - /* Until we have iterated through all CU's, we might do lazy lookups. */ - mod->lazycu = 1; - - return DWFL_E_NOERROR; -} - -/* Try to start up libdw on either the main file or the debuginfo file. */ -static void -find_dw (Dwfl_Module *mod) -{ - if (mod->dw != NULL /* Already done. */ - || mod->dwerr != DWFL_E_NOERROR) /* Cached previous failure. */ - return; - - __libdwfl_getelf (mod); - mod->dwerr = mod->elferr; - if (mod->dwerr != DWFL_E_NOERROR) - return; - - /* First see if the main ELF file has the debugging information. */ - mod->dwerr = load_dw (mod, &mod->main); - switch (mod->dwerr) - { - case DWFL_E_NOERROR: - mod->debug.elf = mod->main.elf; - mod->debug.address_sync = mod->main.address_sync; - - /* The Dwarf might need an alt debug file, find that now after - everything about the debug file has been setup (the - find_debuginfo callback might need it). */ - find_debug_altlink (mod, mod->main.name); - return; - - case DWFL_E_NO_DWARF: - break; - - default: - goto canonicalize; - } - - /* Now we have to look for a separate debuginfo file. */ - mod->dwerr = find_debuginfo (mod); - switch (mod->dwerr) - { - case DWFL_E_NOERROR: - mod->dwerr = load_dw (mod, &mod->debug); - if (mod->dwerr == DWFL_E_NOERROR) - { - /* The Dwarf might need an alt debug file, find that now after - everything about the debug file has been setup (the - find_debuginfo callback might need it). */ - find_debug_altlink (mod, mod->debug.name); - return; - } - - break; - - case DWFL_E_CB: /* The find_debuginfo hook failed. */ - mod->dwerr = DWFL_E_NO_DWARF; - return; - - default: - break; - } - - canonicalize: - mod->dwerr = __libdwfl_canon_error (mod->dwerr); -} - -Dwarf * -dwfl_module_getdwarf (Dwfl_Module *mod, Dwarf_Addr *bias) -{ - if (mod == NULL) - return NULL; - - find_dw (mod); - if (mod->dwerr == DWFL_E_NOERROR) - { - /* If dwfl_module_getelf was used previously, then partial apply - relocation to miscellaneous sections in the debug file too. */ - if (mod->e_type == ET_REL - && mod->main.relocated && ! mod->debug.relocated) - { - mod->debug.relocated = true; - if (mod->debug.elf != mod->main.elf) - (void) __libdwfl_relocate (mod, mod->debug.elf, false); - } - - *bias = dwfl_adjusted_dwarf_addr (mod, 0); - return mod->dw; - } - - __libdwfl_seterrno (mod->dwerr); - return NULL; -} -INTDEF (dwfl_module_getdwarf) - -int -dwfl_module_getsymtab (Dwfl_Module *mod) -{ - if (mod == NULL) - return -1; - - find_symtab (mod); - if (mod->symerr == DWFL_E_NOERROR) - /* We will skip the auxiliary zero entry if there is another one. */ - return (mod->syments + mod->aux_syments - - (mod->syments > 0 && mod->aux_syments > 0 ? 1 : 0)); - - __libdwfl_seterrno (mod->symerr); - return -1; -} -INTDEF (dwfl_module_getsymtab) - -int -dwfl_module_getsymtab_first_global (Dwfl_Module *mod) -{ - if (mod == NULL) - return -1; - - find_symtab (mod); - if (mod->symerr == DWFL_E_NOERROR) - { - /* All local symbols should come before all global symbols. If - we have an auxiliary table make sure all the main locals come - first, then all aux locals, then all main globals and finally all - aux globals. And skip the auxiliary table zero undefined - entry. */ - int skip_aux_zero = (mod->syments > 0 && mod->aux_syments > 0) ? 1 : 0; - return mod->first_global + mod->aux_first_global - skip_aux_zero; - } - - __libdwfl_seterrno (mod->symerr); - return -1; -} -INTDEF (dwfl_module_getsymtab_first_global) diff --git a/src/libdwfl/dwfl_module_getelf.c b/src/libdwfl/dwfl_module_getelf.c deleted file mode 100644 index f20fb042..00000000 --- a/src/libdwfl/dwfl_module_getelf.c +++ /dev/null @@ -1,67 +0,0 @@ -/* Find debugging and symbol information for a module in libdwfl. - Copyright (C) 2009-2010 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" - -Elf * -dwfl_module_getelf (Dwfl_Module *mod, GElf_Addr *loadbase) -{ - if (mod == NULL) - return NULL; - - __libdwfl_getelf (mod); - if (mod->elferr == DWFL_E_NOERROR) - { - if (mod->e_type == ET_REL && ! mod->main.relocated) - { - /* Before letting them get at the Elf handle, - apply all the relocations we know how to. */ - - mod->main.relocated = true; - if (likely (__libdwfl_module_getebl (mod) == DWFL_E_NOERROR)) - { - (void) __libdwfl_relocate (mod, mod->main.elf, false); - - if (mod->debug.elf == mod->main.elf) - mod->debug.relocated = true; - else if (mod->debug.elf != NULL && ! mod->debug.relocated) - { - mod->debug.relocated = true; - (void) __libdwfl_relocate (mod, mod->debug.elf, false); - } - } - } - - *loadbase = dwfl_adjusted_address (mod, 0); - return mod->main.elf; - } - - __libdwfl_seterrno (mod->elferr); - return NULL; -} -INTDEF (dwfl_module_getelf) diff --git a/src/libdwfl/dwfl_module_getsrc.c b/src/libdwfl/dwfl_module_getsrc.c deleted file mode 100644 index f6d88390..00000000 --- a/src/libdwfl/dwfl_module_getsrc.c +++ /dev/null @@ -1,81 +0,0 @@ -/* Find source location for PC address in module. - Copyright (C) 2005, 2008, 2014 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" -#include "../libdw/libdwP.h" - -Dwfl_Line * -dwfl_module_getsrc (Dwfl_Module *mod, Dwarf_Addr addr) -{ - Dwarf_Addr bias; - if (INTUSE(dwfl_module_getdwarf) (mod, &bias) == NULL) - return NULL; - - struct dwfl_cu *cu; - Dwfl_Error error = __libdwfl_addrcu (mod, addr, &cu); - if (likely (error == DWFL_E_NOERROR)) - error = __libdwfl_cu_getsrclines (cu); - if (likely (error == DWFL_E_NOERROR)) - { - Dwarf_Lines *lines = cu->die.cu->lines; - size_t nlines = lines->nlines; - if (nlines > 0) - { - /* This is guaranteed for us by libdw read_srclines. */ - assert(lines->info[nlines - 1].end_sequence); - - /* Now we look at the module-relative address. */ - addr -= bias; - - /* The lines are sorted by address, so we can use binary search. */ - size_t l = 0, u = nlines - 1; - while (l < u) - { - size_t idx = u - (u - l) / 2; - Dwarf_Line *line = &lines->info[idx]; - if (addr < line->addr) - u = idx - 1; - else - l = idx; - } - - /* The last line which is less than or equal to addr is what we want, - except with an end_sequence which can only be strictly equal. */ - Dwarf_Line *line = &lines->info[l]; - if (line->addr == addr - || (! line->end_sequence && line->addr < addr)) - return &cu->lines->idx[l]; - } - - error = DWFL_E_ADDR_OUTOFRANGE; - } - - __libdwfl_seterrno (error); - return NULL; -} -INTDEF (dwfl_module_getsrc) diff --git a/src/libdwfl/dwfl_module_getsrc_file.c b/src/libdwfl/dwfl_module_getsrc_file.c deleted file mode 100644 index 20aa8a5f..00000000 --- a/src/libdwfl/dwfl_module_getsrc_file.c +++ /dev/null @@ -1,167 +0,0 @@ -/* Find matching source locations in a module. - Copyright (C) 2005 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" -#include "../libdw/libdwP.h" - - -int -dwfl_module_getsrc_file (Dwfl_Module *mod, - const char *fname, int lineno, int column, - Dwfl_Line ***srcsp, size_t *nsrcs) -{ - if (mod == NULL) - return -1; - - if (mod->dw == NULL) - { - Dwarf_Addr bias; - if (INTUSE(dwfl_module_getdwarf) (mod, &bias) == 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; - Dwfl_Line **match = *nsrcs == 0 ? NULL : *srcsp; - - struct dwfl_cu *cu = NULL; - Dwfl_Error error; - while ((error = __libdwfl_nextcu (mod, cu, &cu)) == DWFL_E_NOERROR - && cu != NULL - && (error = __libdwfl_cu_getsrclines (cu)) == DWFL_E_NOERROR) - { - inline const char *INTUSE(dwarf_line_file) (const Dwarf_Line *line) - { - return line->files->info[line->file].name; - } - inline Dwarf_Line *dwfl_line (const Dwfl_Line *line) - { - return &dwfl_linecu (line)->die.cu->lines->info[line->idx]; - } - inline const char *dwfl_line_file (const Dwfl_Line *line) - { - return INTUSE(dwarf_line_file) (dwfl_line (line)); - } - - /* 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. */ - const char *lastfile = NULL; - bool lastmatch = false; - for (size_t cnt = 0; cnt < cu->die.cu->lines->nlines; ++cnt) - { - Dwarf_Line *line = &cu->die.cu->lines->info[cnt]; - - if (unlikely (line->file >= line->files->nfiles)) - { - __libdwfl_seterrno (DWFL_E (LIBDW, DWARF_E_INVALID_DWARF)); - return -1; - } - else - { - const char *file = INTUSE(dwarf_line_file) (line); - if (file != lastfile) - { - /* Match the name with the name the user provided. */ - lastfile = file; - lastmatch = !strcmp (is_basename ? basename (file) : file, - fname); - } - } - 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 (dwfl_line_file (match[inner]) - == INTUSE(dwarf_line_file) (line)) - break; - if (inner < cur_match - && (dwfl_line (match[inner])->line != line->line - || dwfl_line (match[inner])->line != lineno - || (column != 0 - && (dwfl_line (match[inner])->column != line->column - || dwfl_line (match[inner])->column != column)))) - { - /* We know about this file already. If this is a better - match for the line number, use it. */ - if (dwfl_line (match[inner])->line >= line->line - && (dwfl_line (match[inner])->line != line->line - || dwfl_line (match[inner])->column >= line->column)) - /* Use the new line. Otherwise the old one. */ - match[inner] = &cu->lines->idx[cnt]; - continue; - } - - if (cur_match < max_match) - { - if (cur_match == act_match) - { - /* Enlarge the array for the results. */ - act_match += 10; - Dwfl_Line **newp = realloc (match, - act_match - * sizeof (Dwfl_Line *)); - if (newp == NULL) - { - free (match); - __libdwfl_seterrno (DWFL_E_NOMEM); - return -1; - } - match = newp; - } - - match[cur_match++] = &cu->lines->idx[cnt]; - } - } - } - - if (cur_match > 0) - { - assert (*nsrcs == 0 || *srcsp == match); - - *nsrcs = cur_match; - *srcsp = match; - - return 0; - } - - __libdwfl_seterrno (DWFL_E_NO_MATCH); - return -1; -} diff --git a/src/libdwfl/dwfl_module_getsym.c b/src/libdwfl/dwfl_module_getsym.c deleted file mode 100644 index 42d2b679..00000000 --- a/src/libdwfl/dwfl_module_getsym.c +++ /dev/null @@ -1,216 +0,0 @@ -/* Find debugging and symbol information for a module in libdwfl. - Copyright (C) 2006-2014 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" - -const char * -internal_function -__libdwfl_getsym (Dwfl_Module *mod, int ndx, GElf_Sym *sym, GElf_Addr *addr, - GElf_Word *shndxp, Elf **elfp, Dwarf_Addr *biasp, - bool *resolved, bool adjust_st_value) -{ - if (unlikely (mod == NULL)) - return NULL; - - if (unlikely (mod->symdata == NULL)) - { - int result = INTUSE(dwfl_module_getsymtab) (mod); - if (result < 0) - return NULL; - } - - /* All local symbols should come before all global symbols. If we - have an auxiliary table make sure all the main locals come first, - then all aux locals, then all main globals and finally all aux globals. - And skip the auxiliary table zero undefined entry. */ - GElf_Word shndx; - int tndx = ndx; - int skip_aux_zero = (mod->syments > 0 && mod->aux_syments > 0) ? 1 : 0; - Elf *elf; - Elf_Data *symdata; - Elf_Data *symxndxdata; - Elf_Data *symstrdata; - if (mod->aux_symdata == NULL - || ndx < mod->first_global) - { - /* main symbol table (locals). */ - tndx = ndx; - elf = mod->symfile->elf; - symdata = mod->symdata; - symxndxdata = mod->symxndxdata; - symstrdata = mod->symstrdata; - } - else if (ndx < mod->first_global + mod->aux_first_global - skip_aux_zero) - { - /* aux symbol table (locals). */ - tndx = ndx - mod->first_global + skip_aux_zero; - elf = mod->aux_sym.elf; - symdata = mod->aux_symdata; - symxndxdata = mod->aux_symxndxdata; - symstrdata = mod->aux_symstrdata; - } - else if ((size_t) ndx < mod->syments + mod->aux_first_global - skip_aux_zero) - { - /* main symbol table (globals). */ - tndx = ndx - mod->aux_first_global + skip_aux_zero; - elf = mod->symfile->elf; - symdata = mod->symdata; - symxndxdata = mod->symxndxdata; - symstrdata = mod->symstrdata; - } - else - { - /* aux symbol table (globals). */ - tndx = ndx - mod->syments + skip_aux_zero; - elf = mod->aux_sym.elf; - symdata = mod->aux_symdata; - symxndxdata = mod->aux_symxndxdata; - symstrdata = mod->aux_symstrdata; - } - sym = gelf_getsymshndx (symdata, symxndxdata, tndx, sym, &shndx); - - if (unlikely (sym == NULL)) - { - __libdwfl_seterrno (DWFL_E_LIBELF); - return NULL; - } - - if (sym->st_shndx != SHN_XINDEX) - shndx = sym->st_shndx; - - /* Figure out whether this symbol points into an SHF_ALLOC section. */ - bool alloc = true; - if ((shndxp != NULL || mod->e_type != ET_REL) - && (sym->st_shndx == SHN_XINDEX - || (sym->st_shndx < SHN_LORESERVE && sym->st_shndx != SHN_UNDEF))) - { - GElf_Shdr shdr_mem; - GElf_Shdr *shdr = gelf_getshdr (elf_getscn (elf, shndx), &shdr_mem); - alloc = unlikely (shdr == NULL) || (shdr->sh_flags & SHF_ALLOC); - } - - /* In case of an value in an allocated section the main Elf Ebl - might know where the real value is (e.g. for function - descriptors). */ - - char *ident; - GElf_Addr st_value = sym->st_value & ebl_func_addr_mask (mod->ebl); - *resolved = false; - if (! adjust_st_value && mod->e_type != ET_REL && alloc - && (GELF_ST_TYPE (sym->st_info) == STT_FUNC - || (GELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC - && (ident = elf_getident (elf, NULL)) != NULL - && ident[EI_OSABI] == ELFOSABI_LINUX))) - { - if (likely (__libdwfl_module_getebl (mod) == DWFL_E_NOERROR)) - { - if (elf != mod->main.elf) - { - st_value = dwfl_adjusted_st_value (mod, elf, st_value); - st_value = dwfl_deadjust_st_value (mod, mod->main.elf, st_value); - } - - *resolved = ebl_resolve_sym_value (mod->ebl, &st_value); - if (! *resolved) - st_value = sym->st_value; - } - } - - if (shndxp != NULL) - /* Yield -1 in case of a non-SHF_ALLOC section. */ - *shndxp = alloc ? shndx : (GElf_Word) -1; - - switch (sym->st_shndx) - { - case SHN_ABS: /* XXX sometimes should use bias?? */ - case SHN_UNDEF: - case SHN_COMMON: - break; - - default: - if (mod->e_type == ET_REL) - { - /* In an ET_REL file, the symbol table values are relative - to the section, not to the module's load base. */ - size_t symshstrndx = SHN_UNDEF; - Dwfl_Error result = __libdwfl_relocate_value (mod, elf, - &symshstrndx, - shndx, &st_value); - if (unlikely (result != DWFL_E_NOERROR)) - { - __libdwfl_seterrno (result); - return NULL; - } - } - else if (alloc) - /* Apply the bias to the symbol value. */ - st_value = dwfl_adjusted_st_value (mod, - *resolved ? mod->main.elf : elf, - st_value); - break; - } - - if (adjust_st_value) - sym->st_value = st_value; - - if (addr != NULL) - *addr = st_value; - - if (unlikely (sym->st_name >= symstrdata->d_size)) - { - __libdwfl_seterrno (DWFL_E_BADSTROFF); - return NULL; - } - if (elfp) - *elfp = elf; - if (biasp) - *biasp = dwfl_adjusted_st_value (mod, elf, 0); - return (const char *) symstrdata->d_buf + sym->st_name; -} - -const char * -dwfl_module_getsym_info (Dwfl_Module *mod, int ndx, - GElf_Sym *sym, GElf_Addr *addr, - GElf_Word *shndxp, - Elf **elfp, Dwarf_Addr *bias) -{ - bool resolved; - return __libdwfl_getsym (mod, ndx, sym, addr, shndxp, elfp, bias, - &resolved, false); -} -INTDEF (dwfl_module_getsym_info) - -const char * -dwfl_module_getsym (Dwfl_Module *mod, int ndx, - GElf_Sym *sym, GElf_Word *shndxp) -{ - bool resolved; - return __libdwfl_getsym (mod, ndx, sym, NULL, shndxp, NULL, NULL, - &resolved, true); -} -INTDEF (dwfl_module_getsym) diff --git a/src/libdwfl/dwfl_module_info.c b/src/libdwfl/dwfl_module_info.c deleted file mode 100644 index df16be41..00000000 --- a/src/libdwfl/dwfl_module_info.c +++ /dev/null @@ -1,61 +0,0 @@ -/* Return information about a module. - Copyright (C) 2005-2010 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" - -const char * -dwfl_module_info (Dwfl_Module *mod, void ***userdata, - Dwarf_Addr *start, Dwarf_Addr *end, - Dwarf_Addr *dwbias, Dwarf_Addr *symbias, - const char **mainfile, const char **debugfile) -{ - if (mod == NULL) - return NULL; - - if (userdata) - *userdata = &mod->userdata; - if (start) - *start = mod->low_addr; - if (end) - *end = mod->high_addr; - - if (dwbias) - *dwbias = (mod->debug.elf == NULL ? (Dwarf_Addr) -1 - : dwfl_adjusted_dwarf_addr (mod, 0)); - if (symbias) - *symbias = (mod->symfile == NULL ? (Dwarf_Addr) -1 - : dwfl_adjusted_st_value (mod, mod->symfile->elf, 0)); - - if (mainfile) - *mainfile = mod->main.name; - - if (debugfile) - *debugfile = mod->debug.name; - - return mod->name; -} diff --git a/src/libdwfl/dwfl_module_nextcu.c b/src/libdwfl/dwfl_module_nextcu.c deleted file mode 100644 index 6f81f4cc..00000000 --- a/src/libdwfl/dwfl_module_nextcu.c +++ /dev/null @@ -1,44 +0,0 @@ -/* Iterate through DWARF compilation units in a module. - Copyright (C) 2005 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" - -Dwarf_Die * -dwfl_module_nextcu (Dwfl_Module *mod, Dwarf_Die *lastcu, Dwarf_Addr *bias) -{ - if (INTUSE(dwfl_module_getdwarf) (mod, bias) == NULL) - return NULL; - - struct dwfl_cu *cu; - Dwfl_Error error = __libdwfl_nextcu (mod, (struct dwfl_cu *) lastcu, &cu); - if (likely (error == DWFL_E_NOERROR)) - return &cu->die; /* Same as a cast, so ok for null too. */ - - __libdwfl_seterrno (error); - return NULL; -} diff --git a/src/libdwfl/dwfl_module_register_names.c b/src/libdwfl/dwfl_module_register_names.c deleted file mode 100644 index 2da4b539..00000000 --- a/src/libdwfl/dwfl_module_register_names.c +++ /dev/null @@ -1,79 +0,0 @@ -/* Enumerate DWARF register numbers and their names. - Copyright (C) 2005, 2006 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" - - -int -dwfl_module_register_names (mod, func, arg) - Dwfl_Module *mod; - int (*func) (void *, int regno, const char *setname, - const char *prefix, const char *regname, - int bits, int type); - void *arg; -{ - if (unlikely (mod == NULL)) - return -1; - - if (unlikely (mod->ebl == NULL)) - { - Dwfl_Error error = __libdwfl_module_getebl (mod); - if (error != DWFL_E_NOERROR) - { - __libdwfl_seterrno (error); - return -1; - } - } - - int nregs = ebl_register_info (mod->ebl, -1, NULL, 0, - NULL, NULL, NULL, NULL); - int result = 0; - for (int regno = 0; regno < nregs && likely (result == 0); ++regno) - { - char name[32]; - const char *setname = NULL; - const char *prefix = NULL; - int bits = -1; - int type = -1; - ssize_t len = ebl_register_info (mod->ebl, regno, name, sizeof name, - &prefix, &setname, &bits, &type); - if (unlikely (len < 0)) - { - __libdwfl_seterrno (DWFL_E_LIBEBL); - result = -1; - break; - } - if (likely (len > 0)) - { - assert (len > 1); /* Backend should never yield "". */ - result = (*func) (arg, regno, setname, prefix, name, bits, type); - } - } - - return result; -} diff --git a/src/libdwfl/dwfl_module_report_build_id.c b/src/libdwfl/dwfl_module_report_build_id.c deleted file mode 100644 index b41512b4..00000000 --- a/src/libdwfl/dwfl_module_report_build_id.c +++ /dev/null @@ -1,80 +0,0 @@ -/* Report build ID information for a module. - Copyright (C) 2007, 2008 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" - -// XXX vs report changed module: punting old file -int -dwfl_module_report_build_id (Dwfl_Module *mod, - const unsigned char *bits, size_t len, - GElf_Addr vaddr) -{ - if (mod == NULL) - return -1; - - if (mod->main.elf != NULL) - { - /* Once we know about a file, we won't take any lies about - its contents. The only permissible call is a no-op. */ - - if ((size_t) mod->build_id_len == len - && (mod->build_id_vaddr == vaddr || vaddr == 0) - && !memcmp (bits, mod->build_id_bits, len)) - return 0; - - __libdwfl_seterrno (DWFL_E_ALREADY_ELF); - return -1; - } - - if (vaddr != 0 && (vaddr < mod->low_addr || vaddr + len > mod->high_addr)) - { - __libdwfl_seterrno (DWFL_E_ADDR_OUTOFRANGE); - return -1; - } - - void *copy = NULL; - if (len > 0) - { - copy = malloc (len); - if (unlikely (copy == NULL)) - { - __libdwfl_seterrno (DWFL_E_NOMEM); - return -1; - } - memcpy (copy, bits, len); - } - - free (mod->build_id_bits); - - mod->build_id_bits = copy; - mod->build_id_len = len; - mod->build_id_vaddr = vaddr; - - return 0; -} -INTDEF (dwfl_module_report_build_id) diff --git a/src/libdwfl/dwfl_module_return_value_location.c b/src/libdwfl/dwfl_module_return_value_location.c deleted file mode 100644 index ad83cbf9..00000000 --- a/src/libdwfl/dwfl_module_return_value_location.c +++ /dev/null @@ -1,64 +0,0 @@ -/* Return location expression to find return value given a function type DIE. - Copyright (C) 2005, 2006 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" - - -int -dwfl_module_return_value_location (mod, functypedie, locops) - Dwfl_Module *mod; - Dwarf_Die *functypedie; - const Dwarf_Op **locops; -{ - if (mod == NULL) - return -1; - - if (mod->ebl == NULL) - { - Dwfl_Error error = __libdwfl_module_getebl (mod); - if (error != DWFL_E_NOERROR) - { - __libdwfl_seterrno (error); - return -1; - } - } - - int nops = ebl_return_value_location (mod->ebl, functypedie, locops); - if (unlikely (nops < 0)) - { - if (nops == -1) - __libdwfl_seterrno (DWFL_E_LIBDW); - else if (nops == -2) - __libdwfl_seterrno (DWFL_E_WEIRD_TYPE); - else - __libdwfl_seterrno (DWFL_E_LIBEBL); - nops = -1; - } - - return nops; -} diff --git a/src/libdwfl/dwfl_nextcu.c b/src/libdwfl/dwfl_nextcu.c deleted file mode 100644 index 9ea83881..00000000 --- a/src/libdwfl/dwfl_nextcu.c +++ /dev/null @@ -1,82 +0,0 @@ -/* Iterate through DWARF compilation units across all modules. - Copyright (C) 2005-2010 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" - -Dwarf_Die * -dwfl_nextcu (Dwfl *dwfl, Dwarf_Die *lastcu, Dwarf_Addr *bias) -{ - if (dwfl == NULL) - return NULL; - - struct dwfl_cu *cu = (struct dwfl_cu *) lastcu; - Dwfl_Module *mod; - - if (cu == NULL) - { - mod = dwfl->modulelist; - goto nextmod; - } - else - mod = cu->mod; - - Dwfl_Error error; - do - { - error = __libdwfl_nextcu (mod, cu, &cu); - if (error != DWFL_E_NOERROR) - break; - - if (cu != NULL) - { - *bias = dwfl_adjusted_dwarf_addr (mod, 0); - return &cu->die; - } - - do - { - mod = mod->next; - - nextmod: - if (mod == NULL) - return NULL; - - if (mod->dwerr == DWFL_E_NOERROR - && (mod->dw != NULL - || INTUSE(dwfl_module_getdwarf) (mod, bias) != NULL)) - break; - } - while (mod->dwerr == DWFL_E_NO_DWARF); - error = mod->dwerr; - } - while (error == DWFL_E_NOERROR); - - __libdwfl_seterrno (error); - return NULL; -} -INTDEF (dwfl_nextcu) diff --git a/src/libdwfl/dwfl_onesrcline.c b/src/libdwfl/dwfl_onesrcline.c deleted file mode 100644 index 4c20d657..00000000 --- a/src/libdwfl/dwfl_onesrcline.c +++ /dev/null @@ -1,56 +0,0 @@ -/* Return one of the sources lines of a CU. - Copyright (C) 2005 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" - -Dwfl_Line * -dwfl_onesrcline (Dwarf_Die *cudie, size_t idx) -{ - struct dwfl_cu *cu = (struct dwfl_cu *) cudie; - - if (cudie == NULL) - return NULL; - - if (cu->lines == NULL) - { - Dwfl_Error error = __libdwfl_cu_getsrclines (cu); - if (error != DWFL_E_NOERROR) - { - __libdwfl_seterrno (error); - return NULL; - } - } - - if (idx >= cu->die.cu->lines->nlines) - { - __libdwfl_seterrno (DWFL_E (LIBDW, DWARF_E_INVALID_LINE_IDX)); - return NULL; - } - - return &cu->lines->idx[idx]; -} diff --git a/src/libdwfl/dwfl_report_elf.c b/src/libdwfl/dwfl_report_elf.c deleted file mode 100644 index 3a4ae2ef..00000000 --- a/src/libdwfl/dwfl_report_elf.c +++ /dev/null @@ -1,338 +0,0 @@ -/* Report a module to libdwfl based on ELF program headers. - Copyright (C) 2005-2010 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" -#include <fcntl.h> -#include <unistd.h> - - -/* We start every ET_REL module at a moderately aligned boundary. - This keeps the low addresses easy to read compared to a layout - starting at 0 (as when using -e). It also makes it unlikely - that a middle section will have a larger alignment and require - rejiggering (see below). */ -#define REL_MIN_ALIGN ((GElf_Xword) 0x100) - -bool -internal_function -__libdwfl_elf_address_range (Elf *elf, GElf_Addr base, bool add_p_vaddr, - bool sanity, GElf_Addr *vaddrp, - GElf_Addr *address_syncp, GElf_Addr *startp, - GElf_Addr *endp, GElf_Addr *biasp, - GElf_Half *e_typep) -{ - GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (elf, &ehdr_mem); - if (ehdr == NULL) - { - elf_error: - __libdwfl_seterrno (DWFL_E_LIBELF); - return false; - } - - GElf_Addr vaddr = 0; - GElf_Addr address_sync = 0; - GElf_Addr start = 0, end = 0, bias = 0; - switch (ehdr->e_type) - { - case ET_REL: - /* For a relocatable object, we do an arbitrary section layout. - By updating the section header in place, we leave the layout - information to be found by relocation. */ - - start = end = base = (base + REL_MIN_ALIGN - 1) & -REL_MIN_ALIGN; - - bool first = true; - Elf_Scn *scn = NULL; - while ((scn = elf_nextscn (elf, scn)) != NULL) - { - GElf_Shdr shdr_mem; - GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); - if (unlikely (shdr == NULL)) - goto elf_error; - - if (shdr->sh_flags & SHF_ALLOC) - { - const GElf_Xword align = shdr->sh_addralign ?: 1; - const GElf_Addr next = (end + align - 1) & -align; - if (shdr->sh_addr == 0 - /* Once we've started doing layout we have to do it all, - unless we just layed out the first section at 0 when - it already was at 0. */ - || (bias == 0 && end > start && end != next)) - { - shdr->sh_addr = next; - if (end == base) - /* This is the first section assigned a location. - Use its aligned address as the module's base. */ - start = base = shdr->sh_addr; - else if (unlikely (base & (align - 1))) - { - /* If BASE has less than the maximum alignment of - any section, we eat more than the optimal amount - of padding and so make the module's apparent - size come out larger than it would when placed - at zero. So reset the layout with a better base. */ - - start = end = base = (base + align - 1) & -align; - Elf_Scn *prev_scn = NULL; - do - { - prev_scn = elf_nextscn (elf, prev_scn); - GElf_Shdr prev_shdr_mem; - GElf_Shdr *prev_shdr = gelf_getshdr (prev_scn, - &prev_shdr_mem); - if (unlikely (prev_shdr == NULL)) - goto elf_error; - if (prev_shdr->sh_flags & SHF_ALLOC) - { - const GElf_Xword prev_align - = prev_shdr->sh_addralign ?: 1; - - prev_shdr->sh_addr - = (end + prev_align - 1) & -prev_align; - end = prev_shdr->sh_addr + prev_shdr->sh_size; - - if (unlikely (! gelf_update_shdr (prev_scn, - prev_shdr))) - goto elf_error; - } - } - while (prev_scn != scn); - continue; - } - - end = shdr->sh_addr + shdr->sh_size; - if (likely (shdr->sh_addr != 0) - && unlikely (! gelf_update_shdr (scn, shdr))) - goto elf_error; - } - else - { - /* The address is already assigned. Just track it. */ - if (first || end < shdr->sh_addr + shdr->sh_size) - end = shdr->sh_addr + shdr->sh_size; - if (first || bias > shdr->sh_addr) - /* This is the lowest address in the module. */ - bias = shdr->sh_addr; - - if ((shdr->sh_addr - bias + base) & (align - 1)) - /* This section winds up misaligned using BASE. - Adjust BASE upwards to make it congruent to - the lowest section address in the file modulo ALIGN. */ - base = (((base + align - 1) & -align) - + (bias & (align - 1))); - } - - first = false; - } - } - - if (bias != 0) - { - /* The section headers had nonzero sh_addr values. The layout - was already done. We've just collected the total span. - Now just compute the bias from the requested base. */ - start = base; - end = end - bias + start; - bias = start - bias; - } - break; - - /* Everything else has to have program headers. */ - - case ET_EXEC: - case ET_CORE: - /* An assigned base address is meaningless for these. */ - base = 0; - add_p_vaddr = true; - - case ET_DYN: - default:; - size_t phnum; - if (unlikely (elf_getphdrnum (elf, &phnum) != 0)) - goto elf_error; - for (size_t i = 0; i < phnum; ++i) - { - GElf_Phdr phdr_mem, *ph = gelf_getphdr (elf, i, &phdr_mem); - if (unlikely (ph == NULL)) - goto elf_error; - if (ph->p_type == PT_LOAD) - { - vaddr = ph->p_vaddr & -ph->p_align; - address_sync = ph->p_vaddr + ph->p_memsz; - break; - } - } - if (add_p_vaddr) - { - start = base + vaddr; - bias = base; - } - else - { - start = base; - bias = base - vaddr; - } - - for (size_t i = phnum; i-- > 0;) - { - GElf_Phdr phdr_mem, *ph = gelf_getphdr (elf, i, &phdr_mem); - if (unlikely (ph == NULL)) - goto elf_error; - if (ph->p_type == PT_LOAD - && ph->p_vaddr + ph->p_memsz > 0) - { - end = bias + (ph->p_vaddr + ph->p_memsz); - break; - } - } - - if (end == 0 && sanity) - { - __libdwfl_seterrno (DWFL_E_NO_PHDR); - return false; - } - break; - } - if (vaddrp) - *vaddrp = vaddr; - if (address_syncp) - *address_syncp = address_sync; - if (startp) - *startp = start; - if (endp) - *endp = end; - if (biasp) - *biasp = bias; - if (e_typep) - *e_typep = ehdr->e_type; - return true; -} - -Dwfl_Module * -internal_function -__libdwfl_report_elf (Dwfl *dwfl, const char *name, const char *file_name, - int fd, Elf *elf, GElf_Addr base, bool add_p_vaddr, - bool sanity) -{ - GElf_Addr vaddr, address_sync, start, end, bias; - GElf_Half e_type; - if (! __libdwfl_elf_address_range (elf, base, add_p_vaddr, sanity, &vaddr, - &address_sync, &start, &end, &bias, - &e_type)) - return NULL; - Dwfl_Module *m = INTUSE(dwfl_report_module) (dwfl, name, start, end); - if (m != NULL) - { - if (m->main.name == NULL) - { - m->main.name = strdup (file_name); - m->main.fd = fd; - } - else if ((fd >= 0 && m->main.fd != fd) - || strcmp (m->main.name, file_name)) - { - overlap: - m->gc = true; - __libdwfl_seterrno (DWFL_E_OVERLAP); - return NULL; - } - - /* Preinstall the open ELF handle for the module. */ - if (m->main.elf == NULL) - { - m->main.elf = elf; - m->main.vaddr = vaddr; - m->main.address_sync = address_sync; - m->main_bias = bias; - m->e_type = e_type; - } - else - { - elf_end (elf); - if (m->main_bias != bias - || m->main.vaddr != vaddr || m->main.address_sync != address_sync) - goto overlap; - } - } - return m; -} - -Dwfl_Module * -dwfl_report_elf (Dwfl *dwfl, const char *name, const char *file_name, int fd, - GElf_Addr base, bool add_p_vaddr) -{ - bool closefd = false; - if (fd < 0) - { - closefd = true; - fd = open64 (file_name, O_RDONLY); - if (fd < 0) - { - __libdwfl_seterrno (DWFL_E_ERRNO); - return NULL; - } - } - - Elf *elf; - Dwfl_Error error = __libdw_open_file (&fd, &elf, closefd, false); - if (error != DWFL_E_NOERROR) - { - __libdwfl_seterrno (error); - return NULL; - } - - Dwfl_Module *mod = __libdwfl_report_elf (dwfl, name, file_name, - fd, elf, base, add_p_vaddr, true); - if (mod == NULL) - { - elf_end (elf); - if (closefd) - close (fd); - } - - return mod; -} -INTDEF (dwfl_report_elf) -NEW_VERSION (dwfl_report_elf, ELFUTILS_0.156) - -#ifdef SHARED -Dwfl_Module * - _compat_without_add_p_vaddr_dwfl_report_elf (Dwfl *dwfl, const char *name, - const char *file_name, int fd, - GElf_Addr base); -COMPAT_VERSION_NEWPROTO (dwfl_report_elf, ELFUTILS_0.122, without_add_p_vaddr) - -Dwfl_Module * -_compat_without_add_p_vaddr_dwfl_report_elf (Dwfl *dwfl, const char *name, - const char *file_name, int fd, - GElf_Addr base) -{ - return dwfl_report_elf (dwfl, name, file_name, fd, base, true); -} -#endif diff --git a/src/libdwfl/dwfl_segment_report_module.c b/src/libdwfl/dwfl_segment_report_module.c deleted file mode 100644 index 898457f1..00000000 --- a/src/libdwfl/dwfl_segment_report_module.c +++ /dev/null @@ -1,922 +0,0 @@ -/* Sniff out modules from ELF headers visible in memory segments. - Copyright (C) 2008-2012, 2014 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include <config.h> -#include "../libelf/libelfP.h" /* For NOTE_ALIGN. */ -#undef _ -#include "libdwflP.h" -#include "common.h" - -#include <elf.h> -#include <gelf.h> -#include <inttypes.h> -#include <sys/param.h> -#include <alloca.h> -#include <endian.h> -#include <unistd.h> -#include <fcntl.h> - - -/* A good size for the initial read from memory, if it's not too costly. - This more than covers the phdrs and note segment in the average 64-bit - binary. */ - -#define INITIAL_READ 1024 - -#if __BYTE_ORDER == __LITTLE_ENDIAN -# define MY_ELFDATA ELFDATA2LSB -#else -# define MY_ELFDATA ELFDATA2MSB -#endif - - -/* Return user segment index closest to ADDR but not above it. - If NEXT, return the closest to ADDR but not below it. */ -static int -addr_segndx (Dwfl *dwfl, size_t segment, GElf_Addr addr, bool next) -{ - int ndx = -1; - do - { - if (dwfl->lookup_segndx[segment] >= 0) - ndx = dwfl->lookup_segndx[segment]; - if (++segment >= dwfl->lookup_elts - 1) - return next ? ndx + 1 : ndx; - } - while (dwfl->lookup_addr[segment] < addr); - - if (next) - { - while (dwfl->lookup_segndx[segment] < 0) - if (++segment >= dwfl->lookup_elts - 1) - return ndx + 1; - ndx = dwfl->lookup_segndx[segment]; - } - - return ndx; -} - -/* Return whether there is SZ bytes available at PTR till END. */ - -static bool -buf_has_data (const void *ptr, const void *end, size_t sz) -{ - return ptr < end && (size_t) (end - ptr) >= sz; -} - -/* Read SZ bytes into *RETP from *PTRP (limited by END) in format EI_DATA. - Function comes from src/readelf.c . */ - -static bool -buf_read_ulong (unsigned char ei_data, size_t sz, - const void **ptrp, const void *end, uint64_t *retp) -{ - if (! buf_has_data (*ptrp, end, sz)) - return false; - - union - { - uint64_t u64; - uint32_t u32; - } u; - - memcpy (&u, *ptrp, sz); - (*ptrp) += sz; - - if (retp == NULL) - return true; - - if (MY_ELFDATA != ei_data) - { - if (sz == 4) - CONVERT (u.u32); - else - CONVERT (u.u64); - } - if (sz == 4) - *retp = u.u32; - else - *retp = u.u64; - return true; -} - -/* Try to find matching entry for module from address MODULE_START to - MODULE_END in NT_FILE note located at NOTE_FILE of NOTE_FILE_SIZE - bytes in format EI_CLASS and EI_DATA. */ - -static const char * -handle_file_note (GElf_Addr module_start, GElf_Addr module_end, - unsigned char ei_class, unsigned char ei_data, - const void *note_file, size_t note_file_size) -{ - if (note_file == NULL) - return NULL; - - size_t sz; - switch (ei_class) - { - case ELFCLASS32: - sz = 4; - break; - case ELFCLASS64: - sz = 8; - break; - default: - return NULL; - } - - const void *ptr = note_file; - const void *end = note_file + note_file_size; - uint64_t count; - if (! buf_read_ulong (ei_data, sz, &ptr, end, &count)) - return NULL; - if (! buf_read_ulong (ei_data, sz, &ptr, end, NULL)) // page_size - return NULL; - - uint64_t maxcount = (size_t) (end - ptr) / (3 * sz); - if (count > maxcount) - return NULL; - - /* Where file names are stored. */ - const char *fptr = ptr + 3 * count * sz; - - ssize_t firstix = -1; - ssize_t lastix = -1; - for (size_t mix = 0; mix < count; mix++) - { - uint64_t mstart, mend, moffset; - if (! buf_read_ulong (ei_data, sz, &ptr, fptr, &mstart) - || ! buf_read_ulong (ei_data, sz, &ptr, fptr, &mend) - || ! buf_read_ulong (ei_data, sz, &ptr, fptr, &moffset)) - return NULL; - if (mstart == module_start && moffset == 0) - firstix = lastix = mix; - if (firstix != -1 && mstart < module_end) - lastix = mix; - if (mend >= module_end) - break; - } - if (firstix == -1) - return NULL; - - const char *retval = NULL; - for (ssize_t mix = 0; mix <= lastix; mix++) - { - const char *fnext = memchr (fptr, 0, (const char *) end - fptr); - if (fnext == NULL) - return NULL; - if (mix == firstix) - retval = fptr; - if (firstix < mix && mix <= lastix && strcmp (fptr, retval) != 0) - return NULL; - fptr = fnext + 1; - } - return retval; -} - -/* Return true iff we are certain ELF cannot match BUILD_ID of - BUILD_ID_LEN bytes. Pass DISK_FILE_HAS_BUILD_ID as false if it is - certain ELF does not contain build-id (it is only a performance hit - to pass it always as true). */ - -static bool -invalid_elf (Elf *elf, bool disk_file_has_build_id, - const void *build_id, size_t build_id_len) -{ - if (! disk_file_has_build_id && build_id_len > 0) - { - /* Module found in segments with build-id is more reliable - than a module found via DT_DEBUG on disk without any - build-id. */ - return true; - } - if (disk_file_has_build_id && build_id_len > 0) - { - const void *elf_build_id; - ssize_t elf_build_id_len; - - /* If there is a build id in the elf file, check it. */ - elf_build_id_len = INTUSE(dwelf_elf_gnu_build_id) (elf, &elf_build_id); - if (elf_build_id_len > 0) - { - if (build_id_len != (size_t) elf_build_id_len - || memcmp (build_id, elf_build_id, build_id_len) != 0) - return true; - } - } - return false; -} - -int -dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, - Dwfl_Memory_Callback *memory_callback, - void *memory_callback_arg, - Dwfl_Module_Callback *read_eagerly, - void *read_eagerly_arg, - const void *note_file, size_t note_file_size, - const struct r_debug_info *r_debug_info) -{ - size_t segment = ndx; - - if (segment >= dwfl->lookup_elts) - segment = dwfl->lookup_elts - 1; - - while (segment > 0 - && (dwfl->lookup_segndx[segment] > ndx - || dwfl->lookup_segndx[segment] == -1)) - --segment; - - while (dwfl->lookup_segndx[segment] < ndx) - if (++segment == dwfl->lookup_elts) - return 0; - - GElf_Addr start = dwfl->lookup_addr[segment]; - - inline bool segment_read (int segndx, - void **buffer, size_t *buffer_available, - GElf_Addr addr, size_t minread) - { - return ! (*memory_callback) (dwfl, segndx, buffer, buffer_available, - addr, minread, memory_callback_arg); - } - - inline void release_buffer (void **buffer, size_t *buffer_available) - { - if (*buffer != NULL) - (void) segment_read (-1, buffer, buffer_available, 0, 0); - } - - /* First read in the file header and check its sanity. */ - - void *buffer = NULL; - size_t buffer_available = INITIAL_READ; - Elf *elf = NULL; - int fd = -1; - - inline int finish (void) - { - release_buffer (&buffer, &buffer_available); - if (elf != NULL) - elf_end (elf); - if (fd != -1) - close (fd); - return ndx; - } - - if (segment_read (ndx, &buffer, &buffer_available, - start, sizeof (Elf64_Ehdr)) - || memcmp (buffer, ELFMAG, SELFMAG) != 0) - return finish (); - - inline bool read_portion (void **data, size_t *data_size, - GElf_Addr vaddr, size_t filesz) - { - if (vaddr - start + filesz > buffer_available - /* If we're in string mode, then don't consider the buffer we have - sufficient unless it contains the terminator of the string. */ - || (filesz == 0 && memchr (vaddr - start + buffer, '\0', - buffer_available - (vaddr - start)) == NULL)) - { - *data = NULL; - *data_size = filesz; - return segment_read (addr_segndx (dwfl, segment, vaddr, false), - data, data_size, vaddr, filesz); - } - - /* We already have this whole note segment from our initial read. */ - *data = vaddr - start + buffer; - *data_size = 0; - return false; - } - - inline void finish_portion (void **data, size_t *data_size) - { - if (*data_size != 0) - release_buffer (data, data_size); - } - - /* Extract the information we need from the file header. */ - const unsigned char *e_ident; - unsigned char ei_class; - unsigned char ei_data; - uint16_t e_type; - union - { - Elf32_Ehdr e32; - Elf64_Ehdr e64; - } ehdr; - GElf_Off phoff; - uint_fast16_t phnum; - uint_fast16_t phentsize; - GElf_Off shdrs_end; - Elf_Data xlatefrom = - { - .d_type = ELF_T_EHDR, - .d_buf = (void *) buffer, - .d_version = EV_CURRENT, - }; - Elf_Data xlateto = - { - .d_type = ELF_T_EHDR, - .d_buf = &ehdr, - .d_size = sizeof ehdr, - .d_version = EV_CURRENT, - }; - e_ident = ((const unsigned char *) buffer); - ei_class = e_ident[EI_CLASS]; - ei_data = e_ident[EI_DATA]; - switch (ei_class) - { - case ELFCLASS32: - xlatefrom.d_size = sizeof (Elf32_Ehdr); - if (elf32_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL) - return finish (); - e_type = ehdr.e32.e_type; - phoff = ehdr.e32.e_phoff; - phnum = ehdr.e32.e_phnum; - phentsize = ehdr.e32.e_phentsize; - if (phentsize != sizeof (Elf32_Phdr)) - return finish (); - shdrs_end = ehdr.e32.e_shoff + ehdr.e32.e_shnum * ehdr.e32.e_shentsize; - break; - - case ELFCLASS64: - xlatefrom.d_size = sizeof (Elf64_Ehdr); - if (elf64_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL) - return finish (); - e_type = ehdr.e64.e_type; - phoff = ehdr.e64.e_phoff; - phnum = ehdr.e64.e_phnum; - phentsize = ehdr.e64.e_phentsize; - if (phentsize != sizeof (Elf64_Phdr)) - return finish (); - shdrs_end = ehdr.e64.e_shoff + ehdr.e64.e_shnum * ehdr.e64.e_shentsize; - break; - - default: - return finish (); - } - - /* The file header tells where to find the program headers. - These are what we need to find the boundaries of the module. - Without them, we don't have a module to report. */ - - if (phnum == 0) - return finish (); - - xlatefrom.d_type = xlateto.d_type = ELF_T_PHDR; - xlatefrom.d_size = phnum * phentsize; - - void *ph_buffer = NULL; - size_t ph_buffer_size = 0; - if (read_portion (&ph_buffer, &ph_buffer_size, - start + phoff, xlatefrom.d_size)) - return finish (); - - xlatefrom.d_buf = ph_buffer; - - union - { - Elf32_Phdr p32[phnum]; - Elf64_Phdr p64[phnum]; - } phdrs; - - xlateto.d_buf = &phdrs; - xlateto.d_size = sizeof phdrs; - - /* Track the bounds of the file visible in memory. */ - GElf_Off file_trimmed_end = 0; /* Proper p_vaddr + p_filesz end. */ - GElf_Off file_end = 0; /* Rounded up to effective page size. */ - GElf_Off contiguous = 0; /* Visible as contiguous file from START. */ - GElf_Off total_filesz = 0; /* Total size of data to read. */ - - /* Collect the bias between START and the containing PT_LOAD's p_vaddr. */ - GElf_Addr bias = 0; - bool found_bias = false; - - /* Collect the unbiased bounds of the module here. */ - GElf_Addr module_start = -1l; - GElf_Addr module_end = 0; - GElf_Addr module_address_sync = 0; - - /* If we see PT_DYNAMIC, record it here. */ - GElf_Addr dyn_vaddr = 0; - GElf_Xword dyn_filesz = 0; - - /* Collect the build ID bits here. */ - void *build_id = NULL; - size_t build_id_len = 0; - GElf_Addr build_id_vaddr = 0; - - /* Consider a PT_NOTE we've found in the image. */ - inline void consider_notes (GElf_Addr vaddr, GElf_Xword filesz) - { - /* If we have already seen a build ID, we don't care any more. */ - if (build_id != NULL || filesz == 0) - return; - - void *data; - size_t data_size; - if (read_portion (&data, &data_size, vaddr, filesz)) - return; - - assert (sizeof (Elf32_Nhdr) == sizeof (Elf64_Nhdr)); - - void *notes; - if (ei_data == MY_ELFDATA) - notes = data; - else - { - notes = malloc (filesz); - if (unlikely (notes == NULL)) - return; - xlatefrom.d_type = xlateto.d_type = ELF_T_NHDR; - xlatefrom.d_buf = (void *) data; - xlatefrom.d_size = filesz; - xlateto.d_buf = notes; - xlateto.d_size = filesz; - if (elf32_xlatetom (&xlateto, &xlatefrom, - ehdr.e32.e_ident[EI_DATA]) == NULL) - goto done; - } - - const GElf_Nhdr *nh = notes; - while ((const void *) nh < (const void *) notes + filesz) - { - const void *note_name = nh + 1; - const void *note_desc = note_name + NOTE_ALIGN (nh->n_namesz); - if (unlikely ((size_t) ((const void *) notes + filesz - - note_desc) < nh->n_descsz)) - break; - - if (nh->n_type == NT_GNU_BUILD_ID - && nh->n_descsz > 0 - && nh->n_namesz == sizeof "GNU" - && !memcmp (note_name, "GNU", sizeof "GNU")) - { - build_id_vaddr = note_desc - (const void *) notes + vaddr; - build_id_len = nh->n_descsz; - build_id = malloc (nh->n_descsz); - if (likely (build_id != NULL)) - memcpy (build_id, note_desc, build_id_len); - break; - } - - nh = note_desc + NOTE_ALIGN (nh->n_descsz); - } - - done: - if (notes != data) - free (notes); - finish_portion (&data, &data_size); - } - - /* Consider each of the program headers we've read from the image. */ - inline void consider_phdr (GElf_Word type, - GElf_Addr vaddr, GElf_Xword memsz, - GElf_Off offset, GElf_Xword filesz, - GElf_Xword align) - { - switch (type) - { - case PT_DYNAMIC: - dyn_vaddr = vaddr; - dyn_filesz = filesz; - break; - - case PT_NOTE: - /* We calculate from the p_offset of the note segment, - because we don't yet know the bias for its p_vaddr. */ - consider_notes (start + offset, filesz); - break; - - case PT_LOAD: - align = dwfl->segment_align > 1 ? dwfl->segment_align : align ?: 1; - - GElf_Addr vaddr_end = (vaddr + memsz + align - 1) & -align; - GElf_Addr filesz_vaddr = filesz < memsz ? vaddr + filesz : vaddr_end; - GElf_Off filesz_offset = filesz_vaddr - vaddr + offset; - - if (file_trimmed_end < offset + filesz) - { - file_trimmed_end = offset + filesz; - - /* Trim the last segment so we don't bother with zeros - in the last page that are off the end of the file. - However, if the extra bit in that page includes the - section headers, keep them. */ - if (shdrs_end <= filesz_offset && shdrs_end > file_trimmed_end) - { - filesz += shdrs_end - file_trimmed_end; - file_trimmed_end = shdrs_end; - } - } - - total_filesz += filesz; - - if (file_end < filesz_offset) - { - file_end = filesz_offset; - if (filesz_vaddr - start == filesz_offset) - contiguous = file_end; - } - - if (!found_bias && (offset & -align) == 0 - && likely (filesz_offset >= phoff + phnum * phentsize)) - { - bias = start - vaddr; - found_bias = true; - } - - if ((vaddr & -align) < module_start) - { - module_start = vaddr & -align; - module_address_sync = vaddr + memsz; - } - - if (module_end < vaddr_end) - module_end = vaddr_end; - break; - } - } - if (ei_class == ELFCLASS32) - { - if (elf32_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL) - found_bias = false; /* Trigger error check. */ - else - for (uint_fast16_t i = 0; i < phnum; ++i) - consider_phdr (phdrs.p32[i].p_type, - phdrs.p32[i].p_vaddr, phdrs.p32[i].p_memsz, - phdrs.p32[i].p_offset, phdrs.p32[i].p_filesz, - phdrs.p32[i].p_align); - } - else - { - if (elf64_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL) - found_bias = false; /* Trigger error check. */ - else - for (uint_fast16_t i = 0; i < phnum; ++i) - consider_phdr (phdrs.p64[i].p_type, - phdrs.p64[i].p_vaddr, phdrs.p64[i].p_memsz, - phdrs.p64[i].p_offset, phdrs.p64[i].p_filesz, - phdrs.p64[i].p_align); - } - - finish_portion (&ph_buffer, &ph_buffer_size); - - /* We must have seen the segment covering offset 0, or else the ELF - header we read at START was not produced by these program headers. */ - if (unlikely (!found_bias)) - { - free (build_id); - return finish (); - } - - /* Now we know enough to report a module for sure: its bounds. */ - module_start += bias; - module_end += bias; - - dyn_vaddr += bias; - - /* NAME found from link map has precedence over DT_SONAME possibly read - below. */ - bool name_is_final = false; - - /* Try to match up DYN_VADDR against L_LD as found in link map. - Segments sniffing may guess invalid address as the first read-only memory - mapping may not be dumped to the core file (if ELF headers are not dumped) - and the ELF header is dumped first with the read/write mapping of the same - file at higher addresses. */ - if (r_debug_info != NULL) - for (const struct r_debug_info_module *module = r_debug_info->module; - module != NULL; module = module->next) - if (module_start <= module->l_ld && module->l_ld < module_end) - { - /* L_LD read from link map must be right while DYN_VADDR is unsafe. - Therefore subtract DYN_VADDR and add L_LD to get a possibly - corrective displacement for all addresses computed so far. */ - GElf_Addr fixup = module->l_ld - dyn_vaddr; - if ((fixup & (dwfl->segment_align - 1)) == 0 - && module_start + fixup <= module->l_ld - && module->l_ld < module_end + fixup) - { - module_start += fixup; - module_end += fixup; - dyn_vaddr += fixup; - bias += fixup; - if (module->name[0] != '\0') - { - name = basename (module->name); - name_is_final = true; - } - break; - } - } - - if (r_debug_info != NULL) - { - bool skip_this_module = false; - for (struct r_debug_info_module *module = r_debug_info->module; - module != NULL; module = module->next) - if ((module_end > module->start && module_start < module->end) - || dyn_vaddr == module->l_ld) - { - if (module->elf != NULL - && invalid_elf (module->elf, module->disk_file_has_build_id, - build_id, build_id_len)) - { - elf_end (module->elf); - close (module->fd); - module->elf = NULL; - module->fd = -1; - } - if (module->elf != NULL) - { - /* Ignore this found module if it would conflict in address - space with any already existing module of DWFL. */ - skip_this_module = true; - } - } - if (skip_this_module) - { - free (build_id); - return finish (); - } - } - - const char *file_note_name = handle_file_note (module_start, module_end, - ei_class, ei_data, - note_file, note_file_size); - if (file_note_name) - { - name = file_note_name; - name_is_final = true; - bool invalid = false; - fd = open64 (name, O_RDONLY); - if (fd >= 0) - { - Dwfl_Error error = __libdw_open_file (&fd, &elf, true, false); - if (error == DWFL_E_NOERROR) - invalid = invalid_elf (elf, true /* disk_file_has_build_id */, - build_id, build_id_len); - } - if (invalid) - { - free (build_id); - return finish (); - } - } - - /* Our return value now says to skip the segments contained - within the module. */ - ndx = addr_segndx (dwfl, segment, module_end, true); - - /* Examine its .dynamic section to get more interesting details. - If it has DT_SONAME, we'll use that as the module name. - If it has a DT_DEBUG, then it's actually a PIE rather than a DSO. - We need its DT_STRTAB and DT_STRSZ to decipher DT_SONAME, - and they also tell us the essential portion of the file - for fetching symbols. */ - GElf_Addr soname_stroff = 0; - GElf_Addr dynstr_vaddr = 0; - GElf_Xword dynstrsz = 0; - bool execlike = false; - inline bool consider_dyn (GElf_Sxword tag, GElf_Xword val) - { - switch (tag) - { - default: - return false; - - case DT_DEBUG: - execlike = true; - break; - - case DT_SONAME: - soname_stroff = val; - break; - - case DT_STRTAB: - dynstr_vaddr = val; - break; - - case DT_STRSZ: - dynstrsz = val; - break; - } - - return soname_stroff != 0 && dynstr_vaddr != 0 && dynstrsz != 0; - } - - const size_t dyn_entsize = (ei_class == ELFCLASS32 - ? sizeof (Elf32_Dyn) : sizeof (Elf64_Dyn)); - void *dyn_data = NULL; - size_t dyn_data_size = 0; - if (dyn_filesz != 0 && dyn_filesz % dyn_entsize == 0 - && ! read_portion (&dyn_data, &dyn_data_size, dyn_vaddr, dyn_filesz)) - { - union - { - Elf32_Dyn d32[dyn_filesz / sizeof (Elf32_Dyn)]; - Elf64_Dyn d64[dyn_filesz / sizeof (Elf64_Dyn)]; - } dyn; - - xlatefrom.d_type = xlateto.d_type = ELF_T_DYN; - xlatefrom.d_buf = (void *) dyn_data; - xlatefrom.d_size = dyn_filesz; - xlateto.d_buf = &dyn; - xlateto.d_size = sizeof dyn; - - if (ei_class == ELFCLASS32) - { - if (elf32_xlatetom (&xlateto, &xlatefrom, ei_data) != NULL) - for (size_t i = 0; i < dyn_filesz / sizeof dyn.d32[0]; ++i) - if (consider_dyn (dyn.d32[i].d_tag, dyn.d32[i].d_un.d_val)) - break; - } - else - { - if (elf64_xlatetom (&xlateto, &xlatefrom, ei_data) != NULL) - for (size_t i = 0; i < dyn_filesz / sizeof dyn.d64[0]; ++i) - if (consider_dyn (dyn.d64[i].d_tag, dyn.d64[i].d_un.d_val)) - break; - } - } - finish_portion (&dyn_data, &dyn_data_size); - - /* We'll use the name passed in or a stupid default if not DT_SONAME. */ - if (name == NULL) - name = e_type == ET_EXEC ? "[exe]" : execlike ? "[pie]" : "[dso]"; - - void *soname = NULL; - size_t soname_size = 0; - if (! name_is_final && dynstrsz != 0 && dynstr_vaddr != 0) - { - /* We know the bounds of the .dynstr section. - - The DYNSTR_VADDR pointer comes from the .dynamic section - (DT_STRTAB, detected above). Ordinarily the dynamic linker - will have adjusted this pointer in place so it's now an - absolute address. But sometimes .dynamic is read-only (in - vDSOs and odd architectures), and sometimes the adjustment - just hasn't happened yet in the memory image we looked at. - So treat DYNSTR_VADDR as an absolute address if it falls - within the module bounds, or try applying the phdr bias - when that adjusts it to fall within the module bounds. */ - - if ((dynstr_vaddr < module_start || dynstr_vaddr >= module_end) - && dynstr_vaddr + bias >= module_start - && dynstr_vaddr + bias < module_end) - dynstr_vaddr += bias; - - if (unlikely (dynstr_vaddr + dynstrsz > module_end)) - dynstrsz = 0; - - /* Try to get the DT_SONAME string. */ - if (soname_stroff != 0 && soname_stroff + 1 < dynstrsz - && ! read_portion (&soname, &soname_size, - dynstr_vaddr + soname_stroff, 0)) - name = soname; - } - - /* Now that we have chosen the module's name and bounds, report it. - If we found a build ID, report that too. */ - - Dwfl_Module *mod = INTUSE(dwfl_report_module) (dwfl, name, - module_start, module_end); - - // !execlike && ET_EXEC is PIE. - // execlike && !ET_EXEC is a static executable. - if (mod != NULL && (execlike || ehdr.e32.e_type == ET_EXEC)) - mod->is_executable = true; - - if (likely (mod != NULL) && build_id != NULL - && unlikely (INTUSE(dwfl_module_report_build_id) (mod, - build_id, - build_id_len, - build_id_vaddr))) - { - mod->gc = true; - mod = NULL; - } - - /* At this point we do not need BUILD_ID or NAME any more. - They have been copied. */ - free (build_id); - finish_portion (&soname, &soname_size); - - if (unlikely (mod == NULL)) - { - ndx = -1; - return finish (); - } - - /* We have reported the module. Now let the caller decide whether we - should read the whole thing in right now. */ - - const GElf_Off cost = (contiguous < file_trimmed_end ? total_filesz - : buffer_available >= contiguous ? 0 - : contiguous - buffer_available); - const GElf_Off worthwhile = ((dynstr_vaddr == 0 || dynstrsz == 0) ? 0 - : dynstr_vaddr + dynstrsz - start); - const GElf_Off whole = MAX (file_trimmed_end, shdrs_end); - - if (elf == NULL - && (*read_eagerly) (MODCB_ARGS (mod), &buffer, &buffer_available, - cost, worthwhile, whole, contiguous, - read_eagerly_arg, &elf) - && elf == NULL) - { - /* The caller wants to read the whole file in right now, but hasn't - done it for us. Fill in a local image of the virtual file. */ - - void *contents = calloc (1, file_trimmed_end); - if (unlikely (contents == NULL)) - return finish (); - - inline void final_read (size_t offset, GElf_Addr vaddr, size_t size) - { - void *into = contents + offset; - size_t read_size = size; - (void) segment_read (addr_segndx (dwfl, segment, vaddr, false), - &into, &read_size, vaddr, size); - } - - if (contiguous < file_trimmed_end) - { - /* We can't use the memory image verbatim as the file image. - So we'll be reading into a local image of the virtual file. */ - - inline void read_phdr (GElf_Word type, GElf_Addr vaddr, - GElf_Off offset, GElf_Xword filesz) - { - if (type == PT_LOAD) - final_read (offset, vaddr + bias, filesz); - } - - if (ei_class == ELFCLASS32) - for (uint_fast16_t i = 0; i < phnum; ++i) - read_phdr (phdrs.p32[i].p_type, phdrs.p32[i].p_vaddr, - phdrs.p32[i].p_offset, phdrs.p32[i].p_filesz); - else - for (uint_fast16_t i = 0; i < phnum; ++i) - read_phdr (phdrs.p64[i].p_type, phdrs.p64[i].p_vaddr, - phdrs.p64[i].p_offset, phdrs.p64[i].p_filesz); - } - else - { - /* The whole file sits contiguous in memory, - but the caller didn't want to just do it. */ - - const size_t have = MIN (buffer_available, file_trimmed_end); - memcpy (contents, buffer, have); - - if (have < file_trimmed_end) - final_read (have, start + have, file_trimmed_end - have); - } - - elf = elf_memory (contents, file_trimmed_end); - if (unlikely (elf == NULL)) - free (contents); - else - elf->flags |= ELF_F_MALLOCED; - } - - if (elf != NULL) - { - /* Install the file in the module. */ - mod->main.elf = elf; - elf = NULL; - fd = -1; - mod->main.vaddr = module_start - bias; - mod->main.address_sync = module_address_sync; - mod->main_bias = bias; - } - - return finish (); -} diff --git a/src/libdwfl/dwfl_validate_address.c b/src/libdwfl/dwfl_validate_address.c deleted file mode 100644 index 7334c3e2..00000000 --- a/src/libdwfl/dwfl_validate_address.c +++ /dev/null @@ -1,61 +0,0 @@ -/* Validate an address and the relocatability of an offset from it. - Copyright (C) 2005 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" - -int -dwfl_validate_address (Dwfl *dwfl, Dwarf_Addr address, Dwarf_Sword offset) -{ - Dwfl_Module *mod = INTUSE(dwfl_addrmodule) (dwfl, address); - if (mod == NULL) - return -1; - - Dwarf_Addr relative = address; - int idx = INTUSE(dwfl_module_relocate_address) (mod, &relative); - if (idx < 0) - return -1; - - if (offset != 0) - { - int offset_idx = -1; - relative = address + offset; - if (relative >= mod->low_addr && relative <= mod->high_addr) - { - offset_idx = INTUSE(dwfl_module_relocate_address) (mod, &relative); - if (offset_idx < 0) - return -1; - } - if (offset_idx != idx) - { - __libdwfl_seterrno (DWFL_E_ADDR_OUTOFRANGE); - return -1; - } - } - - return 0; -} diff --git a/src/libdwfl/dwfl_version.c b/src/libdwfl/dwfl_version.c deleted file mode 100644 index 9673a536..00000000 --- a/src/libdwfl/dwfl_version.c +++ /dev/null @@ -1,36 +0,0 @@ -/* Return implementation's version string suitable for printing. - Copyright (C) 2006, 2007 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" - -const char * -dwfl_version (dwfl) - Dwfl *dwfl __attribute__ ((unused)); -{ - return PACKAGE_VERSION; -} diff --git a/src/libdwfl/elf-from-memory.c b/src/libdwfl/elf-from-memory.c deleted file mode 100644 index b35fac71..00000000 --- a/src/libdwfl/elf-from-memory.c +++ /dev/null @@ -1,370 +0,0 @@ -/* Reconstruct an ELF file by reading the segments out of remote memory. - Copyright (C) 2005-2011, 2014 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include <config.h> -#include "../libelf/libelfP.h" -#undef _ - -#include "libdwflP.h" - -#include <gelf.h> -#include <sys/types.h> -#include <stdbool.h> -#include <stdlib.h> -#include <string.h> - -/* Reconstruct an ELF file by reading the segments out of remote memory - based on the ELF file header at EHDR_VMA and the ELF program headers it - points to. If not null, *LOADBASEP is filled in with the difference - between the addresses from which the segments were read, and the - addresses the file headers put them at. - - The function READ_MEMORY is called to copy at least MINREAD and at most - MAXREAD bytes from the remote memory at target address ADDRESS into the - local buffer at DATA; it should return -1 for errors (with code in - `errno'), 0 if it failed to read at least MINREAD bytes due to EOF, or - the number of bytes read if >= MINREAD. ARG is passed through. - - PAGESIZE is the minimum page size and alignment used for the PT_LOAD - segments. */ - -Elf * -elf_from_remote_memory (GElf_Addr ehdr_vma, - GElf_Xword pagesize, - GElf_Addr *loadbasep, - ssize_t (*read_memory) (void *arg, void *data, - GElf_Addr address, - size_t minread, - size_t maxread), - void *arg) -{ - /* First read in the file header and check its sanity. */ - - const size_t initial_bufsize = 256; - unsigned char *buffer = malloc (initial_bufsize); - if (buffer == NULL) - { - no_memory: - __libdwfl_seterrno (DWFL_E_NOMEM); - return NULL; - } - - ssize_t nread = (*read_memory) (arg, buffer, ehdr_vma, - sizeof (Elf32_Ehdr), initial_bufsize); - if (nread <= 0) - { - read_error: - free (buffer); - __libdwfl_seterrno (nread < 0 ? DWFL_E_ERRNO : DWFL_E_TRUNCATED); - return NULL; - } - - if (memcmp (buffer, ELFMAG, SELFMAG) != 0) - { - bad_elf: - free (buffer); - __libdwfl_seterrno (DWFL_E_BADELF); - return NULL; - } - - /* Extract the information we need from the file header. */ - - union - { - Elf32_Ehdr e32; - Elf64_Ehdr e64; - } ehdr; - Elf_Data xlatefrom = - { - .d_type = ELF_T_EHDR, - .d_buf = buffer, - .d_version = EV_CURRENT, - }; - Elf_Data xlateto = - { - .d_type = ELF_T_EHDR, - .d_buf = &ehdr, - .d_size = sizeof ehdr, - .d_version = EV_CURRENT, - }; - - GElf_Off phoff; - uint_fast16_t phnum; - uint_fast16_t phentsize; - GElf_Off shdrs_end; - - switch (buffer[EI_CLASS]) - { - case ELFCLASS32: - xlatefrom.d_size = sizeof (Elf32_Ehdr); - if (elf32_xlatetom (&xlateto, &xlatefrom, buffer[EI_DATA]) == NULL) - { - libelf_error: - __libdwfl_seterrno (DWFL_E_LIBELF); - return NULL; - } - phoff = ehdr.e32.e_phoff; - phnum = ehdr.e32.e_phnum; - phentsize = ehdr.e32.e_phentsize; - if (phentsize != sizeof (Elf32_Phdr) || phnum == 0) - goto bad_elf; - shdrs_end = ehdr.e32.e_shoff + ehdr.e32.e_shnum * ehdr.e32.e_shentsize; - break; - - case ELFCLASS64: - xlatefrom.d_size = sizeof (Elf64_Ehdr); - if (elf64_xlatetom (&xlateto, &xlatefrom, buffer[EI_DATA]) == NULL) - goto libelf_error; - phoff = ehdr.e64.e_phoff; - phnum = ehdr.e64.e_phnum; - phentsize = ehdr.e64.e_phentsize; - if (phentsize != sizeof (Elf64_Phdr) || phnum == 0) - goto bad_elf; - shdrs_end = ehdr.e64.e_shoff + ehdr.e64.e_shnum * ehdr.e64.e_shentsize; - break; - - default: - goto bad_elf; - } - - - /* The file header tells where to find the program headers. - These are what we use to actually choose what to read. */ - - xlatefrom.d_type = xlateto.d_type = ELF_T_PHDR; - xlatefrom.d_size = phnum * phentsize; - - if ((size_t) nread >= phoff + phnum * phentsize) - /* We already have all the phdrs from the initial read. */ - xlatefrom.d_buf = buffer + phoff; - else - { - /* Read in the program headers. */ - - if (initial_bufsize < phnum * phentsize) - { - unsigned char *newbuf = realloc (buffer, phnum * phentsize); - if (newbuf == NULL) - { - free (buffer); - goto no_memory; - } - buffer = newbuf; - } - nread = (*read_memory) (arg, buffer, ehdr_vma + phoff, - phnum * phentsize, phnum * phentsize); - if (nread <= 0) - goto read_error; - - xlatefrom.d_buf = buffer; - } - - union - { - Elf32_Phdr p32[phnum]; - Elf64_Phdr p64[phnum]; - } phdrs; - - xlateto.d_buf = &phdrs; - xlateto.d_size = sizeof phdrs; - - /* Scan for PT_LOAD segments to find the total size of the file image. */ - size_t contents_size = 0; - GElf_Off segments_end = 0; - GElf_Off segments_end_mem = 0; - GElf_Addr loadbase = ehdr_vma; - bool found_base = false; - switch (ehdr.e32.e_ident[EI_CLASS]) - { - /* Sanity checks segments and calculates segment_end, - segments_end, segments_end_mem and loadbase (if not - found_base yet). Returns true if sanity checking failed, - false otherwise. */ - inline bool handle_segment (GElf_Addr vaddr, GElf_Off offset, - GElf_Xword filesz, GElf_Xword memsz) - { - /* Sanity check the segment load aligns with the pagesize. */ - if (((vaddr - offset) & (pagesize - 1)) != 0) - return true; - - GElf_Off segment_end = ((offset + filesz + pagesize - 1) - & -pagesize); - - if (segment_end > (GElf_Off) contents_size) - contents_size = segment_end; - - if (!found_base && (offset & -pagesize) == 0) - { - loadbase = ehdr_vma - (vaddr & -pagesize); - found_base = true; - } - - segments_end = offset + filesz; - segments_end_mem = offset + memsz; - return false; - } - - case ELFCLASS32: - if (elf32_xlatetom (&xlateto, &xlatefrom, - ehdr.e32.e_ident[EI_DATA]) == NULL) - goto libelf_error; - for (uint_fast16_t i = 0; i < phnum; ++i) - if (phdrs.p32[i].p_type == PT_LOAD) - if (handle_segment (phdrs.p32[i].p_vaddr, phdrs.p32[i].p_offset, - phdrs.p32[i].p_filesz, phdrs.p32[i].p_memsz)) - goto bad_elf; - break; - - case ELFCLASS64: - if (elf64_xlatetom (&xlateto, &xlatefrom, - ehdr.e64.e_ident[EI_DATA]) == NULL) - goto libelf_error; - for (uint_fast16_t i = 0; i < phnum; ++i) - if (phdrs.p64[i].p_type == PT_LOAD) - if (handle_segment (phdrs.p64[i].p_vaddr, phdrs.p64[i].p_offset, - phdrs.p64[i].p_filesz, phdrs.p64[i].p_memsz)) - goto bad_elf; - break; - - default: - abort (); - break; - } - - /* Trim the last segment so we don't bother with zeros in the last page - that are off the end of the file. However, if the extra bit in that - page includes the section headers and the memory isn't extended (which - might indicate it will have been reused otherwise), keep them. */ - if ((GElf_Off) contents_size > segments_end - && (GElf_Off) contents_size >= shdrs_end - && segments_end == segments_end_mem) - { - contents_size = segments_end; - if ((GElf_Off) contents_size < shdrs_end) - contents_size = shdrs_end; - } - else - contents_size = segments_end; - - free (buffer); - - /* Now we know the size of the whole image we want read in. */ - buffer = calloc (1, contents_size); - if (buffer == NULL) - goto no_memory; - - switch (ehdr.e32.e_ident[EI_CLASS]) - { - /* Reads the given segment. Returns true if reading fails, - false otherwise. */ - inline bool handle_segment (GElf_Addr vaddr, GElf_Off offset, - GElf_Xword filesz) - { - GElf_Off start = offset & -pagesize; - GElf_Off end = (offset + filesz + pagesize - 1) & -pagesize; - if (end > (GElf_Off) contents_size) - end = contents_size; - nread = (*read_memory) (arg, buffer + start, - (loadbase + vaddr) & -pagesize, - end - start, end - start); - return nread <= 0; - } - - case ELFCLASS32: - for (uint_fast16_t i = 0; i < phnum; ++i) - if (phdrs.p32[i].p_type == PT_LOAD) - if (handle_segment (phdrs.p32[i].p_vaddr, phdrs.p32[i].p_offset, - phdrs.p32[i].p_filesz)) - goto read_error; - - /* If the segments visible in memory didn't include the section - headers, then clear them from the file header. */ - if (contents_size < shdrs_end) - { - ehdr.e32.e_shoff = 0; - ehdr.e32.e_shnum = 0; - ehdr.e32.e_shstrndx = 0; - } - - /* This will normally have been in the first PT_LOAD segment. But it - conceivably could be missing, and we might have just changed it. */ - xlatefrom.d_type = xlateto.d_type = ELF_T_EHDR; - xlatefrom.d_size = xlateto.d_size = sizeof ehdr.e32; - xlatefrom.d_buf = &ehdr.e32; - xlateto.d_buf = buffer; - if (elf32_xlatetof (&xlateto, &xlatefrom, - ehdr.e32.e_ident[EI_DATA]) == NULL) - goto libelf_error; - break; - - case ELFCLASS64: - for (uint_fast16_t i = 0; i < phnum; ++i) - if (phdrs.p64[i].p_type == PT_LOAD) - if (handle_segment (phdrs.p64[i].p_vaddr, phdrs.p64[i].p_offset, - phdrs.p64[i].p_filesz)) - goto read_error; - - /* If the segments visible in memory didn't include the section - headers, then clear them from the file header. */ - if (contents_size < shdrs_end) - { - ehdr.e64.e_shoff = 0; - ehdr.e64.e_shnum = 0; - ehdr.e64.e_shstrndx = 0; - } - - /* This will normally have been in the first PT_LOAD segment. But it - conceivably could be missing, and we might have just changed it. */ - xlatefrom.d_type = xlateto.d_type = ELF_T_EHDR; - xlatefrom.d_size = xlateto.d_size = sizeof ehdr.e64; - xlatefrom.d_buf = &ehdr.e64; - xlateto.d_buf = buffer; - if (elf64_xlatetof (&xlateto, &xlatefrom, - ehdr.e64.e_ident[EI_DATA]) == NULL) - goto libelf_error; - break; - - default: - abort (); - break; - } - - /* Now we have the image. Open libelf on it. */ - - Elf *elf = elf_memory ((char *) buffer, contents_size); - if (elf == NULL) - { - free (buffer); - goto libelf_error; - } - - elf->flags |= ELF_F_MALLOCED; - if (loadbasep != NULL) - *loadbasep = loadbase; - return elf; -} diff --git a/src/libdwfl/find-debuginfo.c b/src/libdwfl/find-debuginfo.c deleted file mode 100644 index 3f5314ad..00000000 --- a/src/libdwfl/find-debuginfo.c +++ /dev/null @@ -1,351 +0,0 @@ -/* Standard find_debuginfo callback for libdwfl. - Copyright (C) 2005-2010, 2014 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" -#include <stdio.h> -#include <fcntl.h> -#include <unistd.h> -#include <sys/stat.h> -#include "system.h" - - -/* Try to open64 [DIR/][SUBDIR/]DEBUGLINK, return file descriptor or -1. - On success, *DEBUGINFO_FILE_NAME has the malloc'd name of the open file. */ -static int -try_open (const struct stat64 *main_stat, - const char *dir, const char *subdir, const char *debuglink, - char **debuginfo_file_name) -{ - char *fname; - if (dir == NULL && subdir == NULL) - { - fname = strdup (debuglink); - if (fname == NULL) - return -1; - } - else if ((subdir == NULL ? asprintf (&fname, "%s/%s", dir, debuglink) - : dir == NULL ? asprintf (&fname, "%s/%s", subdir, debuglink) - : asprintf (&fname, "%s/%s/%s", dir, subdir, debuglink)) < 0) - return -1; - - struct stat64 st; - int fd = TEMP_FAILURE_RETRY (open64 (fname, O_RDONLY)); - if (fd < 0) - free (fname); - else if (fstat64 (fd, &st) == 0 - && st.st_ino == main_stat->st_ino - && st.st_dev == main_stat->st_dev) - { - /* This is the main file by another name. Don't look at it again. */ - close (fd); - errno = ENOENT; - fd = -1; - } - else - *debuginfo_file_name = fname; - - return fd; -} - -/* Return true iff the FD's contents CRC matches DEBUGLINK_CRC. */ -static inline bool -check_crc (int fd, GElf_Word debuglink_crc) -{ - uint32_t file_crc; - return (__libdwfl_crc32_file (fd, &file_crc) == 0 - && file_crc == debuglink_crc); -} - -static bool -validate (Dwfl_Module *mod, int fd, bool check, GElf_Word debuglink_crc) -{ - /* For alt debug files always check the build-id from the Dwarf and alt. */ - if (mod->dw != NULL) - { - bool valid = false; - const void *build_id; - const char *altname; - ssize_t build_id_len = INTUSE(dwelf_dwarf_gnu_debugaltlink) (mod->dw, - &altname, - &build_id); - if (build_id_len > 0) - { - /* We need to open an Elf handle on the file so we can check its - build ID note for validation. Backdoor the handle into the - module data structure since we had to open it early anyway. */ - Dwfl_Error error = __libdw_open_file (&fd, &mod->alt_elf, - false, false); - if (error != DWFL_E_NOERROR) - __libdwfl_seterrno (error); - else - { - const void *alt_build_id; - ssize_t alt_len = INTUSE(dwelf_elf_gnu_build_id) (mod->alt_elf, - &alt_build_id); - if (alt_len > 0 && alt_len == build_id_len - && memcmp (build_id, alt_build_id, alt_len) == 0) - valid = true; - else - { - /* A mismatch! */ - elf_end (mod->alt_elf); - mod->alt_elf = NULL; - close (fd); - fd = -1; - } - } - } - return valid; - } - - /* If we have a build ID, check only that. */ - if (mod->build_id_len > 0) - { - /* We need to open an Elf handle on the file so we can check its - build ID note for validation. Backdoor the handle into the - module data structure since we had to open it early anyway. */ - - mod->debug.valid = false; - Dwfl_Error error = __libdw_open_file (&fd, &mod->debug.elf, false, false); - if (error != DWFL_E_NOERROR) - __libdwfl_seterrno (error); - else if (likely (__libdwfl_find_build_id (mod, false, - mod->debug.elf) == 2)) - /* Also backdoor the gratuitous flag. */ - mod->debug.valid = true; - else - { - /* A mismatch! */ - elf_end (mod->debug.elf); - mod->debug.elf = NULL; - close (fd); - fd = -1; - } - - return mod->debug.valid; - } - - return !check || check_crc (fd, debuglink_crc); -} - -static int -find_debuginfo_in_path (Dwfl_Module *mod, const char *file_name, - const char *debuglink_file, GElf_Word debuglink_crc, - char **debuginfo_file_name) -{ - bool cancheck = debuglink_crc != (GElf_Word) 0; - - const char *file_basename = file_name == NULL ? NULL : basename (file_name); - if (debuglink_file == NULL) - { - /* For a alt debug multi file we need a name, for a separate debug - name we may be able to fall back on file_basename.debug. */ - if (file_basename == NULL || mod->dw != NULL) - { - errno = 0; - return -1; - } - - size_t len = strlen (file_basename); - char *localname = alloca (len + sizeof ".debug"); - memcpy (localname, file_basename, len); - memcpy (&localname[len], ".debug", sizeof ".debug"); - debuglink_file = localname; - cancheck = false; - } - - /* Look for a file named DEBUGLINK_FILE in the directories - indicated by the debug directory path setting. */ - - const Dwfl_Callbacks *const cb = mod->dwfl->callbacks; - char *path = strdupa ((cb->debuginfo_path ? *cb->debuginfo_path : NULL) - ?: DEFAULT_DEBUGINFO_PATH); - - /* A leading - or + in the whole path sets whether to check file CRCs. */ - bool defcheck = true; - if (path[0] == '-' || path[0] == '+') - { - defcheck = path[0] == '+'; - ++path; - } - - /* XXX dev/ino should be cached in struct dwfl_file. */ - struct stat64 main_stat; - if (unlikely ((mod->main.fd != -1 ? fstat64 (mod->main.fd, &main_stat) - : file_name != NULL ? stat64 (file_name, &main_stat) - : -1) < 0)) - { - main_stat.st_dev = 0; - main_stat.st_ino = 0; - } - - char *file_dirname = (file_basename == file_name ? NULL - : strndupa (file_name, file_basename - 1 - file_name)); - char *p; - while ((p = strsep (&path, ":")) != NULL) - { - /* A leading - or + says whether to check file CRCs for this element. */ - bool check = defcheck; - if (*p == '+' || *p == '-') - check = *p++ == '+'; - check = check && cancheck; - - const char *dir, *subdir, *file; - switch (p[0]) - { - case '\0': - /* An empty entry says to try the main file's directory. */ - dir = file_dirname; - subdir = NULL; - file = debuglink_file; - break; - case '/': - /* An absolute path says to look there for a subdirectory - named by the main file's absolute directory. This cannot - be applied to a relative file name. For alt debug files - it means to look for the basename file in that dir or the - .dwz subdir (see below). */ - if (mod->dw == NULL - && (file_dirname == NULL || file_dirname[0] != '/')) - continue; - dir = p; - if (mod->dw == NULL) - { - subdir = file_dirname + 1; - file = debuglink_file; - } - else - { - subdir = NULL; - file = basename (debuglink_file); - } - break; - default: - /* A relative path says to try a subdirectory of that name - in the main file's directory. */ - dir = file_dirname; - subdir = p; - file = debuglink_file; - break; - } - - char *fname = NULL; - int fd = try_open (&main_stat, dir, subdir, file, &fname); - if (fd < 0) - switch (errno) - { - case ENOENT: - case ENOTDIR: - /* If we are looking for the alt file also try the .dwz subdir. - But only if this is the empty or absolute path. */ - if (mod->dw != NULL && (p[0] == '\0' || p[0] == '/')) - { - fd = try_open (&main_stat, dir, ".dwz", - basename (file), &fname); - if (fd < 0) - { - if (errno != ENOENT && errno != ENOTDIR) - return -1; - else - continue; - } - break; - } - continue; - default: - return -1; - } - if (validate (mod, fd, check, debuglink_crc)) - { - *debuginfo_file_name = fname; - return fd; - } - free (fname); - close (fd); - } - - /* No dice. */ - errno = 0; - return -1; -} - -int -dwfl_standard_find_debuginfo (Dwfl_Module *mod, - void **userdata __attribute__ ((unused)), - const char *modname __attribute__ ((unused)), - GElf_Addr base __attribute__ ((unused)), - const char *file_name, - const char *debuglink_file, - GElf_Word debuglink_crc, - char **debuginfo_file_name) -{ - /* First try by build ID if we have one. If that succeeds or fails - other than just by finding nothing, that's all we do. */ - const unsigned char *bits; - GElf_Addr vaddr; - if (INTUSE(dwfl_module_build_id) (mod, &bits, &vaddr) > 0) - { - /* Dropping most arguments means we cannot rely on them in - dwfl_build_id_find_debuginfo. But leave it that way since - some user code out there also does this, so we'll have to - handle it anyway. */ - int fd = INTUSE(dwfl_build_id_find_debuginfo) (mod, - NULL, NULL, 0, - NULL, NULL, 0, - debuginfo_file_name); - - /* Did the build_id callback find something or report an error? - Then we are done. Otherwise fallback on path based search. */ - if (fd >= 0 - || (mod->dw == NULL && mod->debug.elf != NULL) - || (mod->dw != NULL && mod->alt_elf != NULL) - || errno != 0) - return fd; - } - - /* Failing that, search the path by name. */ - int fd = find_debuginfo_in_path (mod, file_name, - debuglink_file, debuglink_crc, - debuginfo_file_name); - - if (fd < 0 && errno == 0) - { - /* If FILE_NAME is a symlink, the debug file might be associated - with the symlink target name instead. */ - - char *canon = canonicalize_file_name (file_name); - if (canon != NULL && strcmp (file_name, canon)) - fd = find_debuginfo_in_path (mod, canon, - debuglink_file, debuglink_crc, - debuginfo_file_name); - free (canon); - } - - return fd; -} -INTDEF (dwfl_standard_find_debuginfo) diff --git a/src/libdwfl/frame_unwind.c b/src/libdwfl/frame_unwind.c deleted file mode 100644 index 16cebd08..00000000 --- a/src/libdwfl/frame_unwind.c +++ /dev/null @@ -1,725 +0,0 @@ -/* Get previous frame state for an existing frame state. - Copyright (C) 2013, 2014 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - -#include "cfi.h" -#include <stdlib.h> -#include "libdwflP.h" -#include "../libdw/dwarf.h" -#include <sys/ptrace.h> - -/* Maximum number of DWARF expression stack slots before returning an error. */ -#define DWARF_EXPR_STACK_MAX 0x100 - -/* Maximum number of DWARF expression executed operations before returning an - error. */ -#define DWARF_EXPR_STEPS_MAX 0x1000 - -#ifndef MAX -# define MAX(a, b) ((a) > (b) ? (a) : (b)) -#endif - -bool -internal_function -__libdwfl_frame_reg_get (Dwfl_Frame *state, unsigned regno, Dwarf_Addr *val) -{ - Ebl *ebl = state->thread->process->ebl; - if (! ebl_dwarf_to_regno (ebl, ®no)) - return false; - if (regno >= ebl_frame_nregs (ebl)) - return false; - if ((state->regs_set[regno / sizeof (*state->regs_set) / 8] - & ((uint64_t) 1U << (regno % (sizeof (*state->regs_set) * 8)))) == 0) - return false; - if (val) - *val = state->regs[regno]; - return true; -} - -bool -internal_function -__libdwfl_frame_reg_set (Dwfl_Frame *state, unsigned regno, Dwarf_Addr val) -{ - Ebl *ebl = state->thread->process->ebl; - if (! ebl_dwarf_to_regno (ebl, ®no)) - return false; - if (regno >= ebl_frame_nregs (ebl)) - return false; - /* For example i386 user_regs_struct has signed fields. */ - if (ebl_get_elfclass (ebl) == ELFCLASS32) - val &= 0xffffffff; - state->regs_set[regno / sizeof (*state->regs_set) / 8] |= - ((uint64_t) 1U << (regno % (sizeof (*state->regs_set) * 8))); - state->regs[regno] = val; - return true; -} - -static bool -state_get_reg (Dwfl_Frame *state, unsigned regno, Dwarf_Addr *val) -{ - if (! __libdwfl_frame_reg_get (state, regno, val)) - { - __libdwfl_seterrno (DWFL_E_INVALID_REGISTER); - return false; - } - return true; -} - -static int -bra_compar (const void *key_voidp, const void *elem_voidp) -{ - Dwarf_Word offset = (uintptr_t) key_voidp; - const Dwarf_Op *op = elem_voidp; - return (offset > op->offset) - (offset < op->offset); -} - -/* If FRAME is NULL is are computing CFI frame base. In such case another - DW_OP_call_frame_cfa is no longer permitted. */ - -static bool -expr_eval (Dwfl_Frame *state, Dwarf_Frame *frame, const Dwarf_Op *ops, - size_t nops, Dwarf_Addr *result, Dwarf_Addr bias) -{ - Dwfl_Process *process = state->thread->process; - if (nops == 0) - { - __libdwfl_seterrno (DWFL_E_INVALID_DWARF); - return false; - } - Dwarf_Addr *stack = NULL; - size_t stack_used = 0, stack_allocated = 0; - - bool - push (Dwarf_Addr val) - { - if (stack_used >= DWARF_EXPR_STACK_MAX) - { - __libdwfl_seterrno (DWFL_E_INVALID_DWARF); - return false; - } - if (stack_used == stack_allocated) - { - stack_allocated = MAX (stack_allocated * 2, 32); - Dwarf_Addr *stack_new = realloc (stack, stack_allocated * sizeof (*stack)); - if (stack_new == NULL) - { - __libdwfl_seterrno (DWFL_E_NOMEM); - return false; - } - stack = stack_new; - } - stack[stack_used++] = val; - return true; - } - - bool - pop (Dwarf_Addr *val) - { - if (stack_used == 0) - { - __libdwfl_seterrno (DWFL_E_INVALID_DWARF); - return false; - } - *val = stack[--stack_used]; - return true; - } - - Dwarf_Addr val1, val2; - bool is_location = false; - size_t steps_count = 0; - for (const Dwarf_Op *op = ops; op < ops + nops; op++) - { - if (++steps_count > DWARF_EXPR_STEPS_MAX) - { - __libdwfl_seterrno (DWFL_E_INVALID_DWARF); - return false; - } - switch (op->atom) - { - /* DW_OP_* order matches libgcc/unwind-dw2.c execute_stack_op: */ - case DW_OP_lit0 ... DW_OP_lit31: - if (! push (op->atom - DW_OP_lit0)) - { - free (stack); - return false; - } - break; - case DW_OP_addr: - if (! push (op->number + bias)) - { - free (stack); - return false; - } - break; - case DW_OP_GNU_encoded_addr: - /* Missing support in the rest of elfutils. */ - __libdwfl_seterrno (DWFL_E_UNSUPPORTED_DWARF); - return false; - case DW_OP_const1u: - case DW_OP_const1s: - case DW_OP_const2u: - case DW_OP_const2s: - case DW_OP_const4u: - case DW_OP_const4s: - case DW_OP_const8u: - case DW_OP_const8s: - case DW_OP_constu: - case DW_OP_consts: - if (! push (op->number)) - { - free (stack); - return false; - } - break; - case DW_OP_reg0 ... DW_OP_reg31: - if (! state_get_reg (state, op->atom - DW_OP_reg0, &val1) - || ! push (val1)) - { - free (stack); - return false; - } - break; - case DW_OP_regx: - if (! state_get_reg (state, op->number, &val1) || ! push (val1)) - { - free (stack); - return false; - } - break; - case DW_OP_breg0 ... DW_OP_breg31: - if (! state_get_reg (state, op->atom - DW_OP_breg0, &val1)) - { - free (stack); - return false; - } - val1 += op->number; - if (! push (val1)) - { - free (stack); - return false; - } - break; - case DW_OP_bregx: - if (! state_get_reg (state, op->number, &val1)) - { - free (stack); - return false; - } - val1 += op->number2; - if (! push (val1)) - { - free (stack); - return false; - } - break; - case DW_OP_dup: - if (! pop (&val1) || ! push (val1) || ! push (val1)) - { - free (stack); - return false; - } - break; - case DW_OP_drop: - if (! pop (&val1)) - { - free (stack); - return false; - } - break; - case DW_OP_pick: - if (stack_used <= op->number) - { - free (stack); - __libdwfl_seterrno (DWFL_E_INVALID_DWARF); - return false; - } - if (! push (stack[stack_used - 1 - op->number])) - { - free (stack); - return false; - } - break; - case DW_OP_over: - if (! pop (&val1) || ! pop (&val2) - || ! push (val2) || ! push (val1) || ! push (val2)) - { - free (stack); - return false; - } - break; - case DW_OP_swap: - if (! pop (&val1) || ! pop (&val2) || ! push (val1) || ! push (val2)) - { - free (stack); - return false; - } - break; - case DW_OP_rot: - { - Dwarf_Addr val3; - if (! pop (&val1) || ! pop (&val2) || ! pop (&val3) - || ! push (val1) || ! push (val3) || ! push (val2)) - { - free (stack); - return false; - } - } - break; - case DW_OP_deref: - case DW_OP_deref_size: - if (process->callbacks->memory_read == NULL) - { - free (stack); - __libdwfl_seterrno (DWFL_E_INVALID_ARGUMENT); - return false; - } - if (! pop (&val1) - || ! process->callbacks->memory_read (process->dwfl, val1, &val1, - process->callbacks_arg)) - { - free (stack); - return false; - } - if (op->atom == DW_OP_deref_size) - { - const int elfclass = frame->cache->e_ident[EI_CLASS]; - const unsigned addr_bytes = elfclass == ELFCLASS32 ? 4 : 8; - if (op->number > addr_bytes) - { - free (stack); - __libdwfl_seterrno (DWFL_E_INVALID_DWARF); - return false; - } -#if BYTE_ORDER == BIG_ENDIAN - if (op->number == 0) - val1 = 0; - else - val1 >>= (addr_bytes - op->number) * 8; -#else - if (op->number < 8) - val1 &= (1 << (op->number * 8)) - 1; -#endif - } - if (! push (val1)) - { - free (stack); - return false; - } - break; -#define UNOP(atom, expr) \ - case atom: \ - if (! pop (&val1) || ! push (expr)) \ - { \ - free (stack); \ - return false; \ - } \ - break; - UNOP (DW_OP_abs, abs ((int64_t) val1)) - UNOP (DW_OP_neg, -(int64_t) val1) - UNOP (DW_OP_not, ~val1) -#undef UNOP - case DW_OP_plus_uconst: - if (! pop (&val1) || ! push (val1 + op->number)) - { - free (stack); - return false; - } - break; -#define BINOP(atom, op) \ - case atom: \ - if (! pop (&val2) || ! pop (&val1) || ! push (val1 op val2)) \ - { \ - free (stack); \ - return false; \ - } \ - break; -#define BINOP_SIGNED(atom, op) \ - case atom: \ - if (! pop (&val2) || ! pop (&val1) \ - || ! push ((int64_t) val1 op (int64_t) val2)) \ - { \ - free (stack); \ - return false; \ - } \ - break; - BINOP (DW_OP_and, &) - case DW_OP_div: - if (! pop (&val2) || ! pop (&val1)) - { - free (stack); - return false; - } - if (val2 == 0) - { - free (stack); - __libdwfl_seterrno (DWFL_E_INVALID_DWARF); - return false; - } - if (! push ((int64_t) val1 / (int64_t) val2)) - { - free (stack); - return false; - } - break; - BINOP (DW_OP_minus, -) - case DW_OP_mod: - if (! pop (&val2) || ! pop (&val1)) - { - free (stack); - return false; - } - if (val2 == 0) - { - free (stack); - __libdwfl_seterrno (DWFL_E_INVALID_DWARF); - return false; - } - if (! push (val1 % val2)) - { - free (stack); - return false; - } - break; - BINOP (DW_OP_mul, *) - BINOP (DW_OP_or, |) - BINOP (DW_OP_plus, +) - BINOP (DW_OP_shl, <<) - BINOP (DW_OP_shr, >>) - BINOP_SIGNED (DW_OP_shra, >>) - BINOP (DW_OP_xor, ^) - BINOP_SIGNED (DW_OP_le, <=) - BINOP_SIGNED (DW_OP_ge, >=) - BINOP_SIGNED (DW_OP_eq, ==) - BINOP_SIGNED (DW_OP_lt, <) - BINOP_SIGNED (DW_OP_gt, >) - BINOP_SIGNED (DW_OP_ne, !=) -#undef BINOP -#undef BINOP_SIGNED - case DW_OP_bra: - if (! pop (&val1)) - { - free (stack); - return false; - } - if (val1 == 0) - break; - /* FALLTHRU */ - case DW_OP_skip:; - Dwarf_Word offset = op->offset + 1 + 2 + (int16_t) op->number; - const Dwarf_Op *found = bsearch ((void *) (uintptr_t) offset, ops, nops, - sizeof (*ops), bra_compar); - if (found == NULL) - { - free (stack); - /* PPC32 vDSO has such invalid operations. */ - __libdwfl_seterrno (DWFL_E_INVALID_DWARF); - return false; - } - /* Undo the 'for' statement increment. */ - op = found - 1; - break; - case DW_OP_nop: - break; - /* DW_OP_* not listed in libgcc/unwind-dw2.c execute_stack_op: */ - case DW_OP_call_frame_cfa:; - // Not used by CFI itself but it is synthetized by elfutils internation. - Dwarf_Op *cfa_ops; - size_t cfa_nops; - Dwarf_Addr cfa; - if (frame == NULL - || dwarf_frame_cfa (frame, &cfa_ops, &cfa_nops) != 0 - || ! expr_eval (state, NULL, cfa_ops, cfa_nops, &cfa, bias) - || ! push (cfa)) - { - __libdwfl_seterrno (DWFL_E_LIBDW); - free (stack); - return false; - } - is_location = true; - break; - case DW_OP_stack_value: - // Not used by CFI itself but it is synthetized by elfutils internation. - is_location = false; - break; - default: - __libdwfl_seterrno (DWFL_E_INVALID_DWARF); - return false; - } - } - if (! pop (result)) - { - free (stack); - return false; - } - free (stack); - if (is_location) - { - if (process->callbacks->memory_read == NULL) - { - __libdwfl_seterrno (DWFL_E_INVALID_ARGUMENT); - return false; - } - if (! process->callbacks->memory_read (process->dwfl, *result, result, - process->callbacks_arg)) - return false; - } - return true; -} - -static void -new_unwound (Dwfl_Frame *state) -{ - assert (state->unwound == NULL); - Dwfl_Thread *thread = state->thread; - Dwfl_Process *process = thread->process; - Ebl *ebl = process->ebl; - size_t nregs = ebl_frame_nregs (ebl); - assert (nregs > 0); - Dwfl_Frame *unwound; - unwound = malloc (sizeof (*unwound) + sizeof (*unwound->regs) * nregs); - state->unwound = unwound; - unwound->thread = thread; - unwound->unwound = NULL; - unwound->signal_frame = false; - unwound->initial_frame = false; - unwound->pc_state = DWFL_FRAME_STATE_ERROR; - memset (unwound->regs_set, 0, sizeof (unwound->regs_set)); -} - -/* The logic is to call __libdwfl_seterrno for any CFI bytecode interpretation - error so one can easily catch the problem with a debugger. Still there are - archs with invalid CFI for some registers where the registers are never used - later. Therefore we continue unwinding leaving the registers undefined. */ - -static void -handle_cfi (Dwfl_Frame *state, Dwarf_Addr pc, Dwarf_CFI *cfi, Dwarf_Addr bias) -{ - Dwarf_Frame *frame; - if (INTUSE(dwarf_cfi_addrframe) (cfi, pc, &frame) != 0) - { - __libdwfl_seterrno (DWFL_E_LIBDW); - return; - } - new_unwound (state); - Dwfl_Frame *unwound = state->unwound; - unwound->signal_frame = frame->fde->cie->signal_frame; - Dwfl_Thread *thread = state->thread; - Dwfl_Process *process = thread->process; - Ebl *ebl = process->ebl; - size_t nregs = ebl_frame_nregs (ebl); - assert (nregs > 0); - - /* The return register is special for setting the unwound->pc_state. */ - unsigned ra = frame->fde->cie->return_address_register; - bool ra_set = false; - ebl_dwarf_to_regno (ebl, &ra); - - for (unsigned regno = 0; regno < nregs; regno++) - { - Dwarf_Op reg_ops_mem[3], *reg_ops; - size_t reg_nops; - if (dwarf_frame_register (frame, regno, reg_ops_mem, ®_ops, - ®_nops) != 0) - { - __libdwfl_seterrno (DWFL_E_LIBDW); - continue; - } - Dwarf_Addr regval; - if (reg_nops == 0) - { - if (reg_ops == reg_ops_mem) - { - /* REGNO is undefined. */ - if (regno == ra) - unwound->pc_state = DWFL_FRAME_STATE_PC_UNDEFINED; - continue; - } - else if (reg_ops == NULL) - { - /* REGNO is same-value. */ - if (! state_get_reg (state, regno, ®val)) - continue; - } - else - { - __libdwfl_seterrno (DWFL_E_INVALID_DWARF); - continue; - } - } - else if (! expr_eval (state, frame, reg_ops, reg_nops, ®val, bias)) - { - /* PPC32 vDSO has various invalid operations, ignore them. The - register will look as unset causing an error later, if used. - But PPC32 does not use such registers. */ - continue; - } - - /* Some architectures encode some extra info in the return address. */ - if (regno == frame->fde->cie->return_address_register) - regval &= ebl_func_addr_mask (ebl); - - /* This is another strange PPC[64] case. There are two - registers numbers that can represent the same DWARF return - register number. We only want one to actually set the return - register value. But we always want to override the value if - the register is the actual CIE return address register. */ - if (ra_set && regno != frame->fde->cie->return_address_register) - { - unsigned r = regno; - if (ebl_dwarf_to_regno (ebl, &r) && r == ra) - continue; - } - - if (! __libdwfl_frame_reg_set (unwound, regno, regval)) - { - __libdwfl_seterrno (DWFL_E_INVALID_REGISTER); - continue; - } - else if (! ra_set) - { - unsigned r = regno; - if (ebl_dwarf_to_regno (ebl, &r) && r == ra) - ra_set = true; - } - } - if (unwound->pc_state == DWFL_FRAME_STATE_ERROR - && __libdwfl_frame_reg_get (unwound, - frame->fde->cie->return_address_register, - &unwound->pc)) - { - /* PPC32 __libc_start_main properly CFI-unwinds PC as zero. Currently - none of the archs supported for unwinding have zero as a valid PC. */ - if (unwound->pc == 0) - unwound->pc_state = DWFL_FRAME_STATE_PC_UNDEFINED; - else - unwound->pc_state = DWFL_FRAME_STATE_PC_SET; - } - free (frame); -} - -static bool -setfunc (int firstreg, unsigned nregs, const Dwarf_Word *regs, void *arg) -{ - Dwfl_Frame *state = arg; - Dwfl_Frame *unwound = state->unwound; - if (firstreg < 0) - { - assert (firstreg == -1); - assert (nregs == 1); - assert (unwound->pc_state == DWFL_FRAME_STATE_PC_UNDEFINED); - unwound->pc = *regs; - unwound->pc_state = DWFL_FRAME_STATE_PC_SET; - return true; - } - while (nregs--) - if (! __libdwfl_frame_reg_set (unwound, firstreg++, *regs++)) - return false; - return true; -} - -static bool -getfunc (int firstreg, unsigned nregs, Dwarf_Word *regs, void *arg) -{ - Dwfl_Frame *state = arg; - assert (firstreg >= 0); - while (nregs--) - if (! __libdwfl_frame_reg_get (state, firstreg++, regs++)) - return false; - return true; -} - -static bool -readfunc (Dwarf_Addr addr, Dwarf_Word *datap, void *arg) -{ - Dwfl_Frame *state = arg; - Dwfl_Thread *thread = state->thread; - Dwfl_Process *process = thread->process; - return process->callbacks->memory_read (process->dwfl, addr, datap, - process->callbacks_arg); -} - -void -internal_function -__libdwfl_frame_unwind (Dwfl_Frame *state) -{ - if (state->unwound) - return; - /* Do not ask dwfl_frame_pc for ISACTIVATION, it would try to unwind STATE - which would deadlock us. */ - Dwarf_Addr pc; - bool ok = INTUSE(dwfl_frame_pc) (state, &pc, NULL); - assert (ok); - /* Check whether this is the initial frame or a signal frame. - Then we need to unwind from the original, unadjusted PC. */ - if (! state->initial_frame && ! state->signal_frame) - pc--; - Dwfl_Module *mod = INTUSE(dwfl_addrmodule) (state->thread->process->dwfl, pc); - if (mod == NULL) - __libdwfl_seterrno (DWFL_E_NO_DWARF); - else - { - Dwarf_Addr bias; - Dwarf_CFI *cfi_eh = INTUSE(dwfl_module_eh_cfi) (mod, &bias); - if (cfi_eh) - { - handle_cfi (state, pc - bias, cfi_eh, bias); - if (state->unwound) - return; - } - Dwarf_CFI *cfi_dwarf = INTUSE(dwfl_module_dwarf_cfi) (mod, &bias); - if (cfi_dwarf) - { - handle_cfi (state, pc - bias, cfi_dwarf, bias); - if (state->unwound) - return; - } - } - assert (state->unwound == NULL); - Dwfl_Thread *thread = state->thread; - Dwfl_Process *process = thread->process; - Ebl *ebl = process->ebl; - new_unwound (state); - state->unwound->pc_state = DWFL_FRAME_STATE_PC_UNDEFINED; - // &Dwfl_Frame.signal_frame cannot be passed as it is a bitfield. - bool signal_frame = false; - if (! ebl_unwind (ebl, pc, setfunc, getfunc, readfunc, state, &signal_frame)) - { - // Discard the unwind attempt. During next __libdwfl_frame_unwind call - // we may have for example the appropriate Dwfl_Module already mapped. - assert (state->unwound->unwound == NULL); - free (state->unwound); - state->unwound = NULL; - // __libdwfl_seterrno has been called above. - return; - } - assert (state->unwound->pc_state == DWFL_FRAME_STATE_PC_SET); - state->unwound->signal_frame = signal_frame; -} diff --git a/src/libdwfl/gzip.c b/src/libdwfl/gzip.c deleted file mode 100644 index b7dde5d4..00000000 --- a/src/libdwfl/gzip.c +++ /dev/null @@ -1,295 +0,0 @@ -/* Decompression support for libdwfl: zlib (gzip) and/or bzlib (bzip2). - Copyright (C) 2009 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" -#include "system.h" - -#include <unistd.h> - -#ifdef LZMA -# define USE_INFLATE 1 -# include <lzma.h> -# define unzip __libdw_unlzma -# define DWFL_E_ZLIB DWFL_E_LZMA -# define MAGIC "\xFD" "7zXZ\0" /* XZ file format. */ -# define MAGIC2 "\x5d\0" /* Raw LZMA format. */ -# define Z(what) LZMA_##what -# define LZMA_ERRNO LZMA_PROG_ERROR -# define z_stream lzma_stream -# define inflateInit(z) lzma_auto_decoder (z, 1 << 30, 0) -# define do_inflate(z) lzma_code (z, LZMA_RUN) -# define inflateEnd(z) lzma_end (z) -#elif defined BZLIB -# define USE_INFLATE 1 -# include <bzlib.h> -# define unzip __libdw_bunzip2 -# define DWFL_E_ZLIB DWFL_E_BZLIB -# define MAGIC "BZh" -# define Z(what) BZ_##what -# define BZ_ERRNO BZ_IO_ERROR -# define z_stream bz_stream -# define inflateInit(z) BZ2_bzDecompressInit (z, 0, 0) -# define do_inflate(z) BZ2_bzDecompress (z) -# define inflateEnd(z) BZ2_bzDecompressEnd (z) -#else -# define USE_INFLATE 0 -# define crc32 loser_crc32 -# include <zlib.h> -# define unzip __libdw_gunzip -# define MAGIC "\037\213" -# define Z(what) Z_##what -#endif - -#define READ_SIZE (1 << 20) - -/* If this is not a compressed image, return DWFL_E_BADELF. - If we uncompressed it into *WHOLE, *WHOLE_SIZE, return DWFL_E_NOERROR. - Otherwise return an error for bad compressed data or I/O failure. - If we return an error after reading the first part of the file, - leave that portion malloc'd in *WHOLE, *WHOLE_SIZE. If *WHOLE - is not null on entry, we'll use it in lieu of repeating a read. */ - -Dwfl_Error internal_function -unzip (int fd, off64_t start_offset, - void *mapped, size_t mapped_size, - void **whole, size_t *whole_size) -{ - void *buffer = NULL; - size_t size = 0; - inline bool bigger_buffer (size_t start) - { - size_t more = size ? size * 2 : start; - char *b = realloc (buffer, more); - while (unlikely (b == NULL) && more >= size + 1024) - b = realloc (buffer, more -= 1024); - if (unlikely (b == NULL)) - return false; - buffer = b; - size = more; - return true; - } - inline void smaller_buffer (size_t end) - { - buffer = realloc (buffer, end) ?: end == 0 ? NULL : buffer; - size = end; - } - - void *input_buffer = NULL; - off_t input_pos = 0; - - inline Dwfl_Error fail (Dwfl_Error failure) - { - if (input_pos == (off_t) mapped_size) - *whole = input_buffer; - else - { - free (input_buffer); - *whole = NULL; - } - free (buffer); - return failure; - } - - inline Dwfl_Error zlib_fail (int result) - { - switch (result) - { - case Z (MEM_ERROR): - return fail (DWFL_E_NOMEM); - case Z (ERRNO): - return fail (DWFL_E_ERRNO); - default: - return fail (DWFL_E_ZLIB); - } - } - - if (mapped == NULL) - { - if (*whole == NULL) - { - input_buffer = malloc (READ_SIZE); - if (unlikely (input_buffer == NULL)) - return DWFL_E_NOMEM; - - ssize_t n = pread_retry (fd, input_buffer, READ_SIZE, start_offset); - if (unlikely (n < 0)) - return zlib_fail (Z (ERRNO)); - - input_pos = n; - mapped = input_buffer; - mapped_size = n; - } - else - { - input_buffer = *whole; - input_pos = mapped_size = *whole_size; - } - } - -#define NOMAGIC(magic) \ - (mapped_size <= sizeof magic || memcmp (mapped, magic, sizeof magic - 1)) - - /* First, look at the header. */ - if (NOMAGIC (MAGIC) -#ifdef MAGIC2 - && NOMAGIC (MAGIC2) -#endif - ) - /* Not a compressed file. */ - return DWFL_E_BADELF; - -#if USE_INFLATE - - /* This style actually only works with bzlib and liblzma. - The stupid zlib interface has nothing to grok the - gzip file headers except the slow gzFile interface. */ - - z_stream z = { .next_in = mapped, .avail_in = mapped_size }; - int result = inflateInit (&z); - if (result != Z (OK)) - { - inflateEnd (&z); - return zlib_fail (result); - } - - do - { - if (z.avail_in == 0 && input_buffer != NULL) - { - ssize_t n = pread_retry (fd, input_buffer, READ_SIZE, - start_offset + input_pos); - if (unlikely (n < 0)) - { - inflateEnd (&z); - return zlib_fail (Z (ERRNO)); - } - z.next_in = input_buffer; - z.avail_in = n; - input_pos += n; - } - if (z.avail_out == 0) - { - ptrdiff_t pos = (void *) z.next_out - buffer; - if (!bigger_buffer (z.avail_in)) - { - result = Z (MEM_ERROR); - break; - } - z.next_out = buffer + pos; - z.avail_out = size - pos; - } - } - while ((result = do_inflate (&z)) == Z (OK)); - -#ifdef BZLIB - uint64_t total_out = (((uint64_t) z.total_out_hi32 << 32) - | z.total_out_lo32); - smaller_buffer (total_out); -#else - smaller_buffer (z.total_out); -#endif - - inflateEnd (&z); - - if (result != Z (STREAM_END)) - return zlib_fail (result); - -#else /* gzip only. */ - - /* Let the decompression library read the file directly. */ - - gzFile zf; - Dwfl_Error open_stream (void) - { - int d = dup (fd); - if (unlikely (d < 0)) - return DWFL_E_BADELF; - if (start_offset != 0) - { - off64_t off = lseek (d, start_offset, SEEK_SET); - if (off != start_offset) - { - close (d); - return DWFL_E_BADELF; - } - } - zf = gzdopen (d, "r"); - if (unlikely (zf == NULL)) - { - close (d); - return zlib_fail (Z (MEM_ERROR)); - } - - /* From here on, zlib will close D. */ - - return DWFL_E_NOERROR; - } - - Dwfl_Error result = open_stream (); - - if (result == DWFL_E_NOERROR && gzdirect (zf)) - { - gzclose (zf); - return fail (DWFL_E_BADELF); - } - - if (result != DWFL_E_NOERROR) - return fail (result); - - ptrdiff_t pos = 0; - while (1) - { - if (!bigger_buffer (1024)) - { - gzclose (zf); - return zlib_fail (Z (MEM_ERROR)); - } - int n = gzread (zf, buffer + pos, size - pos); - if (n < 0) - { - int code; - gzerror (zf, &code); - gzclose (zf); - return zlib_fail (code); - } - if (n == 0) - break; - pos += n; - } - - gzclose (zf); - smaller_buffer (pos); -#endif - - free (input_buffer); - - *whole = buffer; - *whole_size = size; - - return DWFL_E_NOERROR; -} diff --git a/src/libdwfl/image-header.c b/src/libdwfl/image-header.c deleted file mode 100644 index a4f6799a..00000000 --- a/src/libdwfl/image-header.c +++ /dev/null @@ -1,101 +0,0 @@ -/* Linux kernel image support for libdwfl. - Copyright (C) 2009-2011 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" -#include "system.h" - -#include <unistd.h> -#include <endian.h> - -#if BYTE_ORDER == LITTLE_ENDIAN -# define LE16(x) (x) -#else -# define LE16(x) bswap_16 (x) -#endif - -/* See Documentation/x86/boot.txt in Linux kernel sources - for an explanation of these format details. */ - -#define MAGIC1 0xaa55 -#define MAGIC2 0x53726448 /* "HdrS" little-endian */ -#define MIN_VERSION 0x0208 - -#define H_START (H_SETUP_SECTS & -4) -#define H_SETUP_SECTS 0x1f1 -#define H_MAGIC1 0x1fe -#define H_MAGIC2 0x202 -#define H_VERSION 0x206 -#define H_PAYLOAD_OFFSET 0x248 -#define H_PAYLOAD_LENGTH 0x24c -#define H_END 0x250 -#define H_READ_SIZE (H_END - H_START) - -Dwfl_Error -internal_function -__libdw_image_header (int fd, off64_t *start_offset, - void *mapped, size_t mapped_size) -{ - if (likely (mapped_size > H_END)) - { - const void *header = mapped; - char header_buffer[H_READ_SIZE]; - if (header == NULL) - { - ssize_t n = pread_retry (fd, header_buffer, H_READ_SIZE, - *start_offset + H_START); - if (n < 0) - return DWFL_E_ERRNO; - if (n < H_READ_SIZE) - return DWFL_E_BADELF; - - header = header_buffer - H_START; - } - - if (*(uint16_t *) (header + H_MAGIC1) == LE16 (MAGIC1) - && *(uint32_t *) (header + H_MAGIC2) == LE32 (MAGIC2) - && LE16 (*(uint16_t *) (header + H_VERSION)) >= MIN_VERSION) - { - /* The magic numbers match and the version field is sufficient. - Extract the payload bounds. */ - - uint32_t offset = LE32 (*(uint32_t *) (header + H_PAYLOAD_OFFSET)); - uint32_t length = LE32 (*(uint32_t *) (header + H_PAYLOAD_LENGTH)); - - offset += ((*(uint8_t *) (header + H_SETUP_SECTS) ?: 4) + 1) * 512; - - if (offset > H_END && offset < mapped_size - && mapped_size - offset >= length) - { - /* It looks kosher. Use it! */ - *start_offset += offset; - return DWFL_E_NOERROR; - } - } - } - return DWFL_E_BADELF; -} diff --git a/src/libdwfl/libdwfl.h b/src/libdwfl/libdwfl.h deleted file mode 100644 index 2bb4f455..00000000 --- a/src/libdwfl/libdwfl.h +++ /dev/null @@ -1,812 +0,0 @@ -/* Interfaces for libdwfl. - Copyright (C) 2005-2010, 2013 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#ifndef _LIBDWFL_H -#define _LIBDWFL_H 1 - -#include "libdw.h" -#include <stdio.h> - -/* Handle for a session using the library. */ -typedef struct Dwfl Dwfl; - -/* Handle for a module. */ -typedef struct Dwfl_Module Dwfl_Module; - -/* Handle describing a line record. */ -typedef struct Dwfl_Line Dwfl_Line; - -/* This holds information common for all the frames of one backtrace for - a partical thread/task/TID. Several threads belong to one Dwfl. */ -typedef struct Dwfl_Thread Dwfl_Thread; - -/* This holds everything we know about the state of the frame at a particular - PC location described by an FDE belonging to Dwfl_Thread. */ -typedef struct Dwfl_Frame Dwfl_Frame; - -/* Callbacks. */ -typedef struct -{ - int (*find_elf) (Dwfl_Module *mod, void **userdata, - const char *modname, Dwarf_Addr base, - char **file_name, Elf **elfp); - - int (*find_debuginfo) (Dwfl_Module *mod, void **userdata, - const char *modname, Dwarf_Addr base, - const char *file_name, - const char *debuglink_file, GElf_Word debuglink_crc, - char **debuginfo_file_name); - - /* Fill *ADDR with the loaded address of the section called SECNAME in - the given module. Use (Dwarf_Addr) -1 if this section is omitted from - accessible memory. This is called exactly once for each SHF_ALLOC - section that relocations affecting DWARF data refer to, so it can - easily be used to collect state about the sections referenced. */ - int (*section_address) (Dwfl_Module *mod, void **userdata, - const char *modname, Dwarf_Addr base, - const char *secname, - GElf_Word shndx, const GElf_Shdr *shdr, - Dwarf_Addr *addr); - - char **debuginfo_path; /* See dwfl_standard_find_debuginfo. */ -} Dwfl_Callbacks; - - -#ifdef __cplusplus -extern "C" { -#endif - -/* Start a new session with the library. */ -extern Dwfl *dwfl_begin (const Dwfl_Callbacks *callbacks) - __nonnull_attribute__ (1); - - -/* End a session. */ -extern void dwfl_end (Dwfl *); - -/* Return implementation's version string suitable for printing. */ -extern const char *dwfl_version (Dwfl *); - -/* Return error code of last failing function call. This value is kept - separately for each thread. */ -extern int dwfl_errno (void); - -/* Return error string for ERROR. If ERROR is zero, return error string - for most recent error or NULL if 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 *dwfl_errmsg (int err); - - -/* Start reporting the current set of segments and modules to the library. - All existing segments are wiped. Existing modules are marked to be - deleted, and will not be found via dwfl_addrmodule et al if they are not - re-reported before dwfl_report_end is called. */ -extern void dwfl_report_begin (Dwfl *dwfl); - -/* Report that segment NDX begins at PHDR->p_vaddr + BIAS. - If NDX is < 0, the value succeeding the last call's NDX - is used instead (zero on the first call). - - If nonzero, the smallest PHDR->p_align value seen sets the - effective page size for the address space DWFL describes. - This is the granularity at which reported module boundary - addresses will be considered to fall in or out of a segment. - - Returns -1 for errors, or NDX (or its assigned replacement) on success. - - When NDX is the value succeeding the last call's NDX (or is implicitly - so as above), IDENT is nonnull and matches the value in the last call, - and the PHDR and BIAS values reflect a segment that would be contiguous, - in both memory and file, with the last segment reported, then this - segment may be coalesced internally with preceding segments. When given - an address inside this segment, dwfl_addrsegment may return the NDX of a - preceding contiguous segment. To prevent coalesced segments, always - pass a null pointer for IDENT. - - The values passed are not stored (except to track coalescence). - The only information that can be extracted from DWFL later is the - mapping of an address to a segment index that starts at or below - it. Reporting segments at all is optional. Its only benefit to - the caller is to offer this quick lookup via dwfl_addrsegment, - or use other segment-based calls. */ -extern int dwfl_report_segment (Dwfl *dwfl, int ndx, - const GElf_Phdr *phdr, GElf_Addr bias, - const void *ident); - -/* Report that a module called NAME spans addresses [START, END). - Returns the module handle, either existing or newly allocated, - or returns a null pointer for an allocation error. */ -extern Dwfl_Module *dwfl_report_module (Dwfl *dwfl, const char *name, - Dwarf_Addr start, Dwarf_Addr end); - -/* Report a module to address BASE with start and end addresses computed - from the ELF program headers in the given file - see the table below. - FD may be -1 to open FILE_NAME. On success, FD is consumed by the - library, and the `find_elf' callback will not be used for this module. - ADD_P_VADDR BASE - ET_EXEC ignored ignored - ET_DYN false absolute address where to place the file - true start address relative to ELF's phdr p_vaddr - ET_REL ignored absolute address where to place the file - ET_CORE ignored ignored - ET_DYN ELF phdr p_vaddr address can be non-zero if the shared library - has been prelinked by tool prelink(8). */ -extern Dwfl_Module *dwfl_report_elf (Dwfl *dwfl, const char *name, - const char *file_name, int fd, - GElf_Addr base, bool add_p_vaddr); - -/* Similar, but report the module for offline use. All ET_EXEC files - being reported must be reported before any relocatable objects. - If this is used, dwfl_report_module and dwfl_report_elf may not be - used in the same reporting session. */ -extern Dwfl_Module *dwfl_report_offline (Dwfl *dwfl, const char *name, - const char *file_name, int fd); - - -/* Finish reporting the current set of modules to the library. - If REMOVED is not null, it's called for each module that - existed before but was not included in the current report. - Returns a nonzero return value from the callback. - The callback may call dwfl_report_module; doing so with the - details of the module being removed prevents its removal. - DWFL cannot be used until this function has returned zero. */ -extern int dwfl_report_end (Dwfl *dwfl, - int (*removed) (Dwfl_Module *, void *, - const char *, Dwarf_Addr, - void *arg), - void *arg); - -/* Start reporting additional modules to the library. No calls but - dwfl_report_* can be made on DWFL until dwfl_report_end is called. - This is like dwfl_report_begin, but all the old modules are kept on. - More dwfl_report_* calls can follow to add more modules. - When dwfl_report_end is called, no old modules will be removed. */ -extern void dwfl_report_begin_add (Dwfl *dwfl); - - -/* Return the name of the module, and for each non-null argument store - interesting details: *USERDATA is a location for storing your own - pointer, **USERDATA is initially null; *START and *END give the address - range covered by the module; *DWBIAS is the address bias for debugging - information, and *SYMBIAS for symbol table entries (either is -1 if not - yet accessed); *MAINFILE is the name of the ELF file, and *DEBUGFILE the - name of the debuginfo file (might be equal to *MAINFILE; either is null - if not yet accessed). */ -extern const char *dwfl_module_info (Dwfl_Module *mod, void ***userdata, - Dwarf_Addr *start, Dwarf_Addr *end, - Dwarf_Addr *dwbias, Dwarf_Addr *symbias, - const char **mainfile, - const char **debugfile); - -/* Iterate through the modules, starting the walk with OFFSET == 0. - Calls *CALLBACK for each module as long as it returns DWARF_CB_OK. - When *CALLBACK returns another value, the walk stops and the - return value can be passed as OFFSET to resume it. Returns 0 when - there are no more modules, or -1 for errors. */ -extern ptrdiff_t dwfl_getmodules (Dwfl *dwfl, - int (*callback) (Dwfl_Module *, void **, - const char *, Dwarf_Addr, - void *arg), - void *arg, - ptrdiff_t offset); - -/* Find the module containing the given address. */ -extern Dwfl_Module *dwfl_addrmodule (Dwfl *dwfl, Dwarf_Addr address); - -/* Find the segment, if any, and module, if any, containing ADDRESS. - Returns a segment index returned by dwfl_report_segment, or -1 - if no segment matches the address. Regardless of the return value, - *MOD is always set to the module containing ADDRESS, or to null. */ -extern int dwfl_addrsegment (Dwfl *dwfl, Dwarf_Addr address, Dwfl_Module **mod); - - - -/* Report the known build ID bits associated with a module. - If VADDR is nonzero, it gives the absolute address where those - bits are found within the module. This can be called at any - time, but is usually used immediately after dwfl_report_module. - Once the module's main ELF file is opened, the ID note found - there takes precedence and cannot be changed. */ -extern int dwfl_module_report_build_id (Dwfl_Module *mod, - const unsigned char *bits, size_t len, - GElf_Addr vaddr) - __nonnull_attribute__ (2); - -/* Extract the build ID bits associated with a module. - Returns -1 for errors, 0 if no ID is known, or the number of ID bytes. - When an ID is found, *BITS points to it; *VADDR is the absolute address - at which the ID bits are found within the module, or 0 if unknown. - - This returns 0 when the module's main ELF file has not yet been loaded - and its build ID bits were not reported. To ensure the ID is always - returned when determinable, call dwfl_module_getelf first. */ -extern int dwfl_module_build_id (Dwfl_Module *mod, - const unsigned char **bits, GElf_Addr *vaddr) - __nonnull_attribute__ (2, 3); - - -/*** Standard callbacks ***/ - -/* These standard find_elf and find_debuginfo callbacks are - controlled by a string specifying directories to look in. - If `debuginfo_path' is set in the Dwfl_Callbacks structure - and the char * it points to is not null, that supplies the - string. Otherwise a default path is used. - - If the first character of the string is + or - that enables or - disables CRC32 checksum validation when it's necessary. The - remainder of the string is composed of elements separated by - colons. Each element can start with + or - to override the - global checksum behavior. This flag is never relevant when - working with build IDs, but it's always parsed in the path - string. The remainder of the element indicates a directory. - - Searches by build ID consult only the elements naming absolute - directory paths. They look under those directories for a link - named ".build-id/xx/yy" or ".build-id/xx/yy.debug", where "xxyy" - is the lower-case hexadecimal representation of the ID bytes. - - In searches for debuginfo by name, if the remainder of the - element is empty, the directory containing the main file is - tried; if it's an absolute path name, the absolute directory path - containing the main file is taken as a subdirectory of this path; - a relative path name is taken as a subdirectory of the directory - containing the main file. Hence for /bin/ls, the default string - ":.debug:/usr/lib/debug" says to look in /bin, then /bin/.debug, - then /usr/lib/debug/bin, for the file name in the .gnu_debuglink - section (or "ls.debug" if none was found). */ - -/* Standard find_elf callback function working solely on build ID. - This can be tried first by any find_elf callback, to use the - bits passed to dwfl_module_report_build_id, if any. */ -extern int dwfl_build_id_find_elf (Dwfl_Module *, void **, - const char *, Dwarf_Addr, - char **, Elf **); - -/* Standard find_debuginfo callback function working solely on build ID. - This can be tried first by any find_debuginfo callback, - to use the build ID bits from the main file when present. */ -extern int dwfl_build_id_find_debuginfo (Dwfl_Module *, void **, - const char *, Dwarf_Addr, - const char *, const char *, - GElf_Word, char **); - -/* Standard find_debuginfo callback function. - If a build ID is available, this tries first to use that. - If there is no build ID or no valid debuginfo found by ID, - it searches the debuginfo path by name, as described above. - Any file found in the path is validated by build ID if possible, - or else by CRC32 checksum if enabled, and skipped if it does not match. */ -extern int dwfl_standard_find_debuginfo (Dwfl_Module *, void **, - const char *, Dwarf_Addr, - const char *, const char *, - GElf_Word, char **); - - -/* This callback must be used when using dwfl_offline_* to report modules, - if ET_REL is to be supported. */ -extern int dwfl_offline_section_address (Dwfl_Module *, void **, - const char *, Dwarf_Addr, - const char *, GElf_Word, - const GElf_Shdr *, - Dwarf_Addr *addr); - - -/* Callbacks for working with kernel modules in the running Linux kernel. */ -extern int dwfl_linux_kernel_find_elf (Dwfl_Module *, void **, - const char *, Dwarf_Addr, - char **, Elf **); -extern int dwfl_linux_kernel_module_section_address (Dwfl_Module *, void **, - const char *, Dwarf_Addr, - const char *, GElf_Word, - const GElf_Shdr *, - Dwarf_Addr *addr); - -/* Call dwfl_report_elf for the running Linux kernel. - Returns zero on success, -1 if dwfl_report_module failed, - or an errno code if opening the kernel binary failed. */ -extern int dwfl_linux_kernel_report_kernel (Dwfl *dwfl); - -/* Call dwfl_report_module for each kernel module in the running Linux kernel. - Returns zero on success, -1 if dwfl_report_module failed, - or an errno code if reading the list of modules failed. */ -extern int dwfl_linux_kernel_report_modules (Dwfl *dwfl); - -/* Report a kernel and its modules found on disk, for offline use. - If RELEASE starts with '/', it names a directory to look in; - if not, it names a directory to find under /lib/modules/; - if null, /lib/modules/`uname -r` is used. - Returns zero on success, -1 if dwfl_report_module failed, - or an errno code if finding the files on disk failed. - - If PREDICATE is not null, it is called with each module to be reported; - its arguments are the module name, and the ELF file name or null if unknown, - and its return value should be zero to skip the module, one to report it, - or -1 to cause the call to fail and return errno. */ -extern int dwfl_linux_kernel_report_offline (Dwfl *dwfl, const char *release, - int (*predicate) (const char *, - const char *)); - -/* Examine an ET_CORE file and report modules based on its contents. - This can follow a dwfl_report_offline call to bootstrap the - DT_DEBUG method of following the dynamic linker link_map chain, in - case the core file does not contain enough of the executable's text - segment to locate its PT_DYNAMIC in the dump. In such case you need to - supply non-NULL EXECUTABLE, otherwise dynamic libraries will not be loaded - into the DWFL map. This might call dwfl_report_elf on file names found in - the dump if reading some link_map files is the only way to ascertain those - modules' addresses. Returns the number of modules reported, or -1 for - errors. */ -extern int dwfl_core_file_report (Dwfl *dwfl, Elf *elf, const char *executable); - -/* Call dwfl_report_module for each file mapped into the address space of PID. - Returns zero on success, -1 if dwfl_report_module failed, - or an errno code if opening the proc files failed. */ -extern int dwfl_linux_proc_report (Dwfl *dwfl, pid_t pid); - -/* Similar, but reads an input stream in the format of Linux /proc/PID/maps - files giving module layout, not the file for a live process. */ -extern int dwfl_linux_proc_maps_report (Dwfl *dwfl, FILE *); - -/* Trivial find_elf callback for use with dwfl_linux_proc_report. - This uses the module name as a file name directly and tries to open it - if it begin with a slash, or handles the magic string "[vdso]". */ -extern int dwfl_linux_proc_find_elf (Dwfl_Module *mod, void **userdata, - const char *module_name, Dwarf_Addr base, - char **file_name, Elf **); - -/* Standard argument parsing for using a standard callback set. */ -struct argp; -extern const struct argp *dwfl_standard_argp (void) __attribute__ ((const)); - - -/*** Relocation of addresses from Dwfl ***/ - -/* Return the number of relocatable bases associated with the module, - which is zero for ET_EXEC and one for ET_DYN. Returns -1 for errors. */ -extern int dwfl_module_relocations (Dwfl_Module *mod); - -/* Return the relocation base index associated with the *ADDRESS location, - and adjust *ADDRESS to be an offset relative to that base. - Returns -1 for errors. */ -extern int dwfl_module_relocate_address (Dwfl_Module *mod, - Dwarf_Addr *address); - -/* Return the ELF section name for the given relocation base index; - if SHNDXP is not null, set *SHNDXP to the ELF section index. - For ET_DYN, returns "" and sets *SHNDXP to SHN_ABS; the relocation - base is the runtime start address reported for the module. - Returns null for errors. */ -extern const char *dwfl_module_relocation_info (Dwfl_Module *mod, - unsigned int idx, - GElf_Word *shndxp); - -/* Validate that ADDRESS and ADDRESS+OFFSET lie in a known module - and both within the same contiguous region for relocation purposes. - Returns zero for success and -1 for errors. */ -extern int dwfl_validate_address (Dwfl *dwfl, - Dwarf_Addr address, Dwarf_Sword offset); - - -/*** ELF access functions ***/ - -/* Fetch the module main ELF file (where the allocated sections - are found) for use with libelf. If successful, fills in *BIAS - with the difference between addresses within the loaded module - and those in symbol tables or Dwarf information referring to it. */ -extern Elf *dwfl_module_getelf (Dwfl_Module *, GElf_Addr *bias) - __nonnull_attribute__ (1, 2); - -/* Return the number of symbols in the module's symbol table, - or -1 for errors. */ -extern int dwfl_module_getsymtab (Dwfl_Module *mod); - -/* Return the index of the first global symbol in the module's symbol - table, or -1 for errors. In each symbol table, all symbols with - STB_LOCAL binding precede the weak and global symbols. This - function returns the symbol table index one greater than the last - local symbol. */ -extern int dwfl_module_getsymtab_first_global (Dwfl_Module *mod); - -/* Fetch one entry from the module's symbol table. On errors, returns - NULL. If successful, fills in *SYM and returns the string for st_name. - This works like gelf_getsym except that st_value is always adjusted to - an absolute value based on the module's location, when the symbol is in - an SHF_ALLOC section. If SHNDXP is non-null, it's set with the section - index (whether from st_shndx or extended index table); in case of a - symbol in a non-allocated section, *SHNDXP is instead set to -1. - Note that since symbols can come from either the main, debug or auxiliary - ELF symbol file (either dynsym or symtab) the section index can only - be reliably used to compare against special section constants like - SHN_UNDEF or SHN_ABS. It is recommended to use dwfl_module_getsym_info - which doesn't have these deficiencies. */ -extern const char *dwfl_module_getsym (Dwfl_Module *mod, int ndx, - GElf_Sym *sym, GElf_Word *shndxp) - __nonnull_attribute__ (3); - -/* Fetch one entry from the module's symbol table and the associated - address value. On errors, returns NULL. If successful, fills in - *SYM, *ADDR and returns the string for st_name. This works like - gelf_getsym. *ADDR is set to the st_value adjusted to an absolute - value based on the module's location, when the symbol is in an - SHF_ALLOC section. For non-ET_REL files, if the arch uses function - descriptors, and the st_value points to one, *ADDR will be resolved - to the actual function entry address. The SYM->ST_VALUE itself - isn't adjusted in any way. Fills in ELFP, if not NULL, with the - ELF file the symbol originally came from. Note that symbols can - come from either the main, debug or auxiliary ELF symbol file - (either dynsym or symtab). If SHNDXP is non-null, it's set with - the section index (whether from st_shndx or extended index table); - in case of a symbol in a non-allocated section, *SHNDXP is instead - set to -1. Fills in BIAS, if not NULL, with the difference between - addresses within the loaded module and those in symbol table of the - ELF file. Note that the address associated with the symbol might - be in a different section than the returned symbol. The section in - the main elf file in which returned ADDR falls can be found with - dwfl_module_address_section. */ -extern const char *dwfl_module_getsym_info (Dwfl_Module *mod, int ndx, - GElf_Sym *sym, GElf_Addr *addr, - GElf_Word *shndxp, - Elf **elfp, Dwarf_Addr *bias) - __nonnull_attribute__ (3, 4); - -/* Find the symbol that ADDRESS lies inside, and return its name. */ -extern const char *dwfl_module_addrname (Dwfl_Module *mod, GElf_Addr address); - -/* Find the symbol associated with ADDRESS. Return its name or NULL - when nothing was found. If the architecture uses function - descriptors, and symbol st_value points to one, ADDRESS wil be - matched against either the adjusted st_value or the associated - function entry value as described in dwfl_module_getsym_info. If - OFFSET is not NULL it will be filled in with the difference from - the start of the symbol (or function entry). If SYM is not NULL it - is filled in with the symbol associated with the matched ADDRESS. - The SYM->ST_VALUE itself isn't adjusted in any way. Fills in ELFP, - if not NULL, with the ELF file the symbol originally came from. - Note that symbols can come from either the main, debug or auxiliary - ELF symbol file (either dynsym or symtab). If SHNDXP is non-null, - it's set with the section index (whether from st_shndx or extended - index table). Fills in BIAS, if not NULL, with the difference - between addresses within the loaded module and those in symbol - table of the ELF file. Note that the address matched against the - symbol might be in a different section than the returned symbol. - The section in the main elf file in ADDRESS falls can be found with - dwfl_module_address_section. */ -extern const char *dwfl_module_addrinfo (Dwfl_Module *mod, GElf_Addr address, - GElf_Off *offset, GElf_Sym *sym, - GElf_Word *shndxp, Elf **elfp, - Dwarf_Addr *bias) - __nonnull_attribute__ (3); - -/* Find the symbol that ADDRESS lies inside, and return detailed - information as for dwfl_module_getsym (above). Note that like - dwfl_module_getsym this function also adjusts SYM->ST_VALUE to an - absolute value based on the module's location. ADDRESS is only - matched against this adjusted SYM->ST_VALUE. This means that - depending on architecture this might only match symbols that - represent function descriptor addresses (and not function entry - addresses). For these reasons it is recommended to use - dwfl_module_addrinfo instead. */ -extern const char *dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr address, - GElf_Sym *sym, GElf_Word *shndxp) - __nonnull_attribute__ (3); - -/* Find the ELF section that *ADDRESS lies inside and return it. - On success, adjusts *ADDRESS to be relative to the section, - and sets *BIAS to the difference between addresses used in - the returned section's headers and run-time addresses. */ -extern Elf_Scn *dwfl_module_address_section (Dwfl_Module *mod, - Dwarf_Addr *address, - Dwarf_Addr *bias) - __nonnull_attribute__ (2, 3); - - -/*** Dwarf access functions ***/ - -/* Fetch the module's debug information for use with libdw. - If successful, fills in *BIAS with the difference between - addresses within the loaded module and those to use with libdw. */ -extern Dwarf *dwfl_module_getdwarf (Dwfl_Module *, Dwarf_Addr *bias) - __nonnull_attribute__ (2); - -/* Get the libdw handle for each module. */ -extern ptrdiff_t dwfl_getdwarf (Dwfl *, - int (*callback) (Dwfl_Module *, void **, - const char *, Dwarf_Addr, - Dwarf *, Dwarf_Addr, void *), - void *arg, ptrdiff_t offset); - -/* Look up the module containing ADDR and return its debugging information, - loading it if necessary. */ -extern Dwarf *dwfl_addrdwarf (Dwfl *dwfl, Dwarf_Addr addr, Dwarf_Addr *bias) - __nonnull_attribute__ (3); - - -/* Find the CU containing ADDR and return its DIE. */ -extern Dwarf_Die *dwfl_addrdie (Dwfl *dwfl, Dwarf_Addr addr, Dwarf_Addr *bias) - __nonnull_attribute__ (3); -extern Dwarf_Die *dwfl_module_addrdie (Dwfl_Module *mod, - Dwarf_Addr addr, Dwarf_Addr *bias) - __nonnull_attribute__ (3); - -/* Iterate through the CUs, start with null for LASTCU. */ -extern Dwarf_Die *dwfl_nextcu (Dwfl *dwfl, Dwarf_Die *lastcu, Dwarf_Addr *bias) - __nonnull_attribute__ (3); -extern Dwarf_Die *dwfl_module_nextcu (Dwfl_Module *mod, - Dwarf_Die *lastcu, Dwarf_Addr *bias) - __nonnull_attribute__ (3); - -/* Return the module containing the CU DIE. */ -extern Dwfl_Module *dwfl_cumodule (Dwarf_Die *cudie); - - -/* Cache the source line information fo the CU and return the - number of Dwfl_Line entries it has. */ -extern int dwfl_getsrclines (Dwarf_Die *cudie, size_t *nlines); - -/* Access one line number entry within the CU. */ -extern Dwfl_Line *dwfl_onesrcline (Dwarf_Die *cudie, size_t idx); - -/* Get source for address. */ -extern Dwfl_Line *dwfl_module_getsrc (Dwfl_Module *mod, Dwarf_Addr addr); -extern Dwfl_Line *dwfl_getsrc (Dwfl *dwfl, Dwarf_Addr addr); - -/* Get address for source. */ -extern int dwfl_module_getsrc_file (Dwfl_Module *mod, - const char *fname, int lineno, int column, - Dwfl_Line ***srcsp, size_t *nsrcs); - -/* Return the module containing this line record. */ -extern Dwfl_Module *dwfl_linemodule (Dwfl_Line *line); - -/* Return the CU containing this line record. */ -extern Dwarf_Die *dwfl_linecu (Dwfl_Line *line); - -/* Return the source file name and fill in other information. - Arguments may be null for unneeded fields. */ -extern const char *dwfl_lineinfo (Dwfl_Line *line, Dwarf_Addr *addr, - int *linep, int *colp, - Dwarf_Word *mtime, Dwarf_Word *length); - - /* Return the equivalent Dwarf_Line and the bias to apply to its address. */ -extern Dwarf_Line *dwfl_dwarf_line (Dwfl_Line *line, Dwarf_Addr *bias); - -/* Return the compilation directory (AT_comp_dir) from this line's CU. */ -extern const char *dwfl_line_comp_dir (Dwfl_Line *line); - - -/*** Machine backend access functions ***/ - -/* Return location expression to find return value given a - DW_TAG_subprogram, DW_TAG_subroutine_type, or similar DIE describing - function itself (whose DW_AT_type attribute describes its return type). - The given DIE must come from the given module. Returns -1 for errors. - Returns zero if the function has no return value (e.g. "void" in C). - Otherwise, *LOCOPS gets a location expression to find the return value, - and returns the number of operations in the expression. The pointer is - permanently allocated at least as long as the module is live. */ -extern int dwfl_module_return_value_location (Dwfl_Module *mod, - Dwarf_Die *functypedie, - const Dwarf_Op **locops); - -/* Enumerate the DWARF register numbers and their names. - For each register, CALLBACK gets its DWARF number, a string describing - the register set (such as "integer" or "FPU"), a prefix used in - assembler syntax (such as "%" or "$", may be ""), and the name for the - register (contains identifier characters only, possibly all digits). - The REGNAME string is valid only during the callback. */ -extern int dwfl_module_register_names (Dwfl_Module *mod, - int (*callback) (void *arg, - int regno, - const char *setname, - const char *prefix, - const char *regname, - int bits, int type), - void *arg); - - -/* Find the CFI for this module. Returns NULL if there is no CFI. - On success, fills in *BIAS with the difference between addresses - within the loaded module and those in the CFI referring to it. - The pointer returned can be used until the module is cleaned up. - Calling these more than once returns the same pointers. - - dwfl_module_dwarf_cfi gets the '.debug_frame' information found with the - rest of the DWARF information. dwfl_module_eh_cfi gets the '.eh_frame' - information found linked into the text. A module might have either or - both. */ -extern Dwarf_CFI *dwfl_module_dwarf_cfi (Dwfl_Module *mod, Dwarf_Addr *bias); -extern Dwarf_CFI *dwfl_module_eh_cfi (Dwfl_Module *mod, Dwarf_Addr *bias); - - -typedef struct -{ - /* Called to iterate through threads. Returns next TID (thread ID) on - success, a negative number on failure and zero if there are no more - threads. dwfl_errno () should be set if negative number has been - returned. *THREAD_ARGP is NULL on first call, and may be optionally - set by the implementation. The value set by the implementation will - be passed in on the next call to NEXT_THREAD. THREAD_ARGP is never - NULL. *THREAD_ARGP will be passed to set_initial_registers or - thread_detach callbacks together with Dwfl_Thread *thread. This - method must not be NULL. */ - pid_t (*next_thread) (Dwfl *dwfl, void *dwfl_arg, void **thread_argp) - __nonnull_attribute__ (1); - - /* Called to get a specific thread. Returns true if there is a - thread with the given thread id number, returns false if no such - thread exists and will set dwfl_errno in that case. THREAD_ARGP - is never NULL. *THREAD_ARGP will be passed to - set_initial_registers or thread_detach callbacks together with - Dwfl_Thread *thread. This method may be NULL and will then be - emulated using the next_thread callback. */ - bool (*get_thread) (Dwfl *dwfl, pid_t tid, void *dwfl_arg, - void **thread_argp) - __nonnull_attribute__ (1); - - /* Called during unwinding to access memory (stack) state. Returns true for - successfully read *RESULT or false and sets dwfl_errno () on failure. - This method may be NULL - in such case dwfl_thread_getframes will return - only the initial frame. */ - bool (*memory_read) (Dwfl *dwfl, Dwarf_Addr addr, Dwarf_Word *result, - void *dwfl_arg) - __nonnull_attribute__ (1, 3); - - /* Called on initial unwind to get the initial register state of the first - frame. Should call dwfl_thread_state_registers, possibly multiple times - for different ranges and possibly also dwfl_thread_state_register_pc, to - fill in initial (DWARF) register values. After this call, till at least - thread_detach is called, the thread is assumed to be frozen, so that it is - safe to unwind. Returns true on success or false and sets dwfl_errno () - on failure. In the case of a failure thread_detach will not be called. - This method must not be NULL. */ - bool (*set_initial_registers) (Dwfl_Thread *thread, void *thread_arg) - __nonnull_attribute__ (1); - - /* Called by dwfl_end. All thread_detach method calls have been already - done. This method may be NULL. */ - void (*detach) (Dwfl *dwfl, void *dwfl_arg) - __nonnull_attribute__ (1); - - /* Called when unwinding is done. No callback will be called after - this method has been called. Iff set_initial_registers was called for - a TID and it returned success thread_detach will be called before the - detach method above. This method may be NULL. */ - void (*thread_detach) (Dwfl_Thread *thread, void *thread_arg) - __nonnull_attribute__ (1); -} Dwfl_Thread_Callbacks; - -/* PID is the process id associated with the DWFL state. Architecture of DWFL - modules is specified by ELF, ELF must remain valid during DWFL lifetime. - Use NULL ELF to detect architecture from DWFL, the function will then detect - it from arbitrary Dwfl_Module of DWFL. DWFL_ARG is the callback backend - state. DWFL_ARG will be provided to the callbacks. *THREAD_CALLBACKS - function pointers must remain valid during lifetime of DWFL. Function - returns true on success, false otherwise. */ -bool dwfl_attach_state (Dwfl *dwfl, Elf *elf, pid_t pid, - const Dwfl_Thread_Callbacks *thread_callbacks, - void *dwfl_arg) - __nonnull_attribute__ (1, 4); - -/* Calls dwfl_attach_state with Dwfl_Thread_Callbacks setup for extracting - thread state from the ELF core file. Returns the pid number extracted - from the core file, or -1 for errors. */ -extern int dwfl_core_file_attach (Dwfl *dwfl, Elf *elf); - -/* Calls dwfl_attach_state with Dwfl_Thread_Callbacks setup for extracting - thread state from the proc file system. Uses ptrace to attach and stop - the thread under inspection and detaches when thread_detach is called - and unwinding for the thread is done, unless ASSUME_PTRACE_STOPPED is - true. If ASSUME_PTRACE_STOPPED is true the caller should make sure that - the thread is ptrace attached and stopped before unwinding by calling - either dwfl_thread_getframes or dwfl_getthread_frames. Returns zero on - success, -1 if dwfl_attach_state failed, or an errno code if opening the - proc files failed. */ -extern int dwfl_linux_proc_attach (Dwfl *dwfl, pid_t pid, - bool assume_ptrace_stopped); - -/* Return PID for the process associated with DWFL. Function returns -1 if - dwfl_attach_state was not called for DWFL. */ -pid_t dwfl_pid (Dwfl *dwfl) - __nonnull_attribute__ (1); - -/* Return DWFL from which THREAD was created using dwfl_getthreads. */ -Dwfl *dwfl_thread_dwfl (Dwfl_Thread *thread) - __nonnull_attribute__ (1); - -/* Return positive TID (thread ID) for THREAD. This function never fails. */ -pid_t dwfl_thread_tid (Dwfl_Thread *thread) - __nonnull_attribute__ (1); - -/* Return thread for frame STATE. This function never fails. */ -Dwfl_Thread *dwfl_frame_thread (Dwfl_Frame *state) - __nonnull_attribute__ (1); - -/* Called by Dwfl_Thread_Callbacks.set_initial_registers implementation. - For every known continuous block of registers <FIRSTREG..FIRSTREG+NREGS) - (inclusive..exclusive) set their content to REGS (array of NREGS items). - Function returns false if any of the registers has invalid number. */ -bool dwfl_thread_state_registers (Dwfl_Thread *thread, int firstreg, - unsigned nregs, const Dwarf_Word *regs) - __nonnull_attribute__ (1, 4); - -/* Called by Dwfl_Thread_Callbacks.set_initial_registers implementation. - If PC is not contained among DWARF registers passed by - dwfl_thread_state_registers on the target architecture pass the PC value - here. */ -void dwfl_thread_state_register_pc (Dwfl_Thread *thread, Dwarf_Word pc) - __nonnull_attribute__ (1); - -/* Iterate through the threads for a process. Returns zero if all threads have - been processed by the callback, returns -1 on error, or the value of the - callback when not DWARF_CB_OK. -1 returned on error will set dwfl_errno (). - Keeps calling the callback with the next thread while the callback returns - DWARF_CB_OK, till there are no more threads. */ -int dwfl_getthreads (Dwfl *dwfl, - int (*callback) (Dwfl_Thread *thread, void *arg), - void *arg) - __nonnull_attribute__ (1, 2); - -/* Iterate through the frames for a thread. Returns zero if all frames - have been processed by the callback, returns -1 on error, or the value of - the callback when not DWARF_CB_OK. -1 returned on error will - set dwfl_errno (). Some systems return error instead of zero on end of the - backtrace, for cross-platform compatibility callers should consider error as - a zero. Keeps calling the callback with the next frame while the callback - returns DWARF_CB_OK, till there are no more frames. On start will call the - set_initial_registers callback and on return will call the detach_thread - callback of the Dwfl_Thread. */ -int dwfl_thread_getframes (Dwfl_Thread *thread, - int (*callback) (Dwfl_Frame *state, void *arg), - void *arg) - __nonnull_attribute__ (1, 2); - -/* Like dwfl_thread_getframes, but specifying the thread by its unique - identifier number. Returns zero if all frames have been processed - by the callback, returns -1 on error (and when no thread with - the given thread id number exists), or the value of the callback - when not DWARF_CB_OK. -1 returned on error will set dwfl_errno (). */ -int dwfl_getthread_frames (Dwfl *dwfl, pid_t tid, - int (*callback) (Dwfl_Frame *thread, void *arg), - void *arg) - __nonnull_attribute__ (1, 3); - -/* Return *PC (program counter) for thread-specific frame STATE. - Set *ISACTIVATION according to DWARF frame "activation" definition. - Typically you need to substract 1 from *PC if *ACTIVATION is false to safely - find function of the caller. ACTIVATION may be NULL. PC must not be NULL. - Function returns false if it failed to find *PC. */ -bool dwfl_frame_pc (Dwfl_Frame *state, Dwarf_Addr *pc, bool *isactivation) - __nonnull_attribute__ (1, 2); - -#ifdef __cplusplus -} -#endif - -#endif /* libdwfl.h */ diff --git a/src/libdwfl/libdwflP.h b/src/libdwfl/libdwflP.h deleted file mode 100644 index 12ee116e..00000000 --- a/src/libdwfl/libdwflP.h +++ /dev/null @@ -1,760 +0,0 @@ -/* Internal definitions for libdwfl. - Copyright (C) 2005-2014 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#ifndef _LIBDWFLP_H -#define _LIBDWFLP_H 1 - -#ifndef PACKAGE_NAME -# include <config.h> -#endif -#include <libdwfl.h> -#include <libebl.h> -#include <assert.h> -#include <dirent.h> -#include <errno.h> -#include <stdbool.h> -#include <stdlib.h> -#include <string.h> - -#include "../libdw/libdwP.h" /* We need its INTDECLs. */ -#include "../libdwelf/libdwelfP.h" - -typedef struct Dwfl_Process Dwfl_Process; - -/* gettext helper macros. */ -#define _(Str) dgettext ("elfutils", Str) - -#define DWFL_ERRORS \ - DWFL_ERROR (NOERROR, N_("no error")) \ - DWFL_ERROR (UNKNOWN_ERROR, N_("unknown error")) \ - DWFL_ERROR (NOMEM, N_("out of memory")) \ - DWFL_ERROR (ERRNO, N_("See errno")) \ - DWFL_ERROR (LIBELF, N_("See elf_errno")) \ - DWFL_ERROR (LIBDW, N_("See dwarf_errno")) \ - DWFL_ERROR (LIBEBL, N_("See ebl_errno (XXX missing)")) \ - DWFL_ERROR (ZLIB, N_("gzip decompression failed")) \ - DWFL_ERROR (BZLIB, N_("bzip2 decompression failed")) \ - DWFL_ERROR (LZMA, N_("LZMA decompression failed")) \ - DWFL_ERROR (UNKNOWN_MACHINE, N_("no support library found for machine")) \ - DWFL_ERROR (NOREL, N_("Callbacks missing for ET_REL file")) \ - DWFL_ERROR (BADRELTYPE, N_("Unsupported relocation type")) \ - DWFL_ERROR (BADRELOFF, N_("r_offset is bogus")) \ - DWFL_ERROR (BADSTROFF, N_("offset out of range")) \ - DWFL_ERROR (RELUNDEF, N_("relocation refers to undefined symbol")) \ - DWFL_ERROR (CB, N_("Callback returned failure")) \ - DWFL_ERROR (NO_DWARF, N_("No DWARF information found")) \ - DWFL_ERROR (NO_SYMTAB, N_("No symbol table found")) \ - DWFL_ERROR (NO_PHDR, N_("No ELF program headers")) \ - DWFL_ERROR (OVERLAP, N_("address range overlaps an existing module")) \ - DWFL_ERROR (ADDR_OUTOFRANGE, N_("address out of range")) \ - DWFL_ERROR (NO_MATCH, N_("no matching address range")) \ - DWFL_ERROR (TRUNCATED, N_("image truncated")) \ - DWFL_ERROR (ALREADY_ELF, N_("ELF file opened")) \ - DWFL_ERROR (BADELF, N_("not a valid ELF file")) \ - DWFL_ERROR (WEIRD_TYPE, N_("cannot handle DWARF type description")) \ - DWFL_ERROR (WRONG_ID_ELF, N_("ELF file does not match build ID")) \ - DWFL_ERROR (BAD_PRELINK, N_("corrupt .gnu.prelink_undo section data")) \ - DWFL_ERROR (LIBEBL_BAD, N_("Internal error due to ebl")) \ - DWFL_ERROR (CORE_MISSING, N_("Missing data in core file")) \ - DWFL_ERROR (INVALID_REGISTER, N_("Invalid register")) \ - DWFL_ERROR (PROCESS_MEMORY_READ, N_("Error reading process memory")) \ - DWFL_ERROR (PROCESS_NO_ARCH, N_("Couldn't find architecture of any ELF")) \ - DWFL_ERROR (PARSE_PROC, N_("Error parsing /proc filesystem")) \ - DWFL_ERROR (INVALID_DWARF, N_("Invalid DWARF")) \ - DWFL_ERROR (UNSUPPORTED_DWARF, N_("Unsupported DWARF")) \ - DWFL_ERROR (NEXT_THREAD_FAIL, N_("Unable to find more threads")) \ - DWFL_ERROR (ATTACH_STATE_CONFLICT, N_("Dwfl already has attached state")) \ - DWFL_ERROR (NO_ATTACH_STATE, N_("Dwfl has no attached state")) \ - DWFL_ERROR (NO_UNWIND, N_("Unwinding not supported for this architecture")) \ - DWFL_ERROR (INVALID_ARGUMENT, N_("Invalid argument")) \ - DWFL_ERROR (NO_CORE_FILE, N_("Not an ET_CORE ELF file")) - -#define DWFL_ERROR(name, text) DWFL_E_##name, -typedef enum { DWFL_ERRORS DWFL_E_NUM } Dwfl_Error; -#undef DWFL_ERROR - -#define OTHER_ERROR(name) ((unsigned int) DWFL_E_##name << 16) -#define DWFL_E(name, errno) (OTHER_ERROR (name) | (errno)) - -extern int __libdwfl_canon_error (Dwfl_Error) internal_function; -extern void __libdwfl_seterrno (Dwfl_Error) internal_function; - -struct Dwfl -{ - const Dwfl_Callbacks *callbacks; - - Dwfl_Module *modulelist; /* List in order used by full traversals. */ - - Dwfl_Process *process; - Dwfl_Error attacherr; /* Previous error attaching process. */ - - GElf_Addr offline_next_address; - - GElf_Addr segment_align; /* Smallest granularity of segments. */ - - /* Binary search table in three parallel malloc'd arrays. */ - size_t lookup_elts; /* Elements in use. */ - size_t lookup_alloc; /* Elements allococated. */ - GElf_Addr *lookup_addr; /* Start address of segment. */ - Dwfl_Module **lookup_module; /* Module associated with segment, or null. */ - int *lookup_segndx; /* User segment index, or -1. */ - - /* Cache from last dwfl_report_segment call. */ - const void *lookup_tail_ident; - GElf_Off lookup_tail_vaddr; - GElf_Off lookup_tail_offset; - int lookup_tail_ndx; - - char *executable_for_core; /* --executable if --core was specified. */ -}; - -#define OFFLINE_REDZONE 0x10000 - -struct dwfl_file -{ - char *name; - int fd; - bool valid; /* The build ID note has been matched. */ - bool relocated; /* Partial relocation of all sections done. */ - - Elf *elf; - - /* This is the lowest p_vaddr in this ELF file, aligned to p_align. - For a file without phdrs, this is zero. */ - GElf_Addr vaddr; - - /* This is an address chosen for synchronization between the main file - and the debug file. See dwfl_module_getdwarf.c for how it's chosen. */ - GElf_Addr address_sync; -}; - -struct Dwfl_Module -{ - Dwfl *dwfl; - struct Dwfl_Module *next; /* Link on Dwfl.modulelist. */ - - void *userdata; - - char *name; /* Iterator name for this module. */ - GElf_Addr low_addr, high_addr; - - struct dwfl_file main, debug, aux_sym; - GElf_Addr main_bias; - Ebl *ebl; - GElf_Half e_type; /* GElf_Ehdr.e_type cache. */ - Dwfl_Error elferr; /* Previous failure to open main file. */ - - struct dwfl_relocation *reloc_info; /* Relocatable sections. */ - - struct dwfl_file *symfile; /* Either main or debug. */ - Elf_Data *symdata; /* Data in the ELF symbol table section. */ - Elf_Data *aux_symdata; /* Data in the auxiliary ELF symbol table. */ - size_t syments; /* sh_size / sh_entsize of that section. */ - size_t aux_syments; /* sh_size / sh_entsize of aux_sym section. */ - int first_global; /* Index of first global symbol of table. */ - int aux_first_global; /* Index of first global of aux_sym table. */ - Elf_Data *symstrdata; /* Data for its string table. */ - Elf_Data *aux_symstrdata; /* Data for aux_sym string table. */ - Elf_Data *symxndxdata; /* Data in the extended section index table. */ - Elf_Data *aux_symxndxdata; /* Data in the extended auxiliary table. */ - - Dwarf *dw; /* libdw handle for its debugging info. */ - Dwarf *alt; /* Dwarf used for dwarf_setalt, or NULL. */ - int alt_fd; /* descriptor, only valid when alt != NULL. */ - Elf *alt_elf; /* Elf for alt Dwarf. */ - - Dwfl_Error symerr; /* Previous failure to load symbols. */ - Dwfl_Error dwerr; /* Previous failure to load DWARF. */ - - /* Known CU's in this module. */ - struct dwfl_cu *first_cu, **cu; - - void *lazy_cu_root; /* Table indexed by Dwarf_Off of CU. */ - - struct dwfl_arange *aranges; /* Mapping of addresses in module to CUs. */ - - void *build_id_bits; /* malloc'd copy of build ID bits. */ - GElf_Addr build_id_vaddr; /* Address where they reside, 0 if unknown. */ - int build_id_len; /* -1 for prior failure, 0 if unset. */ - - unsigned int ncu; - unsigned int lazycu; /* Possible users, deleted when none left. */ - unsigned int naranges; - - Dwarf_CFI *dwarf_cfi; /* Cached DWARF CFI for this module. */ - Dwarf_CFI *eh_cfi; /* Cached EH CFI for this module. */ - - int segment; /* Index of first segment table entry. */ - bool gc; /* Mark/sweep flag. */ - bool is_executable; /* Use Dwfl::executable_for_core? */ -}; - -/* This holds information common for all the threads/tasks/TIDs of one process - for backtraces. */ - -struct Dwfl_Process -{ - struct Dwfl *dwfl; - pid_t pid; - const Dwfl_Thread_Callbacks *callbacks; - void *callbacks_arg; - struct ebl *ebl; - bool ebl_close:1; -}; - -/* See its typedef in libdwfl.h. */ - -struct Dwfl_Thread -{ - Dwfl_Process *process; - pid_t tid; - /* The current frame being unwound. Initially it is the bottom frame. - Later the processed frames get freed and this pointer is updated. */ - Dwfl_Frame *unwound; - void *callbacks_arg; -}; - -/* See its typedef in libdwfl.h. */ - -struct Dwfl_Frame -{ - Dwfl_Thread *thread; - /* Previous (outer) frame. */ - Dwfl_Frame *unwound; - bool signal_frame : 1; - bool initial_frame : 1; - enum - { - /* This structure is still being initialized or there was an error - initializing it. */ - DWFL_FRAME_STATE_ERROR, - /* PC field is valid. */ - DWFL_FRAME_STATE_PC_SET, - /* PC field is undefined, this means the next (inner) frame was the - outermost frame. */ - DWFL_FRAME_STATE_PC_UNDEFINED - } pc_state; - /* Either initialized from appropriate REGS element or on some archs - initialized separately as the return address has no DWARF register. */ - Dwarf_Addr pc; - /* (1 << X) bitmask where 0 <= X < ebl_frame_nregs. */ - uint64_t regs_set[3]; - /* REGS array size is ebl_frame_nregs. - REGS_SET tells which of the REGS are valid. */ - Dwarf_Addr regs[]; -}; - -/* Fetch value from Dwfl_Frame->regs indexed by DWARF REGNO. - No error code is set if the function returns FALSE. */ -bool __libdwfl_frame_reg_get (Dwfl_Frame *state, unsigned regno, - Dwarf_Addr *val) - internal_function; - -/* Store value to Dwfl_Frame->regs indexed by DWARF REGNO. - No error code is set if the function returns FALSE. */ -bool __libdwfl_frame_reg_set (Dwfl_Frame *state, unsigned regno, - Dwarf_Addr val) - internal_function; - -/* Information cached about each CU in Dwfl_Module.dw. */ -struct dwfl_cu -{ - /* This caches libdw information about the CU. It's also the - address passed back to users, so we take advantage of the - fact that it's placed first to cast back. */ - Dwarf_Die die; - - Dwfl_Module *mod; /* Pointer back to containing module. */ - - struct dwfl_cu *next; /* CU immediately following in the file. */ - - struct Dwfl_Lines *lines; -}; - -struct Dwfl_Lines -{ - struct dwfl_cu *cu; - - /* This is what the opaque Dwfl_Line * pointers we pass to users are. - We need to recover pointers to our struct dwfl_cu and a record in - libdw's Dwarf_Line table. To minimize the memory used in addition - to libdw's Dwarf_Lines buffer, we just point to our own index in - this table, and have one pointer back to the CU. The indices here - match those in libdw's Dwarf_CU.lines->info table. */ - struct Dwfl_Line - { - unsigned int idx; /* My index in the dwfl_cu.lines table. */ - } idx[0]; -}; - -static inline struct dwfl_cu * -dwfl_linecu_inline (const Dwfl_Line *line) -{ - const struct Dwfl_Lines *lines = ((const void *) line - - offsetof (struct Dwfl_Lines, - idx[line->idx])); - return lines->cu; -} -#define dwfl_linecu dwfl_linecu_inline - -static inline GElf_Addr -dwfl_adjusted_address (Dwfl_Module *mod, GElf_Addr addr) -{ - return addr + mod->main_bias; -} - -static inline GElf_Addr -dwfl_deadjust_address (Dwfl_Module *mod, GElf_Addr addr) -{ - return addr - mod->main_bias; -} - -static inline Dwarf_Addr -dwfl_adjusted_dwarf_addr (Dwfl_Module *mod, Dwarf_Addr addr) -{ - return dwfl_adjusted_address (mod, (addr - - mod->debug.address_sync - + mod->main.address_sync)); -} - -static inline Dwarf_Addr -dwfl_deadjust_dwarf_addr (Dwfl_Module *mod, Dwarf_Addr addr) -{ - return (dwfl_deadjust_address (mod, addr) - - mod->main.address_sync - + mod->debug.address_sync); -} - -static inline Dwarf_Addr -dwfl_adjusted_aux_sym_addr (Dwfl_Module *mod, Dwarf_Addr addr) -{ - return dwfl_adjusted_address (mod, (addr - - mod->aux_sym.address_sync - + mod->main.address_sync)); -} - -static inline Dwarf_Addr -dwfl_deadjust_aux_sym_addr (Dwfl_Module *mod, Dwarf_Addr addr) -{ - return (dwfl_deadjust_address (mod, addr) - - mod->main.address_sync - + mod->aux_sym.address_sync); -} - -static inline GElf_Addr -dwfl_adjusted_st_value (Dwfl_Module *mod, Elf *symelf, GElf_Addr addr) -{ - if (symelf == mod->main.elf) - return dwfl_adjusted_address (mod, addr); - if (symelf == mod->debug.elf) - return dwfl_adjusted_dwarf_addr (mod, addr); - return dwfl_adjusted_aux_sym_addr (mod, addr); -} - -static inline GElf_Addr -dwfl_deadjust_st_value (Dwfl_Module *mod, Elf *symelf, GElf_Addr addr) -{ - if (symelf == mod->main.elf) - return dwfl_deadjust_address (mod, addr); - if (symelf == mod->debug.elf) - return dwfl_deadjust_dwarf_addr (mod, addr); - return dwfl_deadjust_aux_sym_addr (mod, addr); -} - -/* This describes a contiguous address range that lies in a single CU. - We condense runs of Dwarf_Arange entries for the same CU into this. */ -struct dwfl_arange -{ - struct dwfl_cu *cu; - size_t arange; /* Index in Dwarf_Aranges. */ -}; - - -/* Structure used for keeping track of ptrace attaching a thread. - Shared by linux-pid-attach and linux-proc-maps. If it has been setup - then get the instance through __libdwfl_get_pid_arg. */ -struct __libdwfl_pid_arg -{ - DIR *dir; - /* It is 0 if not used. */ - pid_t tid_attached; - /* Valid only if TID_ATTACHED is not zero. */ - bool tid_was_stopped; - /* True if threads are ptrace stopped by caller. */ - bool assume_ptrace_stopped; -}; - -/* If DWfl is not NULL and a Dwfl_Process has been setup that has - Dwfl_Thread_Callbacks set to pid_thread_callbacks, then return the - callbacks_arg, which will be a struct __libdwfl_pid_arg. Otherwise - returns NULL. */ -extern struct __libdwfl_pid_arg *__libdwfl_get_pid_arg (Dwfl *dwfl) - internal_function; - -/* Makes sure the given tid is attached. On success returns true and - sets tid_was_stopped. */ -extern bool __libdwfl_ptrace_attach (pid_t tid, bool *tid_was_stoppedp) - internal_function; - -/* Detaches a tid that was attached through - __libdwfl_ptrace_attach. Must be given the tid_was_stopped as set - by __libdwfl_ptrace_attach. */ -extern void __libdwfl_ptrace_detach (pid_t tid, bool tid_was_stopped) - internal_function; - - -/* Internal wrapper for old dwfl_module_getsym and new dwfl_module_getsym_info. - adjust_st_value set to true returns adjusted SYM st_value, set to false - it will not adjust SYM at all, but does match against resolved *ADDR. */ -extern const char *__libdwfl_getsym (Dwfl_Module *mod, int ndx, GElf_Sym *sym, - GElf_Addr *addr, GElf_Word *shndxp, - Elf **elfp, Dwarf_Addr *biasp, - bool *resolved, bool adjust_st_value) - internal_function; - -/* Internal wrapper for old dwfl_module_addrsym and new dwfl_module_addrinfo. - adjust_st_value set to true returns adjusted SYM st_value, set to false - it will not adjust SYM at all, but does match against resolved values. */ -extern const char *__libdwfl_addrsym (Dwfl_Module *mod, GElf_Addr addr, - GElf_Off *off, GElf_Sym *sym, - GElf_Word *shndxp, Elf **elfp, - Dwarf_Addr *bias, - bool adjust_st_value) internal_function; - -extern void __libdwfl_module_free (Dwfl_Module *mod) internal_function; - -/* Find the main ELF file, update MOD->elferr and/or MOD->main.elf. */ -extern void __libdwfl_getelf (Dwfl_Module *mod) internal_function; - -/* Process relocations in debugging sections in an ET_REL file. - FILE must be opened with ELF_C_READ_MMAP_PRIVATE or ELF_C_READ, - to make it possible to relocate the data in place (or ELF_C_RDWR or - ELF_C_RDWR_MMAP if you intend to modify the Elf file on disk). After - this, dwarf_begin_elf on FILE will read the relocated data. - - When DEBUG is false, apply partial relocation to all sections. */ -extern Dwfl_Error __libdwfl_relocate (Dwfl_Module *mod, Elf *file, bool debug) - internal_function; - -/* Find the section index in mod->main.elf that contains the given - *ADDR. Adjusts *ADDR to be section relative on success, returns - SHN_UNDEF on failure. */ -extern size_t __libdwfl_find_section_ndx (Dwfl_Module *mod, Dwarf_Addr *addr) - internal_function; - -/* Process (simple) relocations in arbitrary section TSCN of an ET_REL file. - RELOCSCN is SHT_REL or SHT_RELA and TSCN is its sh_info target section. */ -extern Dwfl_Error __libdwfl_relocate_section (Dwfl_Module *mod, Elf *relocated, - Elf_Scn *relocscn, Elf_Scn *tscn, - bool partial) - internal_function; - -/* Adjust *VALUE from section-relative to absolute. - MOD->dwfl->callbacks->section_address is called to determine the actual - address of a loaded section. */ -extern Dwfl_Error __libdwfl_relocate_value (Dwfl_Module *mod, Elf *elf, - size_t *shstrndx_cache, - Elf32_Word shndx, - GElf_Addr *value) - internal_function; - -/* Ensure that MOD->ebl is set up. */ -extern Dwfl_Error __libdwfl_module_getebl (Dwfl_Module *mod) internal_function; - -/* Install a new Dwarf_CFI in *SLOT (MOD->eh_cfi or MOD->dwarf_cfi). */ -extern Dwarf_CFI *__libdwfl_set_cfi (Dwfl_Module *mod, Dwarf_CFI **slot, - Dwarf_CFI *cfi) - internal_function; - -/* Iterate through all the CU's in the module. Start by passing a null - LASTCU, and then pass the last *CU returned. Success return with null - *CU no more CUs. */ -extern Dwfl_Error __libdwfl_nextcu (Dwfl_Module *mod, struct dwfl_cu *lastcu, - struct dwfl_cu **cu) internal_function; - -/* Find the CU by address. */ -extern Dwfl_Error __libdwfl_addrcu (Dwfl_Module *mod, Dwarf_Addr addr, - struct dwfl_cu **cu) internal_function; - -/* Ensure that CU->lines (and CU->cu->lines) is set up. */ -extern Dwfl_Error __libdwfl_cu_getsrclines (struct dwfl_cu *cu) - internal_function; - -/* Look in ELF for an NT_GNU_BUILD_ID note. Store it to BUILD_ID_BITS, - its vaddr in ELF to BUILD_ID_VADDR (it is unrelocated, even if MOD is not - NULL) and store length to BUILD_ID_LEN. Returns -1 for errors, 1 if it was - stored and 0 if no note is found. MOD may be NULL, MOD must be non-NULL - only if ELF is ET_REL. */ -extern int __libdwfl_find_elf_build_id (Dwfl_Module *mod, Elf *elf, - const void **build_id_bits, - GElf_Addr *build_id_elfaddr, - int *build_id_len) - internal_function; - -/* Look in ELF for an NT_GNU_BUILD_ID note. If SET is true, store it - in MOD and return its length. If SET is false, instead compare it - to that stored in MOD and return 2 if they match, 1 if they do not. - Returns -1 for errors, 0 if no note is found. */ -extern int __libdwfl_find_build_id (Dwfl_Module *mod, bool set, Elf *elf) - internal_function; - -/* Open a main or debuginfo file by its build ID, returns the fd. */ -extern int __libdwfl_open_mod_by_build_id (Dwfl_Module *mod, bool debug, - char **file_name) internal_function; - -/* Same, but takes an explicit build_id, can also be used for alt debug. */ -extern int __libdwfl_open_by_build_id (Dwfl_Module *mod, bool debug, - char **file_name, const size_t id_len, - const uint8_t *id) internal_function; - -extern uint32_t __libdwfl_crc32 (uint32_t crc, unsigned char *buf, size_t len) - attribute_hidden; -extern int __libdwfl_crc32_file (int fd, uint32_t *resp) attribute_hidden; - - -/* Given ELF and some parameters return TRUE if the *P return value parameters - have been successfully filled in. Any of the *P parameters can be NULL. */ -extern bool __libdwfl_elf_address_range (Elf *elf, GElf_Addr base, - bool add_p_vaddr, bool sanity, - GElf_Addr *vaddrp, - GElf_Addr *address_syncp, - GElf_Addr *startp, GElf_Addr *endp, - GElf_Addr *biasp, GElf_Half *e_typep) - internal_function; - -/* Meat of dwfl_report_elf, given elf_begin just called. - Consumes ELF on success, not on failure. */ -extern Dwfl_Module *__libdwfl_report_elf (Dwfl *dwfl, const char *name, - const char *file_name, int fd, - Elf *elf, GElf_Addr base, - bool add_p_vaddr, bool sanity) - internal_function; - -/* Meat of dwfl_report_offline. */ -extern Dwfl_Module *__libdwfl_report_offline (Dwfl *dwfl, const char *name, - const char *file_name, - int fd, bool closefd, - int (*predicate) (const char *, - const char *)) - internal_function; - -/* Free PROCESS. Unlink and free also any structures it references. */ -extern void __libdwfl_process_free (Dwfl_Process *process) - internal_function; - -/* Update STATE->unwound for the unwound frame. - On error STATE->unwound == NULL - or STATE->unwound->pc_state == DWFL_FRAME_STATE_ERROR; - in such case dwfl_errno () is set. - If STATE->unwound->pc_state == DWFL_FRAME_STATE_PC_UNDEFINED - then STATE was the last valid frame. */ -extern void __libdwfl_frame_unwind (Dwfl_Frame *state) - internal_function; - -/* Align segment START downwards or END upwards addresses according to DWFL. */ -extern GElf_Addr __libdwfl_segment_start (Dwfl *dwfl, GElf_Addr start) - internal_function; -extern GElf_Addr __libdwfl_segment_end (Dwfl *dwfl, GElf_Addr end) - internal_function; - -/* Decompression wrappers: decompress whole file into memory. */ -extern Dwfl_Error __libdw_gunzip (int fd, off64_t start_offset, - void *mapped, size_t mapped_size, - void **whole, size_t *whole_size) - internal_function; -extern Dwfl_Error __libdw_bunzip2 (int fd, off64_t start_offset, - void *mapped, size_t mapped_size, - void **whole, size_t *whole_size) - internal_function; -extern Dwfl_Error __libdw_unlzma (int fd, off64_t start_offset, - void *mapped, size_t mapped_size, - void **whole, size_t *whole_size) - internal_function; - -/* Skip the image header before a file image: updates *START_OFFSET. */ -extern Dwfl_Error __libdw_image_header (int fd, off64_t *start_offset, - void *mapped, size_t mapped_size) - internal_function; - -/* Open Elf handle on *FDP. This handles decompression and checks - elf_kind. Succeed only for ELF_K_ELF, or also ELF_K_AR if ARCHIVE_OK. - Returns DWFL_E_NOERROR and sets *ELFP on success, resets *FDP to -1 if - it's no longer used. Resets *FDP on failure too iff CLOSE_ON_FAIL. */ -extern Dwfl_Error __libdw_open_file (int *fdp, Elf **elfp, - bool close_on_fail, bool archive_ok) - internal_function; - -/* Fetch PT_DYNAMIC P_VADDR from ELF and store it to *VADDRP. Return success. - *VADDRP is not modified if the function fails. */ -extern bool __libdwfl_dynamic_vaddr_get (Elf *elf, GElf_Addr *vaddrp) - internal_function; - -/* These are working nicely for --core, but are not ready to be - exported interfaces quite yet. */ - -/* Type of callback function ... - */ -typedef bool Dwfl_Memory_Callback (Dwfl *dwfl, int segndx, - void **buffer, size_t *buffer_available, - GElf_Addr vaddr, size_t minread, void *arg); - -/* Type of callback function ... - */ -typedef bool Dwfl_Module_Callback (Dwfl_Module *mod, void **userdata, - const char *name, Dwarf_Addr base, - void **buffer, size_t *buffer_available, - GElf_Off cost, GElf_Off worthwhile, - GElf_Off whole, GElf_Off contiguous, - void *arg, Elf **elfp); - -/* One shared library (or executable) info from DT_DEBUG link map. */ -struct r_debug_info_module -{ - struct r_debug_info_module *next; - /* FD is -1 iff ELF is NULL. */ - int fd; - Elf *elf; - GElf_Addr l_ld; - /* START and END are both zero if not valid. */ - GElf_Addr start, end; - bool disk_file_has_build_id; - char name[0]; -}; - -/* Information gathered from DT_DEBUG by dwfl_link_map_report hinted to - dwfl_segment_report_module. */ -struct r_debug_info -{ - struct r_debug_info_module *module; -}; - -/* ... - */ -extern int dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, - Dwfl_Memory_Callback *memory_callback, - void *memory_callback_arg, - Dwfl_Module_Callback *read_eagerly, - void *read_eagerly_arg, - const void *note_file, - size_t note_file_size, - const struct r_debug_info *r_debug_info); - -/* Report a module for entry in the dynamic linker's struct link_map list. - For each link_map entry, if an existing module resides at its address, - this just modifies that module's name and suggested file name. If - no such module exists, this calls dwfl_report_elf on the l_name string. - - If AUXV is not null, it points to AUXV_SIZE bytes of auxiliary vector - data as contained in an NT_AUXV note or read from a /proc/pid/auxv - file. When this is available, it guides the search. If AUXV is null - or the memory it points to is not accessible, then this search can - only find where to begin if the correct executable file was - previously reported and preloaded as with dwfl_report_elf. - - Fill in R_DEBUG_INFO if it is not NULL. It should be cleared by the - caller, this function does not touch fields it does not need to modify. - If R_DEBUG_INFO is not NULL then no modules get added to DWFL, caller - has to add them from filled in R_DEBUG_INFO. - - Returns the number of modules found, or -1 for errors. */ -extern int dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size, - Dwfl_Memory_Callback *memory_callback, - void *memory_callback_arg, - struct r_debug_info *r_debug_info); - - -/* Avoid PLT entries. */ -INTDECL (dwfl_begin) -INTDECL (dwfl_errmsg) -INTDECL (dwfl_errno) -INTDECL (dwfl_addrmodule) -INTDECL (dwfl_addrsegment) -INTDECL (dwfl_addrdwarf) -INTDECL (dwfl_addrdie) -INTDECL (dwfl_core_file_attach) -INTDECL (dwfl_core_file_report) -INTDECL (dwfl_getmodules) -INTDECL (dwfl_module_addrdie) -INTDECL (dwfl_module_address_section) -INTDECL (dwfl_module_addrinfo) -INTDECL (dwfl_module_addrsym) -INTDECL (dwfl_module_build_id) -INTDECL (dwfl_module_getdwarf) -INTDECL (dwfl_module_getelf) -INTDECL (dwfl_module_getsym) -INTDECL (dwfl_module_getsym_info) -INTDECL (dwfl_module_getsymtab) -INTDECL (dwfl_module_getsymtab_first_global) -INTDECL (dwfl_module_getsrc) -INTDECL (dwfl_module_report_build_id) -INTDECL (dwfl_report_elf) -INTDECL (dwfl_report_begin) -INTDECL (dwfl_report_begin_add) -INTDECL (dwfl_report_module) -INTDECL (dwfl_report_segment) -INTDECL (dwfl_report_offline) -INTDECL (dwfl_report_end) -INTDECL (dwfl_build_id_find_elf) -INTDECL (dwfl_build_id_find_debuginfo) -INTDECL (dwfl_standard_find_debuginfo) -INTDECL (dwfl_link_map_report) -INTDECL (dwfl_linux_kernel_find_elf) -INTDECL (dwfl_linux_kernel_module_section_address) -INTDECL (dwfl_linux_proc_attach) -INTDECL (dwfl_linux_proc_report) -INTDECL (dwfl_linux_proc_maps_report) -INTDECL (dwfl_linux_proc_find_elf) -INTDECL (dwfl_linux_kernel_report_kernel) -INTDECL (dwfl_linux_kernel_report_modules) -INTDECL (dwfl_linux_kernel_report_offline) -INTDECL (dwfl_offline_section_address) -INTDECL (dwfl_module_relocate_address) -INTDECL (dwfl_module_dwarf_cfi) -INTDECL (dwfl_module_eh_cfi) -INTDECL (dwfl_attach_state) -INTDECL (dwfl_pid) -INTDECL (dwfl_thread_dwfl) -INTDECL (dwfl_thread_tid) -INTDECL (dwfl_frame_thread) -INTDECL (dwfl_thread_state_registers) -INTDECL (dwfl_thread_state_register_pc) -INTDECL (dwfl_getthread_frames) -INTDECL (dwfl_getthreads) -INTDECL (dwfl_thread_getframes) -INTDECL (dwfl_frame_pc) - -/* Leading arguments standard to callbacks passed a Dwfl_Module. */ -#define MODCB_ARGS(mod) (mod), &(mod)->userdata, (mod)->name, (mod)->low_addr -#define CBFAIL (errno ? DWFL_E (ERRNO, errno) : DWFL_E_CB); - - -/* The default used by dwfl_standard_find_debuginfo. */ -#define DEFAULT_DEBUGINFO_PATH ":.debug:/usr/lib/debug" - - -#endif /* libdwflP.h */ diff --git a/src/libdwfl/libdwfl_crc32.c b/src/libdwfl/libdwfl_crc32.c deleted file mode 100644 index b89d0d36..00000000 --- a/src/libdwfl/libdwfl_crc32.c +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright (C) 2002, 2005 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - -#define crc32 attribute_hidden __libdwfl_crc32 -#define LIB_SYSTEM_H 1 -#include <libdwflP.h> -#include "../lib/crc32.c" diff --git a/src/libdwfl/libdwfl_crc32_file.c b/src/libdwfl/libdwfl_crc32_file.c deleted file mode 100644 index 6b6b7d3f..00000000 --- a/src/libdwfl/libdwfl_crc32_file.c +++ /dev/null @@ -1,36 +0,0 @@ -/* Copyright (C) 2002, 2005 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - -#define crc32_file attribute_hidden __libdwfl_crc32_file -#define crc32 __libdwfl_crc32 -#define LIB_SYSTEM_H 1 -#include <libdwflP.h> -#include "../lib/crc32_file.c" diff --git a/src/libdwfl/lines.c b/src/libdwfl/lines.c deleted file mode 100644 index 721e29cc..00000000 --- a/src/libdwfl/lines.c +++ /dev/null @@ -1,52 +0,0 @@ -/* Fetch source line info for CU. - Copyright (C) 2005, 2006 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" -#include "../libdw/libdwP.h" - -Dwfl_Error -internal_function -__libdwfl_cu_getsrclines (struct dwfl_cu *cu) -{ - if (cu->lines == NULL) - { - Dwarf_Lines *lines; - size_t nlines; - if (INTUSE(dwarf_getsrclines) (&cu->die, &lines, &nlines) != 0) - return DWFL_E_LIBDW; - - cu->lines = malloc (offsetof (struct Dwfl_Lines, idx[nlines])); - if (cu->lines == NULL) - return DWFL_E_NOMEM; - cu->lines->cu = cu; - for (unsigned int i = 0; i < nlines; ++i) - cu->lines->idx[i].idx = i; - } - - return DWFL_E_NOERROR; -} diff --git a/src/libdwfl/link_map.c b/src/libdwfl/link_map.c deleted file mode 100644 index eaf43b57..00000000 --- a/src/libdwfl/link_map.c +++ /dev/null @@ -1,1021 +0,0 @@ -/* Report modules by examining dynamic linker data structures. - Copyright (C) 2008-2014 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include <config.h> -#include "libdwflP.h" -#include "../libdw/memory-access.h" -#include "system.h" - -#include <byteswap.h> -#include <endian.h> -#include <fcntl.h> - -/* This element is always provided and always has a constant value. - This makes it an easy thing to scan for to discern the format. */ -#define PROBE_TYPE AT_PHENT -#define PROBE_VAL32 sizeof (Elf32_Phdr) -#define PROBE_VAL64 sizeof (Elf64_Phdr) - - -/* Examine an auxv data block and determine its format. - Return true iff we figured it out. */ -static bool -auxv_format_probe (const void *auxv, size_t size, - uint_fast8_t *elfclass, uint_fast8_t *elfdata) -{ - const union - { - char buf[size]; - Elf32_auxv_t a32[size / sizeof (Elf32_auxv_t)]; - Elf64_auxv_t a64[size / sizeof (Elf64_auxv_t)]; - } *u = auxv; - - inline bool check64 (size_t i) - { - /* The AUXV pointer might not even be naturally aligned for 64-bit - data, because note payloads in a core file are not aligned. - But we assume the data is 32-bit aligned. */ - - uint64_t type = read_8ubyte_unaligned_noncvt (&u->a64[i].a_type); - uint64_t val = read_8ubyte_unaligned_noncvt (&u->a64[i].a_un.a_val); - - if (type == BE64 (PROBE_TYPE) - && val == BE64 (PROBE_VAL64)) - { - *elfdata = ELFDATA2MSB; - return true; - } - - if (type == LE64 (PROBE_TYPE) - && val == LE64 (PROBE_VAL64)) - { - *elfdata = ELFDATA2LSB; - return true; - } - - return false; - } - - inline bool check32 (size_t i) - { - if (u->a32[i].a_type == BE32 (PROBE_TYPE) - && u->a32[i].a_un.a_val == BE32 (PROBE_VAL32)) - { - *elfdata = ELFDATA2MSB; - return true; - } - - if (u->a32[i].a_type == LE32 (PROBE_TYPE) - && u->a32[i].a_un.a_val == LE32 (PROBE_VAL32)) - { - *elfdata = ELFDATA2LSB; - return true; - } - - return false; - } - - for (size_t i = 0; i < size / sizeof (Elf64_auxv_t); ++i) - { - if (check64 (i)) - { - *elfclass = ELFCLASS64; - return true; - } - - if (check32 (i * 2) || check32 (i * 2 + 1)) - { - *elfclass = ELFCLASS32; - return true; - } - } - - return false; -} - -/* This is a Dwfl_Memory_Callback that wraps another memory callback. - If the underlying callback cannot fill the data, then this will - fall back to fetching data from module files. */ - -struct integrated_memory_callback -{ - Dwfl_Memory_Callback *memory_callback; - void *memory_callback_arg; - void *buffer; -}; - -static bool -integrated_memory_callback (Dwfl *dwfl, int ndx, - void **buffer, size_t *buffer_available, - GElf_Addr vaddr, - size_t minread, - void *arg) -{ - struct integrated_memory_callback *info = arg; - - if (ndx == -1) - { - /* Called for cleanup. */ - if (info->buffer != NULL) - { - /* The last probe buffer came from the underlying callback. - Let it do its cleanup. */ - assert (*buffer == info->buffer); /* XXX */ - *buffer = info->buffer; - info->buffer = NULL; - return (*info->memory_callback) (dwfl, ndx, buffer, buffer_available, - vaddr, minread, - info->memory_callback_arg); - } - *buffer = NULL; - *buffer_available = 0; - return false; - } - - if (*buffer != NULL) - /* For a final-read request, we only use the underlying callback. */ - return (*info->memory_callback) (dwfl, ndx, buffer, buffer_available, - vaddr, minread, info->memory_callback_arg); - - /* Let the underlying callback try to fill this request. */ - if ((*info->memory_callback) (dwfl, ndx, &info->buffer, buffer_available, - vaddr, minread, info->memory_callback_arg)) - { - *buffer = info->buffer; - return true; - } - - /* Now look for module text covering this address. */ - - Dwfl_Module *mod; - (void) INTUSE(dwfl_addrsegment) (dwfl, vaddr, &mod); - if (mod == NULL) - return false; - - Dwarf_Addr bias; - Elf_Scn *scn = INTUSE(dwfl_module_address_section) (mod, &vaddr, &bias); - if (unlikely (scn == NULL)) - { -#if 0 // XXX would have to handle ndx=-1 cleanup calls passed down. - /* If we have no sections we can try to fill it from the module file - based on its phdr mappings. */ - if (likely (mod->e_type != ET_REL) && mod->main.elf != NULL) - return INTUSE(dwfl_elf_phdr_memory_callback) - (dwfl, 0, buffer, buffer_available, - vaddr - mod->main.bias, minread, mod->main.elf); -#endif - return false; - } - - Elf_Data *data = elf_rawdata (scn, NULL); - if (unlikely (data == NULL)) - // XXX throw error? - return false; - - if (unlikely (data->d_size < vaddr)) - return false; - - /* Provide as much data as we have. */ - void *contents = data->d_buf + vaddr; - size_t avail = data->d_size - vaddr; - if (unlikely (avail < minread)) - return false; - - /* If probing for a string, make sure it's terminated. */ - if (minread == 0 && unlikely (memchr (contents, '\0', avail) == NULL)) - return false; - - /* We have it! */ - *buffer = contents; - *buffer_available = avail; - return true; -} - -static size_t -addrsize (uint_fast8_t elfclass) -{ - return elfclass * 4; -} - -/* Report a module for each struct link_map in the linked list at r_map - in the struct r_debug at R_DEBUG_VADDR. For r_debug_info description - see dwfl_link_map_report in libdwflP.h. If R_DEBUG_INFO is not NULL then no - modules get added to DWFL, caller has to add them from filled in - R_DEBUG_INFO. - - For each link_map entry, if an existing module resides at its address, - this just modifies that module's name and suggested file name. If - no such module exists, this calls dwfl_report_elf on the l_name string. - - Returns the number of modules found, or -1 for errors. */ - -static int -report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata, - Dwfl *dwfl, GElf_Addr r_debug_vaddr, - Dwfl_Memory_Callback *memory_callback, - void *memory_callback_arg, - struct r_debug_info *r_debug_info) -{ - /* Skip r_version, to aligned r_map field. */ - GElf_Addr read_vaddr = r_debug_vaddr + addrsize (elfclass); - - void *buffer = NULL; - size_t buffer_available = 0; - inline int release_buffer (int result) - { - if (buffer != NULL) - (void) (*memory_callback) (dwfl, -1, &buffer, &buffer_available, 0, 0, - memory_callback_arg); - return result; - } - - GElf_Addr addrs[4]; - inline bool read_addrs (GElf_Addr vaddr, size_t n) - { - size_t nb = n * addrsize (elfclass); /* Address words -> bytes to read. */ - - /* Read a new buffer if the old one doesn't cover these words. */ - if (buffer == NULL - || vaddr < read_vaddr - || vaddr - read_vaddr + nb > buffer_available) - { - release_buffer (0); - - read_vaddr = vaddr; - int segndx = INTUSE(dwfl_addrsegment) (dwfl, vaddr, NULL); - if (unlikely (segndx < 0) - || unlikely (! (*memory_callback) (dwfl, segndx, - &buffer, &buffer_available, - vaddr, nb, memory_callback_arg))) - return true; - } - - const union - { - Elf32_Addr a32[n]; - Elf64_Addr a64[n]; - } *in = vaddr - read_vaddr + buffer; - - if (elfclass == ELFCLASS32) - { - if (elfdata == ELFDATA2MSB) - for (size_t i = 0; i < n; ++i) - addrs[i] = BE32 (in->a32[i]); - else - for (size_t i = 0; i < n; ++i) - addrs[i] = LE32 (in->a32[i]); - } - else - { - if (elfdata == ELFDATA2MSB) - for (size_t i = 0; i < n; ++i) - addrs[i] = BE64 (in->a64[i]); - else - for (size_t i = 0; i < n; ++i) - addrs[i] = LE64 (in->a64[i]); - } - - return false; - } - - if (unlikely (read_addrs (read_vaddr, 1))) - return release_buffer (-1); - - GElf_Addr next = addrs[0]; - - Dwfl_Module **lastmodp = &dwfl->modulelist; - int result = 0; - - /* There can't be more elements in the link_map list than there are - segments. DWFL->lookup_elts is probably twice that number, so it - is certainly above the upper bound. If we iterate too many times, - there must be a loop in the pointers due to link_map clobberation. */ - size_t iterations = 0; - while (next != 0 && ++iterations < dwfl->lookup_elts) - { - if (read_addrs (next, 4)) - return release_buffer (-1); - - /* Unused: l_addr is the difference between the address in memory - and the ELF file when the core was created. We need to - recalculate the difference below because the ELF file we use - might be differently pre-linked. */ - // GElf_Addr l_addr = addrs[0]; - GElf_Addr l_name = addrs[1]; - GElf_Addr l_ld = addrs[2]; - next = addrs[3]; - - /* If a clobbered or truncated memory image has no useful pointer, - just skip this element. */ - if (l_ld == 0) - continue; - - /* Fetch the string at the l_name address. */ - const char *name = NULL; - if (buffer != NULL - && read_vaddr <= l_name - && l_name + 1 - read_vaddr < buffer_available - && memchr (l_name - read_vaddr + buffer, '\0', - buffer_available - (l_name - read_vaddr)) != NULL) - name = l_name - read_vaddr + buffer; - else - { - release_buffer (0); - read_vaddr = l_name; - int segndx = INTUSE(dwfl_addrsegment) (dwfl, l_name, NULL); - if (likely (segndx >= 0) - && (*memory_callback) (dwfl, segndx, - &buffer, &buffer_available, - l_name, 0, memory_callback_arg)) - name = buffer; - } - - if (name != NULL && name[0] == '\0') - name = NULL; - - if (iterations == 1 && dwfl->executable_for_core != NULL) - name = dwfl->executable_for_core; - - struct r_debug_info_module *r_debug_info_module = NULL; - if (r_debug_info != NULL) - { - /* Save link map information about valid shared library (or - executable) which has not been found on disk. */ - const char *name1 = name == NULL ? "" : name; - r_debug_info_module = malloc (sizeof (*r_debug_info_module) - + strlen (name1) + 1); - if (r_debug_info_module == NULL) - return release_buffer (result); - r_debug_info_module->fd = -1; - r_debug_info_module->elf = NULL; - r_debug_info_module->l_ld = l_ld; - r_debug_info_module->start = 0; - r_debug_info_module->end = 0; - r_debug_info_module->disk_file_has_build_id = false; - strcpy (r_debug_info_module->name, name1); - r_debug_info_module->next = r_debug_info->module; - r_debug_info->module = r_debug_info_module; - } - - Dwfl_Module *mod = NULL; - if (name != NULL) - { - /* This code is mostly inlined dwfl_report_elf. */ - // XXX hook for sysroot - int fd = open64 (name, O_RDONLY); - if (fd >= 0) - { - Elf *elf; - Dwfl_Error error = __libdw_open_file (&fd, &elf, true, false); - GElf_Addr elf_dynamic_vaddr; - if (error == DWFL_E_NOERROR - && __libdwfl_dynamic_vaddr_get (elf, &elf_dynamic_vaddr)) - { - const void *build_id_bits; - GElf_Addr build_id_elfaddr; - int build_id_len; - bool valid = true; - - if (__libdwfl_find_elf_build_id (NULL, elf, &build_id_bits, - &build_id_elfaddr, - &build_id_len) > 0 - && build_id_elfaddr != 0) - { - if (r_debug_info_module != NULL) - r_debug_info_module->disk_file_has_build_id = true; - GElf_Addr build_id_vaddr = (build_id_elfaddr - - elf_dynamic_vaddr + l_ld); - - release_buffer (0); - int segndx = INTUSE(dwfl_addrsegment) (dwfl, - build_id_vaddr, - NULL); - if (! (*memory_callback) (dwfl, segndx, - &buffer, &buffer_available, - build_id_vaddr, build_id_len, - memory_callback_arg)) - { - /* File has valid build-id which cannot be read from - memory. This happens for core files without bit 4 - (0x10) set in Linux /proc/PID/coredump_filter. */ - } - else - { - if (memcmp (build_id_bits, buffer, build_id_len) != 0) - /* File has valid build-id which does not match - the one in memory. */ - valid = false; - release_buffer (0); - } - } - - if (valid) - { - // It is like l_addr but it handles differently prelinked - // files at core dumping vs. core loading time. - GElf_Addr base = l_ld - elf_dynamic_vaddr; - if (r_debug_info_module == NULL) - { - // XXX hook for sysroot - mod = __libdwfl_report_elf (dwfl, basename (name), - name, fd, elf, base, - true, true); - if (mod != NULL) - { - elf = NULL; - fd = -1; - } - } - else if (__libdwfl_elf_address_range (elf, base, true, - true, NULL, NULL, - &r_debug_info_module->start, - &r_debug_info_module->end, - NULL, NULL)) - { - r_debug_info_module->elf = elf; - r_debug_info_module->fd = fd; - elf = NULL; - fd = -1; - } - } - if (elf != NULL) - elf_end (elf); - if (fd != -1) - close (fd); - } - } - } - - if (mod != NULL) - { - ++result; - - /* Move this module to the end of the list, so that we end - up with a list in the same order as the link_map chain. */ - if (mod->next != NULL) - { - if (*lastmodp != mod) - { - lastmodp = &dwfl->modulelist; - while (*lastmodp != mod) - lastmodp = &(*lastmodp)->next; - } - *lastmodp = mod->next; - mod->next = NULL; - while (*lastmodp != NULL) - lastmodp = &(*lastmodp)->next; - *lastmodp = mod; - } - - lastmodp = &mod->next; - } - } - - return release_buffer (result); -} - -static GElf_Addr -consider_executable (Dwfl_Module *mod, GElf_Addr at_phdr, GElf_Addr at_entry, - uint_fast8_t *elfclass, uint_fast8_t *elfdata, - Dwfl_Memory_Callback *memory_callback, - void *memory_callback_arg) -{ - GElf_Ehdr ehdr; - if (unlikely (gelf_getehdr (mod->main.elf, &ehdr) == NULL)) - return 0; - - if (at_entry != 0) - { - /* If we have an AT_ENTRY value, reject this executable if - its entry point address could not have supplied that. */ - - if (ehdr.e_entry == 0) - return 0; - - if (mod->e_type == ET_EXEC) - { - if (ehdr.e_entry != at_entry) - return 0; - } - else - { - /* It could be a PIE. */ - } - } - - // XXX this could be saved in the file cache: phdr vaddr, DT_DEBUG d_val vaddr - /* Find the vaddr of the DT_DEBUG's d_ptr. This is the memory - address where &r_debug was written at runtime. */ - GElf_Xword align = mod->dwfl->segment_align; - GElf_Addr d_val_vaddr = 0; - size_t phnum; - if (elf_getphdrnum (mod->main.elf, &phnum) != 0) - return 0; - - for (size_t i = 0; i < phnum; ++i) - { - GElf_Phdr phdr_mem; - GElf_Phdr *phdr = gelf_getphdr (mod->main.elf, i, &phdr_mem); - if (phdr == NULL) - break; - - if (phdr->p_align > 1 && (align == 0 || phdr->p_align < align)) - align = phdr->p_align; - - if (at_phdr != 0 - && phdr->p_type == PT_LOAD - && (phdr->p_offset & -align) == (ehdr.e_phoff & -align)) - { - /* This is the segment that would map the phdrs. - If we have an AT_PHDR value, reject this executable - if its phdr mapping could not have supplied that. */ - if (mod->e_type == ET_EXEC) - { - if (ehdr.e_phoff - phdr->p_offset + phdr->p_vaddr != at_phdr) - return 0; - } - else - { - /* It could be a PIE. If the AT_PHDR value and our - phdr address don't match modulo ALIGN, then this - could not have been the right PIE. */ - if (((ehdr.e_phoff - phdr->p_offset + phdr->p_vaddr) & -align) - != (at_phdr & -align)) - return 0; - - /* Calculate the bias applied to the PIE's p_vaddr values. */ - GElf_Addr bias = (at_phdr - (ehdr.e_phoff - phdr->p_offset - + phdr->p_vaddr)); - - /* Final sanity check: if we have an AT_ENTRY value, - reject this PIE unless its biased e_entry matches. */ - if (at_entry != 0 && at_entry != ehdr.e_entry + bias) - return 0; - - /* If we're changing the module's address range, - we've just invalidated the module lookup table. */ - GElf_Addr mod_bias = dwfl_adjusted_address (mod, 0); - if (bias != mod_bias) - { - mod->low_addr -= mod_bias; - mod->high_addr -= mod_bias; - mod->low_addr += bias; - mod->high_addr += bias; - - free (mod->dwfl->lookup_module); - mod->dwfl->lookup_module = NULL; - } - } - } - - if (phdr->p_type == PT_DYNAMIC) - { - Elf_Data *data = elf_getdata_rawchunk (mod->main.elf, phdr->p_offset, - phdr->p_filesz, ELF_T_DYN); - if (data == NULL) - continue; - const size_t entsize = gelf_fsize (mod->main.elf, - ELF_T_DYN, 1, EV_CURRENT); - const size_t n = data->d_size / entsize; - for (size_t j = 0; j < n; ++j) - { - GElf_Dyn dyn_mem; - GElf_Dyn *dyn = gelf_getdyn (data, j, &dyn_mem); - if (dyn != NULL && dyn->d_tag == DT_DEBUG) - { - d_val_vaddr = phdr->p_vaddr + entsize * j + entsize / 2; - break; - } - } - } - } - - if (d_val_vaddr != 0) - { - /* Now we have the final address from which to read &r_debug. */ - d_val_vaddr = dwfl_adjusted_address (mod, d_val_vaddr); - - void *buffer = NULL; - size_t buffer_available = addrsize (ehdr.e_ident[EI_CLASS]); - - int segndx = INTUSE(dwfl_addrsegment) (mod->dwfl, d_val_vaddr, NULL); - - if ((*memory_callback) (mod->dwfl, segndx, - &buffer, &buffer_available, - d_val_vaddr, buffer_available, - memory_callback_arg)) - { - const union - { - Elf32_Addr a32; - Elf64_Addr a64; - } *u = buffer; - - GElf_Addr vaddr; - if (ehdr.e_ident[EI_CLASS] == ELFCLASS32) - vaddr = (ehdr.e_ident[EI_DATA] == ELFDATA2MSB - ? BE32 (u->a32) : LE32 (u->a32)); - else - vaddr = (ehdr.e_ident[EI_DATA] == ELFDATA2MSB - ? BE64 (u->a64) : LE64 (u->a64)); - - (*memory_callback) (mod->dwfl, -1, &buffer, &buffer_available, 0, 0, - memory_callback_arg); - - if (*elfclass == ELFCLASSNONE) - *elfclass = ehdr.e_ident[EI_CLASS]; - else if (*elfclass != ehdr.e_ident[EI_CLASS]) - return 0; - - if (*elfdata == ELFDATANONE) - *elfdata = ehdr.e_ident[EI_DATA]; - else if (*elfdata != ehdr.e_ident[EI_DATA]) - return 0; - - return vaddr; - } - } - - return 0; -} - -/* Try to find an existing executable module with a DT_DEBUG. */ -static GElf_Addr -find_executable (Dwfl *dwfl, GElf_Addr at_phdr, GElf_Addr at_entry, - uint_fast8_t *elfclass, uint_fast8_t *elfdata, - Dwfl_Memory_Callback *memory_callback, - void *memory_callback_arg) -{ - for (Dwfl_Module *mod = dwfl->modulelist; mod != NULL; mod = mod->next) - if (mod->main.elf != NULL) - { - GElf_Addr r_debug_vaddr = consider_executable (mod, at_phdr, at_entry, - elfclass, elfdata, - memory_callback, - memory_callback_arg); - if (r_debug_vaddr != 0) - return r_debug_vaddr; - } - - return 0; -} - - -int -dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size, - Dwfl_Memory_Callback *memory_callback, - void *memory_callback_arg, - struct r_debug_info *r_debug_info) -{ - GElf_Addr r_debug_vaddr = 0; - - uint_fast8_t elfclass = ELFCLASSNONE; - uint_fast8_t elfdata = ELFDATANONE; - if (likely (auxv != NULL) - && likely (auxv_format_probe (auxv, auxv_size, &elfclass, &elfdata))) - { - GElf_Addr entry = 0; - GElf_Addr phdr = 0; - GElf_Xword phent = 0; - GElf_Xword phnum = 0; - -#define READ_AUXV32(ptr) read_4ubyte_unaligned_noncvt (ptr) -#define READ_AUXV64(ptr) read_8ubyte_unaligned_noncvt (ptr) -#define AUXV_SCAN(NN, BL) do \ - { \ - const Elf##NN##_auxv_t *av = auxv; \ - for (size_t i = 0; i < auxv_size / sizeof av[0]; ++i) \ - { \ - uint##NN##_t type = READ_AUXV##NN (&av[i].a_type); \ - uint##NN##_t val = BL##NN (READ_AUXV##NN (&av[i].a_un.a_val)); \ - if (type == BL##NN (AT_ENTRY)) \ - entry = val; \ - else if (type == BL##NN (AT_PHDR)) \ - phdr = val; \ - else if (type == BL##NN (AT_PHNUM)) \ - phnum = val; \ - else if (type == BL##NN (AT_PHENT)) \ - phent = val; \ - else if (type == BL##NN (AT_PAGESZ)) \ - { \ - if (val > 1 \ - && (dwfl->segment_align == 0 \ - || val < dwfl->segment_align)) \ - dwfl->segment_align = val; \ - } \ - } \ - } \ - while (0) - - if (elfclass == ELFCLASS32) - { - if (elfdata == ELFDATA2MSB) - AUXV_SCAN (32, BE); - else - AUXV_SCAN (32, LE); - } - else - { - if (elfdata == ELFDATA2MSB) - AUXV_SCAN (64, BE); - else - AUXV_SCAN (64, LE); - } - - /* If we found the phdr dimensions, search phdrs for PT_DYNAMIC. */ - GElf_Addr dyn_vaddr = 0; - GElf_Xword dyn_filesz = 0; - GElf_Addr dyn_bias = (GElf_Addr) -1; - - inline bool consider_phdr (GElf_Word type, - GElf_Addr vaddr, GElf_Xword filesz) - { - switch (type) - { - case PT_PHDR: - if (dyn_bias == (GElf_Addr) -1 - /* Do a sanity check on the putative address. */ - && ((vaddr & (dwfl->segment_align - 1)) - == (phdr & (dwfl->segment_align - 1)))) - { - dyn_bias = phdr - vaddr; - return dyn_vaddr != 0; - } - break; - - case PT_DYNAMIC: - dyn_vaddr = vaddr; - dyn_filesz = filesz; - return dyn_bias != (GElf_Addr) -1; - } - - return false; - } - - if (phdr != 0 && phnum != 0) - { - Dwfl_Module *phdr_mod; - int phdr_segndx = INTUSE(dwfl_addrsegment) (dwfl, phdr, &phdr_mod); - Elf_Data in = - { - .d_type = ELF_T_PHDR, - .d_version = EV_CURRENT, - .d_size = phnum * phent, - .d_buf = NULL - }; - bool in_ok = (*memory_callback) (dwfl, phdr_segndx, &in.d_buf, - &in.d_size, phdr, phnum * phent, - memory_callback_arg); - if (! in_ok && dwfl->executable_for_core != NULL) - { - /* AUXV -> PHDR -> DYNAMIC - Both AUXV and DYNAMIC should be always present in a core file. - PHDR may be missing in core file, try to read it from - EXECUTABLE_FOR_CORE to find where DYNAMIC is located in the - core file. */ - - int fd = open (dwfl->executable_for_core, O_RDONLY); - Elf *elf; - Dwfl_Error error = DWFL_E_ERRNO; - if (fd != -1) - error = __libdw_open_file (&fd, &elf, true, false); - if (error != DWFL_E_NOERROR) - { - __libdwfl_seterrno (error); - return false; - } - GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (elf, &ehdr_mem); - if (ehdr == NULL) - { - elf_end (elf); - close (fd); - __libdwfl_seterrno (DWFL_E_LIBELF); - return false; - } - size_t e_phnum; - if (elf_getphdrnum (elf, &e_phnum) != 0) - { - elf_end (elf); - close (fd); - __libdwfl_seterrno (DWFL_E_LIBELF); - return false; - } - if (e_phnum != phnum || ehdr->e_phentsize != phent) - { - elf_end (elf); - close (fd); - __libdwfl_seterrno (DWFL_E_BADELF); - return false; - } - off_t off = ehdr->e_phoff; - assert (in.d_buf == NULL); - assert (in.d_size == phnum * phent); - in.d_buf = malloc (in.d_size); - if (unlikely (in.d_buf == NULL)) - { - elf_end (elf); - close (fd); - __libdwfl_seterrno (DWFL_E_NOMEM); - return false; - } - ssize_t nread = pread_retry (fd, in.d_buf, in.d_size, off); - elf_end (elf); - close (fd); - if (nread != (ssize_t) in.d_size) - { - free (in.d_buf); - __libdwfl_seterrno (DWFL_E_ERRNO); - return false; - } - in_ok = true; - } - if (in_ok) - { - union - { - Elf32_Phdr p32; - Elf64_Phdr p64; - char data[phnum * phent]; - } buf; - Elf_Data out = - { - .d_type = ELF_T_PHDR, - .d_version = EV_CURRENT, - .d_size = phnum * phent, - .d_buf = &buf - }; - in.d_size = out.d_size; - if (likely ((elfclass == ELFCLASS32 - ? elf32_xlatetom : elf64_xlatetom) - (&out, &in, elfdata) != NULL)) - { - /* We are looking for PT_DYNAMIC. */ - const union - { - Elf32_Phdr p32[phnum]; - Elf64_Phdr p64[phnum]; - } *u = (void *) &buf; - if (elfclass == ELFCLASS32) - { - for (size_t i = 0; i < phnum; ++i) - if (consider_phdr (u->p32[i].p_type, - u->p32[i].p_vaddr, - u->p32[i].p_filesz)) - break; - } - else - { - for (size_t i = 0; i < phnum; ++i) - if (consider_phdr (u->p64[i].p_type, - u->p64[i].p_vaddr, - u->p64[i].p_filesz)) - break; - } - } - - (*memory_callback) (dwfl, -1, &in.d_buf, &in.d_size, 0, 0, - memory_callback_arg); - } - else - /* We could not read the executable's phdrs from the - memory image. If we have a presupplied executable, - we can still use the AT_PHDR and AT_ENTRY values to - verify it, and to adjust its bias if it's a PIE. - - If there was an ET_EXEC module presupplied that contains - the AT_PHDR address, then we only consider that one. - We'll either accept it if its phdr location and e_entry - make sense or reject it if they don't. If there is no - presupplied ET_EXEC, then look for a presupplied module, - which might be a PIE (ET_DYN) that needs its bias adjusted. */ - r_debug_vaddr = ((phdr_mod == NULL - || phdr_mod->main.elf == NULL - || phdr_mod->e_type != ET_EXEC) - ? find_executable (dwfl, phdr, entry, - &elfclass, &elfdata, - memory_callback, - memory_callback_arg) - : consider_executable (phdr_mod, phdr, entry, - &elfclass, &elfdata, - memory_callback, - memory_callback_arg)); - } - - /* If we found PT_DYNAMIC, search it for DT_DEBUG. */ - if (dyn_filesz != 0) - { - if (dyn_bias != (GElf_Addr) -1) - dyn_vaddr += dyn_bias; - - Elf_Data in = - { - .d_type = ELF_T_DYN, - .d_version = EV_CURRENT, - .d_size = dyn_filesz, - .d_buf = NULL - }; - int dyn_segndx = dwfl_addrsegment (dwfl, dyn_vaddr, NULL); - if ((*memory_callback) (dwfl, dyn_segndx, &in.d_buf, &in.d_size, - dyn_vaddr, dyn_filesz, memory_callback_arg)) - { - union - { - Elf32_Dyn d32; - Elf64_Dyn d64; - char data[dyn_filesz]; - } buf; - Elf_Data out = - { - .d_type = ELF_T_DYN, - .d_version = EV_CURRENT, - .d_size = dyn_filesz, - .d_buf = &buf - }; - in.d_size = out.d_size; - if (likely ((elfclass == ELFCLASS32 - ? elf32_xlatetom : elf64_xlatetom) - (&out, &in, elfdata) != NULL)) - { - /* We are looking for DT_DEBUG. */ - const union - { - Elf32_Dyn d32[dyn_filesz / sizeof (Elf32_Dyn)]; - Elf64_Dyn d64[dyn_filesz / sizeof (Elf64_Dyn)]; - } *u = (void *) &buf; - if (elfclass == ELFCLASS32) - { - size_t n = dyn_filesz / sizeof (Elf32_Dyn); - for (size_t i = 0; i < n; ++i) - if (u->d32[i].d_tag == DT_DEBUG) - { - r_debug_vaddr = u->d32[i].d_un.d_val; - break; - } - } - else - { - size_t n = dyn_filesz / sizeof (Elf64_Dyn); - for (size_t i = 0; i < n; ++i) - if (u->d64[i].d_tag == DT_DEBUG) - { - r_debug_vaddr = u->d64[i].d_un.d_val; - break; - } - } - } - - (*memory_callback) (dwfl, -1, &in.d_buf, &in.d_size, 0, 0, - memory_callback_arg); - } - } - } - else - /* We have to look for a presupplied executable file to determine - the vaddr of its dynamic section and DT_DEBUG therein. */ - r_debug_vaddr = find_executable (dwfl, 0, 0, &elfclass, &elfdata, - memory_callback, memory_callback_arg); - - if (r_debug_vaddr == 0) - return 0; - - /* For following pointers from struct link_map, we will use an - integrated memory access callback that can consult module text - elided from the core file. This is necessary when the l_name - pointer for the dynamic linker's own entry is a pointer into the - executable's .interp section. */ - struct integrated_memory_callback mcb = - { - .memory_callback = memory_callback, - .memory_callback_arg = memory_callback_arg - }; - - /* Now we can follow the dynamic linker's library list. */ - return report_r_debug (elfclass, elfdata, dwfl, r_debug_vaddr, - &integrated_memory_callback, &mcb, r_debug_info); -} -INTDEF (dwfl_link_map_report) diff --git a/src/libdwfl/linux-core-attach.c b/src/libdwfl/linux-core-attach.c deleted file mode 100644 index 5a7b3b3d..00000000 --- a/src/libdwfl/linux-core-attach.c +++ /dev/null @@ -1,427 +0,0 @@ -/* Get Dwarf Frame state for target core file. - Copyright (C) 2013, 2014 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" -#include <fcntl.h> -#include "system.h" - -#include "../libdw/memory-access.h" - -#ifndef MIN -# define MIN(a, b) ((a) < (b) ? (a) : (b)) -#endif - -struct core_arg -{ - Elf *core; - Elf_Data *note_data; - size_t thread_note_offset; - Ebl *ebl; -}; - -struct thread_arg -{ - struct core_arg *core_arg; - size_t note_offset; -}; - -static bool -core_memory_read (Dwfl *dwfl, Dwarf_Addr addr, Dwarf_Word *result, - void *dwfl_arg) -{ - Dwfl_Process *process = dwfl->process; - struct core_arg *core_arg = dwfl_arg; - Elf *core = core_arg->core; - assert (core != NULL); - static size_t phnum; - if (elf_getphdrnum (core, &phnum) < 0) - { - __libdwfl_seterrno (DWFL_E_LIBELF); - return false; - } - for (size_t cnt = 0; cnt < phnum; ++cnt) - { - GElf_Phdr phdr_mem, *phdr = gelf_getphdr (core, cnt, &phdr_mem); - if (phdr == NULL || phdr->p_type != PT_LOAD) - continue; - /* Bias is zero here, a core file itself has no bias. */ - GElf_Addr start = __libdwfl_segment_start (dwfl, phdr->p_vaddr); - GElf_Addr end = __libdwfl_segment_end (dwfl, - phdr->p_vaddr + phdr->p_memsz); - unsigned bytes = ebl_get_elfclass (process->ebl) == ELFCLASS64 ? 8 : 4; - if (addr < start || addr + bytes > end) - continue; - Elf_Data *data; - data = elf_getdata_rawchunk (core, phdr->p_offset + addr - start, - bytes, ELF_T_ADDR); - if (data == NULL) - { - __libdwfl_seterrno (DWFL_E_LIBELF); - return false; - } - assert (data->d_size == bytes); - if (bytes == 8) - *result = read_8ubyte_unaligned_noncvt (data->d_buf); - else - *result = read_4ubyte_unaligned_noncvt (data->d_buf); - return true; - } - __libdwfl_seterrno (DWFL_E_ADDR_OUTOFRANGE); - return false; -} - -static pid_t -core_next_thread (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg, - void **thread_argp) -{ - struct core_arg *core_arg = dwfl_arg; - Elf *core = core_arg->core; - GElf_Nhdr nhdr; - size_t name_offset; - size_t desc_offset; - Elf_Data *note_data = core_arg->note_data; - size_t offset; - - struct thread_arg *thread_arg; - if (*thread_argp == NULL) - { - core_arg->thread_note_offset = 0; - thread_arg = malloc (sizeof (*thread_arg)); - if (thread_arg == NULL) - { - __libdwfl_seterrno (DWFL_E_NOMEM); - return -1; - } - thread_arg->core_arg = core_arg; - *thread_argp = thread_arg; - } - else - thread_arg = (struct thread_arg *) *thread_argp; - - while (offset = core_arg->thread_note_offset, offset < note_data->d_size - && (core_arg->thread_note_offset = gelf_getnote (note_data, offset, - &nhdr, &name_offset, - &desc_offset)) > 0) - { - /* Do not check NAME for now, help broken Linux kernels. */ - const char *name = note_data->d_buf + name_offset; - const char *desc = note_data->d_buf + desc_offset; - GElf_Word regs_offset; - size_t nregloc; - const Ebl_Register_Location *reglocs; - size_t nitems; - const Ebl_Core_Item *items; - if (! ebl_core_note (core_arg->ebl, &nhdr, name, - ®s_offset, &nregloc, ®locs, &nitems, &items)) - { - /* This note may be just not recognized, skip it. */ - continue; - } - if (nhdr.n_type != NT_PRSTATUS) - continue; - const Ebl_Core_Item *item; - for (item = items; item < items + nitems; item++) - if (strcmp (item->name, "pid") == 0) - break; - if (item == items + nitems) - continue; - uint32_t val32 = read_4ubyte_unaligned_noncvt (desc + item->offset); - val32 = (elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB - ? be32toh (val32) : le32toh (val32)); - pid_t tid = (int32_t) val32; - eu_static_assert (sizeof val32 <= sizeof tid); - thread_arg->note_offset = offset; - return tid; - } - - free (thread_arg); - return 0; -} - -static bool -core_set_initial_registers (Dwfl_Thread *thread, void *thread_arg_voidp) -{ - struct thread_arg *thread_arg = thread_arg_voidp; - struct core_arg *core_arg = thread_arg->core_arg; - Elf *core = core_arg->core; - size_t offset = thread_arg->note_offset; - GElf_Nhdr nhdr; - size_t name_offset; - size_t desc_offset; - Elf_Data *note_data = core_arg->note_data; - size_t nregs = ebl_frame_nregs (core_arg->ebl); - assert (nregs > 0); - assert (offset < note_data->d_size); - size_t getnote_err = gelf_getnote (note_data, offset, &nhdr, &name_offset, - &desc_offset); - /* __libdwfl_attach_state_for_core already verified the note is there. */ - assert (getnote_err != 0); - /* Do not check NAME for now, help broken Linux kernels. */ - const char *name = note_data->d_buf + name_offset; - const char *desc = note_data->d_buf + desc_offset; - GElf_Word regs_offset; - size_t nregloc; - const Ebl_Register_Location *reglocs; - size_t nitems; - const Ebl_Core_Item *items; - int core_note_err = ebl_core_note (core_arg->ebl, &nhdr, name, ®s_offset, - &nregloc, ®locs, &nitems, &items); - /* __libdwfl_attach_state_for_core already verified the note is there. */ - assert (core_note_err != 0); - assert (nhdr.n_type == NT_PRSTATUS); - const Ebl_Core_Item *item; - for (item = items; item < items + nitems; item++) - if (strcmp (item->name, "pid") == 0) - break; - assert (item < items + nitems); - pid_t tid; - { - uint32_t val32 = read_4ubyte_unaligned_noncvt (desc + item->offset); - val32 = (elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB - ? be32toh (val32) : le32toh (val32)); - tid = (int32_t) val32; - eu_static_assert (sizeof val32 <= sizeof tid); - } - /* core_next_thread already found this TID there. */ - assert (tid == INTUSE(dwfl_thread_tid) (thread)); - for (item = items; item < items + nitems; item++) - if (item->pc_register) - break; - if (item < items + nitems) - { - Dwarf_Word pc; - switch (gelf_getclass (core) == ELFCLASS32 ? 32 : 64) - { - case 32:; - uint32_t val32 = read_4ubyte_unaligned_noncvt (desc + item->offset); - val32 = (elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB - ? be32toh (val32) : le32toh (val32)); - /* Do a host width conversion. */ - pc = val32; - break; - case 64:; - uint64_t val64 = read_8ubyte_unaligned_noncvt (desc + item->offset); - val64 = (elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB - ? be64toh (val64) : le64toh (val64)); - pc = val64; - break; - default: - abort (); - } - INTUSE(dwfl_thread_state_register_pc) (thread, pc); - } - desc += regs_offset; - for (size_t regloci = 0; regloci < nregloc; regloci++) - { - const Ebl_Register_Location *regloc = reglocs + regloci; - // Iterate even regs out of NREGS range so that we can find pc_register. - if (regloc->bits != 32 && regloc->bits != 64) - continue; - const char *reg_desc = desc + regloc->offset; - for (unsigned regno = regloc->regno; - regno < regloc->regno + (regloc->count ?: 1U); - regno++) - { - /* PPC provides DWARF register 65 irrelevant for - CFI which clashes with register 108 (LR) we need. - LR (108) is provided earlier (in NT_PRSTATUS) than the # 65. - FIXME: It depends now on their order in core notes. - FIXME: It uses private function. */ - if (regno < nregs - && __libdwfl_frame_reg_get (thread->unwound, regno, NULL)) - continue; - Dwarf_Word val; - switch (regloc->bits) - { - case 32:; - uint32_t val32 = read_4ubyte_unaligned_noncvt (reg_desc); - reg_desc += sizeof val32; - val32 = (elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB - ? be32toh (val32) : le32toh (val32)); - /* Do a host width conversion. */ - val = val32; - break; - case 64:; - uint64_t val64 = read_8ubyte_unaligned_noncvt (reg_desc); - reg_desc += sizeof val64; - val64 = (elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB - ? be64toh (val64) : le64toh (val64)); - assert (sizeof (*thread->unwound->regs) == sizeof val64); - val = val64; - break; - default: - abort (); - } - /* Registers not valid for CFI are just ignored. */ - if (regno < nregs) - INTUSE(dwfl_thread_state_registers) (thread, regno, 1, &val); - if (regloc->pc_register) - INTUSE(dwfl_thread_state_register_pc) (thread, val); - reg_desc += regloc->pad; - } - } - return true; -} - -static void -core_detach (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg) -{ - struct core_arg *core_arg = dwfl_arg; - ebl_closebackend (core_arg->ebl); - free (core_arg); -} - -static const Dwfl_Thread_Callbacks core_thread_callbacks = -{ - core_next_thread, - NULL, /* get_thread */ - core_memory_read, - core_set_initial_registers, - core_detach, - NULL, /* core_thread_detach */ -}; - -int -dwfl_core_file_attach (Dwfl *dwfl, Elf *core) -{ - Dwfl_Error err = DWFL_E_NOERROR; - Ebl *ebl = ebl_openbackend (core); - if (ebl == NULL) - { - err = DWFL_E_LIBEBL; - fail_err: - if (dwfl->process == NULL && dwfl->attacherr == DWFL_E_NOERROR) - dwfl->attacherr = __libdwfl_canon_error (err); - __libdwfl_seterrno (err); - return -1; - } - size_t nregs = ebl_frame_nregs (ebl); - if (nregs == 0) - { - err = DWFL_E_NO_UNWIND; - fail: - ebl_closebackend (ebl); - goto fail_err; - } - GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (core, &ehdr_mem); - if (ehdr == NULL) - { - err = DWFL_E_LIBELF; - goto fail; - } - if (ehdr->e_type != ET_CORE) - { - err = DWFL_E_NO_CORE_FILE; - goto fail; - } - size_t phnum; - if (elf_getphdrnum (core, &phnum) < 0) - { - err = DWFL_E_LIBELF; - goto fail; - } - pid_t pid = -1; - Elf_Data *note_data = NULL; - for (size_t cnt = 0; cnt < phnum; ++cnt) - { - GElf_Phdr phdr_mem, *phdr = gelf_getphdr (core, cnt, &phdr_mem); - if (phdr != NULL && phdr->p_type == PT_NOTE) - { - note_data = elf_getdata_rawchunk (core, phdr->p_offset, - phdr->p_filesz, ELF_T_NHDR); - break; - } - } - if (note_data == NULL) - { - err = DWFL_E_LIBELF; - goto fail; - } - size_t offset = 0; - GElf_Nhdr nhdr; - size_t name_offset; - size_t desc_offset; - while (offset < note_data->d_size - && (offset = gelf_getnote (note_data, offset, - &nhdr, &name_offset, &desc_offset)) > 0) - { - /* Do not check NAME for now, help broken Linux kernels. */ - const char *name = note_data->d_buf + name_offset; - const char *desc = note_data->d_buf + desc_offset; - GElf_Word regs_offset; - size_t nregloc; - const Ebl_Register_Location *reglocs; - size_t nitems; - const Ebl_Core_Item *items; - if (! ebl_core_note (ebl, &nhdr, name, - ®s_offset, &nregloc, ®locs, &nitems, &items)) - { - /* This note may be just not recognized, skip it. */ - continue; - } - if (nhdr.n_type != NT_PRPSINFO) - continue; - const Ebl_Core_Item *item; - for (item = items; item < items + nitems; item++) - if (strcmp (item->name, "pid") == 0) - break; - if (item == items + nitems) - continue; - uint32_t val32 = read_4ubyte_unaligned_noncvt (desc + item->offset); - val32 = (elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB - ? be32toh (val32) : le32toh (val32)); - pid = (int32_t) val32; - eu_static_assert (sizeof val32 <= sizeof pid); - break; - } - if (pid == -1) - { - /* No valid NT_PRPSINFO recognized in this CORE. */ - err = DWFL_E_BADELF; - goto fail; - } - struct core_arg *core_arg = malloc (sizeof *core_arg); - if (core_arg == NULL) - { - err = DWFL_E_NOMEM; - goto fail; - } - core_arg->core = core; - core_arg->note_data = note_data; - core_arg->thread_note_offset = 0; - core_arg->ebl = ebl; - if (! INTUSE(dwfl_attach_state) (dwfl, core, pid, &core_thread_callbacks, - core_arg)) - { - free (core_arg); - ebl_closebackend (ebl); - return -1; - } - return pid; -} -INTDEF (dwfl_core_file_attach) diff --git a/src/libdwfl/linux-kernel-modules.c b/src/libdwfl/linux-kernel-modules.c deleted file mode 100644 index 8f2dab3a..00000000 --- a/src/libdwfl/linux-kernel-modules.c +++ /dev/null @@ -1,929 +0,0 @@ -/* Standard libdwfl callbacks for debugging the running Linux kernel. - Copyright (C) 2005-2011, 2013, 2014 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -/* We include this before config.h because it can't handle _FILE_OFFSET_BITS. - Everything we need here is fine if its declarations just come first. */ - -#undef _FILE_OFFSET_BITS // Undo the damage caused by AndroidConfig.h. -#include <fts.h> - -#include <config.h> - -#include "libdwflP.h" -#include <inttypes.h> -#include <errno.h> -#include <stdio.h> -#include <stdio_ext.h> -#include <string.h> -#include <stdlib.h> -#include <sys/utsname.h> -#include <fcntl.h> -#include <unistd.h> - - -#define KERNEL_MODNAME "kernel" - -#define MODULEDIRFMT "/lib/modules/%s" - -#define KNOTESFILE "/sys/kernel/notes" -#define MODNOTESFMT "/sys/module/%s/notes" -#define KSYMSFILE "/proc/kallsyms" -#define MODULELIST "/proc/modules" -#define SECADDRDIRFMT "/sys/module/%s/sections/" -#define MODULE_SECT_NAME_LEN 32 /* Minimum any linux/module.h has had. */ - - -#if defined (USE_ZLIB) || defined (USE_BZLIB) || defined (USE_LZMA) -static const char *vmlinux_suffixes[] = - { -#ifdef USE_ZLIB - ".gz", -#endif -#ifdef USE_BZLIB - ".bz2", -#endif -#ifdef USE_LZMA - ".xz", -#endif - }; -#endif - -/* Try to open the given file as it is or under the debuginfo directory. */ -static int -try_kernel_name (Dwfl *dwfl, char **fname, bool try_debug) -{ - if (*fname == NULL) - return -1; - - /* Don't bother trying *FNAME itself here if the path will cause it to be - tried because we give its own basename as DEBUGLINK_FILE. */ - int fd = ((((dwfl->callbacks->debuginfo_path - ? *dwfl->callbacks->debuginfo_path : NULL) - ?: DEFAULT_DEBUGINFO_PATH)[0] == ':') ? -1 - : TEMP_FAILURE_RETRY (open64 (*fname, O_RDONLY))); - - if (fd < 0) - { - Dwfl_Module fakemod = { .dwfl = dwfl }; - /* First try the file's unadorned basename as DEBUGLINK_FILE, - to look for "vmlinux" files. */ - fd = INTUSE(dwfl_standard_find_debuginfo) (&fakemod, NULL, NULL, 0, - *fname, basename (*fname), 0, - &fakemod.debug.name); - if (fd < 0 && try_debug) - /* Next, let the call use the default of basename + ".debug", - to look for "vmlinux.debug" files. */ - fd = INTUSE(dwfl_standard_find_debuginfo) (&fakemod, NULL, NULL, 0, - *fname, NULL, 0, - &fakemod.debug.name); - if (fakemod.debug.name != NULL) - { - free (*fname); - *fname = fakemod.debug.name; - } - } - -#if defined (USE_ZLIB) || defined (USE_BZLIB) || defined (USE_LZMA) - if (fd < 0) - for (size_t i = 0; - i < sizeof vmlinux_suffixes / sizeof vmlinux_suffixes[0]; - ++i) - { - char *zname; - if (asprintf (&zname, "%s%s", *fname, vmlinux_suffixes[i]) > 0) - { - fd = TEMP_FAILURE_RETRY (open64 (zname, O_RDONLY)); - if (fd < 0) - free (zname); - else - { - free (*fname); - *fname = zname; - } - } - } -#endif - - if (fd < 0) - { - free (*fname); - *fname = NULL; - } - - return fd; -} - -static inline const char * -kernel_release (void) -{ - /* Cache the `uname -r` string we'll use. */ - static struct utsname utsname; - if (utsname.release[0] == '\0' && uname (&utsname) != 0) - return NULL; - return utsname.release; -} - -static int -find_kernel_elf (Dwfl *dwfl, const char *release, char **fname) -{ - if ((release[0] == '/' - ? asprintf (fname, "%s/vmlinux", release) - : asprintf (fname, "/boot/vmlinux-%s", release)) < 0) - return -1; - - int fd = try_kernel_name (dwfl, fname, true); - if (fd < 0 && release[0] != '/') - { - free (*fname); - if (asprintf (fname, MODULEDIRFMT "/vmlinux", release) < 0) - return -1; - fd = try_kernel_name (dwfl, fname, true); - } - - return fd; -} - -static int -get_release (Dwfl *dwfl, const char **release) -{ - if (dwfl == NULL) - return -1; - - const char *release_string = release == NULL ? NULL : *release; - if (release_string == NULL) - { - release_string = kernel_release (); - if (release_string == NULL) - return errno; - if (release != NULL) - *release = release_string; - } - - return 0; -} - -static int -report_kernel (Dwfl *dwfl, const char **release, - int (*predicate) (const char *module, const char *file)) -{ - int result = get_release (dwfl, release); - if (unlikely (result != 0)) - return result; - - char *fname; - int fd = find_kernel_elf (dwfl, *release, &fname); - - if (fd < 0) - result = ((predicate != NULL && !(*predicate) (KERNEL_MODNAME, NULL)) - ? 0 : errno ?: ENOENT); - else - { - bool report = true; - - if (predicate != NULL) - { - /* Let the predicate decide whether to use this one. */ - int want = (*predicate) (KERNEL_MODNAME, fname); - if (want < 0) - result = errno; - report = want > 0; - } - - if (report) - { - /* Note that on some architectures (e.g. x86_64) the vmlinux - is ET_EXEC, while on others (e.g. ppc64) it is ET_DYN. - In both cases the phdr p_vaddr load address will be non-zero. - We want the image to be placed as if it was ET_DYN, so - pass true for add_p_vaddr which will do the right thing - (in combination with a zero base) in either case. */ - Dwfl_Module *mod = INTUSE(dwfl_report_elf) (dwfl, KERNEL_MODNAME, - fname, fd, 0, true); - if (mod == NULL) - result = -1; - else - /* The kernel is ET_EXEC, but always treat it as relocatable. */ - mod->e_type = ET_DYN; - } - - free (fname); - - if (!report || result < 0) - close (fd); - } - - return result; -} - -/* Look for a kernel debug archive. If we find one, report all its modules. - If not, return ENOENT. */ -static int -report_kernel_archive (Dwfl *dwfl, const char **release, - int (*predicate) (const char *module, const char *file)) -{ - int result = get_release (dwfl, release); - if (unlikely (result != 0)) - return result; - - char *archive; - int res = (((*release)[0] == '/') - ? asprintf (&archive, "%s/debug.a", *release) - : asprintf (&archive, MODULEDIRFMT "/debug.a", *release)); - if (unlikely (res < 0)) - return ENOMEM; - - int fd = try_kernel_name (dwfl, &archive, false); - if (fd < 0) - result = errno ?: ENOENT; - else - { - /* We have the archive file open! */ - Dwfl_Module *last = __libdwfl_report_offline (dwfl, NULL, archive, fd, - true, predicate); - if (unlikely (last == NULL)) - result = -1; - else - { - /* Find the kernel and move it to the head of the list. */ - Dwfl_Module **tailp = &dwfl->modulelist, **prevp = tailp; - for (Dwfl_Module *m = *prevp; m != NULL; m = *(prevp = &m->next)) - if (!m->gc && m->e_type != ET_REL && !strcmp (m->name, "kernel")) - { - *prevp = m->next; - m->next = *tailp; - *tailp = m; - break; - } - } - } - - free (archive); - return result; -} - -static size_t -check_suffix (const FTSENT *f, size_t namelen) -{ -#define TRY(sfx) \ - if ((namelen ? f->fts_namelen == namelen + sizeof sfx - 1 \ - : f->fts_namelen >= sizeof sfx) \ - && !memcmp (f->fts_name + f->fts_namelen - (sizeof sfx - 1), \ - sfx, sizeof sfx)) \ - return sizeof sfx - 1 - - TRY (".ko"); -#if USE_ZLIB - TRY (".ko.gz"); -#endif -#if USE_BZLIB - TRY (".ko.bz2"); -#endif -#if USE_LZMA - TRY (".ko.xz"); -#endif - - return 0; - -#undef TRY -} - -/* Report a kernel and all its modules found on disk, for offline use. - If RELEASE starts with '/', it names a directory to look in; - if not, it names a directory to find under /lib/modules/; - if null, /lib/modules/`uname -r` is used. - Returns zero on success, -1 if dwfl_report_module failed, - or an errno code if finding the files on disk failed. */ -int -dwfl_linux_kernel_report_offline (Dwfl *dwfl, const char *release, - int (*predicate) (const char *module, - const char *file)) -{ - int result = report_kernel_archive (dwfl, &release, predicate); - if (result != ENOENT) - return result; - - /* First report the kernel. */ - result = report_kernel (dwfl, &release, predicate); - if (result == 0) - { - /* Do "find /lib/modules/RELEASE -name *.ko". */ - - char *modulesdir[] = { NULL, NULL }; - if (release[0] == '/') - modulesdir[0] = (char *) release; - else - { - if (asprintf (&modulesdir[0], MODULEDIRFMT, release) < 0) - return errno; - } - - FTS *fts = fts_open (modulesdir, FTS_NOSTAT | FTS_LOGICAL, NULL); - if (modulesdir[0] == (char *) release) - modulesdir[0] = NULL; - if (fts == NULL) - { - free (modulesdir[0]); - return errno; - } - - FTSENT *f; - while ((f = fts_read (fts)) != NULL) - { - /* Skip a "source" subtree, which tends to be large. - This insane hard-coding of names is what depmod does too. */ - if (f->fts_namelen == sizeof "source" - 1 - && !strcmp (f->fts_name, "source")) - { - fts_set (fts, f, FTS_SKIP); - continue; - } - - switch (f->fts_info) - { - case FTS_F: - case FTS_SL: - case FTS_NSOK:; - /* See if this file name matches "*.ko". */ - const size_t suffix = check_suffix (f, 0); - if (suffix) - { - /* We have a .ko file to report. Following the algorithm - by which the kernel makefiles set KBUILD_MODNAME, we - replace all ',' or '-' with '_' in the file name and - call that the module name. Modules could well be - built using different embedded names than their file - names. To handle that, we would have to look at the - __this_module.name contents in the module's text. */ - - char name[f->fts_namelen - suffix + 1]; - for (size_t i = 0; i < f->fts_namelen - 3U; ++i) - if (f->fts_name[i] == '-' || f->fts_name[i] == ',') - name[i] = '_'; - else - name[i] = f->fts_name[i]; - name[f->fts_namelen - suffix] = '\0'; - - if (predicate != NULL) - { - /* Let the predicate decide whether to use this one. */ - int want = (*predicate) (name, f->fts_path); - if (want < 0) - { - result = -1; - break; - } - if (!want) - continue; - } - - if (dwfl_report_offline (dwfl, name, f->fts_path, -1) == NULL) - { - result = -1; - break; - } - } - continue; - - case FTS_ERR: - case FTS_DNR: - case FTS_NS: - result = f->fts_errno; - break; - - case FTS_SLNONE: - default: - continue; - } - - /* We only get here in error cases. */ - break; - } - fts_close (fts); - free (modulesdir[0]); - } - - return result; -} -INTDEF (dwfl_linux_kernel_report_offline) - - -/* Grovel around to guess the bounds of the runtime kernel image. */ -static int -intuit_kernel_bounds (Dwarf_Addr *start, Dwarf_Addr *end, Dwarf_Addr *notes) -{ - FILE *f = fopen (KSYMSFILE, "r"); - if (f == NULL) - return errno; - - (void) __fsetlocking (f, FSETLOCKING_BYCALLER); - - *notes = 0; - - char *line = NULL; - size_t linesz = 0; - size_t n; - char *p = NULL; - const char *type; - - inline bool read_address (Dwarf_Addr *addr) - { - if ((n = getline (&line, &linesz, f)) < 1 || line[n - 2] == ']') - return false; - *addr = strtoull (line, &p, 16); - p += strspn (p, " \t"); - type = strsep (&p, " \t\n"); - if (type == NULL) - return false; - return p != NULL && p != line; - } - - int result; - do - result = read_address (start) ? 0 : -1; - while (result == 0 && strchr ("TtRr", *type) == NULL); - - if (result == 0) - { - *end = *start; - while (read_address (end)) - if (*notes == 0 && !strcmp (p, "__start_notes\n")) - *notes = *end; - - Dwarf_Addr round_kernel = sysconf (_SC_PAGE_SIZE); - *start &= -(Dwarf_Addr) round_kernel; - *end += round_kernel - 1; - *end &= -(Dwarf_Addr) round_kernel; - if (*start >= *end || *end - *start < round_kernel) - result = -1; - } - free (line); - - if (result == -1) - result = ferror_unlocked (f) ? errno : ENOEXEC; - - fclose (f); - - return result; -} - - -/* Look for a build ID note in NOTESFILE and associate the ID with MOD. */ -static int -check_notes (Dwfl_Module *mod, const char *notesfile, - Dwarf_Addr vaddr, const char *secname) -{ - int fd = open64 (notesfile, O_RDONLY); - if (fd < 0) - return 1; - - assert (sizeof (Elf32_Nhdr) == sizeof (GElf_Nhdr)); - assert (sizeof (Elf64_Nhdr) == sizeof (GElf_Nhdr)); - union - { - GElf_Nhdr nhdr; - unsigned char data[8192]; - } buf; - - ssize_t n = read (fd, buf.data, sizeof buf); - close (fd); - - if (n <= 0) - return 1; - - unsigned char *p = buf.data; - while (p < &buf.data[n]) - { - /* No translation required since we are reading the native kernel. */ - GElf_Nhdr *nhdr = (void *) p; - p += sizeof *nhdr; - unsigned char *name = p; - p += (nhdr->n_namesz + 3) & -4U; - unsigned char *bits = p; - p += (nhdr->n_descsz + 3) & -4U; - - if (p <= &buf.data[n] - && nhdr->n_type == NT_GNU_BUILD_ID - && nhdr->n_namesz == sizeof "GNU" - && !memcmp (name, "GNU", sizeof "GNU")) - { - /* Found it. For a module we must figure out its VADDR now. */ - - if (secname != NULL - && (INTUSE(dwfl_linux_kernel_module_section_address) - (mod, NULL, mod->name, 0, secname, 0, NULL, &vaddr) != 0 - || vaddr == (GElf_Addr) -1l)) - vaddr = 0; - - if (vaddr != 0) - vaddr += bits - buf.data; - return INTUSE(dwfl_module_report_build_id) (mod, bits, - nhdr->n_descsz, vaddr); - } - } - - return 0; -} - -/* Look for a build ID for the kernel. */ -static int -check_kernel_notes (Dwfl_Module *kernelmod, GElf_Addr vaddr) -{ - return check_notes (kernelmod, KNOTESFILE, vaddr, NULL) < 0 ? -1 : 0; -} - -/* Look for a build ID for a loaded kernel module. */ -static int -check_module_notes (Dwfl_Module *mod) -{ - char *dirs[2] = { NULL, NULL }; - if (asprintf (&dirs[0], MODNOTESFMT, mod->name) < 0) - return ENOMEM; - - FTS *fts = fts_open (dirs, FTS_NOSTAT | FTS_LOGICAL, NULL); - if (fts == NULL) - { - free (dirs[0]); - return 0; - } - - int result = 0; - FTSENT *f; - while ((f = fts_read (fts)) != NULL) - { - switch (f->fts_info) - { - case FTS_F: - case FTS_SL: - case FTS_NSOK: - result = check_notes (mod, f->fts_accpath, 0, f->fts_name); - if (result > 0) /* Nothing found. */ - { - result = 0; - continue; - } - break; - - case FTS_ERR: - case FTS_DNR: - result = f->fts_errno; - break; - - case FTS_NS: - case FTS_SLNONE: - default: - continue; - } - - /* We only get here when finished or in error cases. */ - break; - } - fts_close (fts); - free (dirs[0]); - - return result; -} - -int -dwfl_linux_kernel_report_kernel (Dwfl *dwfl) -{ - Dwarf_Addr start; - Dwarf_Addr end; - inline Dwfl_Module *report (void) - { - return INTUSE(dwfl_report_module) (dwfl, KERNEL_MODNAME, start, end); - } - - /* This is a bit of a kludge. If we already reported the kernel, - don't bother figuring it out again--it never changes. */ - for (Dwfl_Module *m = dwfl->modulelist; m != NULL; m = m->next) - if (!strcmp (m->name, KERNEL_MODNAME)) - { - start = m->low_addr; - end = m->high_addr; - return report () == NULL ? -1 : 0; - } - - /* Try to figure out the bounds of the kernel image without - looking for any vmlinux file. */ - Dwarf_Addr notes; - /* The compiler cannot deduce that if intuit_kernel_bounds returns - zero NOTES will be initialized. Fake the initialization. */ - asm ("" : "=m" (notes)); - int result = intuit_kernel_bounds (&start, &end, ¬es); - if (result == 0) - { - Dwfl_Module *mod = report (); - return unlikely (mod == NULL) ? -1 : check_kernel_notes (mod, notes); - } - if (result != ENOENT) - return result; - - /* Find the ELF file for the running kernel and dwfl_report_elf it. */ - return report_kernel (dwfl, NULL, NULL); -} -INTDEF (dwfl_linux_kernel_report_kernel) - - -/* Dwfl_Callbacks.find_elf for the running Linux kernel and its modules. */ - -int -dwfl_linux_kernel_find_elf (Dwfl_Module *mod, - void **userdata __attribute__ ((unused)), - const char *module_name, - Dwarf_Addr base __attribute__ ((unused)), - char **file_name, Elf **elfp) -{ - if (mod->build_id_len > 0) - { - int fd = INTUSE(dwfl_build_id_find_elf) (mod, NULL, NULL, 0, - file_name, elfp); - if (fd >= 0 || mod->main.elf != NULL || errno != 0) - return fd; - } - - const char *release = kernel_release (); - if (release == NULL) - return errno; - - if (!strcmp (module_name, KERNEL_MODNAME)) - return find_kernel_elf (mod->dwfl, release, file_name); - - /* Do "find /lib/modules/`uname -r` -name MODULE_NAME.ko". */ - - char *modulesdir[] = { NULL, NULL }; - if (asprintf (&modulesdir[0], MODULEDIRFMT, release) < 0) - return -1; - - FTS *fts = fts_open (modulesdir, FTS_NOSTAT | FTS_LOGICAL, NULL); - if (fts == NULL) - { - free (modulesdir[0]); - return -1; - } - - size_t namelen = strlen (module_name); - - /* This is a kludge. There is no actual necessary relationship between - the name of the .ko file installed and the module name the kernel - knows it by when it's loaded. The kernel's only idea of the module - name comes from the name embedded in the object's magic - .gnu.linkonce.this_module section. - - In practice, these module names match the .ko file names except for - some using '_' and some using '-'. So our cheap kludge is to look for - two files when either a '_' or '-' appears in a module name, one using - only '_' and one only using '-'. */ - - char alternate_name[namelen + 1]; - inline bool subst_name (char from, char to) - { - const char *n = memchr (module_name, from, namelen); - if (n == NULL) - return false; - char *a = mempcpy (alternate_name, module_name, n - module_name); - *a++ = to; - ++n; - const char *p; - while ((p = memchr (n, from, namelen - (n - module_name))) != NULL) - { - a = mempcpy (a, n, p - n); - *a++ = to; - n = p + 1; - } - memcpy (a, n, namelen - (n - module_name) + 1); - return true; - } - if (!subst_name ('-', '_') && !subst_name ('_', '-')) - alternate_name[0] = '\0'; - - FTSENT *f; - int error = ENOENT; - while ((f = fts_read (fts)) != NULL) - { - /* Skip a "source" subtree, which tends to be large. - This insane hard-coding of names is what depmod does too. */ - if (f->fts_namelen == sizeof "source" - 1 - && !strcmp (f->fts_name, "source")) - { - fts_set (fts, f, FTS_SKIP); - continue; - } - - error = ENOENT; - switch (f->fts_info) - { - case FTS_F: - case FTS_SL: - case FTS_NSOK: - /* See if this file name is "MODULE_NAME.ko". */ - if (check_suffix (f, namelen) - && (!memcmp (f->fts_name, module_name, namelen) - || !memcmp (f->fts_name, alternate_name, namelen))) - { - int fd = open64 (f->fts_accpath, O_RDONLY); - *file_name = strdup (f->fts_path); - fts_close (fts); - free (modulesdir[0]); - if (fd < 0) - free (*file_name); - else if (*file_name == NULL) - { - close (fd); - fd = -1; - } - return fd; - } - break; - - case FTS_ERR: - case FTS_DNR: - case FTS_NS: - error = f->fts_errno; - break; - - case FTS_SLNONE: - default: - break; - } - } - - fts_close (fts); - free (modulesdir[0]); - errno = error; - return -1; -} -INTDEF (dwfl_linux_kernel_find_elf) - - -/* Dwfl_Callbacks.section_address for kernel modules in the running Linux. - We read the information from /sys/module directly. */ - -int -dwfl_linux_kernel_module_section_address -(Dwfl_Module *mod __attribute__ ((unused)), - void **userdata __attribute__ ((unused)), - const char *modname, Dwarf_Addr base __attribute__ ((unused)), - const char *secname, Elf32_Word shndx __attribute__ ((unused)), - const GElf_Shdr *shdr __attribute__ ((unused)), - Dwarf_Addr *addr) -{ - char *sysfile; - if (asprintf (&sysfile, SECADDRDIRFMT "%s", modname, secname) < 0) - return DWARF_CB_ABORT; - - FILE *f = fopen (sysfile, "r"); - free (sysfile); - - if (f == NULL) - { - if (errno == ENOENT) - { - /* The .modinfo and .data.percpu sections are never kept - loaded in the kernel. If the kernel was compiled without - CONFIG_MODULE_UNLOAD, the .exit.* sections are not - actually loaded at all. - - Setting *ADDR to -1 tells the caller this section is - actually absent from memory. */ - - if (!strcmp (secname, ".modinfo") - || !strcmp (secname, ".data.percpu") - || !strncmp (secname, ".exit", 5)) - { - *addr = (Dwarf_Addr) -1l; - return DWARF_CB_OK; - } - - /* The goofy PPC64 module_frob_arch_sections function tweaks - the section names as a way to control other kernel code's - behavior, and this cruft leaks out into the /sys information. - The file name for ".init*" may actually look like "_init*". */ - - const bool is_init = !strncmp (secname, ".init", 5); - if (is_init) - { - if (asprintf (&sysfile, SECADDRDIRFMT "_%s", - modname, &secname[1]) < 0) - return ENOMEM; - f = fopen (sysfile, "r"); - free (sysfile); - if (f != NULL) - goto ok; - } - - /* The kernel truncates section names to MODULE_SECT_NAME_LEN - 1. - In case that size increases in the future, look for longer - truncated names first. */ - size_t namelen = strlen (secname); - if (namelen >= MODULE_SECT_NAME_LEN) - { - int len = asprintf (&sysfile, SECADDRDIRFMT "%s", - modname, secname); - if (len < 0) - return DWARF_CB_ABORT; - char *end = sysfile + len; - do - { - *--end = '\0'; - f = fopen (sysfile, "r"); - if (is_init && f == NULL && errno == ENOENT) - { - sysfile[len - namelen] = '_'; - f = fopen (sysfile, "r"); - sysfile[len - namelen] = '.'; - } - } - while (f == NULL && errno == ENOENT - && end - &sysfile[len - namelen] >= MODULE_SECT_NAME_LEN); - free (sysfile); - - if (f != NULL) - goto ok; - } - } - - return DWARF_CB_ABORT; - } - - ok: - (void) __fsetlocking (f, FSETLOCKING_BYCALLER); - - int result = (fscanf (f, "%" PRIx64 "\n", addr) == 1 ? 0 - : ferror_unlocked (f) ? errno : ENOEXEC); - fclose (f); - - if (result == 0) - return DWARF_CB_OK; - - errno = result; - return DWARF_CB_ABORT; -} -INTDEF (dwfl_linux_kernel_module_section_address) - -int -dwfl_linux_kernel_report_modules (Dwfl *dwfl) -{ - FILE *f = fopen (MODULELIST, "r"); - if (f == NULL) - return errno; - - (void) __fsetlocking (f, FSETLOCKING_BYCALLER); - - int result = 0; - Dwarf_Addr modaddr; - unsigned long int modsz; - char modname[128]; - char *line = NULL; - size_t linesz = 0; - /* We can't just use fscanf here because it's not easy to distinguish \n - from other whitespace so as to take the optional word following the - address but always stop at the end of the line. */ - while (getline (&line, &linesz, f) > 0 - && sscanf (line, "%128s %lu %*s %*s %*s %" PRIx64 " %*s\n", - modname, &modsz, &modaddr) == 3) - { - Dwfl_Module *mod = INTUSE(dwfl_report_module) (dwfl, modname, - modaddr, modaddr + modsz); - if (mod == NULL) - { - result = -1; - break; - } - - result = check_module_notes (mod); - } - free (line); - - if (result == 0) - result = ferror_unlocked (f) ? errno : feof_unlocked (f) ? 0 : ENOEXEC; - - fclose (f); - - return result; -} -INTDEF (dwfl_linux_kernel_report_modules) diff --git a/src/libdwfl/linux-pid-attach.c b/src/libdwfl/linux-pid-attach.c deleted file mode 100644 index ae717028..00000000 --- a/src/libdwfl/linux-pid-attach.c +++ /dev/null @@ -1,475 +0,0 @@ -/* Get Dwarf Frame state for target live PID process. - Copyright (C) 2013, 2014 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" -#include <sys/ptrace.h> -#include <sys/wait.h> -#include <dirent.h> -#include <sys/syscall.h> -#include <unistd.h> - -#ifndef MAX -# define MAX(a, b) ((a) > (b) ? (a) : (b)) -#endif - -#ifdef __linux__ - -static bool -linux_proc_pid_is_stopped (pid_t pid) -{ - char buffer[64]; - FILE *procfile; - bool retval, have_state; - - snprintf (buffer, sizeof (buffer), "/proc/%ld/status", (long) pid); - procfile = fopen (buffer, "r"); - if (procfile == NULL) - return false; - - have_state = false; - while (fgets (buffer, sizeof (buffer), procfile) != NULL) - if (strncmp (buffer, "State:", 6) == 0) - { - have_state = true; - break; - } - retval = (have_state && strstr (buffer, "T (stopped)") != NULL); - fclose (procfile); - return retval; -} - -bool -internal_function -__libdwfl_ptrace_attach (pid_t tid, bool *tid_was_stoppedp) -{ - if (ptrace (PTRACE_ATTACH, tid, NULL, NULL) != 0) - { - __libdwfl_seterrno (DWFL_E_ERRNO); - return false; - } - *tid_was_stoppedp = linux_proc_pid_is_stopped (tid); - if (*tid_was_stoppedp) - { - /* Make sure there is a SIGSTOP signal pending even when the process is - already State: T (stopped). Older kernels might fail to generate - a SIGSTOP notification in that case in response to our PTRACE_ATTACH - above. Which would make the waitpid below wait forever. So emulate - it. Since there can only be one SIGSTOP notification pending this is - safe. See also gdb/linux-nat.c linux_nat_post_attach_wait. */ - syscall (__NR_tkill, tid, SIGSTOP); - ptrace (PTRACE_CONT, tid, NULL, NULL); - } - for (;;) - { - int status; - if (waitpid (tid, &status, __WALL) != tid || !WIFSTOPPED (status)) - { - int saved_errno = errno; - ptrace (PTRACE_DETACH, tid, NULL, NULL); - errno = saved_errno; - __libdwfl_seterrno (DWFL_E_ERRNO); - return false; - } - if (WSTOPSIG (status) == SIGSTOP) - break; - if (ptrace (PTRACE_CONT, tid, NULL, - (void *) (uintptr_t) WSTOPSIG (status)) != 0) - { - int saved_errno = errno; - ptrace (PTRACE_DETACH, tid, NULL, NULL); - errno = saved_errno; - __libdwfl_seterrno (DWFL_E_ERRNO); - return false; - } - } - return true; -} - -static bool -pid_memory_read (Dwfl *dwfl, Dwarf_Addr addr, Dwarf_Word *result, void *arg) -{ - struct __libdwfl_pid_arg *pid_arg = arg; - pid_t tid = pid_arg->tid_attached; - assert (tid > 0); - Dwfl_Process *process = dwfl->process; - if (ebl_get_elfclass (process->ebl) == ELFCLASS64) - { -#if SIZEOF_LONG == 8 - errno = 0; - *result = ptrace (PTRACE_PEEKDATA, tid, (void *) (uintptr_t) addr, NULL); - return errno == 0; -#else /* SIZEOF_LONG != 8 */ - /* This should not happen. */ - return false; -#endif /* SIZEOF_LONG != 8 */ - } -#if SIZEOF_LONG == 8 - /* We do not care about reads unaliged to 4 bytes boundary. - But 0x...ffc read of 8 bytes could overrun a page. */ - bool lowered = (addr & 4) != 0; - if (lowered) - addr -= 4; -#endif /* SIZEOF_LONG == 8 */ - errno = 0; - *result = ptrace (PTRACE_PEEKDATA, tid, (void *) (uintptr_t) addr, NULL); - if (errno != 0) - return false; -#if SIZEOF_LONG == 8 -# if BYTE_ORDER == BIG_ENDIAN - if (! lowered) - *result >>= 32; -# else - if (lowered) - *result >>= 32; -# endif -#endif /* SIZEOF_LONG == 8 */ - *result &= 0xffffffff; - return true; -} - -static pid_t -pid_next_thread (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg, - void **thread_argp) -{ - struct __libdwfl_pid_arg *pid_arg = dwfl_arg; - struct dirent *dirent; - /* Start fresh on first traversal. */ - if (*thread_argp == NULL) - rewinddir (pid_arg->dir); - do - { - errno = 0; - dirent = readdir (pid_arg->dir); - if (dirent == NULL) - { - if (errno != 0) - { - __libdwfl_seterrno (DWFL_E_ERRNO); - return -1; - } - return 0; - } - } - while (strcmp (dirent->d_name, ".") == 0 - || strcmp (dirent->d_name, "..") == 0); - char *end; - errno = 0; - long tidl = strtol (dirent->d_name, &end, 10); - if (errno != 0) - { - __libdwfl_seterrno (DWFL_E_ERRNO); - return -1; - } - pid_t tid = tidl; - if (tidl <= 0 || (end && *end) || tid != tidl) - { - __libdwfl_seterrno (DWFL_E_PARSE_PROC); - return -1; - } - *thread_argp = dwfl_arg; - return tid; -} - -/* Just checks that the thread id exists. */ -static bool -pid_getthread (Dwfl *dwfl __attribute__ ((unused)), pid_t tid, - void *dwfl_arg, void **thread_argp) -{ - *thread_argp = dwfl_arg; - if (kill (tid, 0) < 0) - { - __libdwfl_seterrno (DWFL_E_ERRNO); - return false; - } - return true; -} - -/* Implement the ebl_set_initial_registers_tid setfunc callback. */ - -static bool -pid_thread_state_registers_cb (int firstreg, unsigned nregs, - const Dwarf_Word *regs, void *arg) -{ - Dwfl_Thread *thread = (Dwfl_Thread *) arg; - if (firstreg < 0) - { - assert (firstreg == -1); - assert (nregs == 1); - INTUSE(dwfl_thread_state_register_pc) (thread, *regs); - return true; - } - assert (nregs > 0); - return INTUSE(dwfl_thread_state_registers) (thread, firstreg, nregs, regs); -} - -static bool -pid_set_initial_registers (Dwfl_Thread *thread, void *thread_arg) -{ - struct __libdwfl_pid_arg *pid_arg = thread_arg; - assert (pid_arg->tid_attached == 0); - pid_t tid = INTUSE(dwfl_thread_tid) (thread); - if (! pid_arg->assume_ptrace_stopped - && ! __libdwfl_ptrace_attach (tid, &pid_arg->tid_was_stopped)) - return false; - pid_arg->tid_attached = tid; - Dwfl_Process *process = thread->process; - Ebl *ebl = process->ebl; - return ebl_set_initial_registers_tid (ebl, tid, - pid_thread_state_registers_cb, thread); -} - -static void -pid_detach (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg) -{ - struct __libdwfl_pid_arg *pid_arg = dwfl_arg; - closedir (pid_arg->dir); - free (pid_arg); -} - -void -internal_function -__libdwfl_ptrace_detach (pid_t tid, bool tid_was_stopped) -{ - /* This handling is needed only on older Linux kernels such as - 2.6.32-358.23.2.el6.ppc64. Later kernels such as - 3.11.7-200.fc19.x86_64 remember the T (stopped) state - themselves and no longer need to pass SIGSTOP during - PTRACE_DETACH. */ - ptrace (PTRACE_DETACH, tid, NULL, - (void *) (intptr_t) (tid_was_stopped ? SIGSTOP : 0)); -} - -static void -pid_thread_detach (Dwfl_Thread *thread, void *thread_arg) -{ - struct __libdwfl_pid_arg *pid_arg = thread_arg; - pid_t tid = INTUSE(dwfl_thread_tid) (thread); - assert (pid_arg->tid_attached == tid); - pid_arg->tid_attached = 0; - if (! pid_arg->assume_ptrace_stopped) - __libdwfl_ptrace_detach (tid, pid_arg->tid_was_stopped); -} - -static const Dwfl_Thread_Callbacks pid_thread_callbacks = -{ - pid_next_thread, - pid_getthread, - pid_memory_read, - pid_set_initial_registers, - pid_detach, - pid_thread_detach, -}; - -int -dwfl_linux_proc_attach (Dwfl *dwfl, pid_t pid, bool assume_ptrace_stopped) -{ - char buffer[36]; - FILE *procfile; - int err = 0; /* The errno to return and set for dwfl->attcherr. */ - - /* Make sure to report the actual PID (thread group leader) to - dwfl_attach_state. */ - snprintf (buffer, sizeof (buffer), "/proc/%ld/status", (long) pid); - procfile = fopen (buffer, "r"); - if (procfile == NULL) - { - err = errno; - fail: - if (dwfl->process == NULL && dwfl->attacherr == DWFL_E_NOERROR) - { - errno = err; - dwfl->attacherr = __libdwfl_canon_error (DWFL_E_ERRNO); - } - return err; - } - - char *line = NULL; - size_t linelen = 0; - while (getline (&line, &linelen, procfile) >= 0) - if (strncmp (line, "Tgid:", 5) == 0) - { - errno = 0; - char *endptr; - long val = strtol (&line[5], &endptr, 10); - if ((errno == ERANGE && val == LONG_MAX) - || *endptr != '\n' || val < 0 || val != (pid_t) val) - pid = 0; - else - pid = (pid_t) val; - break; - } - free (line); - fclose (procfile); - - if (pid == 0) - { - err = ESRCH; - goto fail; - } - - char dirname[64]; - int i = snprintf (dirname, sizeof (dirname), "/proc/%ld/task", (long) pid); - assert (i > 0 && i < (ssize_t) sizeof (dirname) - 1); - DIR *dir = opendir (dirname); - if (dir == NULL) - { - err = errno; - goto fail; - } - struct __libdwfl_pid_arg *pid_arg = malloc (sizeof *pid_arg); - if (pid_arg == NULL) - { - closedir (dir); - err = ENOMEM; - goto fail; - } - pid_arg->dir = dir; - pid_arg->tid_attached = 0; - pid_arg->assume_ptrace_stopped = assume_ptrace_stopped; - if (! INTUSE(dwfl_attach_state) (dwfl, NULL, pid, &pid_thread_callbacks, - pid_arg)) - { - closedir (dir); - free (pid_arg); - return -1; - } - return 0; -} -INTDEF (dwfl_linux_proc_attach) - -struct __libdwfl_pid_arg * -internal_function -__libdwfl_get_pid_arg (Dwfl *dwfl) -{ - if (dwfl != NULL && dwfl->process != NULL - && dwfl->process->callbacks == &pid_thread_callbacks) - return (struct __libdwfl_pid_arg *) dwfl->process->callbacks_arg; - - return NULL; -} - -#else /* __linux__ */ - -static pid_t -pid_next_thread (Dwfl *dwfl __attribute__ ((unused)), - void *dwfl_arg __attribute__ ((unused)), - void **thread_argp __attribute__ ((unused))) -{ - errno = ENOSYS; - __libdwfl_seterrno (DWFL_E_ERRNO); - return -1; -} - -static bool -pid_getthread (Dwfl *dwfl __attribute__ ((unused)), - pid_t tid __attribute__ ((unused)), - void *dwfl_arg __attribute__ ((unused)), - void **thread_argp __attribute__ ((unused))) -{ - errno = ENOSYS; - __libdwfl_seterrno (DWFL_E_ERRNO); - return false; -} - -bool -internal_function -__libdwfl_ptrace_attach (pid_t tid __attribute__ ((unused)), - bool *tid_was_stoppedp __attribute__ ((unused))) -{ - errno = ENOSYS; - __libdwfl_seterrno (DWFL_E_ERRNO); - return false; -} - -static bool -pid_memory_read (Dwfl *dwfl __attribute__ ((unused)), - Dwarf_Addr addr __attribute__ ((unused)), - Dwarf_Word *result __attribute__ ((unused)), - void *arg __attribute__ ((unused))) -{ - errno = ENOSYS; - __libdwfl_seterrno (DWFL_E_ERRNO); - return false; -} - -static bool -pid_set_initial_registers (Dwfl_Thread *thread __attribute__ ((unused)), - void *thread_arg __attribute__ ((unused))) -{ - errno = ENOSYS; - __libdwfl_seterrno (DWFL_E_ERRNO); - return false; -} - -static void -pid_detach (Dwfl *dwfl __attribute__ ((unused)), - void *dwfl_arg __attribute__ ((unused))) -{ -} - -void -internal_function -__libdwfl_ptrace_detach (pid_t tid __attribute__ ((unused)), - bool tid_was_stopped __attribute__ ((unused))) -{ -} - -static void -pid_thread_detach (Dwfl_Thread *thread __attribute__ ((unused)), - void *thread_arg __attribute__ ((unused))) -{ -} - -static const Dwfl_Thread_Callbacks pid_thread_callbacks = -{ - pid_next_thread, - pid_getthread, - pid_memory_read, - pid_set_initial_registers, - pid_detach, - pid_thread_detach, -}; - -int -dwfl_linux_proc_attach (Dwfl *dwfl __attribute__ ((unused)), - pid_t pid __attribute__ ((unused)), - bool assume_ptrace_stopped __attribute__ ((unused))) -{ - return ENOSYS; -} -INTDEF (dwfl_linux_proc_attach) - -struct __libdwfl_pid_arg * -internal_function -__libdwfl_get_pid_arg (Dwfl *dwfl __attribute__ ((unused))) -{ - return NULL; -} - -#endif /* ! __linux __ */ - diff --git a/src/libdwfl/linux-proc-maps.c b/src/libdwfl/linux-proc-maps.c deleted file mode 100644 index d0858342..00000000 --- a/src/libdwfl/linux-proc-maps.c +++ /dev/null @@ -1,422 +0,0 @@ -/* Standard libdwfl callbacks for debugging a live Linux process. - Copyright (C) 2005-2010, 2013, 2014 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" -#include <inttypes.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <errno.h> -#include <stdio.h> -#include <stdio_ext.h> -#include <stdbool.h> -#include <string.h> -#include <stdlib.h> -#include <fcntl.h> -#include <unistd.h> -#include <assert.h> -#include <endian.h> -#include "system.h" - - -#define PROCMAPSFMT "/proc/%d/maps" -#define PROCMEMFMT "/proc/%d/mem" -#define PROCAUXVFMT "/proc/%d/auxv" -#define PROCEXEFMT "/proc/%d/exe" - - -/* Return ELFCLASS64 or ELFCLASS32 for the main ELF executable. Return - ELFCLASSNONE for an error. */ - -static unsigned char -get_pid_class (pid_t pid) -{ - char *fname; - if (asprintf (&fname, PROCEXEFMT, pid) < 0) - return ELFCLASSNONE; - - int fd = open64 (fname, O_RDONLY); - free (fname); - if (fd < 0) - return ELFCLASSNONE; - - unsigned char buf[EI_CLASS + 1]; - ssize_t nread = pread_retry (fd, &buf, sizeof buf, 0); - close (fd); - if (nread != sizeof buf || buf[EI_MAG0] != ELFMAG0 - || buf[EI_MAG1] != ELFMAG1 || buf[EI_MAG2] != ELFMAG2 - || buf[EI_MAG3] != ELFMAG3 - || (buf[EI_CLASS] != ELFCLASS64 && buf[EI_CLASS] != ELFCLASS32)) - return ELFCLASSNONE; - - return buf[EI_CLASS]; -} - -/* Search /proc/PID/auxv for the AT_SYSINFO_EHDR tag. - - It would be easiest to call get_pid_class and parse everything according to - the 32-bit or 64-bit class. But this would bring the overhead of syscalls - to open and read the "/proc/%d/exe" file. - - Therefore this function tries to parse the "/proc/%d/auxv" content both - ways, as if it were the 32-bit format and also if it were the 64-bit format. - Only if it gives some valid data in both cases get_pid_class gets called. - In most cases only one of the format bit sizes gives valid data and the - get_pid_class call overhead can be saved. */ - -static int -grovel_auxv (pid_t pid, Dwfl *dwfl, GElf_Addr *sysinfo_ehdr) -{ - char *fname; - if (asprintf (&fname, PROCAUXVFMT, pid) < 0) - return ENOMEM; - - int fd = open64 (fname, O_RDONLY); - free (fname); - if (fd < 0) - return errno == ENOENT ? 0 : errno; - - GElf_Addr sysinfo_ehdr64 = 0; - GElf_Addr sysinfo_ehdr32 = 0; - GElf_Addr segment_align64 = dwfl->segment_align; - GElf_Addr segment_align32 = dwfl->segment_align; - off_t offset = 0; - ssize_t nread; - union - { - Elf64_auxv_t a64[64]; - Elf32_auxv_t a32[128]; - } d; - do - { - eu_static_assert (sizeof d.a64 == sizeof d.a32); - nread = pread_retry (fd, d.a64, sizeof d.a64, offset); - if (nread < 0) - { - int ret = errno; - close (fd); - return ret; - } - for (size_t a32i = 0; a32i < nread / sizeof d.a32[0]; a32i++) - { - const Elf32_auxv_t *a32 = d.a32 + a32i; - switch (a32->a_type) - { - case AT_SYSINFO_EHDR: - sysinfo_ehdr32 = a32->a_un.a_val; - break; - case AT_PAGESZ: - segment_align32 = a32->a_un.a_val; - break; - } - } - for (size_t a64i = 0; a64i < nread / sizeof d.a64[0]; a64i++) - { - const Elf64_auxv_t *a64 = d.a64 + a64i; - switch (a64->a_type) - { - case AT_SYSINFO_EHDR: - sysinfo_ehdr64 = a64->a_un.a_val; - break; - case AT_PAGESZ: - segment_align64 = a64->a_un.a_val; - break; - } - } - offset += nread; - } - while (nread == sizeof d.a64); - - close (fd); - - bool valid64 = sysinfo_ehdr64 != 0 || segment_align64 != dwfl->segment_align; - bool valid32 = sysinfo_ehdr32 != 0 || segment_align32 != dwfl->segment_align; - - unsigned char pid_class = ELFCLASSNONE; - if (valid64 && valid32) - pid_class = get_pid_class (pid); - - if (pid_class == ELFCLASS64 || (valid64 && ! valid32)) - { - *sysinfo_ehdr = sysinfo_ehdr64; - dwfl->segment_align = segment_align64; - return 0; - } - if (pid_class == ELFCLASS32 || (! valid64 && valid32)) - { - *sysinfo_ehdr = sysinfo_ehdr32; - dwfl->segment_align = segment_align32; - return 0; - } - return ENOEXEC; -} - -static int -proc_maps_report (Dwfl *dwfl, FILE *f, GElf_Addr sysinfo_ehdr, pid_t pid) -{ - unsigned int last_dmajor = -1, last_dminor = -1; - uint64_t last_ino = -1; - char *last_file = NULL; - Dwarf_Addr low = 0, high = 0; - - inline bool report (void) - { - if (last_file != NULL) - { - Dwfl_Module *mod = INTUSE(dwfl_report_module) (dwfl, last_file, - low, high); - free (last_file); - last_file = NULL; - if (unlikely (mod == NULL)) - return true; - } - return false; - } - - char *line = NULL; - size_t linesz; - ssize_t len; - while ((len = getline (&line, &linesz, f)) > 0) - { - if (line[len - 1] == '\n') - line[len - 1] = '\0'; - - Dwarf_Addr start, end, offset; - unsigned int dmajor, dminor; - uint64_t ino; - int nread = -1; - if (sscanf (line, "%" PRIx64 "-%" PRIx64 " %*s %" PRIx64 - " %x:%x %" PRIi64 " %n", - &start, &end, &offset, &dmajor, &dminor, &ino, &nread) < 6 - || nread <= 0) - { - free (line); - return ENOEXEC; - } - - /* If this is the special mapping AT_SYSINFO_EHDR pointed us at, - report the last one and then this special one. */ - if (start == sysinfo_ehdr && start != 0) - { - if (report ()) - { - bad_report: - free (line); - return -1; - } - - low = start; - high = end; - if (asprintf (&last_file, "[vdso: %d]", (int) pid) < 0 - || report ()) - goto bad_report; - } - - char *file = line + nread + strspn (line + nread, " \t"); - if (file[0] != '/' || (ino == 0 && dmajor == 0 && dminor == 0)) - /* This line doesn't indicate a file mapping. */ - continue; - - if (last_file != NULL - && ino == last_ino && dmajor == last_dmajor && dminor == last_dminor) - { - /* This is another portion of the same file's mapping. */ - if (strcmp (last_file, file) != 0) - goto bad_report; - high = end; - } - else - { - /* This is a different file mapping. Report the last one. */ - if (report ()) - goto bad_report; - low = start; - high = end; - last_file = strdup (file); - last_ino = ino; - last_dmajor = dmajor; - last_dminor = dminor; - } - } - free (line); - - int result = ferror_unlocked (f) ? errno : feof_unlocked (f) ? 0 : ENOEXEC; - - /* Report the final one. */ - bool lose = report (); - - return result != 0 ? result : lose ? -1 : 0; -} - -int -dwfl_linux_proc_maps_report (Dwfl *dwfl, FILE *f) -{ - return proc_maps_report (dwfl, f, 0, 0); -} -INTDEF (dwfl_linux_proc_maps_report) - -int -dwfl_linux_proc_report (Dwfl *dwfl, pid_t pid) -{ - if (dwfl == NULL) - return -1; - - /* We'll notice the AT_SYSINFO_EHDR address specially when we hit it. */ - GElf_Addr sysinfo_ehdr = 0; - int result = grovel_auxv (pid, dwfl, &sysinfo_ehdr); - if (result != 0) - return result; - - char *fname; - if (asprintf (&fname, PROCMAPSFMT, pid) < 0) - return ENOMEM; - - FILE *f = fopen (fname, "r"); - free (fname); - if (f == NULL) - return errno; - - (void) __fsetlocking (f, FSETLOCKING_BYCALLER); - - result = proc_maps_report (dwfl, f, sysinfo_ehdr, pid); - - fclose (f); - - return result; -} -INTDEF (dwfl_linux_proc_report) - -static ssize_t -read_proc_memory (void *arg, void *data, GElf_Addr address, - size_t minread, size_t maxread) -{ - const int fd = *(const int *) arg; - ssize_t nread = pread64 (fd, data, maxread, (off64_t) address); - /* Some kernels don't actually let us do this read, ignore those errors. */ - if (nread < 0 && (errno == EINVAL || errno == EPERM)) - return 0; - if (nread > 0 && (size_t) nread < minread) - nread = 0; - return nread; -} - -extern Elf *elf_from_remote_memory (GElf_Addr ehdr_vma, - GElf_Xword pagesize, - GElf_Addr *loadbasep, - ssize_t (*read_memory) (void *arg, - void *data, - GElf_Addr address, - size_t minread, - size_t maxread), - void *arg); - - -/* Dwfl_Callbacks.find_elf */ - -int -dwfl_linux_proc_find_elf (Dwfl_Module *mod __attribute__ ((unused)), - void **userdata __attribute__ ((unused)), - const char *module_name, Dwarf_Addr base, - char **file_name, Elf **elfp) -{ - int pid = -1; - if (module_name[0] == '/') - { - /* When this callback is used together with dwfl_linux_proc_report - then we might see mappings of special character devices. Make - sure we only open and return regular files. Special devices - might hang on open or read. (deleted) files are super special. - The image might come from memory if we are attached. */ - struct stat sb; - if (stat (module_name, &sb) == -1 || (sb.st_mode & S_IFMT) != S_IFREG) - { - if (strcmp (strrchr (module_name, ' ') ?: "", " (deleted)") == 0) - pid = INTUSE(dwfl_pid) (mod->dwfl); - else - return -1; - } - - if (pid == -1) - { - int fd = open64 (module_name, O_RDONLY); - if (fd >= 0) - { - *file_name = strdup (module_name); - if (*file_name == NULL) - { - close (fd); - return ENOMEM; - } - } - return fd; - } - } - - if (pid != -1 || sscanf (module_name, "[vdso: %d]", &pid) == 1) - { - /* Special case for in-memory ELF image. */ - - bool detach = false; - bool tid_was_stopped = false; - struct __libdwfl_pid_arg *pid_arg = __libdwfl_get_pid_arg (mod->dwfl); - if (pid_arg != NULL && ! pid_arg->assume_ptrace_stopped) - { - /* If any thread is already attached we are fine. Read - through that thread. It doesn't have to be the main - thread pid. */ - pid_t tid = pid_arg->tid_attached; - if (tid != 0) - pid = tid; - else - detach = __libdwfl_ptrace_attach (pid, &tid_was_stopped); - } - - char *fname; - if (asprintf (&fname, PROCMEMFMT, pid) < 0) - goto detach; - - int fd = open64 (fname, O_RDONLY); - free (fname); - if (fd < 0) - goto detach; - - *elfp = elf_from_remote_memory (base, getpagesize (), NULL, - &read_proc_memory, &fd); - - close (fd); - - *file_name = NULL; - - detach: - if (detach) - __libdwfl_ptrace_detach (pid, tid_was_stopped); - return -1; - } - - return -1; -} -INTDEF (dwfl_linux_proc_find_elf) diff --git a/src/libdwfl/lzma.c b/src/libdwfl/lzma.c deleted file mode 100644 index 3edfdc22..00000000 --- a/src/libdwfl/lzma.c +++ /dev/null @@ -1,4 +0,0 @@ -/* liblzma is pretty close to zlib and bzlib. */ - -#define LZMA -#include "gzip.c" diff --git a/src/libdwfl/offline.c b/src/libdwfl/offline.c deleted file mode 100644 index 982ceab0..00000000 --- a/src/libdwfl/offline.c +++ /dev/null @@ -1,311 +0,0 @@ -/* Recover relocatibility for addresses computed from debug information. - Copyright (C) 2005-2009, 2012 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" -#include <fcntl.h> -#include <unistd.h> - -/* Since dwfl_report_elf lays out the sections already, this will only be - called when the section headers of the debuginfo file are being - consulted instead, or for the section placed at 0. With binutils - strip-to-debug, the symbol table is in the debuginfo file and relocation - looks there. */ -int -dwfl_offline_section_address (Dwfl_Module *mod, - void **userdata __attribute__ ((unused)), - const char *modname __attribute__ ((unused)), - Dwarf_Addr base __attribute__ ((unused)), - const char *secname __attribute__ ((unused)), - Elf32_Word shndx, - const GElf_Shdr *shdr __attribute__ ((unused)), - Dwarf_Addr *addr) -{ - assert (mod->e_type == ET_REL); - assert (shdr->sh_addr == 0); - assert (shdr->sh_flags & SHF_ALLOC); - assert (shndx != 0); - - if (mod->debug.elf == NULL) - /* We are only here because sh_addr is zero even though layout is complete. - The first section in the first file under -e is placed at 0. */ - return 0; - - /* The section numbers might not match between the two files. - The best we can rely on is the order of SHF_ALLOC sections. */ - - Elf_Scn *ourscn = elf_getscn (mod->debug.elf, shndx); - Elf_Scn *scn = NULL; - uint_fast32_t skip_alloc = 0; - while ((scn = elf_nextscn (mod->debug.elf, scn)) != ourscn) - { - assert (scn != NULL); - GElf_Shdr shdr_mem; - GElf_Shdr *sh = gelf_getshdr (scn, &shdr_mem); - if (unlikely (sh == NULL)) - return -1; - if (sh->sh_flags & SHF_ALLOC) - ++skip_alloc; - } - - scn = NULL; - while ((scn = elf_nextscn (mod->main.elf, scn)) != NULL) - { - GElf_Shdr shdr_mem; - GElf_Shdr *main_shdr = gelf_getshdr (scn, &shdr_mem); - if (unlikely (main_shdr == NULL)) - return -1; - if ((main_shdr->sh_flags & SHF_ALLOC) && skip_alloc-- == 0) - { - assert (main_shdr->sh_flags == shdr->sh_flags); - *addr = main_shdr->sh_addr; - return 0; - } - } - - /* This should never happen. */ - return -1; -} -INTDEF (dwfl_offline_section_address) - -/* Forward declarations. */ -static Dwfl_Module *process_elf (Dwfl *dwfl, const char *name, - const char *file_name, int fd, Elf *elf); -static Dwfl_Module *process_archive (Dwfl *dwfl, const char *name, - const char *file_name, int fd, Elf *elf, - int (*predicate) (const char *module, - const char *file)); - -/* Report one module for an ELF file, or many for an archive. - Always consumes ELF and FD. */ -static Dwfl_Module * -process_file (Dwfl *dwfl, const char *name, const char *file_name, int fd, - Elf *elf, int (*predicate) (const char *module, - const char *file)) -{ - switch (elf_kind (elf)) - { - default: - case ELF_K_NONE: - __libdwfl_seterrno (elf == NULL ? DWFL_E_LIBELF : DWFL_E_BADELF); - return NULL; - - case ELF_K_ELF: - return process_elf (dwfl, name, file_name, fd, elf); - - case ELF_K_AR: - return process_archive (dwfl, name, file_name, fd, elf, predicate); - } -} - -/* Report the open ELF file as a module. Always consumes ELF and FD. */ -static Dwfl_Module * -process_elf (Dwfl *dwfl, const char *name, const char *file_name, int fd, - Elf *elf) -{ - Dwfl_Module *mod = __libdwfl_report_elf (dwfl, name, file_name, fd, elf, - dwfl->offline_next_address, true, - false); - if (mod != NULL) - { - /* If this is an ET_EXEC file with fixed addresses, the address range - it consumed may or may not intersect with the arbitrary range we - will use for relocatable modules. Make sure we always use a free - range for the offline allocations. If this module did use - offline_next_address, it may have rounded it up for the module's - alignment requirements. */ - if ((dwfl->offline_next_address >= mod->low_addr - || mod->low_addr - dwfl->offline_next_address < OFFLINE_REDZONE) - && dwfl->offline_next_address < mod->high_addr + OFFLINE_REDZONE) - dwfl->offline_next_address = mod->high_addr + OFFLINE_REDZONE; - - /* Don't keep the file descriptor around. */ - if (mod->main.fd != -1 && elf_cntl (mod->main.elf, ELF_C_FDREAD) == 0) - { - close (mod->main.fd); - mod->main.fd = -1; - } - } - - return mod; -} - -/* Always consumes MEMBER. Returns elf_next result on success. - For errors returns ELF_C_NULL with *MOD set to null. */ -static Elf_Cmd -process_archive_member (Dwfl *dwfl, const char *name, const char *file_name, - int (*predicate) (const char *module, const char *file), - int fd, Elf *member, Dwfl_Module **mod) -{ - const Elf_Arhdr *h = elf_getarhdr (member); - if (unlikely (h == NULL)) - { - __libdwfl_seterrno (DWFL_E_LIBELF); - fail: - elf_end (member); - *mod = NULL; - return ELF_C_NULL; - } - - if (!strcmp (h->ar_name, "/") || !strcmp (h->ar_name, "//") - || !strcmp (h->ar_name, "/SYM64/")) - { - skip:; - /* Skip this and go to the next. */ - Elf_Cmd result = elf_next (member); - elf_end (member); - return result; - } - - char *member_name; - if (unlikely (asprintf (&member_name, "%s(%s)", file_name, h->ar_name) < 0)) - { - nomem: - __libdwfl_seterrno (DWFL_E_NOMEM); - elf_end (member); - *mod = NULL; - return ELF_C_NULL; - } - - char *module_name = NULL; - if (name == NULL || name[0] == '\0') - name = h->ar_name; - else if (unlikely (asprintf (&module_name, "%s:%s", name, h->ar_name) < 0)) - { - free (member_name); - goto nomem; - } - else - name = module_name; - - if (predicate != NULL) - { - /* Let the predicate decide whether to use this one. */ - int want = (*predicate) (name, member_name); - if (want <= 0) - { - free (member_name); - free (module_name); - if (unlikely (want < 0)) - { - __libdwfl_seterrno (DWFL_E_CB); - goto fail; - } - goto skip; - } - } - - /* We let __libdwfl_report_elf cache the fd in mod->main.fd, - though it's the same fd for all the members. - On module teardown we will close it only on the last Elf reference. */ - *mod = process_file (dwfl, name, member_name, fd, member, predicate); - free (member_name); - free (module_name); - - if (*mod == NULL) /* process_file called elf_end. */ - return ELF_C_NULL; - - /* Advance the archive-reading offset for the next iteration. */ - return elf_next (member); -} - -/* Report each member of the archive as its own module. */ -static Dwfl_Module * -process_archive (Dwfl *dwfl, const char *name, const char *file_name, int fd, - Elf *archive, - int (*predicate) (const char *module, const char *file)) - -{ - Dwfl_Module *mod = NULL; - Elf *member = elf_begin (fd, ELF_C_READ_MMAP_PRIVATE, archive); - if (unlikely (member == NULL)) /* Empty archive. */ - { - __libdwfl_seterrno (DWFL_E_BADELF); - return NULL; - } - - while (process_archive_member (dwfl, name, file_name, predicate, - fd, member, &mod) != ELF_C_NULL) - member = elf_begin (fd, ELF_C_READ_MMAP_PRIVATE, archive); - - /* We can drop the archive Elf handle even if we're still using members - in live modules. When the last module's elf_end on a member returns - zero, that module will close FD. If no modules survived the predicate, - we are all done with the file right here. */ - if (mod != NULL /* If no modules, caller will clean up. */ - && elf_end (archive) == 0) - close (fd); - - return mod; -} - -Dwfl_Module * -internal_function -__libdwfl_report_offline (Dwfl *dwfl, const char *name, - const char *file_name, int fd, bool closefd, - int (*predicate) (const char *module, - const char *file)) -{ - Elf *elf; - Dwfl_Error error = __libdw_open_file (&fd, &elf, closefd, true); - if (error != DWFL_E_NOERROR) - { - __libdwfl_seterrno (error); - return NULL; - } - Dwfl_Module *mod = process_file (dwfl, name, file_name, fd, elf, predicate); - if (mod == NULL) - { - elf_end (elf); - if (closefd) - close (fd); - } - return mod; -} - -Dwfl_Module * -dwfl_report_offline (Dwfl *dwfl, const char *name, - const char *file_name, int fd) -{ - if (dwfl == NULL) - return NULL; - - bool closefd = false; - if (fd < 0) - { - closefd = true; - fd = open64 (file_name, O_RDONLY); - if (fd < 0) - { - __libdwfl_seterrno (DWFL_E_ERRNO); - return NULL; - } - } - - return __libdwfl_report_offline (dwfl, name, file_name, fd, closefd, NULL); -} -INTDEF (dwfl_report_offline) diff --git a/src/libdwfl/open.c b/src/libdwfl/open.c deleted file mode 100644 index 40aac388..00000000 --- a/src/libdwfl/open.c +++ /dev/null @@ -1,182 +0,0 @@ -/* Decompression support for libdwfl: zlib (gzip) and/or bzlib (bzip2). - Copyright (C) 2009 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "../libelf/libelfP.h" -#undef _ -#include "libdwflP.h" - -#include <unistd.h> - -#if !USE_ZLIB -# define __libdw_gunzip(...) DWFL_E_BADELF -#endif - -#if !USE_BZLIB -# define __libdw_bunzip2(...) DWFL_E_BADELF -#endif - -#if !USE_LZMA -# define __libdw_unlzma(...) DWFL_E_BADELF -#endif - -/* Consumes and replaces *ELF only on success. */ -static Dwfl_Error -decompress (int fd __attribute__ ((unused)), Elf **elf) -{ - Dwfl_Error error = DWFL_E_BADELF; - void *buffer = NULL; - size_t size = 0; - -#if USE_ZLIB || USE_BZLIB || USE_LZMA - const off64_t offset = (*elf)->start_offset; - void *const mapped = ((*elf)->map_address == NULL ? NULL - : (*elf)->map_address + offset); - const size_t mapped_size = (*elf)->maximum_size; - if (mapped_size == 0) - return error; - - error = __libdw_gunzip (fd, offset, mapped, mapped_size, &buffer, &size); - if (error == DWFL_E_BADELF) - error = __libdw_bunzip2 (fd, offset, mapped, mapped_size, &buffer, &size); - if (error == DWFL_E_BADELF) - error = __libdw_unlzma (fd, offset, mapped, mapped_size, &buffer, &size); -#endif - - if (error == DWFL_E_NOERROR) - { - if (unlikely (size == 0)) - { - error = DWFL_E_BADELF; - free (buffer); - } - else - { - Elf *memelf = elf_memory (buffer, size); - if (memelf == NULL) - { - error = DWFL_E_LIBELF; - free (buffer); - } - else - { - memelf->flags |= ELF_F_MALLOCED; - elf_end (*elf); - *elf = memelf; - } - } - } - else - free (buffer); - - return error; -} - -static Dwfl_Error -what_kind (int fd, Elf **elfp, Elf_Kind *kind, bool *close_fd) -{ - Dwfl_Error error = DWFL_E_NOERROR; - *kind = elf_kind (*elfp); - if (unlikely (*kind == ELF_K_NONE)) - { - if (unlikely (*elfp == NULL)) - error = DWFL_E_LIBELF; - else - { - error = decompress (fd, elfp); - if (error == DWFL_E_NOERROR) - { - *close_fd = true; - *kind = elf_kind (*elfp); - } - } - } - return error; -} - -Dwfl_Error internal_function -__libdw_open_file (int *fdp, Elf **elfp, bool close_on_fail, bool archive_ok) -{ - bool close_fd = false; - - Elf *elf = elf_begin (*fdp, ELF_C_READ_MMAP_PRIVATE, NULL); - - Elf_Kind kind; - Dwfl_Error error = what_kind (*fdp, &elf, &kind, &close_fd); - if (error == DWFL_E_BADELF) - { - /* It's not an ELF file or a compressed file. - See if it's an image with a header preceding the real file. */ - - off64_t offset = elf->start_offset; - error = __libdw_image_header (*fdp, &offset, - (elf->map_address == NULL ? NULL - : elf->map_address + offset), - elf->maximum_size); - if (error == DWFL_E_NOERROR) - { - /* Pure evil. libelf needs some better interfaces. */ - elf->kind = ELF_K_AR; - elf->state.ar.elf_ar_hdr.ar_name = "libdwfl is faking you out"; - elf->state.ar.elf_ar_hdr.ar_size = elf->maximum_size - offset; - elf->state.ar.offset = offset - sizeof (struct ar_hdr); - Elf *subelf = elf_begin (-1, ELF_C_READ_MMAP_PRIVATE, elf); - elf->kind = ELF_K_NONE; - if (unlikely (subelf == NULL)) - error = DWFL_E_LIBELF; - else - { - subelf->parent = NULL; - subelf->flags |= elf->flags & (ELF_F_MMAPPED | ELF_F_MALLOCED); - elf->flags &= ~(ELF_F_MMAPPED | ELF_F_MALLOCED); - elf_end (elf); - elf = subelf; - error = what_kind (*fdp, &elf, &kind, &close_fd); - } - } - } - - if (error == DWFL_E_NOERROR - && kind != ELF_K_ELF - && !(archive_ok && kind == ELF_K_AR)) - error = DWFL_E_BADELF; - - if (error != DWFL_E_NOERROR) - { - elf_end (elf); - elf = NULL; - } - - if (error == DWFL_E_NOERROR ? close_fd : close_on_fail) - { - close (*fdp); - *fdp = -1; - } - - *elfp = elf; - return error; -} diff --git a/src/libdwfl/relocate.c b/src/libdwfl/relocate.c deleted file mode 100644 index e102e1e4..00000000 --- a/src/libdwfl/relocate.c +++ /dev/null @@ -1,683 +0,0 @@ -/* Relocate debug information. - Copyright (C) 2005-2011, 2014 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" - -typedef uint8_t GElf_Byte; - -/* Adjust *VALUE to add the load address of the SHNDX section. - We update the section header in place to cache the result. */ - -Dwfl_Error -internal_function -__libdwfl_relocate_value (Dwfl_Module *mod, Elf *elf, size_t *shstrndx, - Elf32_Word shndx, GElf_Addr *value) -{ - /* No adjustment needed for section zero, it is never loaded. - Handle it first, just in case the ELF file has strange section - zero flags set. */ - if (shndx == 0) - return DWFL_E_NOERROR; - - Elf_Scn *refscn = elf_getscn (elf, shndx); - GElf_Shdr refshdr_mem, *refshdr = gelf_getshdr (refscn, &refshdr_mem); - if (refshdr == NULL) - return DWFL_E_LIBELF; - - if (refshdr->sh_addr == 0 && (refshdr->sh_flags & SHF_ALLOC)) - { - /* This is a loaded section. Find its actual - address and update the section header. */ - - if (*shstrndx == SHN_UNDEF - && unlikely (elf_getshdrstrndx (elf, shstrndx) < 0)) - return DWFL_E_LIBELF; - - const char *name = elf_strptr (elf, *shstrndx, refshdr->sh_name); - if (unlikely (name == NULL)) - return DWFL_E_LIBELF; - - if ((*mod->dwfl->callbacks->section_address) (MODCB_ARGS (mod), - name, shndx, refshdr, - &refshdr->sh_addr)) - return CBFAIL; - - if (refshdr->sh_addr == (Dwarf_Addr) -1l) - /* The callback indicated this section wasn't really loaded but we - don't really care. */ - refshdr->sh_addr = 0; /* Make no adjustment below. */ - - /* Update the in-core file's section header to show the final - load address (or unloadedness). This serves as a cache, - so we won't get here again for the same section. */ - if (likely (refshdr->sh_addr != 0) - && unlikely (! gelf_update_shdr (refscn, refshdr))) - return DWFL_E_LIBELF; - } - - if (refshdr->sh_flags & SHF_ALLOC) - /* Apply the adjustment. */ - *value += dwfl_adjusted_address (mod, refshdr->sh_addr); - - return DWFL_E_NOERROR; -} - - -/* Cache used by relocate_getsym. */ -struct reloc_symtab_cache -{ - Elf *symelf; - Elf_Data *symdata; - Elf_Data *symxndxdata; - Elf_Data *symstrdata; - size_t symshstrndx; - size_t strtabndx; -}; -#define RELOC_SYMTAB_CACHE(cache) \ - struct reloc_symtab_cache cache = \ - { NULL, NULL, NULL, NULL, SHN_UNDEF, SHN_UNDEF } - -/* This is just doing dwfl_module_getsym, except that we must always use - the symbol table in RELOCATED itself when it has one, not MOD->symfile. */ -static Dwfl_Error -relocate_getsym (Dwfl_Module *mod, - Elf *relocated, struct reloc_symtab_cache *cache, - int symndx, GElf_Sym *sym, GElf_Word *shndx) -{ - if (cache->symdata == NULL) - { - if (mod->symfile == NULL || mod->symfile->elf != relocated) - { - /* We have to look up the symbol table in the file we are - relocating, if it has its own. These reloc sections refer to - the symbol table in this file, and a symbol table in the main - file might not match. However, some tools did produce ET_REL - .debug files with relocs but no symtab of their own. */ - Elf_Scn *scn = NULL; - while ((scn = elf_nextscn (relocated, scn)) != NULL) - { - GElf_Shdr shdr_mem, *shdr = gelf_getshdr (scn, &shdr_mem); - if (shdr != NULL) - switch (shdr->sh_type) - { - default: - continue; - case SHT_SYMTAB: - cache->symelf = relocated; - cache->symdata = elf_getdata (scn, NULL); - cache->strtabndx = shdr->sh_link; - if (unlikely (cache->symdata == NULL)) - return DWFL_E_LIBELF; - break; - case SHT_SYMTAB_SHNDX: - cache->symxndxdata = elf_getdata (scn, NULL); - if (unlikely (cache->symxndxdata == NULL)) - return DWFL_E_LIBELF; - break; - } - if (cache->symdata != NULL && cache->symxndxdata != NULL) - break; - } - } - if (cache->symdata == NULL) - { - /* We might not have looked for a symbol table file yet, - when coming from __libdwfl_relocate_section. */ - if (unlikely (mod->symfile == NULL) - && unlikely (INTUSE(dwfl_module_getsymtab) (mod) < 0)) - return dwfl_errno (); - - /* The symbol table we have already cached is the one from - the file being relocated, so it's what we need. Or else - this is an ET_REL .debug file with no .symtab of its own; - the symbols refer to the section indices in the main file. */ - cache->symelf = mod->symfile->elf; - cache->symdata = mod->symdata; - cache->symxndxdata = mod->symxndxdata; - cache->symstrdata = mod->symstrdata; - } - } - - if (unlikely (gelf_getsymshndx (cache->symdata, cache->symxndxdata, - symndx, sym, shndx) == NULL)) - return DWFL_E_LIBELF; - - if (sym->st_shndx != SHN_XINDEX) - *shndx = sym->st_shndx; - - switch (sym->st_shndx) - { - case SHN_ABS: - case SHN_UNDEF: - return DWFL_E_NOERROR; - - case SHN_COMMON: - sym->st_value = 0; /* Value is size, not helpful. */ - return DWFL_E_NOERROR; - } - - return __libdwfl_relocate_value (mod, cache->symelf, &cache->symshstrndx, - *shndx, &sym->st_value); -} - -/* Handle an undefined symbol. We really only support ET_REL for Linux - kernel modules, and offline archives. The behavior of the Linux module - loader is very simple and easy to mimic. It only matches magically - exported symbols, and we match any defined symbols. But we get the same - answer except when the module's symbols are undefined and would prevent - it from being loaded. */ -static Dwfl_Error -resolve_symbol (Dwfl_Module *referer, struct reloc_symtab_cache *symtab, - GElf_Sym *sym, GElf_Word shndx) -{ - /* First we need its name. */ - if (sym->st_name != 0) - { - if (symtab->symstrdata == NULL) - { - /* Cache the strtab for this symtab. */ - assert (referer->symfile == NULL - || referer->symfile->elf != symtab->symelf); - symtab->symstrdata = elf_getdata (elf_getscn (symtab->symelf, - symtab->strtabndx), - NULL); - if (unlikely (symtab->symstrdata == NULL - || symtab->symstrdata->d_buf == NULL)) - return DWFL_E_LIBELF; - } - if (unlikely (sym->st_name >= symtab->symstrdata->d_size)) - return DWFL_E_BADSTROFF; - - const char *name = symtab->symstrdata->d_buf; - name += sym->st_name; - - for (Dwfl_Module *m = referer->dwfl->modulelist; m != NULL; m = m->next) - if (m != referer) - { - /* Get this module's symtab. - If we got a fresh error reading the table, report it. - If we just have no symbols in this module, no harm done. */ - if (m->symdata == NULL - && m->symerr == DWFL_E_NOERROR - && INTUSE(dwfl_module_getsymtab) (m) < 0 - && m->symerr != DWFL_E_NO_SYMTAB) - return m->symerr; - - for (size_t ndx = 1; ndx < m->syments; ++ndx) - { - sym = gelf_getsymshndx (m->symdata, m->symxndxdata, - ndx, sym, &shndx); - if (unlikely (sym == NULL)) - return DWFL_E_LIBELF; - if (sym->st_shndx != SHN_XINDEX) - shndx = sym->st_shndx; - - /* We are looking for a defined global symbol with a name. */ - if (shndx == SHN_UNDEF || shndx == SHN_COMMON - || GELF_ST_BIND (sym->st_info) == STB_LOCAL - || sym->st_name == 0) - continue; - - /* Get this candidate symbol's name. */ - if (unlikely (sym->st_name >= m->symstrdata->d_size)) - return DWFL_E_BADSTROFF; - const char *n = m->symstrdata->d_buf; - n += sym->st_name; - - /* Does the name match? */ - if (strcmp (name, n)) - continue; - - /* We found it! */ - if (shndx == SHN_ABS) /* XXX maybe should apply bias? */ - return DWFL_E_NOERROR; - - if (m->e_type != ET_REL) - { - sym->st_value = dwfl_adjusted_st_value (m, m->symfile->elf, - sym->st_value); - return DWFL_E_NOERROR; - } - - /* In an ET_REL file, the symbol table values are relative - to the section, not to the module's load base. */ - size_t symshstrndx = SHN_UNDEF; - return __libdwfl_relocate_value (m, m->symfile->elf, - &symshstrndx, - shndx, &sym->st_value); - } - } - } - - return DWFL_E_RELUNDEF; -} - -static Dwfl_Error -relocate_section (Dwfl_Module *mod, Elf *relocated, const GElf_Ehdr *ehdr, - size_t shstrndx, struct reloc_symtab_cache *reloc_symtab, - Elf_Scn *scn, GElf_Shdr *shdr, - Elf_Scn *tscn, bool debugscn, bool partial) -{ - /* First, fetch the name of the section these relocations apply to. */ - GElf_Shdr tshdr_mem; - GElf_Shdr *tshdr = gelf_getshdr (tscn, &tshdr_mem); - const char *tname = elf_strptr (relocated, shstrndx, tshdr->sh_name); - if (tname == NULL) - return DWFL_E_LIBELF; - - if (unlikely (tshdr->sh_type == SHT_NOBITS) || unlikely (tshdr->sh_size == 0)) - /* No contents to relocate. */ - return DWFL_E_NOERROR; - - if (debugscn && ! ebl_debugscn_p (mod->ebl, tname)) - /* This relocation section is not for a debugging section. - Nothing to do here. */ - return DWFL_E_NOERROR; - - /* Fetch the section data that needs the relocations applied. */ - Elf_Data *tdata = elf_rawdata (tscn, NULL); - if (tdata == NULL) - return DWFL_E_LIBELF; - - /* If either the section that needs the relocation applied, or the - section that the relocations come from overlap one of the ehdrs, - shdrs or phdrs data then we refuse to do the relocations. It - isn't illegal for ELF section data to overlap the header data, - but updating the (relocation) data might corrupt the in-memory - libelf headers causing strange corruptions or errors. */ - size_t ehsize = gelf_fsize (relocated, ELF_T_EHDR, 1, EV_CURRENT); - if (unlikely (shdr->sh_offset < ehsize - || tshdr->sh_offset < ehsize)) - return DWFL_E_BADELF; - - GElf_Off shdrs_start = ehdr->e_shoff; - size_t shnums; - if (elf_getshdrnum (relocated, &shnums) < 0) - return DWFL_E_LIBELF; - /* Overflows will have been checked by elf_getshdrnum/get|rawdata. */ - size_t shentsize = gelf_fsize (relocated, ELF_T_SHDR, 1, EV_CURRENT); - GElf_Off shdrs_end = shdrs_start + shnums * shentsize; - if (unlikely ((shdrs_start < shdr->sh_offset + shdr->sh_size - && shdr->sh_offset < shdrs_end) - || (shdrs_start < tshdr->sh_offset + tshdr->sh_size - && tshdr->sh_offset < shdrs_end))) - return DWFL_E_BADELF; - - GElf_Off phdrs_start = ehdr->e_phoff; - size_t phnums; - if (elf_getphdrnum (relocated, &phnums) < 0) - return DWFL_E_LIBELF; - if (phdrs_start != 0 && phnums != 0) - { - /* Overflows will have been checked by elf_getphdrnum/get|rawdata. */ - size_t phentsize = gelf_fsize (relocated, ELF_T_PHDR, 1, EV_CURRENT); - GElf_Off phdrs_end = phdrs_start + phnums * phentsize; - if (unlikely ((phdrs_start < shdr->sh_offset + shdr->sh_size - && shdr->sh_offset < phdrs_end) - || (phdrs_start < tshdr->sh_offset + tshdr->sh_size - && tshdr->sh_offset < phdrs_end))) - return DWFL_E_BADELF; - } - - /* Apply one relocation. Returns true for any invalid data. */ - Dwfl_Error relocate (GElf_Addr offset, const GElf_Sxword *addend, - int rtype, int symndx) - { - /* First see if this is a reloc we can handle. - If we are skipping it, don't bother resolving the symbol. */ - - if (unlikely (rtype == 0)) - /* In some odd situations, the linker can leave R_*_NONE relocs - behind. This is probably bogus ld -r behavior, but the only - cases it's known to appear in are harmless: DWARF data - referring to addresses in a section that has been discarded. - So we just pretend it's OK without further relocation. */ - return DWFL_E_NOERROR; - - Elf_Type type = ebl_reloc_simple_type (mod->ebl, rtype); - if (unlikely (type == ELF_T_NUM)) - return DWFL_E_BADRELTYPE; - - /* First, resolve the symbol to an absolute value. */ - GElf_Addr value; - - if (symndx == STN_UNDEF) - /* When strip removes a section symbol referring to a - section moved into the debuginfo file, it replaces - that symbol index in relocs with STN_UNDEF. We - don't actually need the symbol, because those relocs - are always references relative to the nonallocated - debugging sections, which start at zero. */ - value = 0; - else - { - GElf_Sym sym; - GElf_Word shndx; - Dwfl_Error error = relocate_getsym (mod, relocated, reloc_symtab, - symndx, &sym, &shndx); - if (unlikely (error != DWFL_E_NOERROR)) - return error; - - if (shndx == SHN_UNDEF || shndx == SHN_COMMON) - { - /* Maybe we can figure it out anyway. */ - error = resolve_symbol (mod, reloc_symtab, &sym, shndx); - if (error != DWFL_E_NOERROR - && !(error == DWFL_E_RELUNDEF && shndx == SHN_COMMON)) - return error; - } - - value = sym.st_value; - } - - /* These are the types we can relocate. */ -#define TYPES DO_TYPE (BYTE, Byte); DO_TYPE (HALF, Half); \ - DO_TYPE (WORD, Word); DO_TYPE (SWORD, Sword); \ - DO_TYPE (XWORD, Xword); DO_TYPE (SXWORD, Sxword) - size_t size; - switch (type) - { -#define DO_TYPE(NAME, Name) \ - case ELF_T_##NAME: \ - size = sizeof (GElf_##Name); \ - break - TYPES; -#undef DO_TYPE - default: - return DWFL_E_BADRELTYPE; - } - - if (offset > tdata->d_size || tdata->d_size - offset < size) - return DWFL_E_BADRELOFF; - -#define DO_TYPE(NAME, Name) GElf_##Name Name; - union { TYPES; } tmpbuf; -#undef DO_TYPE - Elf_Data tmpdata = - { - .d_type = type, - .d_buf = &tmpbuf, - .d_size = size, - .d_version = EV_CURRENT, - }; - Elf_Data rdata = - { - .d_type = type, - .d_buf = tdata->d_buf + offset, - .d_size = size, - .d_version = EV_CURRENT, - }; - - /* XXX check for overflow? */ - if (addend) - { - /* For the addend form, we have the value already. */ - value += *addend; - switch (type) - { -#define DO_TYPE(NAME, Name) \ - case ELF_T_##NAME: \ - tmpbuf.Name = value; \ - break - TYPES; -#undef DO_TYPE - default: - abort (); - } - } - else - { - /* Extract the original value and apply the reloc. */ - Elf_Data *d = gelf_xlatetom (relocated, &tmpdata, &rdata, - ehdr->e_ident[EI_DATA]); - if (d == NULL) - return DWFL_E_LIBELF; - assert (d == &tmpdata); - switch (type) - { -#define DO_TYPE(NAME, Name) \ - case ELF_T_##NAME: \ - tmpbuf.Name += (GElf_##Name) value; \ - break - TYPES; -#undef DO_TYPE - default: - abort (); - } - } - - /* Now convert the relocated datum back to the target - format. This will write into rdata.d_buf, which - points into the raw section data being relocated. */ - Elf_Data *s = gelf_xlatetof (relocated, &rdata, &tmpdata, - ehdr->e_ident[EI_DATA]); - if (s == NULL) - return DWFL_E_LIBELF; - assert (s == &rdata); - - /* We have applied this relocation! */ - return DWFL_E_NOERROR; - } - - /* Fetch the relocation section and apply each reloc in it. */ - Elf_Data *reldata = elf_getdata (scn, NULL); - if (reldata == NULL) - return DWFL_E_LIBELF; - - Dwfl_Error result = DWFL_E_NOERROR; - bool first_badreltype = true; - inline void check_badreltype (void) - { - if (first_badreltype) - { - first_badreltype = false; - if (ebl_get_elfmachine (mod->ebl) == EM_NONE) - /* This might be because ebl_openbackend failed to find - any libebl_CPU.so library. Diagnose that clearly. */ - result = DWFL_E_UNKNOWN_MACHINE; - } - } - - size_t sh_entsize - = gelf_fsize (relocated, shdr->sh_type == SHT_REL ? ELF_T_REL : ELF_T_RELA, - 1, EV_CURRENT); - size_t nrels = shdr->sh_size / sh_entsize; - size_t complete = 0; - if (shdr->sh_type == SHT_REL) - for (size_t relidx = 0; !result && relidx < nrels; ++relidx) - { - GElf_Rel rel_mem, *r = gelf_getrel (reldata, relidx, &rel_mem); - if (r == NULL) - return DWFL_E_LIBELF; - result = relocate (r->r_offset, NULL, - GELF_R_TYPE (r->r_info), - GELF_R_SYM (r->r_info)); - check_badreltype (); - if (partial) - switch (result) - { - case DWFL_E_NOERROR: - /* We applied the relocation. Elide it. */ - memset (&rel_mem, 0, sizeof rel_mem); - gelf_update_rel (reldata, relidx, &rel_mem); - ++complete; - break; - case DWFL_E_BADRELTYPE: - case DWFL_E_RELUNDEF: - /* We couldn't handle this relocation. Skip it. */ - result = DWFL_E_NOERROR; - break; - default: - break; - } - } - else - for (size_t relidx = 0; !result && relidx < nrels; ++relidx) - { - GElf_Rela rela_mem, *r = gelf_getrela (reldata, relidx, - &rela_mem); - if (r == NULL) - return DWFL_E_LIBELF; - result = relocate (r->r_offset, &r->r_addend, - GELF_R_TYPE (r->r_info), - GELF_R_SYM (r->r_info)); - check_badreltype (); - if (partial) - switch (result) - { - case DWFL_E_NOERROR: - /* We applied the relocation. Elide it. */ - memset (&rela_mem, 0, sizeof rela_mem); - gelf_update_rela (reldata, relidx, &rela_mem); - ++complete; - break; - case DWFL_E_BADRELTYPE: - case DWFL_E_RELUNDEF: - /* We couldn't handle this relocation. Skip it. */ - result = DWFL_E_NOERROR; - break; - default: - break; - } - } - - if (likely (result == DWFL_E_NOERROR)) - { - if (!partial || complete == nrels) - /* Mark this relocation section as being empty now that we have - done its work. This affects unstrip -R, so e.g. it emits an - empty .rela.debug_info along with a .debug_info that has - already been fully relocated. */ - nrels = 0; - else if (complete != 0) - { - /* We handled some of the relocations but not all. - We've zeroed out the ones we processed. - Now remove them from the section. */ - - size_t next = 0; - if (shdr->sh_type == SHT_REL) - for (size_t relidx = 0; relidx < nrels; ++relidx) - { - GElf_Rel rel_mem; - GElf_Rel *r = gelf_getrel (reldata, relidx, &rel_mem); - if (r->r_info != 0 || r->r_offset != 0) - { - if (next != relidx) - gelf_update_rel (reldata, next, r); - ++next; - } - } - else - for (size_t relidx = 0; relidx < nrels; ++relidx) - { - GElf_Rela rela_mem; - GElf_Rela *r = gelf_getrela (reldata, relidx, &rela_mem); - if (r->r_info != 0 || r->r_offset != 0 || r->r_addend != 0) - { - if (next != relidx) - gelf_update_rela (reldata, next, r); - ++next; - } - } - nrels = next; - } - - shdr->sh_size = reldata->d_size = nrels * sh_entsize; - gelf_update_shdr (scn, shdr); - } - - return result; -} - -Dwfl_Error -internal_function -__libdwfl_relocate (Dwfl_Module *mod, Elf *debugfile, bool debug) -{ - assert (mod->e_type == ET_REL); - - GElf_Ehdr ehdr_mem; - const GElf_Ehdr *ehdr = gelf_getehdr (debugfile, &ehdr_mem); - if (ehdr == NULL) - return DWFL_E_LIBELF; - - size_t d_shstrndx; - if (elf_getshdrstrndx (debugfile, &d_shstrndx) < 0) - return DWFL_E_LIBELF; - - RELOC_SYMTAB_CACHE (reloc_symtab); - - /* Look at each section in the debuginfo file, and process the - relocation sections for debugging sections. */ - Dwfl_Error result = DWFL_E_NOERROR; - Elf_Scn *scn = NULL; - while (result == DWFL_E_NOERROR - && (scn = elf_nextscn (debugfile, scn)) != NULL) - { - GElf_Shdr shdr_mem; - GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); - - if ((shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA) - && shdr->sh_size != 0) - { - /* It's a relocation section. */ - - Elf_Scn *tscn = elf_getscn (debugfile, shdr->sh_info); - if (unlikely (tscn == NULL)) - result = DWFL_E_LIBELF; - else - result = relocate_section (mod, debugfile, ehdr, d_shstrndx, - &reloc_symtab, scn, shdr, tscn, - debug, !debug); - } - } - - return result; -} - -Dwfl_Error -internal_function -__libdwfl_relocate_section (Dwfl_Module *mod, Elf *relocated, - Elf_Scn *relocscn, Elf_Scn *tscn, bool partial) -{ - GElf_Ehdr ehdr_mem; - GElf_Shdr shdr_mem; - - RELOC_SYMTAB_CACHE (reloc_symtab); - - size_t shstrndx; - if (elf_getshdrstrndx (relocated, &shstrndx) < 0) - return DWFL_E_LIBELF; - - return (__libdwfl_module_getebl (mod) - ?: relocate_section (mod, relocated, - gelf_getehdr (relocated, &ehdr_mem), shstrndx, - &reloc_symtab, - relocscn, gelf_getshdr (relocscn, &shdr_mem), - tscn, false, partial)); -} diff --git a/src/libdwfl/segment.c b/src/libdwfl/segment.c deleted file mode 100644 index 92769174..00000000 --- a/src/libdwfl/segment.c +++ /dev/null @@ -1,332 +0,0 @@ -/* Manage address space lookup table for libdwfl. - Copyright (C) 2008, 2009, 2010, 2013 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see <http://www.gnu.org/licenses/>. */ - -#include "libdwflP.h" - -GElf_Addr -internal_function -__libdwfl_segment_start (Dwfl *dwfl, GElf_Addr start) -{ - if (dwfl->segment_align > 1) - start &= -dwfl->segment_align; - return start; -} - -GElf_Addr -internal_function -__libdwfl_segment_end (Dwfl *dwfl, GElf_Addr end) -{ - if (dwfl->segment_align > 1) - end = (end + dwfl->segment_align - 1) & -dwfl->segment_align; - return end; -} - -static bool -insert (Dwfl *dwfl, size_t i, GElf_Addr start, GElf_Addr end, int segndx) -{ - bool need_start = (i == 0 || dwfl->lookup_addr[i - 1] != start); - bool need_end = (i >= dwfl->lookup_elts || dwfl->lookup_addr[i + 1] != end); - size_t need = need_start + need_end; - if (need == 0) - return false; - - if (dwfl->lookup_alloc - dwfl->lookup_elts < need) - { - size_t n = dwfl->lookup_alloc == 0 ? 16 : dwfl->lookup_alloc * 2; - GElf_Addr *naddr = realloc (dwfl->lookup_addr, sizeof naddr[0] * n); - if (unlikely (naddr == NULL)) - return true; - int *nsegndx = realloc (dwfl->lookup_segndx, sizeof nsegndx[0] * n); - if (unlikely (nsegndx == NULL)) - { - if (naddr != dwfl->lookup_addr) - free (naddr); - return true; - } - dwfl->lookup_alloc = n; - dwfl->lookup_addr = naddr; - dwfl->lookup_segndx = nsegndx; - - if (dwfl->lookup_module != NULL) - { - /* Make sure this array is big enough too. */ - Dwfl_Module **old = dwfl->lookup_module; - dwfl->lookup_module = realloc (dwfl->lookup_module, - sizeof dwfl->lookup_module[0] * n); - if (unlikely (dwfl->lookup_module == NULL)) - { - free (old); - return true; - } - } - } - - if (unlikely (i < dwfl->lookup_elts)) - { - const size_t move = dwfl->lookup_elts - i; - memmove (&dwfl->lookup_addr[i + need], &dwfl->lookup_addr[i], - move * sizeof dwfl->lookup_addr[0]); - memmove (&dwfl->lookup_segndx[i + need], &dwfl->lookup_segndx[i], - move * sizeof dwfl->lookup_segndx[0]); - if (dwfl->lookup_module != NULL) - memmove (&dwfl->lookup_module[i + need], &dwfl->lookup_module[i], - move * sizeof dwfl->lookup_module[0]); - } - - if (need_start) - { - dwfl->lookup_addr[i] = start; - dwfl->lookup_segndx[i] = segndx; - if (dwfl->lookup_module != NULL) - dwfl->lookup_module[i] = NULL; - ++i; - } - else - dwfl->lookup_segndx[i - 1] = segndx; - - if (need_end) - { - dwfl->lookup_addr[i] = end; - dwfl->lookup_segndx[i] = -1; - if (dwfl->lookup_module != NULL) - dwfl->lookup_module[i] = NULL; - } - - dwfl->lookup_elts += need; - - return false; -} - -static int -lookup (Dwfl *dwfl, GElf_Addr address, int hint) -{ - if (hint >= 0 - && address >= dwfl->lookup_addr[hint] - && ((size_t) hint + 1 == dwfl->lookup_elts - || address < dwfl->lookup_addr[hint + 1])) - return hint; - - /* Do binary search on the array indexed by module load address. */ - size_t l = 0, u = dwfl->lookup_elts; - while (l < u) - { - size_t idx = (l + u) / 2; - if (address < dwfl->lookup_addr[idx]) - u = idx; - else - { - l = idx + 1; - if (l == dwfl->lookup_elts || address < dwfl->lookup_addr[l]) - return idx; - } - } - - return -1; -} - -static bool -reify_segments (Dwfl *dwfl) -{ - int hint = -1; - int highest = -1; - bool fixup = false; - for (Dwfl_Module *mod = dwfl->modulelist; mod != NULL; mod = mod->next) - if (! mod->gc) - { - const GElf_Addr start = __libdwfl_segment_start (dwfl, mod->low_addr); - const GElf_Addr end = __libdwfl_segment_end (dwfl, mod->high_addr); - bool resized = false; - - int idx = lookup (dwfl, start, hint); - if (unlikely (idx < 0)) - { - /* Module starts below any segment. Insert a low one. */ - if (unlikely (insert (dwfl, 0, start, end, -1))) - return true; - idx = 0; - resized = true; - } - else if (dwfl->lookup_addr[idx] > start) - { - /* The module starts in the middle of this segment. Split it. */ - if (unlikely (insert (dwfl, idx + 1, start, end, - dwfl->lookup_segndx[idx]))) - return true; - ++idx; - resized = true; - } - else if (dwfl->lookup_addr[idx] < start) - { - /* The module starts past the end of this segment. - Add a new one. */ - if (unlikely (insert (dwfl, idx + 1, start, end, -1))) - return true; - ++idx; - resized = true; - } - - if ((size_t) idx + 1 < dwfl->lookup_elts - && end < dwfl->lookup_addr[idx + 1]) - { - /* The module ends in the middle of this segment. Split it. */ - if (unlikely (insert (dwfl, idx + 1, - end, dwfl->lookup_addr[idx + 1], -1))) - return true; - resized = true; - } - - if (dwfl->lookup_module == NULL) - { - dwfl->lookup_module = calloc (dwfl->lookup_alloc, - sizeof dwfl->lookup_module[0]); - if (unlikely (dwfl->lookup_module == NULL)) - return true; - } - - /* Cache a backpointer in the module. */ - mod->segment = idx; - - /* Put MOD in the table for each segment that's inside it. */ - do - dwfl->lookup_module[idx++] = mod; - while ((size_t) idx < dwfl->lookup_elts - && dwfl->lookup_addr[idx] < end); - assert (dwfl->lookup_module[mod->segment] == mod); - - if (resized && idx - 1 >= highest) - /* Expanding the lookup tables invalidated backpointers - we've already stored. Reset those ones. */ - fixup = true; - - highest = idx - 1; - hint = (size_t) idx < dwfl->lookup_elts ? idx : -1; - } - - if (fixup) - /* Reset backpointer indices invalidated by table insertions. */ - for (size_t idx = 0; idx < dwfl->lookup_elts; ++idx) - if (dwfl->lookup_module[idx] != NULL) - dwfl->lookup_module[idx]->segment = idx; - - return false; -} - -int -dwfl_addrsegment (Dwfl *dwfl, Dwarf_Addr address, Dwfl_Module **mod) -{ - if (unlikely (dwfl == NULL)) - return -1; - - if (unlikely (dwfl->lookup_module == NULL) - && mod != NULL - && unlikely (reify_segments (dwfl))) - { - __libdwfl_seterrno (DWFL_E_NOMEM); - return -1; - } - - int idx = lookup (dwfl, address, -1); - if (likely (mod != NULL)) - { - if (unlikely (idx < 0) || unlikely (dwfl->lookup_module == NULL)) - *mod = NULL; - else - { - *mod = dwfl->lookup_module[idx]; - - /* If this segment does not have a module, but the address is - the upper boundary of the previous segment's module, use that. */ - if (*mod == NULL && idx > 0 && dwfl->lookup_addr[idx] == address) - { - *mod = dwfl->lookup_module[idx - 1]; - if (*mod != NULL && (*mod)->high_addr != address) - *mod = NULL; - } - } - } - - if (likely (idx >= 0)) - /* Translate internal segment table index to user segment index. */ - idx = dwfl->lookup_segndx[idx]; - - return idx; -} -INTDEF (dwfl_addrsegment) - -int -dwfl_report_segment (Dwfl *dwfl, int ndx, const GElf_Phdr *phdr, GElf_Addr bias, - const void *ident) -{ - if (dwfl == NULL) - return -1; - - if (ndx < 0) - ndx = dwfl->lookup_tail_ndx; - - if (phdr->p_align > 1 && (dwfl->segment_align <= 1 || - phdr->p_align < dwfl->segment_align)) - dwfl->segment_align = phdr->p_align; - - if (unlikely (dwfl->lookup_module != NULL)) - { - free (dwfl->lookup_module); - dwfl->lookup_module = NULL; - } - - GElf_Addr start = __libdwfl_segment_start (dwfl, bias + phdr->p_vaddr); - GElf_Addr end = __libdwfl_segment_end (dwfl, - bias + phdr->p_vaddr + phdr->p_memsz); - - /* Coalesce into the last one if contiguous and matching. */ - if (ndx != dwfl->lookup_tail_ndx - || ident == NULL - || ident != dwfl->lookup_tail_ident - || start != dwfl->lookup_tail_vaddr - || phdr->p_offset != dwfl->lookup_tail_offset) - { - /* Normally just appending keeps us sorted. */ - - size_t i = dwfl->lookup_elts; - while (i > 0 && unlikely (start < dwfl->lookup_addr[i - 1])) - --i; - - if (unlikely (insert (dwfl, i, start, end, ndx))) - { - __libdwfl_seterrno (DWFL_E_NOMEM); - return -1; - } - } - - dwfl->lookup_tail_ident = ident; - dwfl->lookup_tail_vaddr = end; - dwfl->lookup_tail_offset = end - bias - phdr->p_vaddr + phdr->p_offset; - dwfl->lookup_tail_ndx = ndx + 1; - - return ndx; -} -INTDEF (dwfl_report_segment) |