From fe09ca800b988e2ff21225ac5e7468ceade2a30e Mon Sep 17 00:00:00 2001 From: Jeremy Rifkin <51220084+jeremy-rifkin@users.noreply.github.com> Date: Tue, 3 Dec 2024 23:07:45 -0600 Subject: [PATCH] Bump to v0.11.1 --- CMakeLists.txt | 11 +- pull.sh | 9 +- src/lib/libdwarf/CMakeLists.txt | 5 + src/lib/libdwarf/dwarf_alloc.c | 11 +- src/lib/libdwarf/dwarf_debugaddr.c | 9 + src/lib/libdwarf/dwarf_debugnames.c | 29 +- src/lib/libdwarf/dwarf_die_deliv.c | 85 +- src/lib/libdwarf/dwarf_errmsg_list.h | 5 +- src/lib/libdwarf/dwarf_error.c | 15 +- src/lib/libdwarf/dwarf_fission_to_cu.c | 26 + src/lib/libdwarf/dwarf_form.c | 36 +- src/lib/libdwarf/dwarf_generic_init.c | 123 ++- src/lib/libdwarf/dwarf_gnu_index.c | 14 +- src/lib/libdwarf/dwarf_harmless.c | 4 +- src/lib/libdwarf/dwarf_init_finish.c | 10 +- src/lib/libdwarf/dwarf_line.c | 18 +- .../libdwarf/dwarf_line_table_reader_common.h | 7 +- src/lib/libdwarf/dwarf_loc.c | 130 ++- src/lib/libdwarf/dwarf_loc.h | 9 +- src/lib/libdwarf/dwarf_loclists.c | 396 +++++---- src/lib/libdwarf/dwarf_machoread.c | 6 + src/lib/libdwarf/dwarf_macro.c | 5 +- src/lib/libdwarf/dwarf_macro5.c | 2 +- src/lib/libdwarf/dwarf_names.c | 2 +- src/lib/libdwarf/dwarf_opaque.h | 90 ++- src/lib/libdwarf/dwarf_peread.c | 6 +- src/lib/libdwarf/dwarf_query.c | 172 ++-- src/lib/libdwarf/dwarf_ranges.c | 109 +-- src/lib/libdwarf/dwarf_rnglists.c | 756 ++++++++++-------- src/lib/libdwarf/dwarf_rnglists.h | 6 +- src/lib/libdwarf/dwarf_setup_sections.c | 26 +- src/lib/libdwarf/dwarf_tied.c | 21 +- src/lib/libdwarf/dwarf_tsearchhash.c | 6 +- src/lib/libdwarf/dwarf_util.c | 210 +++-- src/lib/libdwarf/dwarf_util.h | 2 - src/lib/libdwarf/libdwarf.h | 43 +- 36 files changed, 1537 insertions(+), 877 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 28f33ed..133523b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.5) -project(libdwarf VERSION 0.11.0 +project(libdwarf VERSION 0.11.1 DESCRIPTION "Library to access DWARF debugging information" HOMEPAGE_URL "https://github.com/davea42/libdwarf-code.git" LANGUAGES C CXX) @@ -183,7 +183,9 @@ else() message(STATUS "intptr_t value considered NO ") endif() +message(STATUS "ENABLE_DECOMPRESSION : " ${ENABLE_DECOMPRESSION}) if (ENABLE_DECOMPRESSION) + #message(STATUS "In ENABLE_DECOMPRESSION setup: TRUE") # Zlib and ZSTD need to be found otherwise disable it if(NOT TARGET ZLIB::ZLIB) find_package(ZLIB) @@ -226,9 +228,14 @@ if (ENABLE_DECOMPRESSION) set(HAVE_ZSTD_H TRUE) set(BUILT_WITH_ZLIB_AND_ZSTD TRUE) endif() + message(STATUS "Found libzstd : ${zstd_FOUND}") + message(STATUS "Found zlib : ${ZLIB_FOUND}") + message(STATUS "Build with zlib and zstd: ${BUILT_WITH_ZLIB_AND_ZSTD}") +else() + message(STATUS "Build with zlib and zstd: NO") endif () -message(STATUS "CMAKE_SIZEOF_VOID_P ... " ${CMAKE_SIZEOF_VOID_P} ) +message(STATUS "CMAKE_SIZEOF_VOID_P ... : ${CMAKE_SIZEOF_VOID_P}") # DW_FWALLXX are gnu C++ options. if (WALL) diff --git a/pull.sh b/pull.sh index afbf685..4b0e76a 100644 --- a/pull.sh +++ b/pull.sh @@ -5,12 +5,13 @@ rm -rfv cmake src CMakeLists.txt COPYING echo "Fetching" git clone https://github.com/davea42/libdwarf-code.git cd libdwarf-code -#git checkout "6216e185863f41d6f19ab850caabfff7326020d7" # v0.8.0 -#git checkout "8b0bd09d8c77d45a68cb1bb00a54186a92b683d9" # v0.9.0 -#git checkout "8cdcc531f310d1c5ae61da469d8056bdd36b77e7" # v0.9.1 + cmake fixes +# git checkout "6216e185863f41d6f19ab850caabfff7326020d7" # v0.8.0 +# git checkout "8b0bd09d8c77d45a68cb1bb00a54186a92b683d9" # v0.9.0 +# git checkout "8cdcc531f310d1c5ae61da469d8056bdd36b77e7" # v0.9.1 + cmake fixes # git checkout "5e43a5ab73cb00c8a46660b361366a8c9c3c93c9" # v0.9.2 # git checkout "45ef8e2763f65c31b27cc38bed197b84dc1441d4" # v0.10.2 -git checkout "285d9d34f3e9f56cc1c487d0055f6dc54a9c54a1" # v0.11.0 +# git checkout "285d9d34f3e9f56cc1c487d0055f6dc54a9c54a1" # v0.11.0 +git checkout "909af3e46b68335df6c4a901ddd256ffa0d193d2" # v0.11.1 cd .. echo "Copying files" mkdir -p src/lib diff --git a/src/lib/libdwarf/CMakeLists.txt b/src/lib/libdwarf/CMakeLists.txt index 0278755..98b7507 100644 --- a/src/lib/libdwarf/CMakeLists.txt +++ b/src/lib/libdwarf/CMakeLists.txt @@ -135,5 +135,10 @@ install(EXPORT libdwarfTargets FILE libdwarf-targets.cmake NAMESPACE libdwarf:: DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/libdwarf") +export( + TARGETS dwarf + NAMESPACE libdwarf:: + FILE "${PROJECT_BINARY_DIR}/libdwarf-targets.cmake" +) install(FILES "${PROJECT_BINARY_DIR}/src/lib/libdwarf/libdwarf.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") install(FILES "${PROJECT_SOURCE_DIR}/cmake/Findzstd.cmake" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/libdwarf") diff --git a/src/lib/libdwarf/dwarf_alloc.c b/src/lib/libdwarf/dwarf_alloc.c index 73ed947..a0ec5e9 100644 --- a/src/lib/libdwarf/dwarf_alloc.c +++ b/src/lib/libdwarf/dwarf_alloc.c @@ -749,6 +749,8 @@ string_is_in_debug_section(Dwarf_Debug dbg,void * space) It is too late to change the documentation. */ void *result = 0; + + /* The alloc tree can be in main or tied or both. */ result = dwarf_tfind((void *)space, &dbg->de_alloc_tree,simple_compare_function); if (!result) { @@ -849,9 +851,6 @@ dwarf_dealloc(Dwarf_Debug dbg, unsigned int type = 0; char * malloc_addr = 0; struct reserve_data_s * r = 0; -#if 0 - Dwarf_Bool check_errmsg_list = FALSE; -#endif if (!space) { #ifdef DEBUG_ALLOC @@ -884,6 +883,9 @@ dwarf_dealloc(Dwarf_Debug dbg, return; #endif /* DEBUG_ALLOC*/ } + if (dbg && alloc_type == DW_DLA_ERROR) { + dbg = dbg->de_errors_dbg; + } if (dbg && dbg->de_alloc_tree) { /* If it's a string in debug_info etc doing (char *)space - DW_RESERVE is totally bogus. */ @@ -969,9 +971,6 @@ dwarf_dealloc(Dwarf_Debug dbg, if (ep->er_static_alloc == DE_MALLOC) { /* This is special, we had no arena but have a full special area as normal. */ -#if 0 - check_errmsg_list = TRUE; -#endif #ifdef DEBUG_ALLOC printf("DEALLOC does free, DE_MALLOC line %d %s\n", __LINE__,__FILE__); diff --git a/src/lib/libdwarf/dwarf_debugaddr.c b/src/lib/libdwarf/dwarf_debugaddr.c index 8b4e87c..3ff6a14 100644 --- a/src/lib/libdwarf/dwarf_debugaddr.c +++ b/src/lib/libdwarf/dwarf_debugaddr.c @@ -196,6 +196,15 @@ dwarf_debug_addr_table(Dwarf_Debug dbg, return DW_DLV_ERROR; } tab.da_dbg = dbg; + tablelen = 0; + if (arealen <= 4) { + _dwarf_error_string(dbg,error, + DW_DLE_SECTION_SIZE_ERROR, + "DW_DLE_SECTION_SIZE_ERROR: " + "The end of a .debug_addr header record is missing, " + "corrupt DWARF"); + return DW_DLV_ERROR; + } tablelen = arealen - 4; /* 4: the rest of the header */ tab.da_length = tablelen; curlocaloffset = offset_size + exten_size; diff --git a/src/lib/libdwarf/dwarf_debugnames.c b/src/lib/libdwarf/dwarf_debugnames.c index 2b40569..2fc9a0d 100644 --- a/src/lib/libdwarf/dwarf_debugnames.c +++ b/src/lib/libdwarf/dwarf_debugnames.c @@ -1694,8 +1694,27 @@ isformrefval(Dwarf_Debug dbg,Dwarf_Half form, Dwarf_Unsigned *bytesread, Dwarf_Error *error) { - Dwarf_Unsigned localval =0; + Dwarf_Unsigned localval = 0; + if (poolptr >= endpool) { + dwarfstring m; + const char * formname = 0; + + dwarfstring_constructor(&m); + dwarfstring_append_printf_u(&m, + "DW_DLE_DEBUG_NAMES_OFF_END: " + "Reading data of form 0x%02x ",form); + dwarf_get_FORM_name((unsigned int)form,&formname); + dwarfstring_append_printf_s(&m, + "%s from entrypool would read " + "off the end of the pool", + (char *)formname); + _dwarf_error_string(dbg,error, + DW_DLE_DEBUG_NAMES_OFF_END, + dwarfstring_string(&m)); + dwarfstring_destructor(&m); + return DW_DLV_ERROR; + } switch(form) { case DW_FORM_ref1: *val = *poolptr; @@ -1771,6 +1790,7 @@ int dwarf_dnames_entrypool_values(Dwarf_Dnames_Head dn, /* make error or harmless error? */ return DW_DLV_NO_ENTRY; } + if (index_of_abbrev >= dn->dn_abbrev_instance_count) { /* make error or harmless error? */ return DW_DLV_NO_ENTRY; @@ -1854,6 +1874,10 @@ int dwarf_dnames_entrypool_values(Dwarf_Dnames_Head dn, array_of_offsets[n] = val; continue; + } else if (form == DW_FORM_flag_present) { + array_of_offsets[n] = 1; + /* No change to poolptr or pooloffset */ + continue; } else { Dwarf_Unsigned val = 0; res =isformrefval(dbg,form,poolptr, @@ -1863,7 +1887,7 @@ int dwarf_dnames_entrypool_values(Dwarf_Dnames_Head dn, } if (res == DW_DLV_OK) { poolptr += bytesread; - if (poolptr > endpool) { + if (poolptr >= endpool) { _dwarf_error_string(dbg,error, DW_DLE_DEBUG_NAMES_ENTRYPOOL_OFFSET, "DW_DLE_DEBUG_NAMES_ENTRYPOOL_OFFSET:" @@ -1871,7 +1895,6 @@ int dwarf_dnames_entrypool_values(Dwarf_Dnames_Head dn, " of the entrypool"); return DW_DLV_ERROR; } - poolptr += bytesread; pooloffset += bytesread; array_of_offsets[n] = val; continue; diff --git a/src/lib/libdwarf/dwarf_die_deliv.c b/src/lib/libdwarf/dwarf_die_deliv.c index b568014..7d7a164 100644 --- a/src/lib/libdwarf/dwarf_die_deliv.c +++ b/src/lib/libdwarf/dwarf_die_deliv.c @@ -1185,7 +1185,6 @@ _dwarf_setup_base_address(Dwarf_Debug dbg, { int lres = 0; Dwarf_Half form = 0; - /* If the form is indexed, we better have seen DW_AT_addr_base.! */ lres = dwarf_whatform(attr,&form,error); @@ -1226,6 +1225,8 @@ _dwarf_setup_base_address(Dwarf_Debug dbg, if it was DW_AT_entry_pc with no DW_AT_low_pc Allowing DW_AT_entry_pc */ cucon->cc_low_pc_present = TRUE; + cucon->cc_base_address_present = TRUE; + cucon->cc_base_address = cucon->cc_low_pc; } else { /* Something is badly wrong. */ return lres; @@ -1290,6 +1291,8 @@ set_producer_type(Dwarf_Die die, } if (_dwarf_prod_contains("Metrowerks",producer)) { cu_context->cc_producer = CC_PROD_METROWERKS; + } else if (_dwarf_prod_contains("Apple",producer)) { + cu_context->cc_producer = CC_PROD_Apple; } } @@ -1318,7 +1321,6 @@ find_cu_die_base_fields(Dwarf_Debug dbg, cu_context = cudie->di_cu_context; version_stamp = cu_context->cc_version_stamp; - alres = dwarf_attrlist(cudie, &alist, &atcount,error); if (alres != DW_DLV_OK) { @@ -1445,10 +1447,6 @@ find_cu_die_base_fields(Dwarf_Debug dbg, int res = 0; Dwarf_Bool is_info = cucon->cc_is_info; -#if 0 - res = dwarf_global_formref(attr, - &at_ranges_offset,error); -#endif res = _dwarf_internal_global_formref_b(attr, /* avoid recurse creating context */ 1, &at_ranges_offset, @@ -1519,14 +1517,14 @@ find_cu_die_base_fields(Dwarf_Debug dbg, udres = _dwarf_internal_global_formref_b(attr, /* avoid recurse creating context */ 1, - &cucon->cc_addr_base, + &cucon->cc_addr_base_offset, &is_info, error); if (udres == DW_DLV_OK) { if (is_info == cucon->cc_is_info) { /* Only accept if same .debug section, which is relevant for DWARF4 */ - cucon->cc_addr_base_present = TRUE; + cucon->cc_addr_base_offset_present = TRUE; } } else { local_attrlist_dealloc(dbg,atcount,alist); @@ -1551,7 +1549,10 @@ find_cu_die_base_fields(Dwarf_Debug dbg, it refers to .debug_ranges. Note that this base applies when referencing from the dwp, but NOT - when referencing from the a.out */ + when referencing from the a.out + + In DW4 extension split dwarf the .debug_ranges + is always in the tied-file (executable). */ int udres = 0; Dwarf_Bool is_info = cucon->cc_is_info; @@ -1610,22 +1611,10 @@ find_cu_die_base_fields(Dwarf_Debug dbg, } } } - if (low_pc_attrnum >= 0 ){ - int battr = 0; - - /* Prefer DW_AT_low_pc */ - Dwarf_Attribute attr = alist[low_pc_attrnum]; - battr = _dwarf_setup_base_address(dbg,"DW_AT_low_pc", - attr,at_addr_base_attrnum, cucon, - bad_pc_form,error); - if (battr != DW_DLV_OK) { - local_attrlist_dealloc(dbg,atcount,alist); - /* Something is wrong, possibly - erroneous Macrowerks compiler. */ - _dwarf_set_children_flag(cucon,cudie); - return battr; - } - } else if (entry_pc_attrnum >= 0) { + /* Only on Apple do we let entry_pc + be used as base address. */ + if (entry_pc_attrnum >= 0 && + cucon->cc_producer == CC_PROD_Apple) { int battr = 0; /* Pretending that DW_AT_entry_pc with no @@ -1636,7 +1625,8 @@ find_cu_die_base_fields(Dwarf_Debug dbg, base address (DW_AT_entry_pc first appears in DWARF3). So we allow that as an extension, as a 'low_pc' if there is DW_AT_entry_pc with - no DW_AT_low_pc. 19 May 2022. */ + no DW_AT_low_pc. 19 May 2022. + Also used by gcc with a DWARF4 split-dwarf extension. */ Dwarf_Attribute attr = alist[entry_pc_attrnum]; battr = _dwarf_setup_base_address(dbg,"DW_AT_entry_pc", attr,at_addr_base_attrnum, cucon, @@ -1648,6 +1638,21 @@ find_cu_die_base_fields(Dwarf_Debug dbg, return battr; } } + if (low_pc_attrnum >= 0 ){ + int battr = 0; + + Dwarf_Attribute attr = alist[low_pc_attrnum]; + battr = _dwarf_setup_base_address(dbg,"DW_AT_low_pc", + attr,at_addr_base_attrnum, cucon, + bad_pc_form,error); + if (battr != DW_DLV_OK) { + local_attrlist_dealloc(dbg,atcount,alist); + /* Something is wrong, possibly + erroneous Macrowerks compiler. */ + _dwarf_set_children_flag(cucon,cudie); + return battr; + } + } local_attrlist_dealloc(dbg,atcount,alist); alist = 0; atcount = 0; @@ -1655,7 +1660,10 @@ find_cu_die_base_fields(Dwarf_Debug dbg, return DW_DLV_OK; } -/* Called only for DWARF4 */ +/* Called only for DWARF4 and earlier + so there is consistent naming of unit_type + even though there was no such field in + DWARF2-DWARF4. */ static void assign_correct_unit_type(Dwarf_CU_Context cu_context) { @@ -1737,7 +1745,9 @@ finish_up_cu_context_from_cudie(Dwarf_Debug dbg, if (cu_context->cc_signature_present) { /* For finding base data from skeleton. For the few fields inherited - (per the DWARF5 standard. */ + (per the DWARF5 standard but for + .debug_rnglists is not interited + in spite of what DW5 says). */ res = _dwarf_find_all_offsets_via_fission(dbg, cu_context,error); if (res == DW_DLV_ERROR) { @@ -1952,8 +1962,8 @@ _dwarf_load_die_containing_section(Dwarf_Debug dbg, int _dwarf_next_cu_header_internal(Dwarf_Debug dbg, - Dwarf_Bool is_info, - Dwarf_Die *cu_die_out, + Dwarf_Bool is_info, + Dwarf_Die * cu_die_out, Dwarf_Unsigned * cu_header_length, Dwarf_Half * version_stamp, Dwarf_Unsigned * abbrev_offset, @@ -2088,14 +2098,17 @@ _dwarf_next_cu_header_internal(Dwarf_Debug dbg, } { Dwarf_Debug tieddbg = 0; - int tres = 0; - tieddbg = dbg->de_tied_data.td_tied_object; - if (tieddbg) { + int tres = DW_DLV_OK; + tieddbg = dbg->de_secondary_dbg; + if (DBG_IS_PRIMARY(dbg) && DBG_IS_SECONDARY(tieddbg)) { + /* We are in the main, merge tied + into main cu_context */ tres = _dwarf_merge_all_base_attrs_of_cu_die( - dbg, cu_context, - tieddbg, 0, + cu_context, + tieddbg, + 0 /* we do not want the context returned */, error); - } + } /* Else no merge */ if (tres == DW_DLV_ERROR && error) { /* We'll assume any errors will be discovered later. Lets get our diff --git a/src/lib/libdwarf/dwarf_errmsg_list.h b/src/lib/libdwarf/dwarf_errmsg_list.h index 71a5ce6..15862df 100644 --- a/src/lib/libdwarf/dwarf_errmsg_list.h +++ b/src/lib/libdwarf/dwarf_errmsg_list.h @@ -688,7 +688,8 @@ static const char _dwarf_errmsgs[DW_DLE_LAST+1][DW_MAX_MSG_LEN] = { {"DW_DLE_UNIV_BIN_OFFSET_SIZE_ERROR(503) Offset/size from " "a Mach-O universal binary has an impossible value"}, {"DW_DLE_PE_SECTION_SIZE_HEURISTIC_FAIL(504) Section size fails " - "a heuristic sanity check"} - + "a heuristic sanity check"}, +{"DW_DLE_LLE_ERROR(505) Generic .debug_loclists read error"}, +{"DW_DLE_RLE_ERROR(506) Generic .debug_rnglists read error"} }; #endif /* DWARF_ERRMSG_LIST_H */ diff --git a/src/lib/libdwarf/dwarf_error.c b/src/lib/libdwarf/dwarf_error.c index 73f60f2..be801b3 100644 --- a/src/lib/libdwarf/dwarf_error.c +++ b/src/lib/libdwarf/dwarf_error.c @@ -110,6 +110,9 @@ _dwarf_error(Dwarf_Debug dbg, Dwarf_Error * error, { _dwarf_error_string(dbg,error,errval,0); } + +/* Errors are all added to the de_primary_dbg, never to + de_secondary_dbg. */ void _dwarf_error_string(Dwarf_Debug dbg, Dwarf_Error * error, Dwarf_Signed errval,char *msg) @@ -123,8 +126,13 @@ _dwarf_error_string(Dwarf_Debug dbg, Dwarf_Error * error, /* If dbg is NULL, use the alternate error struct. However, this will overwrite the earlier error. */ if (dbg) { + /* ERRORs are always associated with + de_primary_dbg so they can be returned + up the tree of calls on the stack + safely. */ errptr = - (Dwarf_Error) _dwarf_get_alloc(dbg, DW_DLA_ERROR, 1); + (Dwarf_Error) _dwarf_get_alloc(dbg->de_errors_dbg, + DW_DLA_ERROR, 1); if (!errptr) { errptr = &_dwarf_failsafe_error; errptr->er_static_alloc = DE_STATIC; @@ -182,13 +190,14 @@ _dwarf_error_string(Dwarf_Debug dbg, Dwarf_Error * error, } if (dbg && dbg->de_errhand != NULL) { - errptr = (Dwarf_Error) _dwarf_get_alloc(dbg, DW_DLA_ERROR, 1); + errptr = (Dwarf_Error) _dwarf_get_alloc(dbg->de_errors_dbg, + DW_DLA_ERROR, 1); if (errptr == NULL) { errptr = &_dwarf_failsafe_error; errptr->er_static_alloc = DE_STATIC; } errptr->er_errval = errval; - dbg->de_errhand(errptr, dbg->de_errarg); + dbg->de_errhand(errptr, dbg->de_errors_dbg->de_errarg); return; } fflush(stderr); diff --git a/src/lib/libdwarf/dwarf_fission_to_cu.c b/src/lib/libdwarf/dwarf_fission_to_cu.c index 8e8e564..bedba41 100644 --- a/src/lib/libdwarf/dwarf_fission_to_cu.c +++ b/src/lib/libdwarf/dwarf_fission_to_cu.c @@ -49,6 +49,27 @@ #include "dwarf_loclists.h" #include "dwarf_rnglists.h" +/* RETURNS DW_DLV_OK and sets values + through the return-value pointers. + Or returns DW_DLV_NO_ENTRY */ +int +_dwarf_has_SECT_fission(Dwarf_CU_Context ctx, + unsigned int SECT_number, + Dwarf_Bool *hasfissionoffset, + Dwarf_Unsigned *loclistsbase) +{ + struct Dwarf_Debug_Fission_Per_CU_s *fis = 0; + Dwarf_Unsigned fisindex = SECT_number; + + fis = &ctx->cc_dwp_offsets; + if (fis->pcu_type && fis->pcu_size[fisindex]) { + *loclistsbase = fis->pcu_offset[fisindex]; + *hasfissionoffset = TRUE; + return DW_DLV_OK; + } + return DW_DLV_NO_ENTRY; +} + /* ASSERT: dbg,cu_context, and fsd are non-NULL as the caller ensured that. With no DW_AT_loclists_base this computes one. */ @@ -270,8 +291,13 @@ load_xu_rnglists_into_cucontext(Dwarf_Debug dbg, if (res != DW_DLV_OK) { return res; } + cu_context->cc_rnglists_base = buildhere->rc_offsets_off_in_sect; +printf("debug SET rnglists base from rc_offsetts_off_in_sectt: " +"0x%lx lie %d\n", +(unsigned long)cu_context->cc_rnglists_base, +__LINE__); cu_context->cc_rnglists_base_present = TRUE; cu_context->cc_rnglists_base_contr_size = size; /* FIXME cc_rnglists_header_length_present? */ diff --git a/src/lib/libdwarf/dwarf_form.c b/src/lib/libdwarf/dwarf_form.c index 2d2812e..f02c62e 100644 --- a/src/lib/libdwarf/dwarf_form.c +++ b/src/lib/libdwarf/dwarf_form.c @@ -741,7 +741,7 @@ dwarf_global_formref(Dwarf_Attribute attr, return res; } -/* If context_level is 0, normal call +/* If context_level is 0, normal call But if non-zero will avoid creating CU Context. */ int dwarf_global_formref_b(Dwarf_Attribute attr, @@ -750,13 +750,16 @@ dwarf_global_formref_b(Dwarf_Attribute attr, Dwarf_Error * error) { int res = 0; + int context_level = 0; res = _dwarf_internal_global_formref_b( attr, - 0, + context_level, ret_offset, offset_is_info, error); return res; } +/* If context_level is 0, normal call + But if non-zero will avoid creating CU Context. */ int _dwarf_internal_global_formref_b(Dwarf_Attribute attr, int context_level, @@ -987,7 +990,7 @@ _dwarf_internal_global_formref_b(Dwarf_Attribute attr, dwarfstring_constructor(&m); dwarfstring_append_printf_u(&m, - "DW_DLE_BAD_REF_FORM: The form code is 0x%x ", + "DW_DLE_BAD_REF_FORM: The form code is 0x%x.. ", formcode); fcres = dwarf_get_FORM_name (formcode,&name); if (fcres != DW_DLV_OK) { @@ -1070,6 +1073,7 @@ _dwarf_get_addr_index_itself(int theform, to a local .debug_addr or a tied file .debug_addr so lets be cautious. */ #if 0 /* Attempted check for index uncertain, unwise. Ignore. */ + /* See de_secondary_dbg before using this */ if (!dbg->de_tied_data.td_tied_object && index > dbg->de_filesize) { _dwarf_error_string(dbg,error,DW_DLE_ATTR_FORM_OFFSET_BAD, @@ -1403,7 +1407,8 @@ _dwarf_allow_formudata(unsigned form) case DW_FORM_data2: case DW_FORM_data4: case DW_FORM_data8: - case DW_FORM_udata: + case DW_FORM_flag: + case DW_FORM_flag_present: case DW_FORM_loclistx: case DW_FORM_rnglistx: return TRUE; @@ -1446,6 +1451,18 @@ _dwarf_formudata_internal(Dwarf_Debug dbg, *return_uval = ret_value; *bytes_read = 1; return DW_DLV_OK; + case DW_FORM_flag_present: + *return_uval = 1; + *bytes_read = 0; + return DW_DLV_OK; + case DW_FORM_flag: + /* equivalent to dwarf_formflag() */ + READ_UNALIGNED_CK(dbg, ret_value, Dwarf_Unsigned, + data, sizeof(Dwarf_Small), + error,section_end); + *return_uval = ret_value; + *bytes_read = 1; + return DW_DLV_OK; /* READ_UNALIGNED does the right thing as it reads the right number bits and generates host order. @@ -2082,7 +2099,8 @@ dwarf_formstring(Dwarf_Attribute attr, if (res == DW_DLV_ERROR) { if (dwarf_errno(alterr) == DW_DLE_NO_TIED_FILE_AVAILABLE) { - dwarf_dealloc(dbg,alterr,DW_DLA_ERROR); + + dwarf_dealloc_error(dbg,alterr); if ( attr->ar_attribute_form == DW_FORM_GNU_strp_alt) { *return_str = @@ -2168,17 +2186,17 @@ _dwarf_get_string_from_tied(Dwarf_Debug dbg, Dwarf_Error localerror = 0; /* Attach errors to dbg, not tieddbg. */ - tieddbg = dbg->de_tied_data.td_tied_object; - if (!tieddbg) { + if (!DBG_HAS_SECONDARY(dbg)) { _dwarf_error(dbg, error, DW_DLE_NO_TIED_FILE_AVAILABLE); return DW_DLV_ERROR; } + tieddbg = dbg->de_secondary_dbg; /* The 'offset' into .debug_str is set. */ res = _dwarf_load_section(tieddbg, &tieddbg->de_debug_str, &localerror); if (res == DW_DLV_ERROR) { Dwarf_Unsigned lerrno = dwarf_errno(localerror); - dwarf_dealloc(tieddbg,localerror,DW_DLA_ERROR); + dwarf_dealloc_error(tieddbg,localerror); _dwarf_error(dbg,error,lerrno); return res; } @@ -2205,7 +2223,7 @@ _dwarf_get_string_from_tied(Dwarf_Debug dbg, &localerror); if (res == DW_DLV_ERROR) { Dwarf_Unsigned lerrno = dwarf_errno(localerror); - dwarf_dealloc(tieddbg,localerror,DW_DLA_ERROR); + dwarf_dealloc_error(tieddbg,localerror); _dwarf_error(dbg,error,lerrno); return res; } diff --git a/src/lib/libdwarf/dwarf_generic_init.c b/src/lib/libdwarf/dwarf_generic_init.c index 3ff8778..c8e6c30 100644 --- a/src/lib/libdwarf/dwarf_generic_init.c +++ b/src/lib/libdwarf/dwarf_generic_init.c @@ -78,6 +78,54 @@ dwarf_init_path_dl(path true_path and globals, dbg1 #include "dwarf_error.h" #include "dwarf_object_detector.h" +/* The design of Dwarf_Debug_s data on --file-tied +data and how it is used. See also dwarf_opaque.h +and dwarf_util.c + +The fields involved are +de_dbg +de_primary_dbg +de_secondary_dbg +de_errors_dbg +de_tied_data.td_tied_object + +On any init completing it will be considered + primary, Call it p1. + p1->de_dbg == p1 + p1->de_primary_dbg == p1 + p1->de_secondary_dbg == NULL + p1->de_errors_dbg == p1 + p1->de_tied_data.td_tied_object = 0 +Init a second object, call it p2 (settings as above). + +Call dwarf_set_tied (p1,p2) (it is ok if p2 == NULL) + p1 is as above except that + p1->de_secondary_dbg == p2 + p1->de_tied_data.td_tied_object = p2; + If p2 is non-null: + p2->de_dbg == p2 + p2->de_primary_dbg = p1. + p2->de_secondary_dbg = p2 + p2->de_errors_dbg = p1 +All this is only useful if p1 has dwo/dwp sections +(split-dwarf) and p2 has the relevant TAG_skeleton(s) + +If px->de_secondary_dbg is non-null + and px->secondary_dbg == px + then px is secondary. + +If x->de_secondary_dbg is non-null + and px->secondary_dbg != px + then px is primary. + +If px->de_secondary_dbg is null + then px is a primary. and there + is no secondary. + + Call dwarf_set_tied(p1,NULL) and both p1 and + p2 are returned to initial conditions + as before they were tied together. */ + static int set_global_paths_init(Dwarf_Debug dbg, Dwarf_Error* error) { @@ -513,31 +561,78 @@ dwarf_finish(Dwarf_Debug dbg) tieddbg should be the executable or .o that has the .debug_addr section that the base dbg refers to. See Split Objects in DWARF5. + Or in DWARF5 maybe .debug_rnglists or .debug_loclists. - Allows setting to NULL (NULL is the default - of de_tied_data.td_tied_object). + Allows calling with NULL though we really just set + primary_dbg->ge_primary to de_primary_dbg, thus cutting + links between main and any previous tied-file setup. New September 2015. + Logic revised Nov 2024. See dwarf_opaque.h */ int -dwarf_set_tied_dbg(Dwarf_Debug dbg, - Dwarf_Debug tieddbg, +dwarf_set_tied_dbg(Dwarf_Debug primary_dbg, + Dwarf_Debug secondary_dbg, Dwarf_Error*error) { - CHECK_DBG(dbg,error,"dwarf_set_tied_dbg()"); - - dbg->de_tied_data.td_tied_object = tieddbg; - if (tieddbg) { - tieddbg->de_tied_data.td_is_tied_object = TRUE; + CHECK_DBG(primary_dbg,error,"dwarf_set_tied_dbg()"); + if (secondary_dbg == primary_dbg) { + _dwarf_error_string(primary_dbg,error, + DW_DLE_NO_TIED_FILE_AVAILABLE, + "DW_DLE_NO_TIED_FILE_AVAILABLE: bad argument to " + "dwarf_set_tied_dbg(), tied and main must not be the " + "same pointer!"); + return DW_DLV_ERROR; + } + if (secondary_dbg) { + if (primary_dbg->de_secondary_dbg ) { + _dwarf_error_string(primary_dbg,error, + DW_DLE_NO_TIED_FILE_AVAILABLE, + "DW_DLE_NO_TIED_FILE_AVAILABLE: bad argument to " + "dwarf_set_tied_dbg(), primary_dbg already has" + " a secondary_dbg!"); + return DW_DLV_ERROR; + } + primary_dbg->de_tied_data.td_tied_object = secondary_dbg; + primary_dbg->de_secondary_dbg = secondary_dbg; + secondary_dbg->de_secondary_dbg = secondary_dbg; + secondary_dbg->de_errors_dbg = primary_dbg; + CHECK_DBG(secondary_dbg,error,"dwarf_set_tied_dbg() " + "dw_secondary_dbg" + "is invalid"); + primary_dbg->de_secondary_dbg = secondary_dbg; + return DW_DLV_OK; + } else { + primary_dbg->de_secondary_dbg = 0; + primary_dbg->de_tied_data.td_tied_object = 0; } return DW_DLV_OK; } -/* New September 2015. */ +/* New September 2015. + As of Aug 2023 this correctly returns tied_dbg + whether main or tied passed in. Before this + it would return the dbg passed in. + If there is no tied-dbg this returns main dbg. */ int -dwarf_get_tied_dbg(Dwarf_Debug dbg, Dwarf_Debug *tieddbg_out, - Dwarf_Error*error) +dwarf_get_tied_dbg(Dwarf_Debug dw_dbg, + Dwarf_Debug *dw_secondary_dbg_out, + Dwarf_Error *dw_error) { - CHECK_DBG(dbg,error,"dwarf_get_tied_dbg()"); - *tieddbg_out = dbg->de_tied_data.td_tied_object; + CHECK_DBG(dw_dbg,dw_error,"dwarf_get_tied_dbg()"); + *dw_secondary_dbg_out = 0; + if (DBG_IS_PRIMARY(dw_dbg)) { + if (!dw_dbg->de_secondary_dbg) { + *dw_secondary_dbg_out = dw_dbg; + return DW_DLV_OK; + } + *dw_secondary_dbg_out = dw_dbg->de_secondary_dbg; + return DW_DLV_OK; + } + if (DBG_IS_SECONDARY(dw_dbg)) { + *dw_secondary_dbg_out = dw_dbg; + return DW_DLV_OK; + } + /* Leave returned secondary_dbg_out NULL, + this should not happen */ return DW_DLV_OK; } diff --git a/src/lib/libdwarf/dwarf_gnu_index.c b/src/lib/libdwarf/dwarf_gnu_index.c index 7a069e4..49cb1d2 100644 --- a/src/lib/libdwarf/dwarf_gnu_index.c +++ b/src/lib/libdwarf/dwarf_gnu_index.c @@ -276,10 +276,10 @@ scan_block_entries(Dwarf_Debug dbg, Dwarf_Unsigned length = 0; unsigned int offsetsize = 0; unsigned int extensize = 0; + unsigned int sumsize = 0; if (curptr == endptr) { - *count_out = count; - return DW_DLV_OK; + break; } /* Not sure how the coders think about the initial value. But the last @@ -296,10 +296,16 @@ scan_block_entries(Dwarf_Debug dbg, } ++count; - curptr += length -offsetsize - extensize; + sumsize = offsetsize +extensize; + if (length < sumsize) { + build_errm_one_num(dbg,for_gnu_pubnames, + "Length of fde/cies header sizes 0x%" DW_PR_DUx + " is impossibly small",length,error); + return DW_DLV_ERROR; + } + curptr += length - sumsize; curptr += 4; } - /* NOTREACHED */ *count_out = count; return DW_DLV_OK; } diff --git a/src/lib/libdwarf/dwarf_harmless.c b/src/lib/libdwarf/dwarf_harmless.c index f97a817..b36679e 100644 --- a/src/lib/libdwarf/dwarf_harmless.c +++ b/src/lib/libdwarf/dwarf_harmless.c @@ -217,12 +217,12 @@ _dwarf_harmless_init(struct Dwarf_Harmless_s *dhp,unsigned size) unsigned i = 0; memset(dhp,0,sizeof(*dhp)); dhp->dh_maxcount = size +1; - dhp->dh_errors = (char **)calloc(dhp->dh_maxcount, sizeof(char *)); + dhp->dh_errors = (char **)calloc(dhp->dh_maxcount, + sizeof(char *)); if (!dhp->dh_errors) { dhp->dh_maxcount = 0; return; } - for (i = 0; i < dhp->dh_maxcount; ++i) { char *newstr = (char *)calloc(1, DW_HARMLESS_ERROR_MSG_STRING_SIZE); diff --git a/src/lib/libdwarf/dwarf_init_finish.c b/src/lib/libdwarf/dwarf_init_finish.c index fa8caf8..55933d2 100644 --- a/src/lib/libdwarf/dwarf_init_finish.c +++ b/src/lib/libdwarf/dwarf_init_finish.c @@ -1035,6 +1035,8 @@ dwarf_object_init_b(Dwarf_Obj_Access_Interface_a* obj, size. */ dbg = _dwarf_get_debug(filesize); if (IS_INVALID_DBG(dbg)) { + dwarf_finish(dbg); + dbg = 0; DWARF_DBG_ERROR(dbg, DW_DLE_DBG_ALLOC, DW_DLV_ERROR); } dbg->de_errhand = errhand; @@ -1044,6 +1046,12 @@ dwarf_object_init_b(Dwarf_Obj_Access_Interface_a* obj, dbg->de_frame_cfa_col_number = DW_FRAME_CFA_COL3; dbg->de_frame_same_value_number = DW_FRAME_SAME_VAL; dbg->de_frame_undefined_value_number = DW_FRAME_UNDEFINED_VAL; + dbg->de_dbg = dbg; + /* See dwarf_set_tied_dbg() dwarf_get_tied_dbg() + and comments in dwarf_opaque.h*/ + dbg->de_primary_dbg = dbg; + dbg->de_secondary_dbg = 0; + dbg->de_errors_dbg = dbg; dbg->de_obj_file = obj; dbg->de_filesize = filesize; @@ -1099,7 +1107,7 @@ dwarf_object_init_b(Dwarf_Obj_Access_Interface_a* obj, /* *error safe */ dwarfstring_append(&msg,dwarf_errmsg(*error)); /* deallocate the soon-stale error pointer. */ - dwarf_dealloc(dbg,*error,DW_DLA_ERROR); + dwarf_dealloc_error(dbg,*error); /* *error safe */ *error = 0; } diff --git a/src/lib/libdwarf/dwarf_line.c b/src/lib/libdwarf/dwarf_line.c index a372c97..ab6d902 100644 --- a/src/lib/libdwarf/dwarf_line.c +++ b/src/lib/libdwarf/dwarf_line.c @@ -844,9 +844,9 @@ _dwarf_internal_srclines(Dwarf_Die die, } section_start = dbg->de_debug_line.dss_data; section_end = section_start +dbg->de_debug_line.dss_size; + line_ptr = dbg->de_debug_line.dss_data + line_offset; { Dwarf_Unsigned fission_size = 0; - uintptr_t line_ptr_as_uint = (uintptr_t)line_ptr; int resf = _dwarf_get_fission_addition_die(die, DW_SECT_LINE, &fission_offset,&fission_size,error); if (resf != DW_DLV_OK) { @@ -856,15 +856,21 @@ _dwarf_internal_srclines(Dwarf_Die die, /* fission_offset may be 0, and adding 0 to a null pointer is undefined behavior with some compilers. */ - line_ptr_as_uint += fission_offset; - line_ptr = (Dwarf_Small *)line_ptr_as_uint; + if (fission_offset) { + line_ptr += fission_offset; + } if (line_ptr > section_end) { dwarf_dealloc(dbg, stmt_list_attr, DW_DLA_ATTR); - _dwarf_error(dbg, error, DW_DLE_FISSION_ADDITION_ERROR); + _dwarf_error_string(dbg, error, + DW_DLE_FISSION_ADDITION_ERROR, + "DW_DLE_FISSION_ADDITION_ERROR: " + "on retrieving the fission addition value for " + "adding that into the line table offset " + "results in running off " + "the end of the line table. Corrupt DWARF."); return DW_DLV_ERROR; } } - section_start = dbg->de_debug_line.dss_data; section_end = section_start +dbg->de_debug_line.dss_size; orig_line_ptr = section_start + line_offset + fission_offset; @@ -895,7 +901,7 @@ _dwarf_internal_srclines(Dwarf_Die die, _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL); return DW_DLV_ERROR; } - line_context->lc_new_style_access = + line_context->lc_new_style_access = (unsigned char)is_new_interface; line_context->lc_compilation_directory = comp_dir; /* We are in dwarf_internal_srclines() */ diff --git a/src/lib/libdwarf/dwarf_line_table_reader_common.h b/src/lib/libdwarf/dwarf_line_table_reader_common.h index b843859..0d1ec99 100644 --- a/src/lib/libdwarf/dwarf_line_table_reader_common.h +++ b/src/lib/libdwarf/dwarf_line_table_reader_common.h @@ -229,7 +229,7 @@ _dwarf_read_line_table_header(Dwarf_Debug dbg, err, section_length,section_end); line_ptr_end = line_ptr + total_length; line_context->lc_line_ptr_end = line_ptr_end; - line_context->lc_length_field_length = + line_context->lc_length_field_length = (Dwarf_Half)(local_length_size + local_extension_size); line_context->lc_section_offset = starting_line_ptr - dbg->de_debug_line.dss_data; @@ -2704,11 +2704,14 @@ read_line_table_program(Dwarf_Debug dbg, /* This is an extended op code we do not know about, other than we know now many bytes it is and the op code and the bytes of operand. */ - Dwarf_Unsigned remaining_bytes = instr_length -1; + Dwarf_Unsigned remaining_bytes = 0; /* ptrdiff_t is generated but not named */ Dwarf_Unsigned space_left = (line_ptr <= line_ptr_end)? (line_ptr_end - line_ptr):0xfffffff; + if (instr_length > 0) { + remaining_bytes = instr_length -1; + } /* By catching this here instead of PRINTING_DETAILS we avoid reading off of our data of interest*/ diff --git a/src/lib/libdwarf/dwarf_loc.c b/src/lib/libdwarf/dwarf_loc.c index eaa299f..0dd7433 100644 --- a/src/lib/libdwarf/dwarf_loc.c +++ b/src/lib/libdwarf/dwarf_loc.c @@ -48,6 +48,9 @@ #include "dwarf_loc.h" #include "dwarf_string.h" +#define DEBUG_LOCLIST 1 +#undef DEBUG_LOCLIST + static int _dwarf_read_loc_section_dwo(Dwarf_Debug dbg, Dwarf_Block_c * return_block, Dwarf_Addr * lowpc, @@ -1136,7 +1139,7 @@ _dwarf_original_loclist_build(Dwarf_Debug dbg, } /* We need to calculate the cooked values for each locldesc entry, that will be done - in dwarf_get_loclist_c(). */ + in dwarf_get_loclist_d(). */ llhead->ll_bytes_total = loclist_offset - starting_loclist_offset; @@ -1267,6 +1270,7 @@ cook_original_loclist_contents(Dwarf_Debug dbg, baseaddress = llc->ld_rawhigh; break; } + /* This is the only way baseaddress is used. */ case DW_LLE_offset_pair: { llc->ld_lopc = llc->ld_rawlow + baseaddress; llc->ld_highpc = llc->ld_rawhigh + baseaddress; @@ -1587,17 +1591,21 @@ dwarf_get_loclist_c(Dwarf_Attribute attr, Dwarf_Unsigned * listlen_out, Dwarf_Error * error) { - Dwarf_Debug dbg = 0; - Dwarf_Half form = 0; - Dwarf_Loc_Head_c llhead = 0; - Dwarf_CU_Context cucontext = 0; - unsigned address_size = 0; - Dwarf_Half cuversionstamp = 0; - Dwarf_Bool is_cu = FALSE; - Dwarf_Unsigned attrnum = 0; - Dwarf_Bool is_dwo = 0; - int setup_res = DW_DLV_ERROR; - int lkind = 0; + Dwarf_Debug dbg = 0; + Dwarf_Half form = 0; + Dwarf_Loc_Head_c llhead = 0; + unsigned address_size = 0; + Dwarf_Half cuversionstamp = 0; + Dwarf_Bool is_cu = FALSE; + Dwarf_Unsigned attrnum = 0; + Dwarf_Bool is_dwo = 0; + int lkind = 0; + Dwarf_CU_Context ctx = 0; + Dwarf_Bool is_loclistx = FALSE; + Dwarf_Unsigned attr_val = 0; + Dwarf_Bool offset_is_info = TRUE; + int res = 0; + int setup_res = 0; if (!attr) { _dwarf_error_string(dbg, error,DW_DLE_ATTR_NULL, @@ -1607,18 +1615,74 @@ dwarf_get_loclist_c(Dwarf_Attribute attr, "dwarf_get_loclist_c()"); return DW_DLV_ERROR; } - dbg = attr->ar_dbg; - CHECK_DBG(dbg,error,"dwarf_get_loclist_c()"); - - /* ***** BEGIN CODE ***** */ - setup_res = _dwarf_setup_loc(attr, &dbg,&cucontext, &form, error); + setup_res = _dwarf_setup_loc(attr, &dbg,&ctx, &form, error); if (setup_res != DW_DLV_OK) { return setup_res; } + + CHECK_DBG(dbg,error,"dwarf_get_loclist_c()"); + if (form == DW_FORM_loclistx) { + is_loclistx = TRUE; + } attrnum = attr->ar_attribute; - cuversionstamp = cucontext->cc_version_stamp; - address_size = cucontext->cc_address_size; - is_dwo = cucontext->cc_is_dwo; + cuversionstamp = ctx->cc_version_stamp; + address_size = ctx->cc_address_size; + is_dwo = ctx->cc_is_dwo; + lkind = determine_location_lkind(cuversionstamp, + form, is_dwo); + + if (form == DW_FORM_loclistx || form == DW_FORM_sec_offset) { + /* Aimed at DWARF5 and later */ + res = dwarf_global_formref_b(attr,&attr_val, + &offset_is_info,error); + if (res != DW_DLV_OK) { + return res; + } + } + if (lkind == DW_LKIND_loclists) { + if (is_loclistx) { + if (ctx->cc_loclists_base_present || + dbg->de_loclists_context_count == 1) { + /* leave on primary. + WARNING: It is not clear whether + looking for a context count of 1 + is actually correct, but it + seems to work. */ + } else if (DBG_HAS_SECONDARY(dbg)){ + dbg = dbg->de_secondary_dbg; + CHECK_DBG(dbg,error, + "dwarf_loclists_get_lle_head() " + "via attribute(sec)"); + } + } else { + /* attr_val is .debug_loclists[.dwo] + section global offset + of a location list*/ + if (!dbg->de_debug_loclists.dss_size || + attr_val >= dbg->de_debug_loclists.dss_size) { + if (DBG_HAS_SECONDARY(dbg)) { + dbg = dbg->de_secondary_dbg; + CHECK_DBG(dbg,error, + "dwarf_loclists_get_lle_head() " + "via attribute(secb)"); + } else { + /* There is an error to be + generated later */ + } + } + } + res = _dwarf_load_section(dbg, + &dbg->de_debug_loclists, + error); + if (res == DW_DLV_ERROR) { + return res; + } + } + + attrnum = attr->ar_attribute; + cuversionstamp = ctx->cc_version_stamp; + address_size = ctx->cc_address_size; + is_dwo = ctx->cc_is_dwo; lkind = determine_location_lkind(cuversionstamp, form, is_dwo); if (lkind == DW_LKIND_unknown) { @@ -1663,27 +1727,29 @@ dwarf_get_loclist_c(Dwarf_Attribute attr, llhead->ll_attrform = (Dwarf_Half)form; llhead->ll_dbg = dbg; llhead->ll_address_size = address_size; - llhead->ll_offset_size = cucontext->cc_length_size; - llhead->ll_context = cucontext; + llhead->ll_offset_size = ctx->cc_length_size; + llhead->ll_context = ctx; llhead->ll_magic = LOCLISTS_MAGIC; llhead->ll_at_loclists_base_present = - cucontext->cc_loclists_base_present; - llhead->ll_at_loclists_base = cucontext->cc_loclists_base; - llhead->ll_cu_base_address_present = cucontext->cc_low_pc_present; - llhead->ll_cu_base_address = cucontext->cc_low_pc; - llhead->ll_cu_addr_base = cucontext->cc_addr_base; - llhead->ll_cu_addr_base_present = - cucontext->cc_addr_base_present; + ctx->cc_loclists_base_present; + llhead->ll_at_loclists_base = ctx->cc_loclists_base; + llhead->ll_cu_base_address_present = + ctx->cc_base_address_present; + llhead->ll_cu_base_address = ctx->cc_base_address; + + llhead->ll_cu_addr_base_offset = ctx->cc_addr_base_offset; + llhead->ll_cu_addr_base_offset_present = + ctx->cc_addr_base_offset_present; if (lkind == DW_LKIND_loclist || lkind == DW_LKIND_GNU_exp_list) { int ores = 0; /* Here we have a loclist to deal with. */ - ores = context_is_cu_not_tu(cucontext,&is_cu); + ores = context_is_cu_not_tu(ctx,&is_cu); if (ores != DW_DLV_OK) { dwarf_dealloc_loc_head_c(llhead); - return setup_res; + return ores; } ores = _dwarf_original_loclist_build(dbg, llhead, attr, error); @@ -1715,7 +1781,7 @@ dwarf_get_loclist_c(Dwarf_Attribute attr, int leres = 0; leres = _dwarf_loclists_fill_in_lle_head(dbg, - attr,llhead,error); + attr,form,attr_val,llhead,error); if (leres != DW_DLV_OK) { dwarf_dealloc_loc_head_c(llhead); return leres; diff --git a/src/lib/libdwarf/dwarf_loc.h b/src/lib/libdwarf/dwarf_loc.h index e0915f6..cfb662e 100644 --- a/src/lib/libdwarf/dwarf_loc.h +++ b/src/lib/libdwarf/dwarf_loc.h @@ -208,14 +208,15 @@ struct Dwarf_Loc_Head_c_s { Dwarf_Bool ll_at_loclists_base_present; Dwarf_Unsigned ll_at_loclists_base; - /* DW_AT_low_pc of CU or zero if none. */ + /* DW_AT_low_pc originally, , perhaps interited + into dwp from skeleton. */ Dwarf_Bool ll_cu_base_address_present; Dwarf_Unsigned ll_cu_base_address; /* DW_AT_addr_base, so we can use .debug_addr if such is needed. */ - Dwarf_Bool ll_cu_addr_base_present; - Dwarf_Unsigned ll_cu_addr_base; + Dwarf_Bool ll_cu_addr_base_offset_present; + Dwarf_Unsigned ll_cu_addr_base_offset; Dwarf_Small * ll_llepointer; Dwarf_Unsigned ll_llearea_offset; @@ -252,6 +253,8 @@ void _dwarf_loclists_head_destructor(void *l); int _dwarf_loclists_fill_in_lle_head(Dwarf_Debug dbg, Dwarf_Attribute attr, + Dwarf_Half theform, + Dwarf_Unsigned attr_val, Dwarf_Loc_Head_c llhead, Dwarf_Error *error); diff --git a/src/lib/libdwarf/dwarf_loclists.c b/src/lib/libdwarf/dwarf_loclists.c index 3b2cf47..12abffe 100644 --- a/src/lib/libdwarf/dwarf_loclists.c +++ b/src/lib/libdwarf/dwarf_loclists.c @@ -324,7 +324,7 @@ read_single_lle_entry(Dwarf_Debug dbg, preserve a testing baseline: baselines/hongg2024-02-18-m.base otherwise we would test against sectionsize first.*/ - Dwarf_Unsigned sectionsize = dbg->de_debug_loclists.dss_size; + Dwarf_Unsigned section_size = dbg->de_debug_loclists.dss_size; if (data > enddata || data < startdata ) { /* Corrupt data being read. */ @@ -334,7 +334,7 @@ read_single_lle_entry(Dwarf_Debug dbg, "of its allowed space"); return DW_DLV_ERROR; } - if (count > sectionsize) { + if (count > section_size) { /* Corrupt data being read. */ _dwarf_error_string(dbg,error,DW_DLE_LOCLISTS_ERROR, "DW_DLE_LOCLISTS_ERROR: " @@ -501,12 +501,12 @@ _dwarf_internal_read_loclists_header(Dwarf_Debug dbg, } /* else no offset table */ buildhere->lc_offsets_off_in_sect = offset+localoff; - buildhere->lc_first_loclist_offset = offset+localoff+ - lists_len; + buildhere->lc_first_loclist_offset = + buildhere->lc_offsets_off_in_sect + lists_len; buildhere->lc_loclists_header = startdata; - buildhere->lc_endaddr = startdata +buildhere->lc_length; + buildhere->lc_endaddr = startdata + buildhere->lc_length; buildhere->lc_past_last_loclist_offset = - buildhere->lc_header_offset +buildhere->lc_length; + buildhere->lc_header_offset + buildhere->lc_length; *next_offset = buildhere->lc_past_last_loclist_offset; return DW_DLV_OK; } @@ -719,6 +719,14 @@ dwarf_get_loclist_offset_index_value(Dwarf_Debug dbg, READ_UNALIGNED_CK(dbg,targetoffset,Dwarf_Unsigned, offsetptr, offset_len,error,con->lc_endaddr); + if (targetoffset >= con->lc_length) { + _dwarf_error_string(dbg,error,DW_DLE_LOCLISTS_ERROR, + "DW_DLE_LOCLISTS_ERROR: " + "An lle target offset value is " + "Too large to be real"); + return DW_DLV_ERROR; + } + if (offset_value_out) { *offset_value_out = targetoffset; } @@ -797,8 +805,9 @@ int dwarf_get_loclist_head_basics(Dwarf_Loc_Head_c head, *loclists_base_address_present = head->ll_cu_base_address_present; *loclists_base_address= head->ll_cu_base_address; - *loclists_debug_addr_base_present = head->ll_cu_addr_base_present; - *loclists_debug_addr_base = head->ll_cu_addr_base; + *loclists_debug_addr_base_present = + head->ll_cu_addr_base_offset_present; + *loclists_debug_addr_base = head->ll_cu_addr_base_offset; *loclists_offset_lle_set = head->ll_llearea_offset; return DW_DLV_OK; } @@ -938,10 +947,14 @@ int dwarf_get_loclist_lle(Dwarf_Debug dbg, return res; } +/* We have more data than we need here if the compiler + provided a loclists_base_address or provided + a DW_SECT_LOCLISTS Per_CU value set for loclists. + Or we plucked an offset from .debug_addr. */ static int _dwarf_which_loclists_context(Dwarf_Debug dbg, Dwarf_CU_Context ctx, - Dwarf_Unsigned loclist_offset, + Dwarf_Unsigned loclist_offset /* Not always set */, Dwarf_Unsigned *index, Dwarf_Error *error) { @@ -951,97 +964,77 @@ _dwarf_which_loclists_context(Dwarf_Debug dbg, Dwarf_Loclists_Context rcx = 0; Dwarf_Unsigned rcxoff = 0; Dwarf_Unsigned rcxend = 0; + Dwarf_Unsigned loclists_base = 0; + Dwarf_Bool loclists_base_present = FALSE; + int res = 0; + Dwarf_Bool found_base = FALSE; + Dwarf_Unsigned chosen_offset = 0; array = dbg->de_loclists_context; count = dbg->de_loclists_context_count; if (!array) { return DW_DLV_NO_ENTRY; } + if (count == 1) { + *index = 0; + return DW_DLV_OK; + } + + if (ctx->cc_loclists_base_present) { + loclists_base_present = ctx->cc_loclists_base_present; + loclists_base = ctx->cc_loclists_base; + found_base = TRUE; + chosen_offset = loclists_base; + } + if (!found_base) { + res = _dwarf_has_SECT_fission(ctx, + DW_SECT_LOCLISTS, + &loclists_base_present,&loclists_base); + if (res == DW_DLV_OK) { + found_base = TRUE; + chosen_offset = loclists_base; + } + } + if (!found_base) { + loclists_base = loclist_offset; + chosen_offset = loclist_offset; + } + rcx = array[i]; rcxoff = rcx->lc_header_offset; rcxend = rcxoff + rcx->lc_length; - if (!ctx->cc_loclists_base_present) { - /* We look at the location of each loclist context - to find one with the offset the DIE gave us. */ - for ( i = 0 ; i < count; ++i) { - rcx = array[i]; - rcxoff = rcx->lc_header_offset; - rcxend = rcxoff + - rcx->lc_length; - rcxend = rcxoff + - rcx->lc_length; - if (loclist_offset < rcxoff){ - continue; - } - if (loclist_offset < rcxend ){ - *index = i; - return DW_DLV_OK; - } + /* We look at the location of each loclist context + to find one with the offset we want */ + for ( i = 0 ; i < count; ++i) { + rcx = array[i]; + rcxoff = rcx->lc_header_offset; + rcxend = rcxoff + + rcx->lc_length; + rcxend = rcxoff + + rcx->lc_length; + if (chosen_offset < rcxoff){ + continue; } - { - dwarfstring m; - - dwarfstring_constructor(&m); - dwarfstring_append_printf_u(&m, - "DW_DLE_LOCLISTS_ERROR: loclist ran off end " - " finding target offset of" - " 0x%" DW_PR_XZEROS DW_PR_DUx ,loclist_offset); - dwarfstring_append(&m, - " Not found anywhere in .debug_loclists " - "data. Corrupted data?"); - _dwarf_error_string(dbg,error, - DW_DLE_LOCLISTS_ERROR, - dwarfstring_string(&m)); - dwarfstring_destructor(&m); - return DW_DLV_ERROR; + if (chosen_offset < rcxend ){ + *index = i; + return DW_DLV_OK; } - } else { - /* We have a DW_AT_loclists_base (lc_loclists_base), - let's use it. */ - Dwarf_Unsigned lookfor = 0;; - lookfor = ctx->cc_loclists_base; - for ( i = 0 ; i < count; ++i) { - dwarfstring m; + } + { + dwarfstring m; - rcx = array[i]; - if (rcx->lc_offsets_off_in_sect == lookfor){ - *index = i; - return DW_DLV_OK; - } - if (rcx->lc_offsets_off_in_sect < lookfor){ - continue; - } - - dwarfstring_constructor(&m); - dwarfstring_append_printf_u(&m, - "DW_DLE_LOCLISTS_ERROR: loclists base of " - " 0x%" DW_PR_XZEROS DW_PR_DUx ,lookfor); - dwarfstring_append_printf_u(&m, - " was not found though we are now at base " - " 0x%" DW_PR_XZEROS DW_PR_DUx , - rcx->lc_offsets_off_in_sect); - _dwarf_error_string(dbg,error, - DW_DLE_LOCLISTS_ERROR, - dwarfstring_string(&m)); - dwarfstring_destructor(&m); - return DW_DLV_ERROR; - } - { - dwarfstring m; - - dwarfstring_constructor(&m); - dwarfstring_append_printf_u(&m, - "DW_DLE_LOCLISTS_ERROR: loclist base of " - " 0x%" DW_PR_XZEROS DW_PR_DUx ,lookfor); - dwarfstring_append(&m, - " was not found anywhere in .debug_loclists " - "data. Corrupted data?"); - _dwarf_error_string(dbg,error, - DW_DLE_LOCLISTS_ERROR, - dwarfstring_string(&m)); - dwarfstring_destructor(&m); - return DW_DLV_ERROR; - } + dwarfstring_constructor(&m); + dwarfstring_append_printf_u(&m, + "DW_DLE_LOCLISTS_ERROR: loclist ran off end " + " finding target offset of" + " 0x%" DW_PR_XZEROS DW_PR_DUx ,chosen_offset); + dwarfstring_append(&m, + " Not found anywhere in .debug_loclists[.dwo] " + "data. Corrupted data?"); + _dwarf_error_string(dbg,error, + DW_DLE_LOCLISTS_ERROR, + dwarfstring_string(&m)); + dwarfstring_destructor(&m); } return DW_DLV_ERROR; } @@ -1077,33 +1070,6 @@ alloc_rle_and_append_to_list(Dwarf_Debug dbg, return DW_DLV_OK; } -static int -_dwarf_implicit_loclists_base(Dwarf_Debug dbg, - Dwarf_Unsigned indexval, - Dwarf_Unsigned *ibase) -{ - Dwarf_Loclists_Context rctx = 0; - if (IS_INVALID_DBG(dbg)) { - return DW_DLV_NO_ENTRY; - } - if (!dbg->de_debug_loclists.dss_size) { - return DW_DLV_NO_ENTRY; - } - if (!dbg->de_loclists_context_count) { - return DW_DLV_NO_ENTRY; - } - /* This implicit base can only work if the 0-th - Rnglists_Context is appropriate here. */ - rctx = dbg->de_loclists_context[0]; - if (indexval > rctx->lc_offset_entry_count) { - /* We are not using base offset, we - will not see a DW_FORM_loclistx */ - return DW_DLV_NO_ENTRY; - } - *ibase = rctx->lc_offsets_off_in_sect; - return DW_DLV_OK; -} - /* Read the group of loclists entries, and finally build an array of Dwarf_Locdesc_c records. Attach to rctx here. @@ -1226,30 +1192,32 @@ build_array_of_lle(Dwarf_Debug dbg, */ int _dwarf_loclists_fill_in_lle_head(Dwarf_Debug dbg, - Dwarf_Attribute attr, + Dwarf_Attribute attr, + Dwarf_Half theform, + Dwarf_Unsigned attr_val, Dwarf_Loc_Head_c llhead, - Dwarf_Error *error) + Dwarf_Error *error) { int res = 0; Dwarf_Unsigned loclists_contextnum = 0; - Dwarf_Small *table_base = 0; - Dwarf_Small *table_entry = 0; - Dwarf_Small *enddata = 0; + Dwarf_Small *table_base = 0; + Dwarf_Small *table_entry = 0; + Dwarf_Small *enddata = 0; Dwarf_Loclists_Context *array = 0; Dwarf_Loclists_Context rctx = 0; Dwarf_Unsigned entrycount = 0; unsigned offsetsize = 0; - Dwarf_Unsigned lle_global_offset = 0; + Dwarf_Unsigned lle_global_offset = 0; Dwarf_CU_Context ctx = 0; - Dwarf_Unsigned offset_in_loclists = 0; - Dwarf_Bool is_loclistx = FALSE; - Dwarf_Half theform = llhead->ll_attrform; - Dwarf_Bool loclists_base_present = - llhead->ll_at_loclists_base_present; - Dwarf_Unsigned loclists_base = - llhead->ll_at_loclists_base; - Dwarf_Unsigned attr_val = 0; + Dwarf_Unsigned offset_in_loclists = 0; + Dwarf_Bool is_loclistx = FALSE; + Dwarf_Unsigned secsize = 0; + if (theform == DW_FORM_loclistx) { + is_loclistx = TRUE; + } else { + offset_in_loclists = attr_val; + } if (!attr) { _dwarf_error_string(NULL, error,DW_DLE_DBG_NULL, "DW_DLE_DBG_NULL " @@ -1258,94 +1226,90 @@ _dwarf_loclists_fill_in_lle_head(Dwarf_Debug dbg, "_dwarf_loclists_fill_in_lle_head()"); return DW_DLV_ERROR; } + secsize = dbg->de_debug_loclists.dss_size; ctx = attr->ar_cu_context; array = dbg->de_loclists_context; - if (theform == DW_FORM_loclistx) { - Dwarf_Bool offset_is_info = 0; - is_loclistx = TRUE; - res = dwarf_global_formref_b(attr, - &attr_val, &offset_is_info, error); - if (res != DW_DLV_OK) { - return res; - } - } else { - if (theform == DW_FORM_sec_offset) { - /* DW_FORM_sec_offset is not formudata , often - seen in in DW5 DW_AT_location etc */ - res = dwarf_global_formref(attr, &attr_val,error); + if (dbg != ctx->cc_dbg) { + /* is_loclistx TRUE */ + /* Now find the correct secondary CU context via + signature. */ + Dwarf_CU_Context lctx = 0; + + if (ctx->cc_signature_present) { + /* Looking in current dbg for the correct cu context */ + res = _dwarf_search_for_signature(dbg, + ctx->cc_signature, + &lctx,error); if (res != DW_DLV_OK) { + if (res == DW_DLV_ERROR) { + _dwarf_error_string(dbg,error, DW_DLE_LLE_ERROR, + "DW_DLE_RLE_ERROR: a .debug_loclists " + "cu context cannot be found with the " + "correct signature"); + } return res; + } else { + ctx = lctx; } + } else { + /* No signature. Hopeless, I think. */ + _dwarf_error_string(dbg,error, DW_DLE_LLE_ERROR, + "DW_DLE_LLE_ERROR: a .debug_loclists " + "cu context cannot be found as there is " + "no signature to use"); + return DW_DLV_ERROR; } } - if (is_loclistx) { - if (loclists_base_present) { - offset_in_loclists = loclists_base; - } else if (ctx->cc_is_dwo) { - /* missing a DW_AT_loclists_base! */ - /* Generate a base and set as 'present' - by looking at the location offset - table that we are supposedly indexing into. - finding what the table value is. - An implicit loclists_base. - Will not work with multiple loclists! */ - int ires = 0; - Dwarf_Unsigned ibase = 0; - ires = _dwarf_implicit_loclists_base(dbg, - attr_val,&ibase); - if (ires != DW_DLV_OK) { - dwarfstring m; - - dwarfstring_constructor(&m); - dwarfstring_append_printf_u(&m, - "DW_DLE_LOCLISTS_ERROR: loclists table" - " index of" - " %u" ,attr_val); - dwarfstring_append(&m, - " is unusable, there is no default " - " loclists base address "); - _dwarf_error_string(dbg,error, - DW_DLE_LOCLISTS_ERROR, - dwarfstring_string(&m)); - dwarfstring_destructor(&m); - return DW_DLV_ERROR; - } - ctx->cc_loclists_base_present = TRUE; - ctx->cc_loclists_base = ibase; - offset_in_loclists = ibase; - } + /* A */ + if (ctx->cc_loclists_base_present) { + offset_in_loclists = ctx->cc_loclists_base; } else { offset_in_loclists = attr_val; } - res = _dwarf_which_loclists_context(dbg,ctx, - offset_in_loclists, - &loclists_contextnum,error); - if (res != DW_DLV_OK) { - return res; + + if (offset_in_loclists >= secsize) { + _dwarf_error_string(dbg,error, DW_DLE_LLE_ERROR, + "DW_DLE_LLE_ERROR: a .debug_loclists offset " + "is greater than the loclists section size"); + return DW_DLV_ERROR; } + /* B */ + { + res = _dwarf_which_loclists_context(dbg,ctx, + offset_in_loclists, + &loclists_contextnum,error); + if (res == DW_DLV_OK) { + /* FALL THROUGH */ + } else if (res == DW_DLV_NO_ENTRY) { + loclists_contextnum = 0; + /* FALL THROUGH */ + } else { + return res; + } + } + + /* C */ rctx = array[loclists_contextnum]; table_base = rctx->lc_offsets_array; entrycount = rctx->lc_offset_entry_count; offsetsize = rctx->lc_offset_size; enddata = rctx->lc_endaddr; - if (is_loclistx) { - if (attr_val >= entrycount) { - dwarfstring m; + if (is_loclistx && attr_val >= entrycount) { + dwarfstring m; - dwarfstring_constructor(&m); - dwarfstring_append_printf_u(&m, - "DW_DLE_LOCLISTS_ERROR: loclists table index of" - " %u" ,attr_val); - dwarfstring_append_printf_u(&m, - " too large for table of %u " - "entries.",entrycount); - _dwarf_error_string(dbg,error, - DW_DLE_LOCLISTS_ERROR, - dwarfstring_string(&m)); - dwarfstring_destructor(&m); - return DW_DLV_ERROR; - } + dwarfstring_constructor(&m); + dwarfstring_append_printf_u(&m, + "DW_DLE_LOCLISTS_ERROR: loclists table index of" + " %u" ,attr_val); + dwarfstring_append_printf_u(&m, + " too large for table of %u " + "entries.",entrycount); + _dwarf_error_string(dbg,error, + DW_DLE_LOCLISTS_ERROR, + dwarfstring_string(&m)); + dwarfstring_destructor(&m); + return DW_DLV_ERROR; } llhead->ll_localcontext = rctx; llhead->ll_index = loclists_contextnum; @@ -1354,21 +1318,49 @@ _dwarf_loclists_fill_in_lle_head(Dwarf_Debug dbg, llhead->ll_address_size = rctx->lc_address_size; llhead->ll_segment_selector_size = rctx->lc_segment_selector_size; - + /* D */ if (is_loclistx) { Dwarf_Unsigned table_entryval = 0; + Dwarf_Unsigned globaloff = 0; table_entry = attr_val*offsetsize + table_base; /* No malloc here yet so no leak if the macro returns DW_DLV_ERROR */ READ_UNALIGNED_CK(dbg,table_entryval, Dwarf_Unsigned, table_entry,offsetsize,error,enddata); - lle_global_offset = rctx->lc_offsets_off_in_sect + - table_entryval; + if (table_entryval >= rctx->lc_length) { + _dwarf_error_string(dbg,error,DW_DLE_LOCLISTS_ERROR, + "DW_DLE_LOCLISTS_ERROR: " + "A DW_FORM_loclistx value is too large for " + "the space in .debug_loclists[.dwo]"); + return DW_DLV_ERROR; + } + globaloff = rctx->lc_offsets_off_in_sect + table_entryval; + lle_global_offset = globaloff; + if (lle_global_offset >= secsize) { + _dwarf_error_string(dbg,error,DW_DLE_LOCLISTS_ERROR, + "DW_DLE_LOCLISTS_ERROR: " + "A DW_FORM_loclistx global offset is too large to " + "the space in .debug_loclists[.dwo]"); + return DW_DLV_ERROR; + } } else { lle_global_offset = attr_val; + if (lle_global_offset >= secsize) { + _dwarf_error_string(dbg,error,DW_DLE_LOCLISTS_ERROR, + "DW_DLE_LOCLISTS_ERROR: " + "A loclist global offset is too large for " + "the space in .debug_loclists[.dwo]"); + return DW_DLV_ERROR; + } } + + /* E */ llhead->ll_end_data_area = enddata; + llhead->ll_cu_base_address_present = + ctx->cc_base_address_present; + llhead->ll_cu_base_address = ctx->cc_base_address; + llhead->ll_dbg = dbg; llhead->ll_llearea_offset = lle_global_offset; llhead->ll_llepointer = lle_global_offset + diff --git a/src/lib/libdwarf/dwarf_machoread.c b/src/lib/libdwarf/dwarf_machoread.c index 55cc3da..b3621a5 100644 --- a/src/lib/libdwarf/dwarf_machoread.c +++ b/src/lib/libdwarf/dwarf_machoread.c @@ -119,14 +119,20 @@ static struct macho_sect_names_s { { "__debug_aranges", ".debug_aranges" }, { "__debug_frame", ".debug_frame" }, { "__debug_info", ".debug_info" }, + { "__debug_addr", ".debug_addr" }, { "__debug_line", ".debug_line" }, + { "__debug_rnglists", ".debug_rnglists" }, + { "__debug_loclists", ".debug_loclists" }, { "__debug_macinfo", ".debug_macinfo" }, { "__debug_loc", ".debug_loc" }, { "__debug_pubnames", ".debug_pubnames" }, { "__debug_pubtypes", ".debug_pubtypes" }, { "__debug_str", ".debug_str" }, + { "__debug_str_offs", ".debug_str_offsets" }, + { "__debug_line_str", ".debug_line_str" }, { "__debug_ranges", ".debug_ranges" }, { "__debug_macro", ".debug_macro" }, + { "__debug_names", ".debug_names" }, { "__debug_gdb_scri", ".debug_gdb_scripts" } }; diff --git a/src/lib/libdwarf/dwarf_macro.c b/src/lib/libdwarf/dwarf_macro.c index 04b1ec1..181fb51 100644 --- a/src/lib/libdwarf/dwarf_macro.c +++ b/src/lib/libdwarf/dwarf_macro.c @@ -331,7 +331,10 @@ dwarf_get_macro_details(Dwarf_Debug dbg, break; case DW_MACINFO_end_file: - if (--depth == 0) { + if (depth) { + --depth; + } + if (!depth) { /* done = 1; no, do not stop here, at least one gcc had the wrong depth settings in the diff --git a/src/lib/libdwarf/dwarf_macro5.c b/src/lib/libdwarf/dwarf_macro5.c index f9aca0d..e5ab1f3 100644 --- a/src/lib/libdwarf/dwarf_macro5.c +++ b/src/lib/libdwarf/dwarf_macro5.c @@ -653,7 +653,7 @@ dwarf_get_macro_defundef(Dwarf_Macro_Context macro_context, *macro_string = (char *)""; } - dwarf_dealloc(dbg,lerr,DW_DLA_ERROR); + dwarf_dealloc_error(dbg,lerr); } else { *macro_string = ""; } diff --git a/src/lib/libdwarf/dwarf_names.c b/src/lib/libdwarf/dwarf_names.c index 819c559..7c557d7 100644 --- a/src/lib/libdwarf/dwarf_names.c +++ b/src/lib/libdwarf/dwarf_names.c @@ -1,5 +1,5 @@ /* Generated routines, do not edit. */ -/* Generated for source version 0.9.3 */ +/* Generated for source version 0.11.1 */ /* BEGIN FILE */ diff --git a/src/lib/libdwarf/dwarf_opaque.h b/src/lib/libdwarf/dwarf_opaque.h index 52a469b..c5d9458 100644 --- a/src/lib/libdwarf/dwarf_opaque.h +++ b/src/lib/libdwarf/dwarf_opaque.h @@ -1,6 +1,6 @@ /* Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. - Portions Copyright (C) 2007-2023 David Anderson. All Rights Reserved. + Portions Copyright (C) 2007-2024 David Anderson. All Rights Reserved. Portions Copyright (C) 2008-2010 Arxan Technologies, Inc. All Rights Reserved. This program is free software; you can redistribute it @@ -70,6 +70,31 @@ .debug_tu_index - - - 5 */ +#define DBG_IS_SECONDARY(p) ((p) && (p)->de_secondary_dbg && \ + ((p)->de_secondary_dbg == (p))) +#define DBG_IS_PRIMARY(p) ((p) && ((!(p)->de_secondary_dbg) || \ + ((p)->de_secondary_dbg && ((p)->de_secondary_dbg != (p))))) +#define DBG_HAS_SECONDARY(p) (DBG_IS_PRIMARY(p) && \ + (DBG_IS_SECONDARY((p)->de_secondary_dbg))) + +#define DEBUG_PRIMARY_DBG 1 /* only for debugging */ +#undef DEBUG_PRIMARY_DBG +#ifdef DEBUG_PRIMARY_DBG +const char * +_dwarf_basename(const char *full); + +void +_dwarf_print_is_primary(const char *msg,Dwarf_Debug p,int line, + const char *filepath); +void +_dwarf_dump_prim_sec(const char *msg,Dwarf_Debug p, int line, + const char *filepath); +void +_dwarf_dump_optional_fields(const char *msg, + Dwarf_CU_Context context, + int line, + const char *filepath); +#endif /* DEBUG_PRIMARY_DBG */ struct Dwarf_Rnglists_Context_s; typedef struct Dwarf_Rnglists_Context_s *Dwarf_Rnglists_Context; @@ -111,6 +136,7 @@ struct Dwarf_Attribute_s { }; #define CC_PROD_METROWERKS 1 +#define CC_PROD_Apple 2 /* Apple clang */ /* This structure provides the context for a compilation unit. @@ -228,8 +254,17 @@ struct Dwarf_CU_Context_s { Dwarf_Bool cc_signature_present; /* Meaning type signature in TU header or, for CU header, signature in CU DIE. */ + + /* cc_low_pc[_present] is applied as base address of + of rnglists and loclists when reading an rle_head, + compied into cc_cu_base_address. Comes from + CU_DIE, not rnglists or loclists */ Dwarf_Bool cc_low_pc_present; - Dwarf_Bool cc_addr_base_present; /* Not TRUE in .dwo */ + + /* From CU_DIE. Copied from cc_low_pc_present. + Used as default base address for rnglists, loclists. + in a DWARF5 dwo, inherited from skeleton (tieddbg). */ + Dwarf_Bool cc_base_address_present; Dwarf_Bool cc_cu_die_has_children; Dwarf_Bool cc_dwo_name_present; @@ -243,6 +278,9 @@ struct Dwarf_CU_Context_s { cc_cu_die_global_sec_offset is meaningful. */ Dwarf_Bool cc_cu_die_offset_present; Dwarf_Bool cc_at_ranges_offset_present; + /* About: DW_AT_addr_base in CU DIE, + offset to .debug_addr table */ + Dwarf_Bool cc_addr_base_offset_present; /* If present, is base address of CU. In DWARF2 nothing says what attribute is the base address. @@ -256,8 +294,13 @@ struct Dwarf_CU_Context_s { In DWARF3, DWARF4 DW_AT_low_pc is specifically mentioned as the base address. */ Dwarf_Unsigned cc_low_pc; + /* from DW_AT_addr_base in CU DIE, offset to .debug_addr table */ - Dwarf_Unsigned cc_addr_base; /* Zero in .dwo */ + Dwarf_Unsigned cc_addr_base_offset; /* Zero in .dwo */ + + /* From cc_low_pc, used as initial base_address + in processing loclists and rnglists */ + Dwarf_Unsigned cc_base_address; /* DW_SECT_LINE */ Dwarf_Bool cc_line_base_present; /*DW5 */ @@ -542,19 +585,13 @@ struct Dwarf_Tied_Data_s { Pointer to the tied_to Dwarf_Debug*/ Dwarf_Debug td_tied_object; - /* TRUE if this tied object is tied to. - It's extra work to look for a DW_AT_dwo_id. - Set when tied dbg (on the base) was created. - This helps us do it only when it may be productive. */ - Dwarf_Bool td_is_tied_object; - /* Used for Type Unit signatures. Type Units are in .debug_types in DW4 but in .debug_info in DW5. Some .debug_info point to them symbolically via DW_AT_signature attributes. If non-zero is a dwarf_tsearch 'tree'. - Only non-zero if td_is_tied_object is set and + Only non-zero if we had a reason to build the search tree.. Type Units have a Dwarf_Sig8 signature in the header, and such is recorded here. @@ -563,7 +600,7 @@ struct Dwarf_Tied_Data_s { signatures in split-dwarf (dwo/dwp) sections. The Key for each record is a Dwarf_Sig8 (8 bytes). - The data for each is a pointer to a Dwarf_CU_context + The data for each is a pointer to a Dwarf_CU_Context record in this dbg (cu_context in one of tied dbg's de_cu_context_list). */ void *td_tied_search; @@ -599,6 +636,15 @@ struct Dwarf_Debug_s { structure and contents. */ struct Dwarf_Obj_Access_Interface_a_s *de_obj_file; + /* See dwarf_generic_init.c comments on the + use of the next four fields. And see + DBG_IS_SECONDARY(p) DBG_IS_PRIMARY(p) + DBG_HAS_SECONDARY(p) below and also dwarf_util.c */ + struct Dwarf_Debug_s * de_dbg; + struct Dwarf_Debug_s * de_primary_dbg; + struct Dwarf_Debug_s * de_secondary_dbg; + struct Dwarf_Debug_s * de_errors_dbg; + Dwarf_Handler de_errhand; Dwarf_Ptr de_errarg; @@ -958,8 +1004,7 @@ int _dwarf_search_for_signature(Dwarf_Debug dbg, Dwarf_CU_Context *context_out, Dwarf_Error *error); -int _dwarf_merge_all_base_attrs_of_cu_die(Dwarf_Debug dbg, - Dwarf_CU_Context context, +int _dwarf_merge_all_base_attrs_of_cu_die(Dwarf_CU_Context context, Dwarf_Debug tieddbg, Dwarf_CU_Context *tiedcontext_out, Dwarf_Error *error); @@ -1155,9 +1200,22 @@ _dwarf_internal_global_formref_b(Dwarf_Attribute attr, Dwarf_Bool * offset_is_info, Dwarf_Error * error); -int _dwarf_skip_leb128(char * /*leb*/, - Dwarf_Unsigned * /*leblen*/, - char * /*endptr*/); +int +_dwarf_has_SECT_fission(Dwarf_CU_Context ctx, + unsigned int SECT_number, /* example: DW_SECT_RNGLISTS */ + Dwarf_Bool *hasfissionoffset, + Dwarf_Unsigned *loclistsbase); + +int _dwarf_skip_leb128(char * leb, + Dwarf_Unsigned * leblen, + char * endptr); + +/* Used for DW_AT_ranges to get base address along with + dwarf_lowpc() */ +int +_dwarf_entrypc(Dwarf_Die die, + Dwarf_Addr *return_addr, + Dwarf_Error *error); int _dwarf_get_suppress_debuglink_crc(void); void _dwarf_dumpsig(const char *msg, Dwarf_Sig8 *sig, int lineno); diff --git a/src/lib/libdwarf/dwarf_peread.c b/src/lib/libdwarf/dwarf_peread.c index d24e69d..8b20eac 100644 --- a/src/lib/libdwarf/dwarf_peread.c +++ b/src/lib/libdwarf/dwarf_peread.c @@ -566,7 +566,8 @@ _dwarf_pe_load_dwarf_section_headers( if (sec_outp->VirtualSize > ((Dwarf_Unsigned)2000* (Dwarf_Unsigned)1000* - (Dwarf_Unsigned)1000)) { + (Dwarf_Unsigned)1000) && + (sec_outp->VirtualSize > pep->pe_filesize)) { /* Likely unreasonable. the hard limit written this way simply for clarity. @@ -574,7 +575,8 @@ _dwarf_pe_load_dwarf_section_headers( *errcode = DW_DLE_PE_SECTION_SIZE_HEURISTIC_FAIL; return DW_DLV_ERROR; } - if (sec_outp->VirtualSize > limit) { + if (sec_outp->VirtualSize > limit && + 0 == pep->pe_is_64bit ) { /* Likely totally unreasonable. Bad. */ *errcode = DW_DLE_PE_SECTION_SIZE_HEURISTIC_FAIL; return DW_DLV_ERROR; diff --git a/src/lib/libdwarf/dwarf_query.c b/src/lib/libdwarf/dwarf_query.c index 98dfa4f..ec1a13b 100644 --- a/src/lib/libdwarf/dwarf_query.c +++ b/src/lib/libdwarf/dwarf_query.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2000,2002,2004 Silicon Graphics, Inc. All Rights Reserved. + Cropyright (C) 2000,2002,2004 Silicon Graphics, Inc. All Rights Reserved. Portions Copyright (C) 2007-2022 David Anderson. All Rights Reserved. Portions Copyright 2012 SN Systems Ltd. All rights reserved. Portions Copyright 2020 Google All rights reserved. @@ -814,7 +814,13 @@ _dwarf_get_value_ptr(Dwarf_Die die, of debug_info or debug_types or a section is unreasonably sized or we are pointing to two different sections? */ - _dwarf_error(dbg,error,DW_DLE_DIE_ABBREV_BAD); + _dwarf_error_string(dbg,error, + DW_DLE_DIE_ABBREV_BAD, + "DW_DLE_DIE_ABBREV_BAD: in calculating the " + "size of a value based on abbreviation data " + "we find there is not enough room in " + "the .debug_info " + "section to contain the attribute value."); return DW_DLV_ERROR; } } @@ -839,6 +845,7 @@ dwarf_die_text(Dwarf_Die die, res = dwarf_attr(die,attrnum,&attr,&lerr); dbg = die->di_cu_context->cc_dbg; if (res == DW_DLV_ERROR) { + dwarf_dealloc_error(dbg,lerr); return DW_DLV_NO_ENTRY; } if (res == DW_DLV_NO_ENTRY) { @@ -967,7 +974,7 @@ dwarf_attr(Dwarf_Die die, Error returned here is on dbg, not tieddbg. This looks for DW_AT_addr_base and if present adds it in appropriately. - You should use _dwarf_look_in_local_and_tied_by_index() + Use _dwarf_look_in_local_and_tied_by_index() instead of this, in general. */ static int @@ -986,12 +993,12 @@ _dwarf_extract_address_from_debug_addr(Dwarf_Debug dbg, Dwarf_Byte_Ptr sectionend = 0; Dwarf_Unsigned sectionsize = 0; - address_base = context->cc_addr_base; + address_base = context->cc_addr_base_offset; res = _dwarf_load_section(dbg, &dbg->de_debug_addr,error); if (res != DW_DLV_OK) { /* Ignore the inner error, report something meaningful */ if (res == DW_DLV_ERROR && error) { - dwarf_dealloc(dbg,*error, DW_DLA_ERROR); + dwarf_dealloc_error(dbg,*error); *error = 0; } _dwarf_error(dbg,error, @@ -1046,6 +1053,10 @@ _dwarf_extract_address_from_debug_addr(Dwarf_Debug dbg, return DW_DLV_OK; } +/* Looks for an address (Dwarf_Addr) value vi an + index into debug_addr. If it fails with + DW_DLE_MISSING_NEEDED_DEBUG_ADDR_SECTION we + find a context in tieddbg and look there. */ int _dwarf_look_in_local_and_tied_by_index( Dwarf_Debug dbg, @@ -1063,11 +1074,12 @@ _dwarf_look_in_local_and_tied_by_index( error && dwarf_errno(*error) == DW_DLE_MISSING_NEEDED_DEBUG_ADDR_SECTION && dbg->de_tied_data.td_tied_object) { + /* see also DBG_HAS_SECONDARY macro */ int res3 = 0; /* We do not want to leak error structs... */ /* *error safe */ - dwarf_dealloc(dbg,*error,DW_DLA_ERROR); + dwarf_dealloc_error(dbg,*error); *error = 0; /* *error safe */ /* Any error is returned on dbg, not tieddbg. */ @@ -1104,9 +1116,11 @@ dwarf_debug_addr_index_to_addr(Dwarf_Die die, error); return res; } -/* ASSERT: +/* ASSERT: attr_form == DW_FORM_GNU_addr_index || attr_form == DW_FORM_addrx + We are looking for data in .debug_addr, + which could be in base file or in tied-file.. */ int _dwarf_look_in_local_and_tied(Dwarf_Half attr_form, @@ -1127,23 +1141,6 @@ _dwarf_look_in_local_and_tied(Dwarf_Half attr_form, if (res2 != DW_DLV_OK) { return res2; } -#if 0 /* An error check that is probably incorect. */ - Dwarf_Unsigned addrtabsize = 0; - addrtabsize = dbg->de_debug_addr.dss_size; - If there is no .debug_addr the error here should - not be reported as will report that - via _dwarf_look_in_local_and_tied_by_index - if (!dbg->de_tied_data.td_tied_object && - (index_to_addr > dbg->de_filesize || - index_to_addr > addrtabsize || - (index_to_addr*context->cc_address_size) > addrtabsize)) { - _dwarf_error_string(dbg,error,DW_DLE_ATTR_FORM_OFFSET_BAD, - "DW_DLE_ATTR_FORM_OFFSET_BAD " - "Looking for an index from an addr FORM " - "we find an impossibly large value. Corrupt DWARF"); - return DW_DLV_ERROR; - } -#endif /* error is returned on dbg, not tieddbg. */ res2 = _dwarf_look_in_local_and_tied_by_index( dbg,context,index_to_addr,return_addr,error); @@ -1151,8 +1148,10 @@ _dwarf_look_in_local_and_tied(Dwarf_Half attr_form, } -int -dwarf_lowpc(Dwarf_Die die, +static int +_dwarf_lowpc_internal(Dwarf_Die die, + Dwarf_Half attrnum, + const char *msg, Dwarf_Addr *return_addr, Dwarf_Error *error) { @@ -1173,7 +1172,7 @@ dwarf_lowpc(Dwarf_Die die, dbg = context->cc_dbg; address_size = context->cc_address_size; offset_size = context->cc_length_size; - res = _dwarf_get_value_ptr(die, DW_AT_low_pc, + res = _dwarf_get_value_ptr(die, attrnum, &attr_form,&info_ptr,0,error); if (res == DW_DLV_ERROR) { return res; @@ -1182,11 +1181,12 @@ dwarf_lowpc(Dwarf_Die die, return res; } version = context->cc_version_stamp; - class = dwarf_get_form_class(version,DW_AT_low_pc, + class = dwarf_get_form_class(version,attrnum, offset_size,attr_form); if (class != DW_FORM_CLASS_ADDRESS) { - /* Not the correct form for DW_AT_low_pc */ - _dwarf_error(dbg, error, DW_DLE_LOWPC_WRONG_CLASS); + /* Not a correct FORM for low_pc or entry_pc */ + _dwarf_error_string(dbg, error, DW_DLE_LOWPC_WRONG_CLASS, + (char *)msg); return DW_DLV_ERROR; } @@ -1209,6 +1209,30 @@ dwarf_lowpc(Dwarf_Die die, *return_addr = ret_addr; return DW_DLV_OK; } +int +dwarf_lowpc(Dwarf_Die die, + Dwarf_Addr *return_addr, + Dwarf_Error *error) +{ + int res = 0; + + res = _dwarf_lowpc_internal (die,DW_AT_low_pc, + "DW_AT_low_pc data unavailable", + return_addr,error); + return res; +} +int +_dwarf_entrypc(Dwarf_Die die, + Dwarf_Addr *return_addr, + Dwarf_Error *error) +{ + int res = 0; + + res = _dwarf_lowpc_internal (die,DW_AT_entry_pc, + "DW_AT_entry_pc and DW_AT_low_pc data unavailable", + return_addr,error); + return res; +} /* If 'die' contains the DW_AT_type attribute, it returns the (global) offset referenced by the attribute through @@ -1245,10 +1269,14 @@ dwarf_dietype_offset(Dwarf_Die die, } /* Only a few values are inherited from the tied - file. Not rnglists or loclists base offsets. */ + file. Not rnglists or loclists base offsets? + merging into main context (dwp) from tieddbg (Skeleton). + and returning a pointer to the tiedcontext created here. + (such contexts are freed by dwarf_finish on the tied + object file). +*/ int -_dwarf_merge_all_base_attrs_of_cu_die(Dwarf_Debug dbg, - Dwarf_CU_Context context, +_dwarf_merge_all_base_attrs_of_cu_die(Dwarf_CU_Context context, Dwarf_Debug tieddbg, Dwarf_CU_Context *tiedcontext_out, Dwarf_Error *error) @@ -1267,31 +1295,53 @@ _dwarf_merge_all_base_attrs_of_cu_die(Dwarf_Debug dbg, &tiedcontext, error); if ( res == DW_DLV_ERROR) { - /* Associate the error with dbg, not tieddbg */ - _dwarf_error_mv_s_to_t(tieddbg,error,dbg,error); return res; } if ( res == DW_DLV_NO_ENTRY) { return res; } - if (!context->cc_low_pc_present) { + if (tiedcontext->cc_low_pc_present) { + /* A dwo/dwp will not have this, merge from tied + Needed for rnglists/loclists + */ context->cc_low_pc_present = tiedcontext->cc_low_pc_present; - context-> cc_low_pc= + context-> cc_low_pc = tiedcontext->cc_low_pc; } - if (!context->cc_addr_base_present) { - context-> cc_addr_base_present = - tiedcontext->cc_addr_base_present; - context-> cc_addr_base= - tiedcontext->cc_addr_base; + + if (tiedcontext->cc_base_address_present) { + context->cc_base_address_present = + tiedcontext->cc_base_address_present; + context-> cc_base_address = + tiedcontext->cc_base_address; } - if (context->cc_version_stamp == DW_CU_VERSION4 && - !context->cc_ranges_base_present) { - context->cc_ranges_base_present = - tiedcontext->cc_ranges_base_present; - context->cc_ranges_base = - tiedcontext->cc_ranges_base;; + if (tiedcontext->cc_addr_base_offset_present) { + /* This is a base-offset, not an address. */ + context-> cc_addr_base_offset_present = + tiedcontext->cc_addr_base_offset_present; + context-> cc_addr_base_offset= + tiedcontext->cc_addr_base_offset; + } + if (context->cc_version_stamp == DW_CU_VERSION4 || + context->cc_version_stamp == DW_CU_VERSION5) { +#if 0 /* we do not inherit cc_rnglists_base_present */ + /* This inheritance has been removed from DWARF6 + during 2024. */ + + if (!context->cc_rnglists_base_present) { + context->cc_rnglists_base_present = + tiedcontext->cc_rnglists_base_present; + context->cc_rnglists_base = + tiedcontext->cc_rnglists_base; + } +#endif + if (!context->cc_ranges_base_present) { + context->cc_ranges_base_present= + tiedcontext->cc_ranges_base_present; + context->cc_ranges_base= + tiedcontext->cc_ranges_base; + } } if (!context->cc_str_offsets_tab_present) { context-> cc_str_offsets_tab_present = @@ -1458,7 +1508,7 @@ dwarf_highpc_b(Dwarf_Die die, */ int -_dwarf_get_addr_from_tied(Dwarf_Debug dbg, +_dwarf_get_addr_from_tied(Dwarf_Debug primary_dbg, Dwarf_CU_Context context, Dwarf_Unsigned index, Dwarf_Addr *addr_out, @@ -1471,25 +1521,21 @@ _dwarf_get_addr_from_tied(Dwarf_Debug dbg, Dwarf_Unsigned addrtabsize = 0; if (!context->cc_signature_present) { - _dwarf_error(dbg, error, DW_DLE_NO_SIGNATURE_TO_LOOKUP); + _dwarf_error(primary_dbg, error, + DW_DLE_NO_SIGNATURE_TO_LOOKUP); return DW_DLV_ERROR; } - tieddbg = dbg->de_tied_data.td_tied_object; - if (!tieddbg) { - _dwarf_error(dbg, error, DW_DLE_NO_TIED_ADDR_AVAILABLE); + if (!DBG_HAS_SECONDARY(primary_dbg)) { + _dwarf_error(primary_dbg, error, + DW_DLE_NO_TIED_ADDR_AVAILABLE); return DW_DLV_ERROR; } - if (!context->cc_addr_base_present) { - /* Does not exist. */ - return DW_DLV_NO_ENTRY; - } + tieddbg = primary_dbg->de_secondary_dbg; res = _dwarf_search_for_signature(tieddbg, context->cc_signature, &tiedcontext, error); if (res == DW_DLV_ERROR) { - /* Associate the error with dbg, not tieddbg */ - _dwarf_error_mv_s_to_t(tieddbg,error,dbg,error); return res; } if ( res == DW_DLV_NO_ENTRY) { @@ -1500,7 +1546,8 @@ _dwarf_get_addr_from_tied(Dwarf_Debug dbg, if ( (index > tieddbg->de_filesize || index > addrtabsize || (index*tiedcontext->cc_address_size) > addrtabsize)) { - _dwarf_error_string(dbg,error,DW_DLE_ATTR_FORM_OFFSET_BAD, + _dwarf_error_string(primary_dbg,error, + DW_DLE_ATTR_FORM_OFFSET_BAD, "DW_DLE_ATTR_FORM_OFFSET_BAD " "Looking for an index from an addr FORM " "we find an impossibly large index value for the tied " @@ -1513,8 +1560,6 @@ _dwarf_get_addr_from_tied(Dwarf_Debug dbg, &local_addr, error); if ( res == DW_DLV_ERROR) { - /* Associate the error with dbg, not tidedbg */ - _dwarf_error_mv_s_to_t(tieddbg,error,dbg,error); return res; } if ( res == DW_DLV_NO_ENTRY) { @@ -1814,6 +1859,7 @@ dw_get_special_offset(Dwarf_Half attrnum, } return DW_FORM_CLASS_LOCLISTPTR; } + case DW_AT_GNU_locviews: case DW_AT_sibling: case DW_AT_byte_size : case DW_AT_bit_offset : @@ -1843,6 +1889,8 @@ dw_get_special_offset(Dwarf_Half attrnum, case DW_AT_object_pointer: case DW_AT_signature: return DW_FORM_CLASS_REFERENCE; + case DW_AT_GNU_entry_view: + return DW_FORM_CLASS_CONSTANT; case DW_AT_MIPS_fde: /* SGI/IRIX extension */ return DW_FORM_CLASS_FRAMEPTR; default: break; diff --git a/src/lib/libdwarf/dwarf_ranges.c b/src/lib/libdwarf/dwarf_ranges.c index 1f18c7e..550ce41 100644 --- a/src/lib/libdwarf/dwarf_ranges.c +++ b/src/lib/libdwarf/dwarf_ranges.c @@ -46,6 +46,9 @@ #include "dwarf_util.h" #include "dwarf_string.h" +#define DEBUG_RANGES 1 +#undef DEBUG_RANGES + struct ranges_entry { struct ranges_entry *next; Dwarf_Ranges cur; @@ -129,7 +132,6 @@ int dwarf_get_ranges_b(Dwarf_Debug dbg, int res = DW_DLV_ERROR; Dwarf_Unsigned ranges_base = 0; Dwarf_Debug localdbg = dbg; - Dwarf_Error localerror = 0; /* default for dwarf_get_ranges() */ Dwarf_Half die_version = 3; @@ -140,7 +142,8 @@ int dwarf_get_ranges_b(Dwarf_Debug dbg, CHECK_DBG(dbg,error,"dwarf_get_ranges_b()"); address_size = localdbg->de_pointer_size; /* default */ if (die) { - /* printing by raw offset from DW_AT_ranges attribute. + /* printing DW_AT_ranges attribute. and the local DIE + it belongs to. If we wind up using the tied file the die_version had better match! It cannot be other than a match. Can return DW_DLV_ERROR, not DW_DLV_NO_ENTRY. @@ -187,16 +190,18 @@ int dwarf_get_ranges_b(Dwarf_Debug dbg, if (res == DW_DLV_ERROR) { return res; } + /* FIX. HAS_TIED or ? */ if (res == DW_DLV_NO_ENTRY) { /* data is in a.out, not dwp */ - localdbg = dbg->de_tied_data.td_tied_object; - if (!localdbg) { + if (!DBG_HAS_SECONDARY(dbg)) { return DW_DLV_NO_ENTRY; } + localdbg = dbg->de_secondary_dbg; res = _dwarf_load_section(localdbg, - &localdbg->de_debug_ranges, &localerror); + &localdbg->de_debug_ranges, error); if (res == DW_DLV_ERROR) { - _dwarf_error_mv_s_to_t(localdbg,&localerror,dbg,error); + /* Error will automatically be put on dbg (main + dbg), not localdbg (tieddbg) as of late 2024. */ return res; } if (res == DW_DLV_NO_ENTRY) { @@ -248,12 +253,6 @@ int dwarf_get_ranges_b(Dwarf_Debug dbg, section_end = localdbg->de_debug_ranges.dss_data + localdbg->de_debug_ranges.dss_size; rangeptr = localdbg->de_debug_ranges.dss_data; -#if 0 - if (!rangeslocal) { - /* printing ranges where range source is dwp, - here we just assume present. */ - } -#endif rangeptr += rangesoffset; beginrangeptr = rangeptr; @@ -366,6 +365,12 @@ dwarf_dealloc_ranges(Dwarf_Debug dbg, Dwarf_Ranges * rangesbuf, dwarf_dealloc(dbg,rangesbuf, DW_DLA_RANGES); } +/* Also used to determine DIE base_address, + but that was wrong. + Only a CU_die DW_AT_low_pc can provide + a CU-wide base address and that is done when a CU is first + read, and available as cucontext->cc_base_address + and cc_base_address_present. */ static int _dwarf_determine_die_range_offset(Dwarf_Debug dw_dbg, Dwarf_Die dw_die, @@ -375,12 +380,11 @@ _dwarf_determine_die_range_offset(Dwarf_Debug dw_dbg, Dwarf_Unsigned *die_base_addr, Dwarf_Error *dw_error) { - Dwarf_Bool hasatranges = FALSE; - Dwarf_Bool haslowpc = FALSE; - Dwarf_Attribute attr = 0; - Dwarf_Unsigned rangeoffset_local = 0; - int res = 0; - Dwarf_Unsigned local_lowpc = 0; + Dwarf_Bool hasatranges = FALSE; + Dwarf_Attribute attr = 0; + Dwarf_Unsigned rangeoffset_local = 0; + int res = 0; + Dwarf_CU_Context cucon = 0; res = dwarf_hasattr(dw_die,DW_AT_ranges, &hasatranges,dw_error); if (res != DW_DLV_OK) { @@ -397,43 +401,27 @@ _dwarf_determine_die_range_offset(Dwarf_Debug dw_dbg, *dw_error = 0; } return res; - } else { - res = dwarf_global_formref(attr, - &rangeoffset_local, dw_error); - if (res != DW_DLV_OK) { - if (res == DW_DLV_ERROR) { - dwarf_dealloc_attribute(attr); - dwarf_dealloc_error(dw_dbg,*dw_error); - *dw_error = 0; - return res; - } - } - /* rangeoffset_local was set . */ } + res = dwarf_global_formref(attr, + &rangeoffset_local, dw_error); + if (res != DW_DLV_OK) { + if (res == DW_DLV_ERROR) { + dwarf_dealloc_attribute(attr); + dwarf_dealloc_error(dw_dbg,*dw_error); + *dw_error = 0; + return res; + } + } + cucon = dw_die->di_cu_context; + if (cucon->cc_base_address_present) { + *die_base_addr = cucon->cc_base_address; + *have_die_base_addr = TRUE; + } + /* rangeoffset_local was set . */ dwarf_dealloc_attribute(attr); attr = 0; *have_die_ranges_offset = TRUE; *die_ranges_offset = rangeoffset_local; - - res = dwarf_hasattr(dw_die,DW_AT_low_pc,&haslowpc,dw_error); - if (res != DW_DLV_OK) { - /* Never returns DW_DLV_NO_ENTRY */ - if (res == DW_DLV_ERROR) { - dwarf_dealloc_error(dw_dbg,*dw_error); - *dw_error = 0; - } - return DW_DLV_OK;; - } - res = dwarf_lowpc(dw_die,&local_lowpc,dw_error); - if (res != DW_DLV_OK) { - if (res == DW_DLV_ERROR) { - dwarf_dealloc_error(dw_dbg,*dw_error); - *dw_error = 0; - } - return DW_DLV_OK; - } - *have_die_base_addr = TRUE; - *die_base_addr = local_lowpc; return DW_DLV_OK; } @@ -457,8 +445,6 @@ dwarf_get_ranges_baseaddress(Dwarf_Debug dw_dbg, Dwarf_CU_Context context = 0; Dwarf_Unsigned local_ranges_offset = 0; Dwarf_Bool local_ranges_offset_present = FALSE; - Dwarf_Unsigned local_base_addr= 0; - Dwarf_Bool local_base_addr_present = FALSE; Dwarf_Bool have_die_ranges_offset = FALSE; Dwarf_Unsigned die_ranges_offset = 0; Dwarf_Bool have_die_base_addr = FALSE; @@ -520,22 +506,9 @@ dwarf_get_ranges_baseaddress(Dwarf_Debug dw_dbg, if (dw_at_ranges_offset_present) { *dw_at_ranges_offset_present = local_ranges_offset_present; } - if (have_die_base_addr) { - local_base_addr_present = have_die_base_addr; - local_base_addr = die_base_addr; - } else { - if (context->cc_low_pc_present ) { - local_base_addr_present = TRUE; - local_base_addr = context->cc_low_pc; - } - } - if (dw_baseaddress) { - /* Unless cc_low_pc_present is TRUE - cc_low_pc is always zero, and it - could be zero regardless. */ - - *dw_baseaddress = local_base_addr; - *dw_known_base = local_base_addr_present; + if (context->cc_base_address_present) { + *dw_baseaddress = context->cc_base_address; + *dw_known_base = context->cc_base_address_present; } return DW_DLV_OK; } diff --git a/src/lib/libdwarf/dwarf_rnglists.c b/src/lib/libdwarf/dwarf_rnglists.c index e579004..89809a8 100644 --- a/src/lib/libdwarf/dwarf_rnglists.c +++ b/src/lib/libdwarf/dwarf_rnglists.c @@ -51,12 +51,14 @@ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "dwarf_string.h" #include "dwarf_rnglists.h" +#undef DEBUG_RNGLIST + #define SIZEOFT8 1 #define SIZEOFT16 2 #define SIZEOFT32 4 #define SIZEOFT64 8 -#if 0 /* dump_bytes */ +#ifdef DEBUG_RNGLIST /* dump_bytes */ static void dump_bytes(const char *msg,Dwarf_Small * start, long len) { @@ -67,6 +69,7 @@ dump_bytes(const char *msg,Dwarf_Small * start, long len) printf("%02x", *cur); } printf("\n"); + fflush(stdout); } #endif /*0*/ #if 0 /* dump_rh */ @@ -129,41 +132,6 @@ dump_rc(const char *msg, } #endif -/* The DWARF5 standard does not make it clear that - there should be a rnglists_base even in a dwp object. - Table F.1 implies such is not needed. - gcc seems to leave it off in the dwp. - ibase is an offset in the array of offsets in a rnglist, - which only makes sense for DW_FORM_rnglistx and - in that case there is no base. - We are dealing with DW_FORM_rnglistx */ -static int -_dwarf_implicit_rnglists_base(Dwarf_Debug dbg, - Dwarf_Unsigned indexval, - Dwarf_Unsigned *ibase) -{ - Dwarf_Rnglists_Context rctx = 0; - if (IS_INVALID_DBG(dbg)) { - return DW_DLV_NO_ENTRY; - } - if (!dbg->de_debug_rnglists.dss_size) { - return DW_DLV_NO_ENTRY; - } - if (!dbg->de_rnglists_context_count) { - return DW_DLV_NO_ENTRY; - } - /* This implicit base can only work if the 0-th - Rnglists_Context is appropriate here. */ - rctx = dbg->de_rnglists_context[0]; - if (indexval > rctx->rc_offset_entry_count) { - /* We are not using base offset, we - will not see a DW_FORM_rnglistx */ - return DW_DLV_NO_ENTRY; - } - *ibase = rctx->rc_offsets_off_in_sect; - return DW_DLV_OK; -} - static void free_rnglists_context(Dwarf_Rnglists_Context cx) { @@ -283,7 +251,7 @@ read_single_rle_entry(Dwarf_Debug dbg, dwarfstring_constructor(&m); dwarfstring_append_printf_u(&m, "DW_DLE_RNGLISTS_ERROR: " - "The rangelists entry at .debug_rnglists" + "The rangelists entry at .debug_rnglists[.dwo]" " offset 0x%x" ,dataoffset); dwarfstring_append_printf_u(&m, " has code 0x%x which is unknown",code); @@ -301,8 +269,7 @@ read_single_rle_entry(Dwarf_Debug dbg, preserve a testing baseline: baselines/hongg2024-02-18-m.base otherwise we would test against sectionsize first.*/ - - Dwarf_Unsigned sectionsize = dbg->de_debug_rnglists.dss_size; + Dwarf_Unsigned sectionsize = 0; if (data > enddata || data < startdata ) { /* Corrupt data being read. */ @@ -312,6 +279,7 @@ read_single_rle_entry(Dwarf_Debug dbg, "of its allowed space"); return DW_DLV_ERROR; } + sectionsize = dbg->de_debug_rnglists.dss_size; if (count > sectionsize) { /* Corrupt data being read. */ _dwarf_error_string(dbg,error,DW_DLE_RNGLISTS_ERROR, @@ -332,8 +300,9 @@ read_single_rle_entry(Dwarf_Debug dbg, /* Reads the header. Determines the various offsets, including offset - of the next header. Does no memory - allocations here. */ + of the next header. ALlocates + an array pointed to by rc_offset_value_array + here. */ int _dwarf_internal_read_rnglists_header(Dwarf_Debug dbg, Dwarf_Bool build_offset_array, @@ -341,21 +310,21 @@ _dwarf_internal_read_rnglists_header(Dwarf_Debug dbg, Dwarf_Unsigned sectionlength, Dwarf_Small *data, Dwarf_Small *end_data, - Dwarf_Unsigned offset, + Dwarf_Unsigned starting_offset, Dwarf_Rnglists_Context buildhere, Dwarf_Unsigned *next_offset, Dwarf_Error *error) { - Dwarf_Small *startdata = data; + Dwarf_Small *startdata = data; Dwarf_Unsigned arealen = 0; - int offset_size = 0; - int exten_size = 0; + int offset_size = 0; + int exten_size = 0; Dwarf_Unsigned version = 0; - unsigned address_size = 0; - unsigned segment_selector_size= 0; + unsigned address_size = 0; + unsigned segment_selector_size= 0; Dwarf_Unsigned offset_entry_count = 0; Dwarf_Unsigned localoff = 0; - Dwarf_Unsigned lists_len = 0; + Dwarf_Unsigned lists_byte_len = 0; Dwarf_Unsigned secsize_dbg = 0; Dwarf_Unsigned sum_size = 0; @@ -369,7 +338,7 @@ _dwarf_internal_read_rnglists_header(Dwarf_Debug dbg, " section_length argument (%lu) mismatch vs.", sectionlength); dwarfstring_append_printf_u(&m, - ".debug_rnglists" + ".debug_rnglists[.dwo]" " section length",secsize_dbg); _dwarf_error_string(dbg,error,DW_DLE_RNGLISTS_ERROR, dwarfstring_string(&m)); @@ -381,17 +350,19 @@ _dwarf_internal_read_rnglists_header(Dwarf_Debug dbg, data,offset_size,exten_size, error, sectionlength,end_data); - sum_size = arealen+offset_size+exten_size; + localoff = offset_size+exten_size; + /* local off is bytes including length field */ + sum_size = arealen+localoff; if (arealen > sectionlength || sum_size < arealen || sum_size > sectionlength) { dwarfstring m; dwarfstring_constructor(&m); dwarfstring_append_printf_u(&m, - "DW_DLE_RNGLISTS_ERROR: A .debug_rnglists " + "DW_DLE_RNGLISTS_ERROR: A .debug_rnglists[.dwo] " "area size of 0x%x ",arealen); dwarfstring_append_printf_u(&m, - "at offset 0x%x ",offset); + "at offset 0x%x ",starting_offset); dwarfstring_append_printf_u(&m, "is larger than the entire section size of " "0x%x. Corrupt DWARF.",sectionlength); @@ -400,11 +371,10 @@ _dwarf_internal_read_rnglists_header(Dwarf_Debug dbg, dwarfstring_destructor(&m); return DW_DLV_ERROR; } - localoff = offset_size+exten_size; - buildhere->rc_length = arealen + localoff; + buildhere->rc_length = sum_size; buildhere->rc_dbg = dbg; buildhere->rc_index = contextnum; - buildhere->rc_header_offset = offset; + buildhere->rc_header_offset = starting_offset; buildhere->rc_offset_size = offset_size; buildhere->rc_extension_size = exten_size; buildhere->rc_magic = RNGLISTS_MAGIC; @@ -431,7 +401,7 @@ _dwarf_internal_read_rnglists_header(Dwarf_Debug dbg, dwarfstring m; dwarfstring_constructor(&m); dwarfstring_append_printf_u(&m, - " DW_DLE_RNGLISTS_ERROR: .debug_rnglists " + " DW_DLE_RNGLISTS_ERROR: .debug_rnglists[.dwo] " "The address size " "of %u is not supported.",address_size); _dwarf_error_string(dbg,error,DW_DLE_RNGLISTS_ERROR, @@ -452,7 +422,7 @@ _dwarf_internal_read_rnglists_header(Dwarf_Debug dbg, dwarfstring m; dwarfstring_constructor(&m); dwarfstring_append_printf_u(&m, - " DW_DLE_RNGLISTS_ERROR: .debug_rnglists" + " DW_DLE_RNGLISTS_ERROR: .debug_rnglists[.dwo]" " The segment selector size " "of %u is not supported.",address_size); _dwarf_error_string(dbg,error,DW_DLE_RNGLISTS_ERROR, @@ -460,13 +430,13 @@ _dwarf_internal_read_rnglists_header(Dwarf_Debug dbg, dwarfstring_destructor(&m); return DW_DLV_ERROR; } - if ((offset+localoff+SIZEOFT32) > secsize_dbg) { + if ((starting_offset+localoff+SIZEOFT32) > secsize_dbg) { dwarfstring m; dwarfstring_constructor(&m); dwarfstring_append_printf_u(&m, - " DW_DLE_RNGLISTS_ERROR: .debug_rnglists" + " DW_DLE_RNGLISTS_ERROR: .debug_rnglists[.dwo]" " Header runs off the end of the section " - " with offset %u",offset+localoff+SIZEOFT32); + " with offset %u",starting_offset+localoff+SIZEOFT32); _dwarf_error_string(dbg,error,DW_DLE_RNGLISTS_ERROR, dwarfstring_string(&m)); dwarfstring_destructor(&m); @@ -482,7 +452,7 @@ _dwarf_internal_read_rnglists_header(Dwarf_Debug dbg, dwarfstring m; dwarfstring_constructor(&m); dwarfstring_append_printf_u(&m, - " DW_DLE_RNGLISTS_ERROR: .debug_rnglists" + " DW_DLE_RNGLISTS_ERROR: .debug_rnglists[.dwo]" " offset entry size impossibly large " " with size 0x%x", offset_entry_count*offset_size); @@ -491,9 +461,9 @@ _dwarf_internal_read_rnglists_header(Dwarf_Debug dbg, dwarfstring_destructor(&m); return DW_DLV_ERROR; } - if (offset_entry_count ){ + if (offset_entry_count){ buildhere->rc_offsets_array = data; - lists_len += offset_size*offset_entry_count; + lists_byte_len += offset_size*offset_entry_count; if (build_offset_array) { Dwarf_Unsigned tabentrynum = 0; @@ -524,11 +494,14 @@ _dwarf_internal_read_rnglists_header(Dwarf_Debug dbg, } } /* else no offset table */ if (offset_entry_count >= secsize_dbg || - lists_len >= secsize_dbg) { + lists_byte_len >= secsize_dbg) { dwarfstring m; + + free(buildhere->rc_offset_value_array); + buildhere->rc_offset_value_array = 0; dwarfstring_constructor(&m); dwarfstring_append_printf_u(&m, - " DW_DLE_RNGLISTS_ERROR: .debug_rnglists" + " DW_DLE_RNGLISTS_ERROR: .debug_rnglists[.dwo]" " offset entry count" " of %u is clearly impossible. Corrupt data", offset_entry_count); @@ -537,14 +510,18 @@ _dwarf_internal_read_rnglists_header(Dwarf_Debug dbg, dwarfstring_destructor(&m); return DW_DLV_ERROR; } - data += lists_len; - buildhere->rc_offsets_off_in_sect = offset+localoff; - localoff += lists_len; + data += lists_byte_len; + buildhere->rc_offsets_off_in_sect = starting_offset+localoff; + localoff += lists_byte_len; if (localoff > buildhere->rc_length) { dwarfstring m; + + free(buildhere->rc_offset_value_array); + buildhere->rc_offset_value_array = 0; + dwarfstring_constructor(&m); dwarfstring_append_printf_u(&m, - " DW_DLE_RNGLISTS_ERROR: .debug_rnglists" + " DW_DLE_RNGLISTS_ERROR: .debug_rnglists[.dwo]" " length of rnglists header too large at" " of %u is clearly impossible. Corrupt data", localoff); @@ -553,14 +530,17 @@ _dwarf_internal_read_rnglists_header(Dwarf_Debug dbg, dwarfstring_destructor(&m); return DW_DLV_ERROR; } - buildhere->rc_first_rnglist_offset = offset+localoff; + buildhere->rc_first_rnglist_offset = starting_offset+localoff; buildhere->rc_rnglists_header = startdata; buildhere->rc_endaddr = startdata +buildhere->rc_length; if (buildhere->rc_endaddr > end_data) { dwarfstring m; + + free(buildhere->rc_offset_value_array); + buildhere->rc_offset_value_array = 0; dwarfstring_constructor(&m); dwarfstring_append_printf_u(&m, - " DW_DLE_RNGLISTS_ERROR: .debug_rnglists" + " DW_DLE_RNGLISTS_ERROR: .debug_rnglists[.dwo]" " length of rnglists header (%u) " "runs off end of section. Corrupt data", buildhere->rc_length); @@ -571,6 +551,13 @@ _dwarf_internal_read_rnglists_header(Dwarf_Debug dbg, } buildhere->rc_past_last_rnglist_offset = buildhere->rc_header_offset +buildhere->rc_length; + if (buildhere->rc_past_last_rnglist_offset > secsize_dbg) { + free(buildhere->rc_offset_value_array); + buildhere->rc_offset_value_array = 0; + _dwarf_error_string(dbg,error,DW_DLE_RNGLISTS_ERROR, + "Impossible end of rnglist"); + return DW_DLV_ERROR; + } *next_offset = buildhere->rc_past_last_rnglist_offset; return DW_DLV_OK; } @@ -591,13 +578,13 @@ internal_load_rnglists_contexts(Dwarf_Debug dbg, Dwarf_Unsigned section_size = dbg->de_debug_rnglists.dss_size; Dwarf_Small * startdata = data; Dwarf_Small * end_data = data +section_size; - Dwarf_Chain curr_chain = 0; - Dwarf_Chain head_chain = 0; - Dwarf_Chain *plast = &head_chain; - int res = 0; + Dwarf_Chain curr_chain = 0; + Dwarf_Chain head_chain = 0; + Dwarf_Chain * plast = &head_chain; + int res = 0; + Dwarf_Unsigned i = 0; Dwarf_Unsigned chainlength = 0; Dwarf_Rnglists_Context *fullarray = 0; - Dwarf_Unsigned i = 0; for (i = 0 ; data < end_data ; ++i,data = startdata+nextoffset) { Dwarf_Rnglists_Context newcontext = 0; @@ -695,6 +682,8 @@ int dwarf_load_rnglists( if (dbg->de_rnglists_context) { if (rnglists_count) { *rnglists_count = dbg->de_rnglists_context_count; + } + if (rnglists_count) { } return DW_DLV_OK; } @@ -761,6 +750,8 @@ dwarf_get_rnglist_offset_index_value( Dwarf_Small *offsetptr = 0; Dwarf_Unsigned targetoffset = 0; Dwarf_Unsigned localoffset = 0; + Dwarf_Unsigned globaloffset = 0; + Dwarf_Unsigned section_size = 0; CHECK_DBG(dbg,error,"dwarf_get_rnglist_offset_index_value()"); if (!dbg->de_rnglists_context) { @@ -786,7 +777,13 @@ dwarf_get_rnglist_offset_index_value( } offset_len = con->rc_offset_size; localoffset = offsetentry_index*offset_len; - offsetptr = con->rc_offsets_array + localoffset; + if (localoffset >= con->rc_length) { + _dwarf_error_string(dbg,error, DW_DLE_RLE_ERROR, + "DW_DLE_RLE_ERROR: a .debug_rnglists[.dwo] " + "section offset " + "is greater than this rnglists table length"); + return DW_DLV_ERROR; + } if ((con->rc_offsets_off_in_sect +localoffset + offset_len) > con->rc_past_last_rnglist_offset) { @@ -804,15 +801,24 @@ dwarf_get_rnglist_offset_index_value( return DW_DLV_ERROR; } + offsetptr = con->rc_offsets_array + localoffset; READ_UNALIGNED_CK(dbg,targetoffset,Dwarf_Unsigned, offsetptr, offset_len,error,con->rc_endaddr); + globaloffset = con->rc_offsets_off_in_sect; + section_size = dbg->de_debug_rnglists.dss_size; + if (globaloffset >= section_size) { + _dwarf_error_string(dbg,error,DW_DLE_RNGLISTS_ERROR, + "DW_DLE_RNGLISTS_ERROR: " + "The offset of a rnglists entry is past " + "its allowed space"); + return DW_DLV_ERROR; + } if (offset_value_out) { *offset_value_out = targetoffset; } if (global_offset_value_out) { - *global_offset_value_out = targetoffset + - con->rc_offsets_off_in_sect; + *global_offset_value_out = globaloffset; } return DW_DLV_OK; } @@ -875,8 +881,9 @@ int dwarf_get_rnglist_head_basics( *rnglists_base_address_present = head->rh_cu_base_address_present; *rnglists_base_address= head->rh_cu_base_address; - *rnglists_debug_addr_base_present = head->rh_cu_addr_base_present; - *rnglists_debug_addr_base = head->rh_cu_addr_base; + *rnglists_debug_addr_base_present = + head->rh_cu_addr_base_offset_present; + *rnglists_debug_addr_base = head->rh_cu_addr_base_offset; return DW_DLV_OK; } @@ -1049,101 +1056,89 @@ int dwarf_get_rnglist_rle( static int _dwarf_which_rnglists_context(Dwarf_Debug dbg, Dwarf_CU_Context ctx, - Dwarf_Unsigned rnglist_offset, + Dwarf_Unsigned rnglist_offset/* not always set */, Dwarf_Unsigned *index, Dwarf_Error *error) { - Dwarf_Unsigned count; + Dwarf_Unsigned count = 0; Dwarf_Rnglists_Context *array; - Dwarf_Unsigned i = 0; + Dwarf_Rnglists_Context rcx = 0; + Dwarf_Unsigned rcxoff = 0; + Dwarf_Unsigned rcxend = 0; + + Dwarf_Unsigned i = 0; + Dwarf_Unsigned rnglists_base = 0; + Dwarf_Bool rnglists_base_present = FALSE; + int res = 0; + Dwarf_Bool found_base = FALSE; + Dwarf_Unsigned chosen_offset = 0; array = dbg->de_rnglists_context; count = dbg->de_rnglists_context_count; - /* Using the slow way, a simple linear search. */ - if (!ctx->cc_rnglists_base_present) { - /* We look at the location of each rnglist context - to find one with the offset the DIE gave us. */ - for ( i = 0 ; i < count; ++i) { - Dwarf_Rnglists_Context rcx = array[i]; - Dwarf_Unsigned rcxoff = rcx->rc_header_offset; - Dwarf_Unsigned rcxend = rcxoff + - rcx->rc_length; - if (rnglist_offset < rcxoff){ - continue; - } - if (rnglist_offset < rcxend ){ - *index = i; - return DW_DLV_OK; - } - } - { - dwarfstring m; - - dwarfstring_constructor(&m); - dwarfstring_append_printf_u(&m, - "DW_DLE_RNGLISTS_ERROR: rnglist ran off end " - " finding target offset of" - " 0x%" DW_PR_XZEROS DW_PR_DUx ,rnglist_offset); - dwarfstring_append(&m, - " Not found anywhere in .debug_rnglists " - "data. Corrupted data?"); - _dwarf_error_string(dbg,error, - DW_DLE_RNGLISTS_ERROR, - dwarfstring_string(&m)); - dwarfstring_destructor(&m); - return DW_DLV_ERROR; - } - } else { - /* We have a DW_AT_rnglists_base (cc_rangelists_base), - let's use it. */ - Dwarf_Unsigned lookfor = 0;; - - lookfor = ctx->cc_rnglists_base; - for ( i = 0 ; i < count; ++i) { - dwarfstring m; - - Dwarf_Rnglists_Context rcx = array[i]; - if (rcx->rc_offsets_off_in_sect == lookfor){ - *index = i; - return DW_DLV_OK; - } - if (rcx->rc_offsets_off_in_sect < lookfor){ - continue; - } - - dwarfstring_constructor(&m); - dwarfstring_append_printf_u(&m, - "DW_DLE_RNGLISTS_ERROR: rnglists base of " - " 0x%" DW_PR_XZEROS DW_PR_DUx ,lookfor); - dwarfstring_append_printf_u(&m, - " was not found though we are now at base " - " 0x%" DW_PR_XZEROS DW_PR_DUx , - rcx->rc_offsets_off_in_sect); - _dwarf_error_string(dbg,error, - DW_DLE_RNGLISTS_ERROR, - dwarfstring_string(&m)); - dwarfstring_destructor(&m); - return DW_DLV_ERROR; - } - { - dwarfstring m; - - dwarfstring_constructor(&m); - dwarfstring_append_printf_u(&m, - "DW_DLE_RNGLISTS_ERROR: rnglist base of " - " 0x%" DW_PR_XZEROS DW_PR_DUx ,lookfor); - dwarfstring_append(&m, - " was not found anywhere in .debug_rnglists " - "data. Corrupted data?"); - _dwarf_error_string(dbg,error, - DW_DLE_RNGLISTS_ERROR, - dwarfstring_string(&m)); - dwarfstring_destructor(&m); - return DW_DLV_ERROR; + if (!array) { + return DW_DLV_NO_ENTRY; + } + if (count == 1) { + *index = 0; + return DW_DLV_OK; + } + if (ctx->cc_rnglists_base_present) { + rnglists_base_present = ctx->cc_rnglists_base_present; + rnglists_base = ctx->cc_rnglists_base; + found_base = TRUE; + chosen_offset = rnglists_base; + } + if (!found_base) { + res = _dwarf_has_SECT_fission(ctx, + DW_SECT_RNGLISTS, + &rnglists_base_present,&rnglists_base); + if (res == DW_DLV_OK) { + found_base = TRUE; + chosen_offset = rnglists_base; } } - /* ASSERT: This line cannot be reached. */ + if (!found_base) { + rnglists_base = rnglist_offset; + chosen_offset = rnglist_offset; + } + + rcx = array[i]; + rcxoff = rcx->rc_header_offset; + rcxend = rcxoff + rcx->rc_length; + + /* We look at the location of each rnglist context + to find one with the offset we want */ + for ( i = 0 ; i < count; ++i) { + rcx = array[i]; + rcxoff = rcx->rc_header_offset; + rcxend = rcxoff + + rcx->rc_length; + if (chosen_offset < rcxoff){ + continue; + } + if (chosen_offset < rcxend ){ + *index = i; + return DW_DLV_OK; + } + } + { + dwarfstring m; + + dwarfstring_constructor(&m); + dwarfstring_append_printf_u(&m, + "DW_DLE_RNGLISTS_ERROR: rnglist ran off end " + " finding target offset of" + " 0x%" DW_PR_XZEROS DW_PR_DUx ,chosen_offset); + dwarfstring_append(&m, + " Not found anywhere in .debug_rnglists[.dwo] " + "data. Corrupted data?"); + _dwarf_error_string(dbg,error, + DW_DLE_RNGLISTS_ERROR, + dwarfstring_string(&m)); + dwarfstring_destructor(&m); + } + return DW_DLV_ERROR; } void @@ -1364,7 +1359,7 @@ build_array_of_rle(Dwarf_Debug dbg, dwarfstring_constructor(&m); dwarfstring_append_printf_u(&m, " DW_DLE_RNGLISTS_ERROR: " - " The .debug_rnglists " + " The .debug_rnglists[.dwo] " " rangelist code 0x%x is unknown, " " DWARF5 is corrupted.",code); _dwarf_error_string(dbg, error, @@ -1403,8 +1398,234 @@ build_array_of_rle(Dwarf_Debug dbg, return DW_DLV_OK; } +static int +_dwarf_fill_in_rle_head(Dwarf_Debug dbg, + Dwarf_Half theform, + /* attr_val is either an offset + (theform == DW_FORM_sec_offset) + to a specific rangelist entry set or + or a rnglistx index DW_FORM_rnglistx + at that index is the local offset of + a specific rangelist entry set. */ + Dwarf_Unsigned attr_val, + /* ctx is the context from the PRIMARY + dbg, not necessarily for *this* dbg */ + Dwarf_CU_Context ctx, + Dwarf_Rnglists_Head *head_out, + Dwarf_Unsigned *entries_count_out, + Dwarf_Unsigned *global_offset_of_rle_set, + Dwarf_Error *error) +{ + Dwarf_Bool is_rnglistx = FALSE; + Dwarf_Unsigned entrycount = 0; + Dwarf_Unsigned offset_in_rnglists = 0; + Dwarf_Rnglists_Context *array = 0; + Dwarf_Rnglists_Context rctx = 0; + struct Dwarf_Rnglists_Head_s shead; + Dwarf_Rnglists_Head lhead = 0; + Dwarf_Unsigned rnglists_contextnum = 0; + int res = 0; + Dwarf_Small *table_base = 0; + Dwarf_Small *table_entry = 0; + Dwarf_Small *enddata = 0; + Dwarf_Unsigned rle_global_offset = 0; + unsigned offsetsize = 0; + Dwarf_Unsigned secsize = 0; + Dwarf_Debug localdbg = 0; + + if (theform == DW_FORM_rnglistx) { + is_rnglistx = TRUE; + } else { + offset_in_rnglists = attr_val; + } + /* ASSERT: the 3 pointers just set are non-null */ + /* the context cc_rnglists_base gives the offset + of the array. of offsets (if cc_rnglists_base_present) */ + secsize = dbg->de_debug_rnglists.dss_size; + if (dbg != ctx->cc_dbg) { + /* is_rnglistx TRUE */ + /* Now find the correct secondary context via + signature. */ + Dwarf_CU_Context lctx = 0; + if (ctx->cc_signature_present) { + /* Looking in current dbg for the correct cu context */ + res = _dwarf_search_for_signature(dbg, + ctx->cc_signature, + &lctx,error); + if (res != DW_DLV_OK) { + if (res == DW_DLV_NO_ENTRY) { + } else { + _dwarf_error_string(dbg,error, DW_DLE_RLE_ERROR, + "DW_DLE_RLE_ERROR: a .debug_rnglists[.dwo] " + "cu context cannot be found with the " + "correct signature"); + } + return res; + } else { + ctx = lctx; + } + } else { + /* No signature. Hopeless, I think. */ + _dwarf_error_string(dbg,error, DW_DLE_RLE_ERROR, + "DW_DLE_RLE_ERROR: a .debug_rnglists[.dwo] " + "cu context cannot be found as there is " + "no signature to use"); + return DW_DLV_ERROR; + } + } + + /* A */ + if (ctx->cc_rnglists_base_present) { + offset_in_rnglists = ctx->cc_rnglists_base; + } else { + offset_in_rnglists = attr_val; + } + if (offset_in_rnglists >= secsize) { + _dwarf_error_string(dbg,error, DW_DLE_RLE_ERROR, + "DW_DLE_RLE_ERROR: a .debug_rnglists[.dwo] offset " + "is greater than the rnglists section size"); + return DW_DLV_ERROR; + } + /* B */ + localdbg = dbg; + { + /* This call works for updated DWARF5 not inheriting + DW_AT_rnglists_base or generating such. + It returns rangelists_context 0 if no + base, which works for gcc/clang. */ + res = _dwarf_which_rnglists_context(localdbg,ctx, + offset_in_rnglists, + &rnglists_contextnum,error); + if (res == DW_DLV_OK) { + /* FALL THROUGH */ + } else if (res == DW_DLV_NO_ENTRY) { + rnglists_contextnum = 0; + /* FALL THROUGH */ + } else { + return res; + } + } + /* C */ + array = localdbg->de_rnglists_context; + rctx = array[rnglists_contextnum]; + table_base = rctx->rc_offsets_array; + entrycount = rctx->rc_offset_entry_count; + offsetsize = rctx->rc_offset_size; + enddata = rctx->rc_endaddr; + if (is_rnglistx && attr_val >= entrycount) { + dwarfstring m; + + dwarfstring_constructor(&m); + dwarfstring_append_printf_u(&m, + "DW_DLE_RNGLISTS_ERROR: rnglists table index of" + " %u" ,attr_val); + dwarfstring_append_printf_u(&m, + " too large for table of %u " + "entries.",entrycount); + _dwarf_error_string(dbg,error, + DW_DLE_RNGLISTS_ERROR, + dwarfstring_string(&m)); + dwarfstring_destructor(&m); + return DW_DLV_ERROR; + } + memset(&shead,0,sizeof(shead)); + shead.rh_context = ctx; + shead.rh_magic = RNGLISTS_MAGIC; + shead.rh_localcontext = rctx; + shead.rh_index = rnglists_contextnum; + shead.rh_version = rctx->rc_version; + shead.rh_offset_size = offsetsize; + shead.rh_address_size = rctx->rc_address_size; + shead.rh_segment_selector_size = + rctx->rc_segment_selector_size; + + /* DW_AT_rnglists_base from CU */ + shead.rh_at_rnglists_base_present = + ctx->cc_rnglists_base_present; + shead.rh_at_rnglists_base = ctx->cc_rnglists_base; + + /* DW_AT_low_pc originally if present. From CU, + possibly inherited into dwo from skeleton. */ + shead.rh_cu_base_address_present = ctx->cc_base_address_present; + shead.rh_cu_base_address = ctx->cc_base_address;; + + /* base address DW_AT_addr_base of our part of + .debug_addr, from CU */ + shead.rh_cu_addr_base_offset = ctx->cc_addr_base_offset; + shead.rh_cu_addr_base_offset_present = + ctx->cc_addr_base_offset_present; + + /* D */ + if (is_rnglistx) { + Dwarf_Unsigned table_entryval = 0; + + table_entry = attr_val*offsetsize + table_base; + /* No malloc here yet so no leak if the macro returns + DW_DLV_ERROR */ + READ_UNALIGNED_CK(localdbg,table_entryval, Dwarf_Unsigned, + table_entry,offsetsize,error,enddata); + if (table_entryval >= secsize) { + _dwarf_error_string(dbg,error, DW_DLE_RLE_ERROR, + "DW_DLE_RLE_ERROR: a .debug_rnglists[.dwo] " + "table entry " + "value is impossibly large"); + return DW_DLV_ERROR; + } + if ((rctx->rc_offsets_off_in_sect + + table_entryval) >= secsize) { + _dwarf_error_string(dbg,error, DW_DLE_RLE_ERROR, + "DW_DLE_RLE_ERROR: a .debug_rnglist[.dwo]s " + "table entry " + "value + section offset is impossibly large"); + return DW_DLV_ERROR; + } + rle_global_offset = rctx->rc_offsets_off_in_sect + + table_entryval; + } else { + rle_global_offset = attr_val; + } + /* E */ + shead.rh_end_data_area = enddata; + shead.rh_rlearea_offset = rle_global_offset; + shead.rh_rlepointer = rle_global_offset + + localdbg->de_debug_rnglists.dss_data; + lhead = (Dwarf_Rnglists_Head) + _dwarf_get_alloc(dbg,DW_DLA_RNGLISTS_HEAD,1); + if (!lhead) { + _dwarf_error_string(dbg, error, DW_DLE_ALLOC_FAIL, + "Allocating a Dwarf_Rnglists_Head struct fails" + " in libdwarf function " + "dwarf_rnglists_index_get_rle_head()"); + return DW_DLV_ERROR; + } + /* To read correctly from DWARF data we must + use the data in the tied (SECONDARY) when + applicable. This is a bit delicate. */ + shead.rh_dbg = localdbg; + *lhead = shead; + res = build_array_of_rle(localdbg,lhead,error); + if (res != DW_DLV_OK) { + dwarf_dealloc(localdbg,lhead,DW_DLA_RNGLISTS_HEAD); + return res; + } + if (global_offset_of_rle_set) { + *global_offset_of_rle_set = rle_global_offset; + } + /* Caller needs the head pointer else there will be leaks. */ + *head_out = lhead; + if (entries_count_out) { + *entries_count_out = lhead->rh_count; + } + return DW_DLV_OK; +} + /* Build a head with all the relevent Entries attached. + If the context is not found in the main object, + and there is a tied-file + use the context signature (should be present) + and look in the tied-file for a match and + get the content there. */ int dwarf_rnglists_get_rle_head( @@ -1423,21 +1644,9 @@ dwarf_rnglists_get_rle_head( Dwarf_Error *error) { int res = 0; - Dwarf_Unsigned rnglists_contextnum = 0; - Dwarf_Small *table_base = 0; - Dwarf_Small *table_entry = 0; - Dwarf_Small *enddata = 0; - Dwarf_Rnglists_Context *array = 0; - Dwarf_Rnglists_Context rctx = 0; - Dwarf_Unsigned entrycount = 0; - unsigned offsetsize = 0; - Dwarf_Unsigned rle_global_offset = 0; - Dwarf_Rnglists_Head lhead = 0; Dwarf_CU_Context ctx = 0; - struct Dwarf_Rnglists_Head_s shead; - Dwarf_Unsigned offset_in_rnglists = 0; Dwarf_Debug dbg = 0; - Dwarf_Bool is_rnglistx = FALSE; + Dwarf_Bool is_rnglistx = FALSE; if (!attr) { _dwarf_error_string(NULL, error,DW_DLE_DBG_NULL, @@ -1447,153 +1656,70 @@ dwarf_rnglists_get_rle_head( "dwarf_rnglists_get_rle_head()"); return DW_DLV_ERROR; } - memset(&shead,0,sizeof(shead)); ctx = attr->ar_cu_context; - dbg = ctx->cc_dbg; - CHECK_DBG(dbg,error, - "dwarf_rnglists_get_rle_head() via attribute"); - - array = dbg->de_rnglists_context; + dbg = ctx->cc_dbg; if (theform == DW_FORM_rnglistx) { is_rnglistx = TRUE; } - /* ASSERT: the 3 pointers just set are non-null */ - /* the context cc_rnglists_base gives the offset - of the array. of offsets (if cc_rnglists_base_present) */ - offset_in_rnglists = attr_val; - if (is_rnglistx) { - if (ctx->cc_rnglists_base_present) { - offset_in_rnglists = ctx->cc_rnglists_base; - } else if (ctx->cc_is_dwo) { - /* Generate a base and set as 'present' - by looking at the location offset - table that we are supposedly indexing into. - finding what the table value is. - An implicit rnglists_base. - Will not work with multiple rnglists! */ - int ires = 0; - Dwarf_Unsigned ibase = 0; - ires = _dwarf_implicit_rnglists_base(dbg, - attr_val,&ibase); - if (ires != DW_DLV_OK) { - dwarfstring m; + CHECK_DBG(dbg,error, + "dwarf_rnglists_get_rle_head() via attribute"); - dwarfstring_constructor(&m); - dwarfstring_append_printf_u(&m, - "DW_DLE_RNGLISTS_ERROR: rnglists table" - " index of" - " %u" ,attr_val); - dwarfstring_append(&m, - " is unusable, there is no default " - " rnglists base address "); - _dwarf_error_string(dbg,error, - DW_DLE_RNGLISTS_ERROR, - dwarfstring_string(&m)); - dwarfstring_destructor(&m); - return DW_DLV_ERROR; - } - ctx->cc_rnglists_base_present = TRUE; - ctx->cc_rnglists_base = ibase; - offset_in_rnglists = ibase; + if (is_rnglistx) { + if (ctx->cc_rnglists_base_present || + dbg->de_rnglists_context_count == 1) { + /* leave on primary. + WARNING: It is not clear whether + looking for a context count of 1 + is actually correct, but it + seems to work. */ + } else if (DBG_HAS_SECONDARY(dbg)){ + dbg = dbg->de_secondary_dbg; + CHECK_DBG(dbg,error, + "dwarf_rnglists_get_rle_head() via attribute(sec)"); } } else { - offset_in_rnglists = attr_val; + /* attr_val is .debug_rnglists section global offset + of a range list*/ + if (!dbg->de_debug_rnglists.dss_size || + attr_val >= dbg->de_debug_rnglists.dss_size) { + if (DBG_HAS_SECONDARY(dbg)) { + dbg = dbg->de_secondary_dbg; + CHECK_DBG(dbg,error, + "dwarf_rnglists_get_rle_head() " + "via attribute(secb)"); + } else { + /* There is an error to be + generated later */ + } + } } - res = _dwarf_which_rnglists_context(dbg,ctx, - offset_in_rnglists, - &rnglists_contextnum,error); - if (res != DW_DLV_OK) { + + res = _dwarf_load_section(dbg, + &dbg->de_debug_rnglists, + error); + if (res == DW_DLV_ERROR) { return res; } - rctx = array[rnglists_contextnum]; - table_base = rctx->rc_offsets_array; - entrycount = rctx->rc_offset_entry_count; - offsetsize = rctx->rc_offset_size; - enddata = rctx->rc_endaddr; - - if (is_rnglistx && attr_val >= entrycount) { - dwarfstring m; - - dwarfstring_constructor(&m); - dwarfstring_append_printf_u(&m, - "DW_DLE_RNGLISTS_ERROR: rnglists table index of" - " %u" ,attr_val); - dwarfstring_append_printf_u(&m, - " too large for table of %u " - "entries.",entrycount); - _dwarf_error_string(dbg,error, - DW_DLE_RNGLISTS_ERROR, - dwarfstring_string(&m)); - dwarfstring_destructor(&m); - return DW_DLV_ERROR; + if (res == DW_DLV_OK && dbg->de_debug_rnglists.dss_size) { + res = _dwarf_fill_in_rle_head(dbg, theform, + /* attr_val is either an offset + (theform == DW_FORM_sec_offset) + to a specific rangelist entry set or + or a rnglistx index DW_FORM_rnglistx + at that index is the local offset of + a specific rangelist entry set offset table. */ + attr_val, + ctx, + head_out, + entries_count_out, + global_offset_of_rle_set, + error); + if (res == DW_DLV_ERROR) { + return res; + } } - shead.rh_context = ctx; - shead.rh_magic = RNGLISTS_MAGIC; - shead.rh_localcontext = rctx; - shead.rh_index = rnglists_contextnum; - shead.rh_version = rctx->rc_version; - shead.rh_offset_size = offsetsize; - shead.rh_address_size = rctx->rc_address_size; - shead.rh_segment_selector_size = - rctx->rc_segment_selector_size; - - /* DW_AT_rnglists_base from CU */ - shead.rh_at_rnglists_base_present = - ctx->cc_rnglists_base_present; - shead.rh_at_rnglists_base = ctx->cc_rnglists_base; - - /* DW_AT_low_pc, if present. From CU */ - shead.rh_cu_base_address_present = ctx->cc_low_pc_present; - shead.rh_cu_base_address = ctx->cc_low_pc; - - /* base address DW_AT_addr_base of our part of - .debug_addr, from CU */ - shead.rh_cu_addr_base = ctx->cc_addr_base; - shead.rh_cu_addr_base_present = ctx->cc_addr_base_present; - if (is_rnglistx) { - Dwarf_Unsigned table_entryval = 0; - - table_entry = attr_val*offsetsize + table_base; - /* No malloc here yet so no leak if the macro returns - DW_DLV_ERROR */ - READ_UNALIGNED_CK(dbg,table_entryval, Dwarf_Unsigned, - table_entry,offsetsize,error,enddata); - rle_global_offset = rctx->rc_offsets_off_in_sect + - table_entryval; - } else { - rle_global_offset = attr_val; - } - - shead.rh_end_data_area = enddata; - shead.rh_rlearea_offset = rle_global_offset; - shead.rh_rlepointer = rle_global_offset + - dbg->de_debug_rnglists.dss_data; - lhead = (Dwarf_Rnglists_Head) - _dwarf_get_alloc(dbg,DW_DLA_RNGLISTS_HEAD,1); - if (!lhead) { - _dwarf_error_string(dbg, error, DW_DLE_ALLOC_FAIL, - "Allocating a Dwarf_Rnglists_Head struct fails" - " in libdwarf function " - "dwarf_rnglists_index_get_rle_head()"); - return DW_DLV_ERROR; - } - shead.rh_dbg = dbg; - *lhead = shead; - res = build_array_of_rle(dbg,lhead,error); - if (res != DW_DLV_OK) { - dwarf_dealloc(dbg,lhead,DW_DLA_RNGLISTS_HEAD); - return res; - } - if (global_offset_of_rle_set) { - *global_offset_of_rle_set = rle_global_offset; - } - /* Caller needs the head pointer else there will be leaks. */ - *head_out = lhead; - if (entries_count_out) { - *entries_count_out = lhead->rh_count; - } - return DW_DLV_OK; + return res; } /* As of 18 Aug 2020 diff --git a/src/lib/libdwarf/dwarf_rnglists.h b/src/lib/libdwarf/dwarf_rnglists.h index d2a1ec1..5a86527 100644 --- a/src/lib/libdwarf/dwarf_rnglists.h +++ b/src/lib/libdwarf/dwarf_rnglists.h @@ -112,7 +112,7 @@ struct Dwarf_Rnglists_Entry_s { Dwarf_Unsigned rle_raw1; Dwarf_Unsigned rle_raw2; /* Cooked means the raw values from the .debug_rnglists - section translated to DIE-specific addresses. */ + section translated to CU-specific addresses. */ Dwarf_Unsigned rle_cooked1; Dwarf_Unsigned rle_cooked2; Dwarf_Rnglists_Entry rle_next; @@ -148,8 +148,8 @@ struct Dwarf_Rnglists_Head_s { /* DW_AT_addr_base, so we can use .debug_addr if such is needed. */ - Dwarf_Bool rh_cu_addr_base_present; - Dwarf_Unsigned rh_cu_addr_base; + Dwarf_Bool rh_cu_addr_base_offset_present; + Dwarf_Unsigned rh_cu_addr_base_offset; Dwarf_Small * rh_rlepointer; Dwarf_Unsigned rh_rlearea_offset; Dwarf_Small * rh_end_data_area; diff --git a/src/lib/libdwarf/dwarf_setup_sections.c b/src/lib/libdwarf/dwarf_setup_sections.c index 0015af6..f3b7801 100644 --- a/src/lib/libdwarf/dwarf_setup_sections.c +++ b/src/lib/libdwarf/dwarf_setup_sections.c @@ -87,7 +87,7 @@ add_debug_section_info(Dwarf_Debug dbg, secdata->dss_name = name; /* Actual name from object file. */ secdata->dss_standard_name = standard_section_name; secdata->dss_number = obj_sec_num; - secdata->dss_zdebug_requires_decompress = + secdata->dss_zdebug_requires_decompress = (Dwarf_Small)havezdebug; /* We don't yet know about SHF_COMPRESSED */ debug_section->ds_duperr = duperr; @@ -105,6 +105,25 @@ add_debug_section_info(Dwarf_Debug dbg, return DW_DLV_ERROR; } +/* Avoid adding offest to null s2. + This function avoids a compiler warning: + error: 'strcmp' reading 1 or more bytes + from a region of size 0 + Offset is a fixed small positive number. */ +static int +both_strings_nonempty(const char *s1, const char *s2, int offset) +{ + const char *s3 = 0; + if (!s1 || !s2) { + return FALSE; + } + s3 = s2 + offset; + if (!s1[0] || !s3[0]) { + return FALSE; + } + return TRUE; +} + /* Return DW_DLV_OK etc. PRECONDITION: secname and targname are non-null pointers to strings. */ @@ -167,8 +186,9 @@ set_up_section(Dwarf_Debug dbg, So we add -Wnostringop-overread to the build as the error is a false positive. We had to drop stringop-overread references in compiler options, such turned off - valuable warnings. */ - if (postzprefix && + valuable warnings. Oct 2024 + refined the test to notice empty string */ + if (both_strings_nonempty(postzprefix,targname,DPREFIXLEN) && !strcmp(postzprefix,targname+DPREFIXLEN)) { /* zprefix version matches the object section name so the section is compressed and is diff --git a/src/lib/libdwarf/dwarf_tied.c b/src/lib/libdwarf/dwarf_tied.c index ad96aaf..984f76a 100644 --- a/src/lib/libdwarf/dwarf_tied.c +++ b/src/lib/libdwarf/dwarf_tied.c @@ -49,7 +49,7 @@ #include "dwarf_tsearch.h" #include "dwarf_tied_decls.h" -#if 0 /*debug dumpsignature */ +#ifdef DEBUG_PRIMARY_DBG /*debug dumpsignature */ void _dwarf_dumpsig(const char *msg, Dwarf_Sig8 *sig,int lineno) { @@ -139,19 +139,8 @@ _dwarf_loop_reading_debug_info_for_cu( it seems. Those signatures point from 'normal' to 'dwo/dwp' (DWARF4) */ int is_info = TRUE; - Dwarf_CU_Context startingcontext = 0; Dwarf_Unsigned next_cu_offset = 0; - startingcontext = tieddbg->de_info_reading.de_cu_context; - - if (startingcontext) { - next_cu_offset = - startingcontext->cc_debug_offset + - startingcontext->cc_length + - startingcontext->cc_length_size + - startingcontext->cc_extension_size; - } - for (;;) { int sres = DW_DLV_OK; Dwarf_Half cu_type = 0; @@ -177,6 +166,9 @@ _dwarf_loop_reading_debug_info_for_cu( &typeoffset, &next_cu_offset, &cu_type, error); + if (sres == DW_DLV_ERROR) { + return sres; + } if (sres == DW_DLV_NO_ENTRY) { break; } @@ -230,7 +222,10 @@ _dwarf_loop_reading_debug_info_for_cu( return DW_DLV_OK; } -/* If out of memory just return DW_DLV_NO_ENTRY. +/* If out of memory just return DW_DLV_NO_ENTRY. + This ensures all the tied CU contexts have been + created though the caller has most likely + never tried to read CUs in the tied-file. */ int _dwarf_search_for_signature(Dwarf_Debug tieddbg, diff --git a/src/lib/libdwarf/dwarf_tsearchhash.c b/src/lib/libdwarf/dwarf_tsearchhash.c index 0119173..a5355c3 100644 --- a/src/lib/libdwarf/dwarf_tsearchhash.c +++ b/src/lib/libdwarf/dwarf_tsearchhash.c @@ -223,7 +223,8 @@ printf("debugging: initial alloc prime to use %lu\n",prime_to_use); /* hashtab_ is an array of hs_entry, indexes 0 through tablesize_ -1. */ base->hashfunc_ = hashfunc; - base->hashtab_ = calloc(base->tablesize_, sizeof(struct ts_entry)); + base->hashtab_ = calloc(base->tablesize_, + sizeof(struct ts_entry)); if (!base->hashtab_) { free(base); return NULL; @@ -368,7 +369,8 @@ resize_table(struct hs_base *head, return; } newhead.tablesize_entry_index_ = new_entry_index; - newhead.hashtab_ = calloc(newhead.tablesize_, sizeof(struct ts_entry)); + newhead.hashtab_ = calloc(newhead.tablesize_, + sizeof(struct ts_entry)); if (!newhead.hashtab_) { /* Oops, too large. Leave table size as is, though things will get slow as it overfills. */ diff --git a/src/lib/libdwarf/dwarf_util.c b/src/lib/libdwarf/dwarf_util.c index b2bb0de..2e60189 100644 --- a/src/lib/libdwarf/dwarf_util.c +++ b/src/lib/libdwarf/dwarf_util.c @@ -70,6 +70,164 @@ dwarf_package_version(void) { return PACKAGE_VERSION; } +#ifdef DEBUG_PRIMARY_DBG +/* These functions are helpers in printing data while + debugging problems. + In normal use these are not compiled or used. + Created November 2024. */ + +const char * +_dwarf_basename(const char *full) +{ + const char *cp = full; + unsigned slashat = 0; + unsigned charnum = 0; + + if (!cp) { + return "null-filepath"; + } + for ( ; *cp; ++cp,++charnum) { + if (*cp == '/') { + slashat=charnum; + } + } + if (slashat) { + ++slashat; /* skip showing /(slash) */ + } + return (full+slashat); +} +void +_dwarf_print_is_primary(const char *msg, + Dwarf_Debug p, + int line, + const char *filepath) +{ + const char *basen = 0; + basen = _dwarf_basename(filepath); + if (DBG_IS_SECONDARY(p)) { + printf("%s SECONDARY dbg 0x%lx line %d %s\n",msg, + (unsigned long)p, + line, + basen); + fflush(stdout); + return; + } + if (DBG_IS_PRIMARY(p)) { + printf("%s PRIMARY dbg 0x%lx line %d %s\n",msg, + (unsigned long)p, + line, + basen); + fflush(stdout); + return; + } + printf("%s Error in primary/secondary. %s. " + "Unknown dbg 0x%lx line %d %s\n", + msg,p?"":"null dbg passed in", + (unsigned long)p,line,basen); + fflush(stdout); +} +void +_dwarf_dump_prim_sec(const char *msg,Dwarf_Debug p, int line, + const char *filepath) +{ + const char *basen = 0; + basen = _dwarf_basename(filepath); + printf("%s Print Primary/Secondary data from line %d %s", + msg,line,basen); + _dwarf_print_is_primary(msg,p,line,filepath); + printf(" dbg.............: 0x%lx\n", + (unsigned long)p); + printf(" de_dbg..........: 0x%lx\n", + (unsigned long)p->de_dbg); + printf(" de_primary_dbg..: 0x%lx\n", + (unsigned long)p->de_primary_dbg); + printf(" de_secondary_dbg: 0x%lx\n", + (unsigned long)p->de_secondary_dbg); + printf(" de_errors_dbg ..: 0x%lx\n", + (unsigned long)p->de_errors_dbg); + printf(" td_tied_object..: 0x%lx\n", + (unsigned long)p->de_tied_data.td_tied_object); + fflush(stdout); +} +void +_dwarf_dump_optional_fields(const char *msg, + Dwarf_CU_Context context, + int line, + const char *filepath) +{ + const char *basen = 0; + Dwarf_Debug dbg = 0; + + basen = _dwarf_basename(filepath); + printf("%s Optional Fields line %d %s\n", + msg,line,basen); + if (!context) { + printf(" ERROR: context not passed in \n"); + fflush(stdout); + return; + } + dbg = context->cc_dbg; + _dwarf_print_is_primary(" For Inheritance and more", + dbg,line,filepath); + printf(" cc_signature_present.......: %d \n", + context->cc_signature_present); + _dwarf_dumpsig(" signature", &context->cc_signature,line); + printf(" cc_low_pc_present..........: %d 0x%lx\n", + context->cc_low_pc_present, + (unsigned long)context->cc_low_pc); + printf(" cc_base_address_present....: %d 0x%lx\n", + context->cc_base_address_present, + (unsigned long)context->cc_base_address); + printf(" cc_dwo_name_present........: %d %s\n", + context->cc_dwo_name_present, + context->cc_dwo_name?context->cc_dwo_name: + "no-dwo-name-"); + /* useful? */ + printf(" cc_at_strx_present.........: %d\n", + context->cc_at_strx_present); + /* useful? */ + printf(" cc_cu_die_offset_present...: %d \n", + context->cc_cu_die_offset_present); + printf(" cc_at_ranges_offset_present: %d 0x%lx\n", + context->cc_at_ranges_offset_present, + (unsigned long)context->cc_at_ranges_offset); + printf(" cc_addr_base_offset_present: %d 0x%lx\n", + context->cc_addr_base_offset_present, + (unsigned long)context->cc_addr_base_offset); + printf(" cc_line_base_present.......: %d 0x%lx\n", + context->cc_line_base_present, + (unsigned long)context->cc_line_base); + printf(" cc_loclists_base_present...: %d 0x%lx\n", + context->cc_loclists_base_present, + (unsigned long)context->cc_loclists_base); + /* useful? */ + printf(" cc_loclists_header_length_present: %d\n", + context->cc_loclists_header_length_present); + printf(" cc_str_offsets_array_offset_present: %d 0x%lx\n", + context->cc_str_offsets_array_offset_present, + (unsigned long)context->cc_str_offsets_array_offset); + /* useful? */ + printf(" cc_str_offsets_tab_present.: %d \n", + context->cc_str_offsets_tab_present); + printf(" cc_macro_base_present......: %d 0x%lx\n", + context->cc_macro_base_present, + (unsigned long)context->cc_macro_base_present); + /* useful? */ + printf(" cc_macro_header_length_present: %d\n", + context->cc_macro_header_length_present); + printf(" cc_ranges_base_present.....: %d 0x%lx\n", + context->cc_ranges_base_present, + (unsigned long)context->cc_ranges_base); + printf(" cc_rnglists_base_present...: %d 0x%lx\n", + context->cc_rnglists_base_present, + (unsigned long)context->cc_rnglists_base); + /* useful? */ + printf(" cc_rnglists_header_length_present: %d\n", + context->cc_rnglists_header_length_present); + fflush(stdout); +} + +#endif /* DEBUG_PRIMARY_DBG */ #if 0 /* dump_bytes */ static void @@ -125,7 +283,8 @@ static void dump_hash_table(char *msg, tab->tb_highest_used_entry); for (i = 0; i < tab->tb_table_entry_count; ++i) { - sprintf(buf,"Tab entry %lu:",i); + sprintf(buf,sizeof(buf), + "Tab entry %lu:",i); /* Only for debug */ dump_ab_list(" ",buf,i,tab->tb_entries[i],__LINE__); } printf(" ---end hash tab---\n"); @@ -1191,7 +1350,7 @@ _dwarf_load_debug_info(Dwarf_Debug dbg, Dwarf_Error * error) return res; } /* debug_info won't be meaningful without - .debug_rnglists and .debug_rnglists if there + .debug_rnglists and .debug_loclists if there is one or both such sections. */ res = dwarf_load_rnglists(dbg,0,error); if (res == DW_DLV_ERROR) { @@ -1363,53 +1522,6 @@ _dwarf_printf(Dwarf_Debug dbg, return; } -/* Often errs and errt point to the same Dwarf_Error, - So exercise care. - All the arguments MUST be non-null, though - we deal with null errs/errt as best we can. - We ensure null dbg? will not cause problem either. */ -void -_dwarf_error_mv_s_to_t(Dwarf_Debug dbgs,Dwarf_Error *errs, - Dwarf_Debug dbgt,Dwarf_Error *errt) -{ - int mydw_errno = 0; - if (!errt) { - if (!errs) { - /* Nobody here! Surely this is impossible. */ - return; - } else { - /* There is no errt to copy errs to! */ - dwarf_dealloc(dbgs,*errs, DW_DLA_ERROR); - *errs = 0; - } - return; - } - if (!errs) { - /* there is no useful errs to build errt with! */ - return; - } - if (dbgs == dbgt) { - /* nothing much to do here. */ - if (errs != errt) { - /* Trivial copy of an error. */ - Dwarf_Error ers = *errs; - *errs = 0; - *errt = ers; - } - return; - } - /* copy errs errno to errt by building - a new errt. - variable if there is one! - Move the error from dbgs to dbgt. - Error numbers are all < 1000. - */ - mydw_errno = (int)dwarf_errno(*errs); - dwarf_dealloc(dbgs,*errs, DW_DLA_ERROR); - *errs = 0; - _dwarf_error(dbgt,errt, mydw_errno); -} - static int inthissection(struct Dwarf_Section_s *sec,Dwarf_Small *ptr) { diff --git a/src/lib/libdwarf/dwarf_util.h b/src/lib/libdwarf/dwarf_util.h index 98cd55f..5207448 100644 --- a/src/lib/libdwarf/dwarf_util.h +++ b/src/lib/libdwarf/dwarf_util.h @@ -487,8 +487,6 @@ int _dwarf_get_address_size(Dwarf_Debug dbg, Dwarf_Die die); int _dwarf_reference_outside_section(Dwarf_Die die, Dwarf_Small * startaddr, Dwarf_Small * pastend); -void _dwarf_error_mv_s_to_t(Dwarf_Debug dbgs,Dwarf_Error *errs, - Dwarf_Debug dbgt,Dwarf_Error *errt); int _dwarf_internal_get_die_comp_dir(Dwarf_Die die, const char **compdir_out, diff --git a/src/lib/libdwarf/libdwarf.h b/src/lib/libdwarf/libdwarf.h index e925100..f1e12b2 100644 --- a/src/lib/libdwarf/libdwarf.h +++ b/src/lib/libdwarf/libdwarf.h @@ -1,7 +1,7 @@ /* Copyright (C) 2000-2010 Silicon Graphics, Inc. All Rights Reserved. Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved. - Portions Copyright 2008-2023 David Anderson. All rights reserved. + Portions Copyright 2008-2024 David Anderson. All rights reserved. Portions Copyright 2008-2010 Arxan Technologies, Inc. All rights reserved. Portions Copyright 2010-2012 SN Systems Ltd. All rights reserved. @@ -99,10 +99,10 @@ extern "C" { */ /* Semantic Version identity for this libdwarf.h */ -#define DW_LIBDWARF_VERSION "0.11.0" +#define DW_LIBDWARF_VERSION "0.11.1" #define DW_LIBDWARF_VERSION_MAJOR 0 #define DW_LIBDWARF_VERSION_MINOR 11 -#define DW_LIBDWARF_VERSION_MICRO 0 +#define DW_LIBDWARF_VERSION_MICRO 1 #define DW_PATHSOURCE_unspecified 0 #define DW_PATHSOURCE_basic 1 @@ -338,8 +338,8 @@ typedef struct Dwarf_Block_s { Provides access to Dwarf_Locdesc_c, a single location description */ -typedef struct Dwarf_Locdesc_c_s * Dwarf_Locdesc_c; +typedef struct Dwarf_Locdesc_c_s * Dwarf_Locdesc_c; /*! @typedef Dwarf_Loc_Head_c provides access to any sort of location description for DWARF2,3,4, or 5. @@ -1477,9 +1477,11 @@ typedef struct Dwarf_Rnglists_Head_s * Dwarf_Rnglists_Head; #define DW_DLE_UNIVERSAL_BINARY_ERROR 502 #define DW_DLE_UNIV_BIN_OFFSET_SIZE_ERROR 503 #define DW_DLE_PE_SECTION_SIZE_HEURISTIC_FAIL 504 +#define DW_DLE_LLE_ERROR 505 +#define DW_DLE_RLE_ERROR 506 /*! @note DW_DLE_LAST MUST EQUAL LAST ERROR NUMBER */ -#define DW_DLE_LAST 504 +#define DW_DLE_LAST 506 #define DW_DLE_LO_USER 0x10000 /*! @} */ @@ -1822,11 +1824,36 @@ DW_API int dwarf_set_tied_dbg(Dwarf_Debug dw_split_dbg, /*! @brief Use with split dwarf. - Given a base Dwarf_Debug this returns - the tied Dwarf_Debug. + Given a main Dwarf_Debug this returns + the tied Dwarf_Debug if there is one + or else returns null(0). + + Before v0.11.0 it was not defined what this + returned if the tied-Dwarf_Debug + was passed in, but it would have returned + null(0) in that case. Unlikely anyone uses this call as - you had the tied and base dbg when calling + callers had the tied and base dbg when calling dwarf_set_tied_dbg(). + + @param dw_dbg + Pass in a non-null Dwarf_Debug which is either + a main-Dwarf_Debug or a tied-Dwarf_Debug. + @param dw_tieddbg_out + On success returns the applicable tied-Dwarf_Debug + through the pointer. + If dw_dbg is a tied-Dwarf_Debug the function returns + null(0) through the poiner. + If there is no tied-Dwarf_Debug (meaning there is + just a main-Dwarf_Debug) the function returns + null (0) through the pointer. + @param dw_error + If the dw_dbg is invalid or damaged then the function + returns DW_DLV_ERROR and + dw_error is set to point to the error details. + @return DW_DLV_OK or DW_DLV_ERROR. + Never returns DW_DLV_NO_ENTRY. + */ DW_API int dwarf_get_tied_dbg(Dwarf_Debug dw_dbg, Dwarf_Debug * dw_tieddbg_out,