summaryrefslogtreecommitdiffstats
path: root/libdw/dwarf_getcfi.c
Commit message (Collapse)AuthorAgeFilesLines
* libdw: Fix eu_search_tree TOCTOU bugsAaron Merey2025-06-021-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | eu_tfind is used to facilitate lazy loading throughout libdw. If a result is not found via eu_tfind, work is done to load the result and cache it in an eu_search_tree. Some calls to eu_tfind allow for TOCTOU bugs. Multiple threads might race to call eu_tfind on some result that hasn't yet been cached. Multiple threads may then attempt to load the result which might cause an unnecessary amount of memory to be allocated. Additionally this memory may not get released when the associated libdw data structure is freed. Fix this by adding additional locking to ensure that only one thread performs lazy loading. One approach used in this patch is to preserve calls to eu_tfind without additional locking, but when the result isn't found then a lock is then used to synchronize access to the lazy loading code. An extra eu_tfind call has been added at the start of these critical section to synchronize verification that lazy loading should proceed. Another approach used is to simply synchronize entire calls to functions where lazy loading via eu_tfind might occur (__libdw_find_fde and __libdw_intern_expression). In this case, new _nolock variants of the eu_t* functions are used to avoid unnecessary double locking. lib/ * eu-search.c: Add eu_tsearch_nolock, eu_tfind_nolock and eu_tdelete_nolock functions. * eu-search.h: Ditto. libdw/ * cfi.h (struct Dwarf_CFI_s): Declare new mutex. * dwarf_begin_elf.c (valid_p): Initialize all locks for fake CUs. * dwarf_cfi_addrframe.c (dwarf_cfi_addrframe): Place lock around __libdw_find_fde. * dwarf_end.c (cu_free): Deallocate all locks unconditionally, whether or not the CU is fake. * dwarf_frame_cfa.c (dwarf_frame_cfa): Place lock around __libdw_intern_expression. * dwarf_frame_register.c (dwarf_frame_register): Ditto. * dwarf_getcfi.c (dwarf_getcfi): Initialize cfi lock. * dwarf_getlocation.c (is_constant_offset): Synchronize access to lazy loading section. (getlocation): Place lock around __libdw_intern_expression. * dwarf_getmacros.c (cache_op_table): Synchronize access to lazy loading section. * frame-cache.c (__libdw_destroy_frame_cache): Free Dwarf_CFI mutex. * libdwP.h (struct Dwarf): Update macro_lock comment. (struct Dwarf_CU): Declare new mutex. libdw_findcu.c (__libdw_intern_next_unit): Initialize intern_lock. (__libdw_findcu): Adjust locking so that the first eu_tfind can be done without extra lock overhead. Signed-off-by: Aaron Merey <[email protected]>
* lib: Add eu_tsearch, eu_tfind, eu_tdelete and eu_tdestroyHeather McIntyre2024-08-201-1/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Add struct search_tree to hold tree root and lock. Add new eu_t* functions for ensuring synchronized tree access. Replace tsearch, tfind, etc with eu_t* equivalents. lib: * Makefile.am (libeu_a_SOURCES): Add eu-search.c. (noinst_HEADERS): Add eu-search.h and locks.h. * eu-config.h: Move rwlock macros to locks.h. * eu-search.c: New file containing tree search functions with locking. * eu-search.h: New file. * locks.h: New file containing rwlock macros previously in eu-config.h. libdw: * cfi.h (struct Dwarf_CFI_s): Change type of search tree members from void * to search_tree. * cie.c: Replace tree search functions with eu-search equivalents. * dwarf_begin_elf.c (valid_p): Initialize search trees. * dwarf_end.c (cu_free): Replace tree search functions with eu-search equivalents. * dwarf_getcfi.c (dwarf_getcfi): Initialize search trees. * dwarf_getlocations.c: Replace search tree functions with eu-search equivalents. (__libdw_intern_expression): Change type of cache parameter to search_tree *. * dwarf_getmacros.c: Replace tree search functions with eu-search equivalents. * dwarf_getsrclines.c: Ditto. * fde.c: Ditto. * frame-cache.c (__libdw_destroy_frame_cache): Initialize search trees. * libdwP.h (struct Dwarf): Change type of search tree members from void * to search_tree. (struct Dwarf_CU): Ditto. (__libdw_intern_expression): Change type of cache parameter to search_tree *. * libdw_find_split_unit.c: Replace tree search functions with eu-search equivalents. * libdw_findcu.c: Ditto. libdwfl: * cu.c: Ditto. * libdwflP.h (struct Dwfl_Module): Replace void *lazy_cu_root with search_tree lazy_cu_tree. libelf: * elf_begin.c (file_read_elf): Initialize rawchunck_tree. * elf_end.c (elf_end): Replace tree search function with eu-search equivalent. * elf_getdata_rawchunck.c: Ditto. * libelfP.h (struct Elf): Replace void * rawchuncks member with search_tree rawchunk_tree. Signed-off-by: Heather S. McIntyre <[email protected]> Signed-off-by: Aaron Merey <[email protected]> Signed-off-by: Mark Wielaard <[email protected]>
* libdw,readelf: Recognize DW_CFA_AARCH64_negate_ra_stateMark Wielaard2020-09-071-0/+5
| | | | | | | | | | | | | | | | | | | | DW_CFA_AARCH64_negate_ra_state is used on aarch64 to indicate whether or not the return address is mangled or not. This has the same value as the DW_CFA_GNU_window_save. So we have to pass around the e_machine value of the process or core we are inspecting to know which one to use. Note that it isn't actually implemented yet. It needs ARMv8.3 hardware. If we don't have such hardware it is enough to simply ignore the DW_CFA_AARCH64_negate_ra_state (and not confuse it with DW_CFA_GNU_window_save) to get backtraces to work on aarch64. Add a testcase for eu-readelf --debug-dump=frames to show the value is correctly recognized. Also don't warn we cannot find any DWARF if we are just dumping frames (those will come from .eh_frame if there is no .debug_frame). Signed-off-by: Mark Wielaard <[email protected]>
* libdw: fix latent bug in dwarf_getcfi.c not setting default_same_value.Jonathon Anderson2019-08-261-0/+1
| | | | Signed-off-by: Jonathon Anderson <[email protected]>
* Remove old-style function definitions.Mark Wielaard2015-09-231-2/+1
| | | | | | | We already require -std=gnu99 and old-style function definitions might hide some compiler warnings. Signed-off-by: Mark Wielaard <[email protected]>
* Update name, license and contributor policy.Mark Wielaard2012-06-051-40/+19
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * Change name from "Red Hat elfutils" to "elfutils". * Update license of standalone tools and test from GPLv2 to GPLv3+. * Change license of libraries from GPLv2+exception to GPLv2/LGPLv3+. * Add Developer Certificate of Origin based contributor policy. top-level: - COPYING: Upgraded from GPLv2 to GPLv3. - CONTRIBUTING, COPYING-GPLv2, COPYING-LGPLv3: New files. - NEWS: Added note about new contribution and license policy. - Makefile.am: Updated to GPLv3, added new files to EXTRA_DIST. - configure.ac: Update to GPLv3, changed AC_INIT name to 'elfutils'. backends, lib, libasm, libcpu, libdw, libdwfl, libebl, libelf: - All files updated to GPLv2/LGPLv3+. Except some very small files (<5 lines) which didn't have any headers at all before, the linker .maps files and the libcpu/defs files which only contain data and libelf/elf.h which comes from glibc and is under LGPLv2+. config: - elfutils.spec.in: Add new License: headers and new %doc files. - Update all license headers to GPLv2/LGPLv3+ for files used by libs. src, tests: - All files updated to GPLv3+. Except for the test bz2 data files, the linker maps and script files and some very small files (<5 lines) that don't have any headers. Signed-off-by: Richard Fontana <[email protected]> Signed-off-by: Mark Wielaard <[email protected]>
* Clear cfi->ebl in dwarf_getcfi().Mark Wielaard2009-09-091-0/+2
|
* CFI support: lookup by PC and translate into DWARF location per registerRoland McGrath2009-07-081-0/+92