Bump to v0.11.1

This commit is contained in:
Jeremy Rifkin 2024-12-03 23:07:45 -06:00
parent 97fd68c602
commit fe09ca800b
No known key found for this signature in database
GPG Key ID: 19AA8270105E8EB4
36 changed files with 1537 additions and 877 deletions

11
CMakeLists.txt vendored
View File

@ -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)

View File

@ -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

View File

@ -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")

View File

@ -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__);

View File

@ -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;

View File

@ -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;

View File

@ -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) {
@ -1953,7 +1963,7 @@ _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_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

View File

@ -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 */

View File

@ -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);

View File

@ -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? */

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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;

View File

@ -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*/

View File

@ -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;
@ -1590,14 +1594,18 @@ dwarf_get_loclist_c(Dwarf_Attribute attr,
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_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;

View File

@ -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);

View File

@ -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,18 +964,47 @@ _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. */
to find one with the offset we want */
for ( i = 0 ; i < count; ++i) {
rcx = array[i];
rcxoff = rcx->lc_header_offset;
@ -970,10 +1012,10 @@ _dwarf_which_loclists_context(Dwarf_Debug dbg,
rcx->lc_length;
rcxend = rcxoff +
rcx->lc_length;
if (loclist_offset < rcxoff){
if (chosen_offset < rcxoff){
continue;
}
if (loclist_offset < rcxend ){
if (chosen_offset < rcxend ){
*index = i;
return DW_DLV_OK;
}
@ -985,63 +1027,14 @@ _dwarf_which_loclists_context(Dwarf_Debug dbg,
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);
" 0x%" DW_PR_XZEROS DW_PR_DUx ,chosen_offset);
dwarfstring_append(&m,
" Not found anywhere in .debug_loclists "
" 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;
}
} 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;
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;
}
}
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.
@ -1227,6 +1193,8 @@ build_array_of_lle(Dwarf_Debug dbg,
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)
{
@ -1243,13 +1211,13 @@ _dwarf_loclists_fill_in_lle_head(Dwarf_Debug dbg,
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 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,79 +1226,76 @@ _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 (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 {
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 (res != DW_DLV_OK) {
return res;
}
}
}
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);
/* 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;
}
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;
}
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) {
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) {
if (is_loclistx && attr_val >= entrycount) {
dwarfstring m;
dwarfstring_constructor(&m);
@ -1346,7 +1311,6 @@ _dwarf_loclists_fill_in_lle_head(Dwarf_Debug dbg,
dwarfstring_destructor(&m);
return DW_DLV_ERROR;
}
}
llhead->ll_localcontext = rctx;
llhead->ll_index = loclists_contextnum;
llhead->ll_cuversion = rctx->lc_version;
@ -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 +

View File

@ -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" }
};

View File

@ -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

View File

@ -653,7 +653,7 @@ dwarf_get_macro_defundef(Dwarf_Macro_Context macro_context,
*macro_string =
(char *)"<Error: DW_FORM_str_sup-got-error>";
}
dwarf_dealloc(dbg,lerr,DW_DLA_ERROR);
dwarf_dealloc_error(dbg,lerr);
} else {
*macro_string = "<DW_FORM_str_sup-no-entry>";
}

View File

@ -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 */

View File

@ -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);

View File

@ -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;

View File

@ -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. */
@ -1107,6 +1119,8 @@ dwarf_debug_addr_index_to_addr(Dwarf_Die die,
/* 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 =
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;;
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;

View File

@ -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,
@ -376,11 +381,10 @@ _dwarf_determine_die_range_offset(Dwarf_Debug dw_dbg,
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_CU_Context cucon = 0;
res = dwarf_hasattr(dw_die,DW_AT_ranges, &hasatranges,dw_error);
if (res != DW_DLV_OK) {
@ -397,7 +401,7 @@ _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) {
@ -408,32 +412,16 @@ _dwarf_determine_die_range_offset(Dwarf_Debug dw_dbg,
return res;
}
}
/* rangeoffset_local was set . */
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;
}

View File

@ -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,7 +310,7 @@ _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)
@ -355,7 +324,7 @@ _dwarf_internal_read_rnglists_header(Dwarf_Debug dbg,
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;
}
@ -593,11 +580,11 @@ internal_load_rnglists_contexts(Dwarf_Debug dbg,
Dwarf_Small * end_data = data +section_size;
Dwarf_Chain curr_chain = 0;
Dwarf_Chain head_chain = 0;
Dwarf_Chain *plast = &head_chain;
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;
@ -696,6 +683,8 @@ int dwarf_load_rnglists(
if (rnglists_count) {
*rnglists_count = dbg->de_rnglists_context_count;
}
if (rnglists_count) {
}
return DW_DLV_OK;
}
if (!dbg->de_debug_rnglists.dss_size) {
@ -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,30 +1056,68 @@ 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_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){
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;
}
}
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 (rnglist_offset < rcxend ){
if (chosen_offset < rcxend ){
*index = i;
return DW_DLV_OK;
}
@ -1084,66 +1129,16 @@ _dwarf_which_rnglists_context(Dwarf_Debug dbg,
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);
" 0x%" DW_PR_XZEROS DW_PR_DUx ,chosen_offset);
dwarfstring_append(&m,
" Not found anywhere in .debug_rnglists "
" 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;
}
} 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;
}
}
/* ASSERT: This line cannot be reached. */
}
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,19 +1644,7 @@ 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;
@ -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;
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;
}
res = _dwarf_which_rnglists_context(dbg,ctx,
offset_in_rnglists,
&rnglists_contextnum,error);
if (res != DW_DLV_OK) {
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;
}
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;
/* 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 {
rle_global_offset = attr_val;
/* There is an error to be
generated later */
}
}
}
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);
res = _dwarf_load_section(dbg,
&dbg->de_debug_rnglists,
error);
if (res == DW_DLV_ERROR) {
return res;
}
if (global_offset_of_rle_set) {
*global_offset_of_rle_set = rle_global_offset;
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;
}
/* 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

View File

@ -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;

View File

@ -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

View File

@ -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;
}
@ -231,6 +223,9 @@ _dwarf_loop_reading_debug_info_for_cu(
}
/* 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,

View File

@ -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. */

View File

@ -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)
{

View File

@ -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,

View File

@ -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,