Bump to v0.9.2

This commit is contained in:
Jeremy 2024-04-27 14:10:16 -05:00
parent 5c0cb251f9
commit 02ecf2cbca
No known key found for this signature in database
GPG Key ID: 19AA8270105E8EB4
41 changed files with 831 additions and 385 deletions

6
CMakeLists.txt vendored
View File

@ -200,10 +200,10 @@ if (ENABLE_DECOMPRESSION)
TARGET ZSTD::ZSTD TARGET ZSTD::ZSTD
) )
) )
find_package(ZSTD) find_package(zstd)
else() else()
# Presumably in this case, the target has been found externally but set this flag just in case # Presumably in this case, the target has been found externally but set this flag just in case
set(ZSTD_FOUND TRUE) set(zstd_FOUND TRUE)
endif() endif()
# Unfortunately aliasing ZSTD::ZSTD to zstd::libzstd_shared/static can lead to problems for end-users, a variable # Unfortunately aliasing ZSTD::ZSTD to zstd::libzstd_shared/static can lead to problems for end-users, a variable
# is used # is used
@ -218,7 +218,7 @@ if (ENABLE_DECOMPRESSION)
else() else()
set(ZSTD_LIB ZSTD::ZSTD) set(ZSTD_LIB ZSTD::ZSTD)
endif() endif()
if (ZLIB_FOUND AND ZSTD_FOUND ) if (ZLIB_FOUND AND zstd_FOUND )
set(HAVE_ZLIB TRUE) set(HAVE_ZLIB TRUE)
set(HAVE_ZLIB_H TRUE) set(HAVE_ZLIB_H TRUE)
set(HAVE_ZSTD TRUE) set(HAVE_ZSTD TRUE)

View File

@ -28,13 +28,13 @@
# #
# :: # ::
# #
# ZSTD_FOUND - True if ZSTD is found. # zstd_FOUND - True if ZSTD is found.
# ZSTD_INCLUDE_DIRS - Where to find zstd.h # ZSTD_INCLUDE_DIRS - Where to find zstd.h
# #
# Finds the Zstandard library. This module defines: # Finds the Zstandard library. This module defines:
# - ZSTD_INCLUDE_DIR, directory containing headers # - ZSTD_INCLUDE_DIR, directory containing headers
# - ZSTD_LIBRARIES, the Zstandard library path # - ZSTD_LIBRARIES, the Zstandard library path
# - ZSTD_FOUND, whether Zstandard has been found # - zstd_FOUND, whether Zstandard has been found
# Find header files # Find header files
find_path(ZSTD_INCLUDE_DIR zstd.h) find_path(ZSTD_INCLUDE_DIR zstd.h)
@ -53,9 +53,9 @@ endif ()
find_library(ZSTD_LIBRARIES NAMES zstd) find_library(ZSTD_LIBRARIES NAMES zstd)
include(FindPackageHandleStandardArgs) include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(ZSTD REQUIRED_VARS ZSTD_LIBRARIES ZSTD_INCLUDE_DIR ZSTD_VERSION VERSION_VAR ZSTD_VERSION) find_package_handle_standard_args(zstd REQUIRED_VARS ZSTD_LIBRARIES ZSTD_INCLUDE_DIR ZSTD_VERSION VERSION_VAR ZSTD_VERSION)
if (ZSTD_FOUND) if (zstd_FOUND)
if (NOT TARGET ZSTD::ZSTD) if (NOT TARGET ZSTD::ZSTD)
add_library(ZSTD::ZSTD UNKNOWN IMPORTED) add_library(ZSTD::ZSTD UNKNOWN IMPORTED)
set_target_properties(ZSTD::ZSTD PROPERTIES IMPORTED_LOCATION "${ZSTD_LIBRARIES}" INTERFACE_INCLUDE_DIRECTORIES "${ZSTD_INCLUDE_DIR}") set_target_properties(ZSTD::ZSTD PROPERTIES IMPORTED_LOCATION "${ZSTD_LIBRARIES}" INTERFACE_INCLUDE_DIRECTORIES "${ZSTD_INCLUDE_DIR}")

View File

@ -7,7 +7,8 @@ git clone https://github.com/davea42/libdwarf-code.git
cd libdwarf-code cd libdwarf-code
#git checkout "6216e185863f41d6f19ab850caabfff7326020d7" # v0.8.0 #git checkout "6216e185863f41d6f19ab850caabfff7326020d7" # v0.8.0
#git checkout "8b0bd09d8c77d45a68cb1bb00a54186a92b683d9" # v0.9.0 #git checkout "8b0bd09d8c77d45a68cb1bb00a54186a92b683d9" # v0.9.0
git checkout "8cdcc531f310d1c5ae61da469d8056bdd36b77e7" # v0.9.1 + cmake fixes #git checkout "8cdcc531f310d1c5ae61da469d8056bdd36b77e7" # v0.9.1 + cmake fixes
git checkout "5e43a5ab73cb00c8a46660b361366a8c9c3c93c9" # v0.9.2
cd .. cd ..
echo "Copying files" echo "Copying files"
mkdir -p src/lib mkdir -p src/lib

View File

@ -105,7 +105,7 @@ target_include_directories(dwarf PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
) )
if(ZLIB_FOUND AND ZSTD_FOUND) if(ZLIB_FOUND AND zstd_FOUND)
target_link_libraries(dwarf PRIVATE ZLIB::ZLIB ${ZSTD_LIB} ) target_link_libraries(dwarf PRIVATE ZLIB::ZLIB ${ZSTD_LIB} )
endif() endif()
set_target_properties(dwarf PROPERTIES PUBLIC_HEADER "libdwarf.h;dwarf.h") set_target_properties(dwarf PROPERTIES PUBLIC_HEADER "libdwarf.h;dwarf.h")
@ -136,4 +136,4 @@ install(EXPORT libdwarfTargets
NAMESPACE libdwarf:: NAMESPACE libdwarf::
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/libdwarf") DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/libdwarf")
install(FILES "${PROJECT_BINARY_DIR}/src/lib/libdwarf/libdwarf.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") 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") install(FILES "${PROJECT_SOURCE_DIR}/cmake/Findzstd.cmake" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/libdwarf")

View File

@ -7,7 +7,7 @@ if(LIBDWARF_BUILT_WITH_ZLIB_AND_ZSTD)
find_dependency(ZLIB) find_dependency(ZLIB)
set(CMAKE_MODULE_PATH_OLD "${CMAKE_MODULE_PATH}") set(CMAKE_MODULE_PATH_OLD "${CMAKE_MODULE_PATH}")
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${CMAKE_CURRENT_LIST_DIR}") set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${CMAKE_CURRENT_LIST_DIR}")
find_dependency(ZSTD) find_dependency(zstd)
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH_OLD}") set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH_OLD}")
unset(CMAKE_MODULE_PATH_OLD) unset(CMAKE_MODULE_PATH_OLD)
endif() endif()

View File

@ -167,7 +167,6 @@ extern "C" {
#define DW_TAG_TI_restrict_type 0x4084 /* TI */ #define DW_TAG_TI_restrict_type 0x4084 /* TI */
#define DW_TAG_TI_onchip_type 0x4085 /* TI */ #define DW_TAG_TI_onchip_type 0x4085 /* TI */
/* HP extensions: ftp://ftp.hp.com/pub/lang/tools/\ /* HP extensions: ftp://ftp.hp.com/pub/lang/tools/\
WDB/wdb-4.0.tar.gz */ WDB/wdb-4.0.tar.gz */
#define DW_TAG_HP_array_descriptor 0x4090 /* HP */ #define DW_TAG_HP_array_descriptor 0x4090 /* HP */
@ -1426,7 +1425,8 @@ most-likely-useful name. */
See http://sourceforge.net/p/elftoolchain/tickets/397/ */ See http://sourceforge.net/p/elftoolchain/tickets/397/ */
#define DW_CFA_METAWARE_info 0x34 #define DW_CFA_METAWARE_info 0x34
#define DW_CFA_high_user 0x3f #define DW_CFA_hi_user 0x3f
#define DW_CFA_high_user 0x3f /* Misspelled. Do not use. */
/* GNU exception header encoding. See the Generic /* GNU exception header encoding. See the Generic
Elf Specification of the Linux Standard Base (LSB). Elf Specification of the Linux Standard Base (LSB).

View File

@ -143,6 +143,7 @@ _dwarf_error_destructor(void *m)
#if DEBUG_ALLOC #if DEBUG_ALLOC
printf("libdwarfdetector DEALLOC Now destruct error " printf("libdwarfdetector DEALLOC Now destruct error "
"string %s\n",dwarfstring_string(erm)); "string %s\n",dwarfstring_string(erm));
fflush(stdout);
#endif /* DEBUG_ALLOC */ #endif /* DEBUG_ALLOC */
dwarfstring_destructor(erm); dwarfstring_destructor(erm);
free(erm); free(erm);
@ -182,6 +183,8 @@ struct reserve_data_s {
#define STATIC_ALLOWED 10 /* arbitrary, must be > 2, see below*/ #define STATIC_ALLOWED 10 /* arbitrary, must be > 2, see below*/
static unsigned static_used = 0; static unsigned static_used = 0;
/* entries in this list point to allocations of
type DW_DLA_ERROR. */
static Dwarf_Error staticerrlist[STATIC_ALLOWED]; static Dwarf_Error staticerrlist[STATIC_ALLOWED];
/* Clean this out if found */ /* Clean this out if found */
@ -215,7 +218,7 @@ dw_empty_errlist_item(Dwarf_Error e_in)
} }
} }
/* If the userr calls dwarf_dealloc on an error /* If the user calls dwarf_dealloc on an error
out of a dwarf_init*() call, this will find out of a dwarf_init*() call, this will find
it in the static err list. Here dbg is NULL it in the static err list. Here dbg is NULL
so not mentioned. */ so not mentioned. */
@ -226,11 +229,21 @@ _dwarf_add_to_static_err_list(Dwarf_Error error)
if (!error) { if (!error) {
return; return;
} }
#ifdef DEBUG_ALLOC
printf("\nlibdwarfdetector add to static err list "
" 0x%lx\n",(unsigned long)(uintptr_t)error);
fflush(stdout);
#endif /* DEBUG_ALLOC */
for ( ; i <static_used; ++i) { for ( ; i <static_used; ++i) {
Dwarf_Error e = staticerrlist[i]; Dwarf_Error e = staticerrlist[i];
if (e) { if (e) {
continue; continue;
} }
#ifdef DEBUG_ALLOC
printf("libdwarfdetector add to static err list at %u\n",
i);
fflush(stdout);
#endif /* DEBUG_ALLOC */
staticerrlist[i] = error; staticerrlist[i] = error;
return; return;
} }
@ -239,6 +252,38 @@ _dwarf_add_to_static_err_list(Dwarf_Error error)
++static_used; ++static_used;
} }
} }
/* See libdwarf vulnerability DW202402-002
for the motivation.
*/
static void
_dwarf_remove_from_staticerrlist(Dwarf_Ptr *space)
{
unsigned i = 0;
if (!space) {
return;
}
#ifdef DEBUG_ALLOC
printf("\nlibdwarfdetector remove from static err list "
" 0x%lx\n",(unsigned long)(uintptr_t)space);
fflush(stdout);
#endif /* DEBUG_ALLOC */
for ( ; i <static_used; ++i) {
Dwarf_Error e = staticerrlist[i];
if (!e) {
continue;
}
if ((void *)e == space) {
#ifdef DEBUG_ALLOC
printf("libdwarfdetector rm from static err list at %u\n",
i);
fflush(stdout);
#endif /* DEBUG_ALLOC */
staticerrlist[i] = 0;
return;
}
}
}
/* This will free everything in the staticerrlist, /* This will free everything in the staticerrlist,
but that is ok */ but that is ok */
void void
@ -671,7 +716,7 @@ _dwarf_get_alloc(Dwarf_Debug dbg,
} }
} }
#if DEBUG_ALLOC #if DEBUG_ALLOC
printf("libdwarfdetector ALLOC ret 0x%lx type 0x%x " printf("\nlibdwarfdetector ALLOC ret 0x%lx type 0x%x "
"size %lu line %d %s\n", "size %lu line %d %s\n",
(unsigned long)ret_mem,(unsigned)alloc_type, (unsigned long)ret_mem,(unsigned)alloc_type,
(unsigned long)size,__LINE__,__FILE__); (unsigned long)size,__LINE__,__FILE__);
@ -804,6 +849,9 @@ dwarf_dealloc(Dwarf_Debug dbg,
unsigned int type = 0; unsigned int type = 0;
char * malloc_addr = 0; char * malloc_addr = 0;
struct reserve_data_s * r = 0; struct reserve_data_s * r = 0;
#if 0
Dwarf_Bool check_errmsg_list = FALSE;
#endif
if (!space) { if (!space) {
#ifdef DEBUG_ALLOC #ifdef DEBUG_ALLOC
@ -921,11 +969,15 @@ dwarf_dealloc(Dwarf_Debug dbg,
if (ep->er_static_alloc == DE_MALLOC) { if (ep->er_static_alloc == DE_MALLOC) {
/* This is special, we had no arena /* This is special, we had no arena
but have a full special area as normal. */ but have a full special area as normal. */
#if 0
check_errmsg_list = TRUE;
#endif
#ifdef DEBUG_ALLOC #ifdef DEBUG_ALLOC
printf("DEALLOC does free, DE_MALLOC line %d %s\n", printf("DEALLOC does free, DE_MALLOC line %d %s\n",
__LINE__,__FILE__); __LINE__,__FILE__);
fflush(stdout); fflush(stdout);
#endif /* DEBUG_ALLOC*/ #endif /* DEBUG_ALLOC*/
_dwarf_remove_from_staticerrlist(space);
} }
/* Was normal alloc, use normal dealloc. */ /* Was normal alloc, use normal dealloc. */
/* DW_DLA_ERROR has a specialdestructor */ /* DW_DLA_ERROR has a specialdestructor */

View File

@ -1155,15 +1155,13 @@ _dwarf_set_children_flag(Dwarf_CU_Context cucon,
} }
} }
static int static int
_dwarf_prod_contains(const char *ck, const char *prod) _dwarf_prod_contains(const char *ck, const char *prod)
{ {
const char *cp = prod; const char *cp = prod;
size_t len = strlen(ck); size_t len = strlen(ck);
for( ; *cp ; ++cp) { for (; *cp ; ++cp) {
if ( ck[0] != *cp) { if ( ck[0] != *cp) {
continue; continue;
} }

View File

@ -1993,7 +1993,8 @@ read_gs_section_group(
} }
grouparray[0] = 1; grouparray[0] = 1;
/* A .group section will have 0 to G sections /* A .group section will have 0 to G sections
listed */ listed. Ignore the initial 'version' value
of 1 in [0] */
dp = dp + DWARF_32BIT_SIZE; dp = dp + DWARF_32BIT_SIZE;
for ( i = 1; i < count; ++i,dp += DWARF_32BIT_SIZE) { for ( i = 1; i < count; ++i,dp += DWARF_32BIT_SIZE) {
Dwarf_Unsigned gseca = 0; Dwarf_Unsigned gseca = 0;
@ -2002,29 +2003,31 @@ read_gs_section_group(
memcpy(dblock,dp,DWARF_32BIT_SIZE); memcpy(dblock,dp,DWARF_32BIT_SIZE);
ASNAR(memcpy,gseca,dblock); ASNAR(memcpy,gseca,dblock);
/* Loading gseca and gsecb with different endianness.
Only one of them can be of any use. */
ASNAR(_dwarf_memcpy_swap_bytes,gsecb,dblock); ASNAR(_dwarf_memcpy_swap_bytes,gsecb,dblock);
if (!gseca) { if (!gseca) {
/* zero! Oops. No point in looking at gsecb */
free(data); free(data);
free(grouparray); free(grouparray);
*errcode = DW_DLE_ELF_SECTION_GROUP_ERROR; *errcode = DW_DLE_ELF_SECTION_GROUP_ERROR;
return DW_DLV_ERROR; return DW_DLV_ERROR;
} }
grouparray[i] = gseca;
if (gseca >= ep->f_loc_shdr.g_count) { if (gseca >= ep->f_loc_shdr.g_count) {
/* Might be confused endianness by /* Might be confused endianness by
the compiler generating the SHT_GROUP. the compiler generating the SHT_GROUP.
This is pretty horrible. */ This is pretty horrible. */
if (gsecb >= ep->f_loc_shdr.g_count) { if (gsecb >= ep->f_loc_shdr.g_count) {
*errcode = DW_DLE_ELF_SECTION_GROUP_ERROR; *errcode = DW_DLE_ELF_SECTION_GROUP_ERROR;
free(data); free(data);
free(grouparray); free(grouparray);
return DW_DLV_ERROR; return DW_DLV_ERROR;
} }
/* Ok. Yes, ugly. */ /* Looks as though gsecb is the correct
interpretation. Yes, ugly. */
gseca = gsecb; gseca = gsecb;
grouparray[i] = gseca;
} }
grouparray[i] = gseca;
targpsh = ep->f_shdr + gseca; targpsh = ep->f_shdr + gseca;
if (_dwarf_ignorethissection(targpsh->gh_namestring)){ if (_dwarf_ignorethissection(targpsh->gh_namestring)){
continue; continue;

View File

@ -140,7 +140,8 @@ _dwarf_error_string(Dwarf_Debug dbg, Dwarf_Error * error,
errptr = &_dwarf_failsafe_error; errptr = &_dwarf_failsafe_error;
errptr->er_static_alloc = DE_STATIC; errptr->er_static_alloc = DE_STATIC;
#ifdef DEBUG #ifdef DEBUG
printf("libdwarf no dbg, fullystatic, " printf("libdwarf no dbg to dwarf_error_string,"
" fullystatic, "
"using DE_STATIC alloc, addr" "using DE_STATIC alloc, addr"
" 0x%lx line %d %s\n", " 0x%lx line %d %s\n",
(unsigned long)errptr, (unsigned long)errptr,
@ -150,7 +151,7 @@ _dwarf_error_string(Dwarf_Debug dbg, Dwarf_Error * error,
errptr->er_static_alloc = DE_MALLOC; errptr->er_static_alloc = DE_MALLOC;
#ifdef DEBUG #ifdef DEBUG
printf("libdwarf no dbg,leaks, " printf("libdwarf no dbg, add to static_err_list "
"static DE_MALLOC alloc, addr" "static DE_MALLOC alloc, addr"
" 0x%lx line %d %s\n", " 0x%lx line %d %s\n",
(unsigned long)errptr, (unsigned long)errptr,

View File

@ -48,6 +48,27 @@ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "dwarf_util.h" #include "dwarf_util.h"
#include "dwarf_string.h" #include "dwarf_string.h"
static void
build_alloc_ab_error(Dwarf_Debug dbg,
Dwarf_Unsigned count,
const char *fieldname,
Dwarf_Error *error)
{
dwarfstring m;
dwarfstring_constructor(&m);
dwarfstring_append_printf_s(&m,
"DW_DLE_ALLOC_FAIL :"
" Attempt to malloc space for %s ",
(char *)fieldname);
dwarfstring_append_printf_u(&m,
" with %u entries failed.",
count);
_dwarf_error_string(dbg,error,DW_DLE_ALLOC_FAIL,
dwarfstring_string(&m));
dwarfstring_destructor(&m);
}
/* /*
This is a pre-scan of the abbrev/form list. This is a pre-scan of the abbrev/form list.
We will not handle DW_FORM_indirect here as that We will not handle DW_FORM_indirect here as that
@ -67,44 +88,29 @@ _dwarf_fill_in_attr_form_abtable(Dwarf_CU_Context context,
abbrev_list->abl_attr = (Dwarf_Half*) abbrev_list->abl_attr = (Dwarf_Half*)
calloc(abbrev_list->abl_abbrev_count, calloc(abbrev_list->abl_abbrev_count,
SIZEOFT16); SIZEOFT16);
if (!abbrev_list->abl_attr) {
build_alloc_ab_error(dbg,abbrev_list->abl_abbrev_count,
"abbrev_list->abl_attr",error);
return DW_DLV_ERROR;
}
abbrev_list->abl_form = (Dwarf_Half *) abbrev_list->abl_form = (Dwarf_Half *)
calloc(abbrev_list->abl_abbrev_count, calloc(abbrev_list->abl_abbrev_count,
SIZEOFT16); SIZEOFT16);
if (!abbrev_list->abl_form) {
build_alloc_ab_error(dbg,abbrev_list->abl_abbrev_count,
"abbrev_list->abl_form",error);
return DW_DLV_ERROR;
}
if (abbrev_list->abl_implicit_const_count > 0) { if (abbrev_list->abl_implicit_const_count > 0) {
abbrev_list->abl_implicit_const = (Dwarf_Signed *) abbrev_list->abl_implicit_const = (Dwarf_Signed *)
calloc(abbrev_list->abl_abbrev_count, calloc(abbrev_list->abl_abbrev_count,
sizeof(Dwarf_Signed)); sizeof(Dwarf_Signed));
if (!abbrev_list->abl_implicit_const) { if (!abbrev_list->abl_implicit_const) {
dwarfstring m; build_alloc_ab_error(dbg,abbrev_list->abl_abbrev_count,
"abbrev_list->abl_implicit_const",error);
dwarfstring_constructor(&m);
dwarfstring_append_printf_u(&m,
"DW_DLE_ALLOC_FAIL :"
" Attempt to malloc space for "
"abbrev_list->abl_implicit_const "
"with %u entries failed.",
abbrev_list->abl_abbrev_count);
_dwarf_error_string(dbg,error,DW_DLE_ALLOC_FAIL,
dwarfstring_string(&m));
dwarfstring_destructor(&m);
return DW_DLV_ERROR; return DW_DLV_ERROR;
} }
} }
if (!abbrev_list->abl_attr || !abbrev_list->abl_form ) {
dwarfstring m;
dwarfstring_constructor(&m);
dwarfstring_append_printf_u(&m,
"DW_DLE_ALLOC_FAIL :"
" Attempt to malloc space for "
"abbrev_list->abl_attr or abl_form "
"with %u entries failed.",
abbrev_list->abl_abbrev_count);
_dwarf_error_string(dbg,error,DW_DLE_ALLOC_FAIL,
dwarfstring_string(&m));
dwarfstring_destructor(&m);
return DW_DLV_ERROR;
}
for (i = 0; i < abbrev_list->abl_abbrev_count; ++i) { for (i = 0; i < abbrev_list->abl_abbrev_count; ++i) {
Dwarf_Unsigned attr = 0; Dwarf_Unsigned attr = 0;
@ -141,18 +147,13 @@ _dwarf_fill_in_attr_form_abtable(Dwarf_CU_Context context,
return res; return res;
} }
if (attr_form > 0xffff) { if (attr_form > 0xffff) {
dwarfstring m; _dwarf_error_string(dbg, error,
DW_DLE_ATTR_FORM_SIZE_BAD,
dwarfstring_constructor(&m);
dwarfstring_append(&m,
"DW_DLE_ATTR_FORM_SIZE_BAD :" "DW_DLE_ATTR_FORM_SIZE_BAD :"
" reading attr_form"); " reading attr_form of"
dwarfstring_append(&m,"an abbrev list entry " " an abbrev list entry: "
"the ULEB form number is too large. " "the ULEB form number is too large "
"to be valid. Corrupt Dwarf."); "to be valid. Corrupt Dwarf.");
_dwarf_error_string(dbg,error,DW_DLE_ATTR_FORM_SIZE_BAD,
dwarfstring_string(&m));
dwarfstring_destructor(&m);
return DW_DLV_ERROR; return DW_DLV_ERROR;
} }
if (!_dwarf_valid_form_we_know(attr_form,attr)) { if (!_dwarf_valid_form_we_know(attr_form,attr)) {

View File

@ -783,6 +783,13 @@ _dwarf_internal_global_formref_b(Dwarf_Attribute attr,
switch (attr->ar_attribute_form) { switch (attr->ar_attribute_form) {
case DW_FORM_ref1: case DW_FORM_ref1:
if (attr->ar_debug_ptr >= section_end) {
_dwarf_error_string(dbg, error,
DW_DLE_ATTR_FORM_OFFSET_BAD,
"DW_DLE_ATTR_FORM_OFFSET_BAD: "
"DW_FORM_ref1 outside of the section.");
return DW_DLV_ERROR;
}
offset = *(Dwarf_Small *) attr->ar_debug_ptr; offset = *(Dwarf_Small *) attr->ar_debug_ptr;
goto fixoffset; goto fixoffset;
@ -1643,14 +1650,23 @@ _dwarf_formblock_internal(Dwarf_Debug dbg,
section_start = section_start =
_dwarf_calculate_info_section_start_ptr(cu_context, _dwarf_calculate_info_section_start_ptr(cu_context,
&section_length); &section_length);
switch (attr->ar_attribute_form) { switch (attr->ar_attribute_form) {
case DW_FORM_block1: {
case DW_FORM_block1: Dwarf_Small *start = attr->ar_debug_ptr;
length = *(Dwarf_Small *) attr->ar_debug_ptr; Dwarf_Small *incremented = start + 1;
data = attr->ar_debug_ptr + sizeof(Dwarf_Small); if ( incremented < start ||
incremented >= section_end) {
/* Error if +1 overflows or if points out of section. */
generate_form_error(dbg,error,attr->ar_attribute_form,
DW_DLE_ATTR_FORM_BAD,
"DW_DLE_ATTR_FORM_BAD",
" DW_FORM_block1 offset invalid");
return DW_DLV_ERROR;
}
length = *start;
data = incremented;
break; break;
}
case DW_FORM_block2: case DW_FORM_block2:
READ_UNALIGNED_CK(dbg, length, Dwarf_Unsigned, READ_UNALIGNED_CK(dbg, length, Dwarf_Unsigned,
attr->ar_debug_ptr, DWARF_HALF_SIZE, attr->ar_debug_ptr, DWARF_HALF_SIZE,
@ -1679,7 +1695,7 @@ _dwarf_formblock_internal(Dwarf_Debug dbg,
generate_form_error(dbg,error,attr->ar_attribute_form, generate_form_error(dbg,error,attr->ar_attribute_form,
DW_DLE_ATTR_FORM_BAD, DW_DLE_ATTR_FORM_BAD,
"DW_DLE_ATTR_FORM_BAD", "DW_DLE_ATTR_FORM_BAD",
"dwarf_formblock"); "dwarf_formblock() finds unknown form");
return DW_DLV_ERROR; return DW_DLV_ERROR;
} }
/* We have the data. Check for errors. */ /* We have the data. Check for errors. */

View File

@ -1812,7 +1812,8 @@ _dwarf_exec_frame_instr(Dwarf_Bool make_instr,
struct Dwarf_Reg_Rule_s *t2reg = table->fr_reg; struct Dwarf_Reg_Rule_s *t2reg = table->fr_reg;
struct Dwarf_Reg_Rule_s *t3reg = localregtab; struct Dwarf_Reg_Rule_s *t3reg = localregtab;
unsigned minregcount = (unsigned)MIN(table->fr_reg_count,reg_count); unsigned minregcount = (unsigned)MIN(table->fr_reg_count,
reg_count);
unsigned curreg = 0; unsigned curreg = 0;
table->fr_loc = current_loc; table->fr_loc = current_loc;
@ -3276,7 +3277,8 @@ dump_frame_rule(char *msg, struct Dwarf_Reg_Rule_s *reg_rule)
Returns the value that was present before we changed it here. */ Returns the value that was present before we changed it here. */
Dwarf_Half Dwarf_Half
dwarf_set_frame_rule_initial_value(Dwarf_Debug dbg, Dwarf_Half value) dwarf_set_frame_rule_initial_value(Dwarf_Debug dbg,
Dwarf_Half value)
{ {
Dwarf_Half orig = Dwarf_Half orig =
(Dwarf_Half)dbg->de_frame_rule_initial_value; (Dwarf_Half)dbg->de_frame_rule_initial_value;

View File

@ -198,7 +198,8 @@ dwarf_gdbindex_header(Dwarf_Debug dbg,
/* Should be impossible, dwarf_load_section() would /* Should be impossible, dwarf_load_section() would
return DW_DLV_ERROR if dss_data could not be return DW_DLV_ERROR if dss_data could not be
set non-null */ set non-null */
_dwarf_error_string(dbg, error, DW_DLE_ERRONEOUS_GDB_INDEX_SECTION, _dwarf_error_string(dbg, error,
DW_DLE_ERRONEOUS_GDB_INDEX_SECTION,
"DW_DLE_ERRONEOUS_GDB_INDEX_SECTION: " "DW_DLE_ERRONEOUS_GDB_INDEX_SECTION: "
"We have non-zero (section) dss_size but " "We have non-zero (section) dss_size but "
"null dss_data pointer"); "null dss_data pointer");

View File

@ -70,8 +70,13 @@
generate an leb with correct but useless trailing generate an leb with correct but useless trailing
zero bytes (note the interaction with sign in the signed case). zero bytes (note the interaction with sign in the signed case).
The value of BYTESLEBMAX is arbitrary but allows catching The value of BYTESLEBMAX is arbitrary but allows catching
corrupt data before dark. corrupt data in a short time.
Before April 2021 BYTESLEBMAX was 10. Before April 2021 BYTESLEBMAX was 10 as it was assumed
there were no 'useless' 0x80 high-order bytes in an LEB.
(0x80 meaning the 7 bits 'value' is zero)
However in DWARF6 (and at least one compiler before
DWARF6) a few high order bytes are allowed as padding.
*/ */
#define BYTESLEBMAX 24 #define BYTESLEBMAX 24
#define BITSPERBYTE 8 #define BITSPERBYTE 8
@ -91,7 +96,7 @@ _dwarf_skip_leb128(char * leb128,
return DW_DLV_ERROR; return DW_DLV_ERROR;
} }
byte = *leb128; byte = *(unsigned char *)leb128;
if ((byte & 0x80) == 0) { if ((byte & 0x80) == 0) {
*leb128_length = 1; *leb128_length = 1;
return DW_DLV_OK; return DW_DLV_OK;
@ -100,7 +105,7 @@ _dwarf_skip_leb128(char * leb128,
if ((leb128+1) >=endptr) { if ((leb128+1) >=endptr) {
return DW_DLV_ERROR; return DW_DLV_ERROR;
} }
byte2 = *(leb128 + 1); byte2 = *(unsigned char *)(leb128 + 1);
if ((byte2 & 0x80) == 0) { if ((byte2 & 0x80) == 0) {
*leb128_length = 2; *leb128_length = 2;
return DW_DLV_OK; return DW_DLV_OK;
@ -117,7 +122,7 @@ _dwarf_skip_leb128(char * leb128,
/* Off end of available space. */ /* Off end of available space. */
return DW_DLV_ERROR; return DW_DLV_ERROR;
} }
byte = *leb128; byte = *(unsigned char *)leb128;
if (byte & 0x80) { if (byte & 0x80) {
if (byte_length >= BYTESLEBMAX) { if (byte_length >= BYTESLEBMAX) {
/* Too long. Not sane length. */ /* Too long. Not sane length. */
@ -129,21 +134,22 @@ _dwarf_skip_leb128(char * leb128,
} }
*leb128_length = byte_length; *leb128_length = byte_length;
return DW_DLV_OK; return DW_DLV_OK;
} }
/* Decode ULEB with checking. */ /* Decode ULEB with checking.
Casting leb128 to (unsigned char *) as
the signedness of char * is unpredictable in C */
int int
dwarf_decode_leb128(char * leb128, dwarf_decode_leb128(char * leb128,
Dwarf_Unsigned * leb128_length, Dwarf_Unsigned * leb128_length,
Dwarf_Unsigned *outval, Dwarf_Unsigned *outval,
char * endptr) char * endptr)
{ {
unsigned byte = 0; unsigned long byte = 0;
Dwarf_Unsigned word_number = 0; Dwarf_Unsigned word_number = 0;
Dwarf_Unsigned number = 0; Dwarf_Unsigned number = 0;
size_t shift = 0; unsigned long shift = 0; /* at least 32 bits, even Win32 */
/* The byte_length value will be a small non-negative integer. */ /* The byte_length value will be a small non-negative integer. */
unsigned byte_length = 0; unsigned int byte_length = 0;
if (leb128 >=endptr) { if (leb128 >=endptr) {
return DW_DLV_ERROR; return DW_DLV_ERROR;
@ -152,7 +158,7 @@ dwarf_decode_leb128(char * leb128,
unpacks into 32 bits to make this as fast as possible. unpacks into 32 bits to make this as fast as possible.
word_number is assumed big enough that the shift has a defined word_number is assumed big enough that the shift has a defined
result. */ result. */
byte = *leb128; byte = *(unsigned char *)leb128;
if ((byte & 0x80) == 0) { if ((byte & 0x80) == 0) {
if (leb128_length) { if (leb128_length) {
*leb128_length = 1; *leb128_length = 1;
@ -162,11 +168,11 @@ dwarf_decode_leb128(char * leb128,
} }
return DW_DLV_OK; return DW_DLV_OK;
} else { } else {
unsigned byte2 = 0; unsigned long byte2 = 0;
if ((leb128+1) >=endptr) { if ((leb128+1) >=endptr) {
return DW_DLV_ERROR; return DW_DLV_ERROR;
} }
byte2 = *(leb128 + 1); byte2 = *(unsigned char *)(leb128 + 1);
if ((byte2 & 0x80) == 0) { if ((byte2 & 0x80) == 0) {
if (leb128_length) { if (leb128_length) {
*leb128_length = 2; *leb128_length = 2;
@ -189,7 +195,7 @@ dwarf_decode_leb128(char * leb128,
shift = 0; shift = 0;
byte_length = 1; byte_length = 1;
for (;;) { for (;;) {
unsigned b = byte & 0x7f; unsigned int b = byte & 0x7f;
if (shift >= (sizeof(number)*BITSPERBYTE)) { if (shift >= (sizeof(number)*BITSPERBYTE)) {
/* Shift is large. Maybe corrupt value, /* Shift is large. Maybe corrupt value,
maybe some padding high-end byte zeroes maybe some padding high-end byte zeroes
@ -220,7 +226,7 @@ dwarf_decode_leb128(char * leb128,
return DW_DLV_ERROR; return DW_DLV_ERROR;
} }
++byte_length; ++byte_length;
byte = *leb128; byte = *(unsigned char *)leb128;
continue; continue;
} }
/* Too big, corrupt data given the non-zero /* Too big, corrupt data given the non-zero
@ -250,12 +256,15 @@ dwarf_decode_leb128(char * leb128,
if (leb128 >= endptr) { if (leb128 >= endptr) {
return DW_DLV_ERROR; return DW_DLV_ERROR;
} }
byte = *leb128; byte = *(unsigned char *)leb128;
} }
return DW_DLV_ERROR; return DW_DLV_ERROR;
} }
/* Decode SLEB with checking */ /* Decode SLEB with checking
Casting leb128 to (unsigned char *) as
the signedness of char * is unpredictable
in C */
int int
dwarf_decode_signed_leb128(char * leb128, dwarf_decode_signed_leb128(char * leb128,
Dwarf_Unsigned * leb128_length, Dwarf_Unsigned * leb128_length,
@ -264,10 +273,10 @@ dwarf_decode_signed_leb128(char * leb128,
Dwarf_Unsigned byte = 0; Dwarf_Unsigned byte = 0;
unsigned int b = 0; unsigned int b = 0;
Dwarf_Signed number = 0; Dwarf_Signed number = 0;
size_t shift = 0; unsigned long shift = 0;
int sign = FALSE; int sign = FALSE;
/* The byte_length value will be a small non-negative integer. */ /* The byte_length value will be a small non-negative integer. */
unsigned byte_length = 1; unsigned int byte_length = 1;
/* byte_length being the number of bytes /* byte_length being the number of bytes
of data absorbed so far in of data absorbed so far in
@ -278,7 +287,7 @@ dwarf_decode_signed_leb128(char * leb128,
if (leb128 >= endptr) { if (leb128 >= endptr) {
return DW_DLV_ERROR; return DW_DLV_ERROR;
} }
byte = *leb128; byte = *(unsigned char *)leb128;
for (;;) { for (;;) {
b = byte & 0x7f; b = byte & 0x7f;
if (shift >= (sizeof(number)*BITSPERBYTE)) { if (shift >= (sizeof(number)*BITSPERBYTE)) {
@ -307,7 +316,7 @@ dwarf_decode_signed_leb128(char * leb128,
if (leb128 >= endptr) { if (leb128 >= endptr) {
return DW_DLV_ERROR; return DW_DLV_ERROR;
} }
byte = *leb128; byte = *(unsigned char *)leb128;
continue; continue;
} }
/* Too big, corrupt data given the non-zero /* Too big, corrupt data given the non-zero
@ -325,7 +334,7 @@ dwarf_decode_signed_leb128(char * leb128,
if (leb128 >= endptr) { if (leb128 >= endptr) {
return DW_DLV_ERROR; return DW_DLV_ERROR;
} }
byte = *leb128; byte = *(unsigned char *)leb128;
byte_length++; byte_length++;
if (byte_length > BYTESLEBMAX) { if (byte_length > BYTESLEBMAX) {
/* Erroneous input. */ /* Erroneous input. */
@ -337,7 +346,7 @@ dwarf_decode_signed_leb128(char * leb128,
} }
if (sign) { if (sign) {
/* The following avoids undefined behavior. */ /* The following avoids undefined behavior. */
unsigned shiftlim = sizeof(Dwarf_Signed) * BITSPERBYTE -1; unsigned int shiftlim = sizeof(Dwarf_Signed) * BITSPERBYTE -1;
if (shift < shiftlim) { if (shift < shiftlim) {
Dwarf_Signed y = (Dwarf_Signed) Dwarf_Signed y = (Dwarf_Signed)
(((Dwarf_Unsigned)1) << shift); (((Dwarf_Unsigned)1) << shift);

View File

@ -782,6 +782,15 @@ _dwarf_read_line_table_header(Dwarf_Debug dbg,
format_values[j].up_first; format_values[j].up_first;
Dwarf_Unsigned lnform = Dwarf_Unsigned lnform =
format_values[j].up_second; format_values[j].up_second;
if (line_ptr >= line_ptr_end) {
free(format_values);
format_values = 0;
_dwarf_error_string(dbg, err,
DW_DLE_LINE_NUMBER_HEADER_ERROR,
" Running off end of line table"
" reading directory path");
return DW_DLV_ERROR;
}
switch (lntype) { switch (lntype) {
case DW_LNCT_path: { case DW_LNCT_path: {
char *inc_dir_ptr = 0; char *inc_dir_ptr = 0;
@ -851,6 +860,14 @@ _dwarf_read_line_table_header(Dwarf_Debug dbg,
_dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
return DW_DLV_ERROR; return DW_DLV_ERROR;
} }
if (line_ptr >= line_ptr_end) {
free(filename_entry_pairs);
_dwarf_error_string(dbg, err,
DW_DLE_LINE_NUMBER_HEADER_ERROR,
"DW_DLE_LINE_NUMBER_HEADER_ERROR: "
"reading filename format entries");
return DW_DLV_ERROR;
}
for (i = 0; i < filename_format_count; i++) { for (i = 0; i < filename_format_count; i++) {
dres=read_uword_de(&line_ptr, dres=read_uword_de(&line_ptr,
&filename_entry_pairs[i].up_first, &filename_entry_pairs[i].up_first,
@ -900,7 +917,9 @@ _dwarf_read_line_table_header(Dwarf_Debug dbg,
malloc(sizeof(struct Dwarf_File_Entry_s)); malloc(sizeof(struct Dwarf_File_Entry_s));
if (curline == NULL) { if (curline == NULL) {
free(filename_entry_pairs); free(filename_entry_pairs);
_dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL); _dwarf_error_string(dbg, err, DW_DLE_ALLOC_FAIL,
"DW_DLE_ALLOC_FAIL: "
"Unable to malloc Dwarf_File_Entry_s");
return DW_DLV_ERROR; return DW_DLV_ERROR;
} }
memset(curline,0,sizeof(*curline)); memset(curline,0,sizeof(*curline));
@ -911,6 +930,16 @@ _dwarf_read_line_table_header(Dwarf_Debug dbg,
filename_entry_pairs[j].up_first; filename_entry_pairs[j].up_first;
Dwarf_Unsigned lnform = Dwarf_Unsigned lnform =
filename_entry_pairs[j].up_second; filename_entry_pairs[j].up_second;
if (line_ptr >= line_ptr_end) {
free(filename_entry_pairs);
_dwarf_error_string(dbg, err,
DW_DLE_LINE_NUMBER_HEADER_ERROR,
"DW_DLE_LINE_NUMBER_HEADER_ERROR: "
"file name format count too large "
"to be correct. Corrupt DWARF/");
return DW_DLV_ERROR;
}
switch (lntype) { switch (lntype) {
/* The LLVM LNCT is documented in /* The LLVM LNCT is documented in
https://releases.llvm.org/9.0.0/docs https://releases.llvm.org/9.0.0/docs
@ -1064,8 +1093,11 @@ _dwarf_read_line_table_header(Dwarf_Debug dbg,
} }
if (line_ptr > line_ptr_end) { if (line_ptr > line_ptr_end) {
free(filename_entry_pairs); free(filename_entry_pairs);
_dwarf_error(dbg, err, _dwarf_error_string(dbg, err,
DW_DLE_LINE_NUMBER_HEADER_ERROR); DW_DLE_LINE_NUMBER_HEADER_ERROR,
"DW_DLE_LINE_NUMBER_HEADER_ERROR: "
"Reading line table header filenames "
"runs off end of section. Corrupt Dwarf");
return DW_DLV_ERROR; return DW_DLV_ERROR;
} }
} }
@ -1106,6 +1138,15 @@ _dwarf_read_line_table_header(Dwarf_Debug dbg,
free(subprog_entry_types); free(subprog_entry_types);
return DW_DLV_ERROR; return DW_DLV_ERROR;
} }
if (line_ptr >= line_ptr_end) {
free(subprog_entry_types);
_dwarf_error_string(dbg, err,
DW_DLE_LINE_NUMBER_HEADER_ERROR,
"DW_DLE_LINE_NUMBER_HEADER_ERROR: "
"Line table forms odd, experimental libdwarf");
return DW_DLV_ERROR;
}
subprog_entry_forms = malloc(sizeof(Dwarf_Unsigned) * subprog_entry_forms = malloc(sizeof(Dwarf_Unsigned) *
subprog_format_count); subprog_format_count);
if (subprog_entry_forms == NULL) { if (subprog_entry_forms == NULL) {
@ -1180,6 +1221,17 @@ _dwarf_read_line_table_header(Dwarf_Debug dbg,
for (i = 0; i < subprogs_count; i++) { for (i = 0; i < subprogs_count; i++) {
struct Dwarf_Subprog_Entry_s *curline = struct Dwarf_Subprog_Entry_s *curline =
line_context->lc_subprogs + i; line_context->lc_subprogs + i;
if (line_ptr >= line_ptr_end) {
free(subprog_entry_types);
free(subprog_entry_forms);
_dwarf_error_string(dbg, err,
DW_DLE_LINE_NUMBER_HEADER_ERROR,
"DW_DLE_LINE_NUMBER_HEADER_ERROR:"
" Reading suprogram entry subprogs"
" in experimental line table"
" we run off the end of the table");
return DW_DLV_ERROR;
}
for (j = 0; j < subprog_format_count; j++) { for (j = 0; j < subprog_format_count; j++) {
Dwarf_Unsigned lntype = Dwarf_Unsigned lntype =
subprog_entry_types[j]; subprog_entry_types[j];

View File

@ -116,6 +116,7 @@ counted_loc_descr(Dwarf_Debug dbg,
return DW_DLV_OK; return DW_DLV_OK;
} }
/* See also read_single_rle_entry() for similar code */
static int static int
read_single_lle_entry(Dwarf_Debug dbg, read_single_lle_entry(Dwarf_Debug dbg,
Dwarf_Small *data, Dwarf_Small *data,
@ -141,9 +142,18 @@ read_single_lle_entry(Dwarf_Debug dbg,
Dwarf_Unsigned loc_ops_len = 0; Dwarf_Unsigned loc_ops_len = 0;
Dwarf_Small *lopsdata = 0; Dwarf_Small *lopsdata = 0;
Dwarf_Unsigned lopsoffset = 0; Dwarf_Unsigned lopsoffset = 0;
Dwarf_Small *startdata = 0;
/* Some of these have a Counted Location Description /* Some of these have a Counted Location Description
in them. */ in them. */
if (data >= enddata) {
_dwarf_error_string(dbg,error,DW_DLE_LOCLISTS_ERROR,
"DW_DLE_LOCLISTS_ERROR: "
"An lle entry begins past the end of "
"its allowed space. Corrupt DWARF.");
return DW_DLV_ERROR;
}
startdata = data;
code = *data; code = *data;
++data; ++data;
++count; ++count;
@ -278,8 +288,24 @@ read_single_lle_entry(Dwarf_Debug dbg,
break; break;
} }
{ {
unsigned int v = (unsigned int)count; /* We want to avoid overflow in additions, and
if ((Dwarf_Unsigned)v != count) { the overall section size is a reasonable check
on count. The sequence of tests is to
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;
if (data > enddata || data < startdata ) {
/* Corrupt data being read. */
_dwarf_error_string(dbg,error,DW_DLE_LOCLISTS_ERROR,
"DW_DLE_LOCLISTS_ERROR: "
"The end of an lle entry is past the end "
"of its allowed space");
return DW_DLV_ERROR;
}
if (count > sectionsize) {
/* Corrupt data being read. */
_dwarf_error_string(dbg,error,DW_DLE_LOCLISTS_ERROR, _dwarf_error_string(dbg,error,DW_DLE_LOCLISTS_ERROR,
"DW_DLE_LOCLISTS_ERROR: " "DW_DLE_LOCLISTS_ERROR: "
"The number of bytes in a single " "The number of bytes in a single "
@ -1000,8 +1026,8 @@ build_array_of_lle(Dwarf_Debug dbg,
Dwarf_Unsigned i = 0; Dwarf_Unsigned i = 0;
for ( ; !done ; ) { for ( ; !done ; ) {
unsigned entrylen = 0; unsigned int entrylen = 0;
unsigned code = 0; unsigned int code = 0;
Dwarf_Unsigned val1 = 0; Dwarf_Unsigned val1 = 0;
Dwarf_Unsigned val2 = 0; Dwarf_Unsigned val2 = 0;
Dwarf_Locdesc_c e = 0; Dwarf_Locdesc_c e = 0;

View File

@ -490,7 +490,6 @@ like environment variable */
#define LC_ATOM_INFO 0x36 #define LC_ATOM_INFO 0x36
/* used with linkedit_data_command */ /* used with linkedit_data_command */
/* /*
* A variable length string in a load command * A variable length string in a load command
* is represented by an lc_str * is represented by an lc_str

View File

@ -57,7 +57,6 @@ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <config.h> #include <config.h>
#include <stdlib.h> /* calloc() free() malloc() */ #include <stdlib.h> /* calloc() free() malloc() */
#include <string.h> /* memcpy() memset() strcmp() strdup() */ #include <string.h> /* memcpy() memset() strcmp() strdup() */

View File

@ -1,5 +1,5 @@
/* Generated routines, do not edit. */ /* Generated routines, do not edit. */
/* Generated for source version 0.9.1 */ /* Generated for source version 0.9.2 */
/* BEGIN FILE */ /* BEGIN FILE */
@ -3452,9 +3452,11 @@ dwarf_get_CFA_name (unsigned int val,
case DW_CFA_METAWARE_info: case DW_CFA_METAWARE_info:
*s_out = "DW_CFA_METAWARE_info"; *s_out = "DW_CFA_METAWARE_info";
return DW_DLV_OK; return DW_DLV_OK;
case DW_CFA_high_user: case DW_CFA_hi_user:
*s_out = "DW_CFA_high_user"; *s_out = "DW_CFA_hi_user";
return DW_DLV_OK; return DW_DLV_OK;
/* Skipping alternate spelling of value
0x3f. DW_CFA_high_user */
case DW_CFA_advance_loc: case DW_CFA_advance_loc:
*s_out = "DW_CFA_advance_loc"; *s_out = "DW_CFA_advance_loc";
return DW_DLV_OK; return DW_DLV_OK;

View File

@ -188,7 +188,6 @@ struct Dwarf_CU_Context_s {
See cc_is_info flag. */ See cc_is_info flag. */
Dwarf_Unsigned cc_debug_offset; Dwarf_Unsigned cc_debug_offset;
/* === START DEBUG FISSION (Split Dwarf) data /* === START DEBUG FISSION (Split Dwarf) data
cc_signature is in the TU header cc_signature is in the TU header
of a type unit of a TU DIE (or for DW5 in the of a type unit of a TU DIE (or for DW5 in the

View File

@ -436,6 +436,8 @@ dwarf_attrlist(Dwarf_Die die,
if (bres != DW_DLV_OK) { if (bres != DW_DLV_OK) {
return bres; return bres;
} }
/* Here we are guaranteed abbrev_list->abl_attr
is non-null */
} }
/* ASSERT list->abl_addr and list->abl_form /* ASSERT list->abl_addr and list->abl_form
are non-null and if list->abl_implicit_const_count > 0 are non-null and if list->abl_implicit_const_count > 0
@ -614,6 +616,23 @@ dwarf_attrlist(Dwarf_Die die,
return DW_DLV_OK; return DW_DLV_OK;
} }
static void
build_alloc_qu_error(Dwarf_Debug dbg,
const char *fieldname,
Dwarf_Error *error)
{
dwarfstring m;
dwarfstring_constructor(&m);
dwarfstring_append_printf_s(&m,
"DW_DLE_ALLOC_FAIL :"
" Attempt to malloc space for %s failed",
(char *)fieldname);
_dwarf_error_string(dbg,error,DW_DLE_ALLOC_FAIL,
dwarfstring_string(&m));
dwarfstring_destructor(&m);
}
/* /*
This function takes a die, and an attr, and returns This function takes a die, and an attr, and returns
a pointer to the start of the value of that attr in a pointer to the start of the value of that attr in
@ -719,7 +738,16 @@ _dwarf_get_value_ptr(Dwarf_Die die,
return bres; return bres;
} }
} }
if (!abbrev_list->abl_form) {
build_alloc_qu_error(dbg,"abbrev_list->abl_form"
" in _dwarf_get_value_ptr()", error);
return DW_DLV_ERROR;
}
if (!abbrev_list->abl_attr) {
build_alloc_qu_error(dbg,"abbrev_list->abl_attr"
" in _dwarf_get_value_ptr()", error);
return DW_DLV_ERROR;
}
for (i = 0; i < abbrev_list->abl_abbrev_count; ++i) { for (i = 0; i < abbrev_list->abl_abbrev_count; ++i) {
Dwarf_Unsigned curr_attr_form = 0; Dwarf_Unsigned curr_attr_form = 0;
Dwarf_Unsigned curr_attr = 0; Dwarf_Unsigned curr_attr = 0;
@ -896,6 +924,11 @@ dwarf_attr(Dwarf_Die die,
return bres; return bres;
} }
} }
if (!abbrev_list->abl_form) {
build_alloc_qu_error(dbg,"abbrev_list->abl_form"
" in dwarf_attr()", error);
return DW_DLV_ERROR;
}
res = _dwarf_get_value_ptr(die, attr, &attr_form,&info_ptr, res = _dwarf_get_value_ptr(die, attr, &attr_form,&info_ptr,
&implicit_const,error); &implicit_const,error);
if (res == DW_DLV_ERROR) { if (res == DW_DLV_ERROR) {
@ -1696,6 +1729,8 @@ dwarf_arrayorder(Dwarf_Die die,
/* Return DW_DLV_OK if ok /* Return DW_DLV_OK if ok
DW_DLV_ERROR if failure. DW_DLV_ERROR if failure.
attr must be a valid attribute pointer.
If the die and the attr are not related the result is If the die and the attr are not related the result is
meaningless. */ meaningless. */
int int
@ -1720,6 +1755,9 @@ dwarf_attr_offset(Dwarf_Die die, Dwarf_Attribute attr,
Dwarf_Unsigned Dwarf_Unsigned
dwarf_die_abbrev_code(Dwarf_Die die) dwarf_die_abbrev_code(Dwarf_Die die)
{ {
if (!die) {
return 0;
}
return die->di_abbrev_code; return die->di_abbrev_code;
} }
@ -1730,6 +1768,9 @@ dwarf_die_abbrev_code(Dwarf_Die die)
int int
dwarf_die_abbrev_children_flag(Dwarf_Die die,Dwarf_Half *ab_has_child) dwarf_die_abbrev_children_flag(Dwarf_Die die,Dwarf_Half *ab_has_child)
{ {
if (!die) {
return DW_DLV_ERROR;
}
if (die->di_abbrev_list) { if (die->di_abbrev_list) {
*ab_has_child = die->di_abbrev_list->abl_has_child; *ab_has_child = die->di_abbrev_list->abl_has_child;
return DW_DLV_OK; return DW_DLV_OK;

View File

@ -116,7 +116,7 @@ free_rnglists_chain(Dwarf_Debug dbg, Dwarf_Chain head)
} }
} }
} }
/* See also read_single_lle_entry() for similar code */
static int static int
read_single_rle_entry(Dwarf_Debug dbg, read_single_rle_entry(Dwarf_Debug dbg,
Dwarf_Small *data, Dwarf_Small *data,
@ -134,7 +134,16 @@ read_single_rle_entry(Dwarf_Debug dbg,
unsigned code = 0; unsigned code = 0;
Dwarf_Unsigned val1 = 0; Dwarf_Unsigned val1 = 0;
Dwarf_Unsigned val2 = 0; Dwarf_Unsigned val2 = 0;
Dwarf_Small * startdata = 0;
if (data >= enddata) {
_dwarf_error_string(dbg,error,DW_DLE_RNGLISTS_ERROR,
"DW_DLE_RNGLISTS_ERROR: "
"An rle entry begins past the end of "
"its allowed space. Corrupt DWARF.");
return DW_DLV_ERROR;
}
startdata = data;
code = *data; code = *data;
++data; ++data;
++count; ++count;
@ -202,6 +211,35 @@ read_single_rle_entry(Dwarf_Debug dbg,
} }
break; break;
} }
{
/* We want to avoid overflow in additions, and
the overall section size is a reasonable check
on count. The sequence of tests is to
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;
if (data > enddata || data < startdata ) {
/* Corrupt data being read. */
_dwarf_error_string(dbg,error,DW_DLE_RNGLISTS_ERROR,
"DW_DLE_RNGLISTS_ERROR: "
"The end of an rle entry is past the end "
"of its allowed space");
return DW_DLV_ERROR;
}
if (count > sectionsize) {
/* Corrupt data being read. */
_dwarf_error_string(dbg,error,DW_DLE_RNGLISTS_ERROR,
"DW_DLE_RNGLISTS_ERROR: "
"The number of bytes in a single "
"rnglist entry is "
"too large to be reasonable");
return DW_DLV_ERROR;
}
}
*bytes_count_out = (unsigned int)count; *bytes_count_out = (unsigned int)count;
*entry_kind = code; *entry_kind = code;
*entry_operand1 = val1; *entry_operand1 = val1;

View File

@ -51,6 +51,9 @@ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endif /* HAVE_FCNTL_H */ #endif /* HAVE_FCNTL_H */
#ifdef _WIN64 #ifdef _WIN64
#ifdef lseek /* defined in msys2 in an io.h */
#undef lseek
#endif /* lseek */
#define lseek _lseeki64 #define lseek _lseeki64
#endif /* _WIN64 */ #endif /* _WIN64 */
@ -78,7 +81,6 @@ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define O_CLOEXEC 0 #define O_CLOEXEC 0
#endif /* O_CLOEXEC */ #endif /* O_CLOEXEC */
#if 0 /* debugging only */ #if 0 /* debugging only */
static void static void
dump_bytes(char * msg,Dwarf_Small * start, long len) dump_bytes(char * msg,Dwarf_Small * start, long len)

View File

@ -57,6 +57,8 @@ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
static unsigned long minimumnewlen = 30; static unsigned long minimumnewlen = 30;
/* Here we set s_data to a valid pointer to a null byte, though
the s_size and s_avail are set to zero. */
int int
dwarfstring_constructor(struct dwarfstring_s *g) dwarfstring_constructor(struct dwarfstring_s *g)
{ {
@ -67,22 +69,30 @@ dwarfstring_constructor(struct dwarfstring_s *g)
return TRUE; return TRUE;
} }
/* We only increase the s_data space.
Only calling dwarfstring_destructor
eliminates space. */
static int static int
dwarfstring_resize_to(struct dwarfstring_s *g,size_t newlen) dwarfstring_add_to(struct dwarfstring_s *g,size_t newlen)
{ {
char *b = 0; char *b = 0;
/* s_size - s_avail is the string without counting
the null following the string. So, is strlen() */
size_t lastpos = g->s_size - g->s_avail; size_t lastpos = g->s_size - g->s_avail;
size_t malloclen = newlen+1; size_t malloclen = newlen+1;
/* ASSERT: malloclen > g->s_size at both call points */ /* ASSERT: newlen as well as malloclen are
greater than g->s_size at both call points */
if (malloclen < minimumnewlen) { if (malloclen < minimumnewlen) {
malloclen = minimumnewlen; malloclen = minimumnewlen;
} }
/* Not zeroing the new buffer block. */
b = malloc(malloclen); b = malloc(malloclen);
if (!b) { if (!b) {
return FALSE; return FALSE;
} }
if (lastpos > 0) { if (lastpos > 0) {
/* Copying the non-null bytes in s_data. */
memcpy(b,g->s_data,lastpos); memcpy(b,g->s_data,lastpos);
} }
if (g->s_malloc) { if (g->s_malloc) {
@ -90,6 +100,13 @@ dwarfstring_resize_to(struct dwarfstring_s *g,size_t newlen)
g->s_data = 0; g->s_data = 0;
} }
g->s_data = b; g->s_data = b;
/* s_data[lastpos] is one past the end of anything
counted as string
in s_data at the point of call, and is guaranteed
to be safe as we increased the size of s_data, we did not
shrink. And, too, we add 1 to newlen, always,
so space for a terminating null byte is guaranteed
available. */
g->s_data[lastpos] = 0; g->s_data[lastpos] = 0;
g->s_size = newlen; g->s_size = newlen;
g->s_avail = newlen - lastpos; g->s_avail = newlen - lastpos;
@ -119,7 +136,7 @@ dwarfstring_constructor_fixed(struct dwarfstring_s *g,
if (len == 0) { if (len == 0) {
return TRUE; return TRUE;
} }
r = dwarfstring_resize_to(g,len); r = dwarfstring_add_to(g,len);
if (!r) { if (!r) {
return FALSE; return FALSE;
} }
@ -162,6 +179,8 @@ int
dwarfstring_append_length(struct dwarfstring_s *g,char *str, dwarfstring_append_length(struct dwarfstring_s *g,char *str,
size_t slen) size_t slen)
{ {
/* lastpos is the length of characters
without the null-terminator we call it strlen */
size_t lastpos = g->s_size - g->s_avail; size_t lastpos = g->s_size - g->s_avail;
int r = 0; int r = 0;
@ -172,7 +191,7 @@ dwarfstring_append_length(struct dwarfstring_s *g,char *str,
size_t newlen = 0; size_t newlen = 0;
newlen = g->s_size + slen+2; newlen = g->s_size + slen+2;
r = dwarfstring_resize_to(g,newlen); r = dwarfstring_add_to(g,newlen);
if (!r) { if (!r) {
/* Unable to resize, dare not do anything. */ /* Unable to resize, dare not do anything. */
return FALSE; return FALSE;
@ -180,6 +199,8 @@ dwarfstring_append_length(struct dwarfstring_s *g,char *str,
} }
memcpy(g->s_data + lastpos,str,slen); memcpy(g->s_data + lastpos,str,slen);
g->s_avail -= slen; g->s_avail -= slen;
/* Adding string terminating null byte.
Space is guaranteed available to do this.*/
g->s_data[g->s_size - g->s_avail] = 0; g->s_data[g->s_size - g->s_avail] = 0;
return TRUE; return TRUE;
} }

View File

@ -79,7 +79,7 @@ extern "C" {
/* /*
libdwarf.h libdwarf.h
$Revision: #9 $ $Date: 2008/01/17 $ Revision: #9 Date: 2008/01/17
For libdwarf consumers (reading DWARF2 and later) For libdwarf consumers (reading DWARF2 and later)
@ -127,20 +127,6 @@ extern "C" {
#define DW_GROUPNUMBER_BASE 1 #define DW_GROUPNUMBER_BASE 1
#define DW_GROUPNUMBER_DWO 2 #define DW_GROUPNUMBER_DWO 2
/* Special values for offset_into_exception_table field
of dwarf fde's. */
/* The following value indicates that there is no
Exception table offset
associated with a dwarf frame. */
#define DW_DLX_NO_EH_OFFSET (-1LL)
/* The following value indicates that the producer
was unable to analyze the
source file to generate Exception tables for this function. */
#define DW_DLX_EH_OFFSET_UNAVAILABLE (-2LL)
/* The augmenter string for CIE */
#define DW_CIE_AUGMENTER_STRING_V0 "z"
/* FRAME special values */ /* FRAME special values */
/* The following 3 are assigned numbers, but /* The following 3 are assigned numbers, but
are only present at run time. are only present at run time.
@ -248,7 +234,7 @@ enum Dwarf_Ranges_Entry_Type { DW_RANGES_ENTRY,
The DWARF4 specification class definition suffices to The DWARF4 specification class definition suffices to
describe all DWARF versions. describe all DWARF versions.
See section 7.5.4, Attribute Encodings. See section 7.5.4, Attribute Encodings.
A return of DW_FORM_CLASS_UNKNOWN means we A return of DW_FORM_CLASS_UNKNOWN means the library
could not properly figure could not properly figure
out what form-class it is. out what form-class it is.
@ -258,7 +244,7 @@ enum Dwarf_Ranges_Entry_Type { DW_RANGES_ENTRY,
DWARF5: DWARF5:
DW_FORM_CLASS_LOCLISTSPTR is like DW_FORM_CLASS_LOCLIST DW_FORM_CLASS_LOCLISTSPTR is like DW_FORM_CLASS_LOCLIST
except that LOCLISTSPTR is aways a section offset, except that LOCLISTSPTR is always a section offset,
never an index, and LOCLISTSPTR is only referenced never an index, and LOCLISTSPTR is only referenced
by DW_AT_loclists_base. by DW_AT_loclists_base.
Note DW_FORM_CLASS_LOCLISTSPTR spelling to distinguish Note DW_FORM_CLASS_LOCLISTSPTR spelling to distinguish
@ -266,7 +252,7 @@ enum Dwarf_Ranges_Entry_Type { DW_RANGES_ENTRY,
DWARF5: DWARF5:
DW_FORM_CLASS_RNGLISTSPTR is like DW_FORM_CLASS_RNGLIST DW_FORM_CLASS_RNGLISTSPTR is like DW_FORM_CLASS_RNGLIST
except that RNGLISTSPTR is aways a section offset, except that RNGLISTSPTR is always a section offset,
never an index. DW_FORM_CLASS_RNGLISTSPTR is only never an index. DW_FORM_CLASS_RNGLISTSPTR is only
referenced by DW_AT_rnglists_base. referenced by DW_AT_rnglists_base.
*/ */
@ -350,11 +336,14 @@ typedef struct Dwarf_Locdesc_c_s * Dwarf_Locdesc_c;
*/ */
typedef struct Dwarf_Loc_Head_c_s * Dwarf_Loc_Head_c; typedef struct Dwarf_Loc_Head_c_s * Dwarf_Loc_Head_c;
/* This provides access to data from sections /*! @typedef Dwarf_Gnu_Index_Head
A pointer to a struct Dwarf_Gnu_Index_Head_s
for sections
.debug_gnu_pubtypes or .debug_gnu_pubnames. .debug_gnu_pubtypes or .debug_gnu_pubnames.
These are not standard DWARF, and can appear These are not standard DWARF, and can appear
with gcc -gdwarf-5 with gcc -gdwarf-5
*/ */
typedef struct Dwarf_Gnu_Index_Head_s * Dwarf_Gnu_Index_Head; typedef struct Dwarf_Gnu_Index_Head_s * Dwarf_Gnu_Index_Head;
/*! @typedef Dwarf_Dsc_Head /*! @typedef Dwarf_Dsc_Head
@ -373,11 +362,44 @@ typedef struct Dwarf_Frame_Instr_Head_s * Dwarf_Frame_Instr_Head;
/*! @typedef dwarf_printf_callback_function_type /*! @typedef dwarf_printf_callback_function_type
Used as a function pointer to a user-written Used as a function pointer to a user-written
callback function. callback function. This provides a detailed
content of line table data.
The default contents of the callback data
are all zero bytes. So no callbacks
involving this data will be done.
See dwarf_register_printf_callback()
@param dw_user_pointer
Passes your callback a pointer to space you allocated as
an identifier of some kind in calling
dwarf_register_printf_callback..
@param dw_linecontent
Passes your callback null-terminated string with
one line of detailed line table content.
*/ */
typedef void (* dwarf_printf_callback_function_type) typedef void (* dwarf_printf_callback_function_type)
(void * /*user_pointer*/, const char * /*linecontent*/); (void * dw_user_pointer, const char * dw_linecontent);
/*! @struct Dwarf_Printf_Callback_Info_s
If one wishes to print detailed line table
information one creates an instance of this
struct and fills in the fields and passes
the struct to the relevant init, for example,
dwarf_init_path().
@var dp_user_pointer
A pointer to data of use in a call back.
@var dp_fptr
@var dp_buffer
@var dp_buffer_len
@var dp_buffer_user_provided
@var dp_reserved.
Set to zero.
*/
struct Dwarf_Printf_Callback_Info_s { struct Dwarf_Printf_Callback_Info_s {
void * dp_user_pointer; void * dp_user_pointer;
dwarf_printf_callback_function_type dp_fptr; dwarf_printf_callback_function_type dp_fptr;
@ -387,7 +409,7 @@ struct Dwarf_Printf_Callback_Info_s {
void * dp_reserved; void * dp_reserved;
}; };
/*! @typedef Dwarf_Cmdline_Options. /*! @struct Dwarf_Cmdline_Options_s
check_verbose_mode defaults to FALSE. check_verbose_mode defaults to FALSE.
If a libdwarf-calling program sets If a libdwarf-calling program sets
@ -399,10 +421,20 @@ struct Dwarf_Printf_Callback_Info_s {
Or the libdwarf calling code can call Or the libdwarf calling code can call
dwarf_record_cmdline_options() to set dwarf_record_cmdline_options() to set
the new value. the new value.
For convenience the type name for the struct
is Dwarf_Cmdline_Options.
@var check_verbose_mode
*/ */
typedef struct Dwarf_Cmdline_Options_s { struct Dwarf_Cmdline_Options_s {
Dwarf_Bool check_verbose_mode; Dwarf_Bool check_verbose_mode;
} Dwarf_Cmdline_Options; };
/*! @typedef Dwarf_Cmdline_Options
*/
typedef struct Dwarf_Cmdline_Options_s Dwarf_Cmdline_Options;
/*! @typedef Dwarf_Str_Offsets_Table /*! @typedef Dwarf_Str_Offsets_Table
Provides an access to the .debug_str_offsets Provides an access to the .debug_str_offsets
@ -496,7 +528,8 @@ typedef struct Dwarf_Ranges_s {
Note that this definition can only deal correctly Note that this definition can only deal correctly
with register numbers that fit in a 16 bit with register numbers that fit in a 16 bit
unsigned value. Changing this would be an incompatible unsigned value. Removing this
restriction would force an incompatible
change to several functions in the libdwarf API. change to several functions in the libdwarf API.
*/ */
@ -526,7 +559,8 @@ typedef struct Dwarf_Regtable_Entry3_s {
Note that this definition can only deal correctly Note that this definition can only deal correctly
with register table size that fits in a 16 bit with register table size that fits in a 16 bit
unsigned value. */ unsigned value.
*/
typedef struct Dwarf_Regtable3_s { typedef struct Dwarf_Regtable3_s {
struct Dwarf_Regtable_Entry3_s rt3_cfa_rule; struct Dwarf_Regtable_Entry3_s rt3_cfa_rule;
Dwarf_Half rt3_reg_table_size; Dwarf_Half rt3_reg_table_size;
@ -535,7 +569,12 @@ typedef struct Dwarf_Regtable3_s {
/* Opaque types for Consumer Library. */ /* Opaque types for Consumer Library. */
/*! @typedef Dwarf_Error /*! @typedef Dwarf_Error
&error is used in most calls to return error details
@code
Dwarf_Error error = 0;
dres = dwarf_siblingof_c(in_die,&return_sib, &error);
@endcode
&error is used in calls to return error details
when the call returns DW_DLV_ERROR. when the call returns DW_DLV_ERROR.
*/ */
typedef struct Dwarf_Error_s* Dwarf_Error; typedef struct Dwarf_Error_s* Dwarf_Error;
@ -569,15 +608,31 @@ typedef struct Dwarf_Line_s* Dwarf_Line;
typedef struct Dwarf_Global_s* Dwarf_Global; typedef struct Dwarf_Global_s* Dwarf_Global;
/*! @typedef Dwarf_Type /*! @typedef Dwarf_Type
Used to reference a reference to an entry in Before release 0.6.0 used to reference a reference
to an entry in
the .debug_pubtypes section (as well as the .debug_pubtypes section (as well as
the SGI-only extension .debug_types). the SGI-only extension .debug_types).
However, we use Dwarf_Global instead now.
*/ */
typedef struct Dwarf_Type_s* Dwarf_Type; typedef struct Dwarf_Type_s* Dwarf_Type;
/* The next three are SGI extensions not used elsewhere. */ /*! @typedef Dwarf_Func
An SGI extension type which is no longer
used at all.
As of release 0.6.0 use Dwarf_Global instead.
*/
typedef struct Dwarf_Func_s* Dwarf_Func; typedef struct Dwarf_Func_s* Dwarf_Func;
/*! @typedef Dwarf_Var
An SGI extension type which is no longer
used at all.
As of release 0.6.0 use Dwarf_Global instead.
*/
typedef struct Dwarf_Var_s* Dwarf_Var; typedef struct Dwarf_Var_s* Dwarf_Var;
/*! @typedef Dwarf_Weak
An SGI extension type which is no longer
used at all.
As of release 0.6.0 use Dwarf_Global instead.
*/
typedef struct Dwarf_Weak_s* Dwarf_Weak; typedef struct Dwarf_Weak_s* Dwarf_Weak;
/*! @typedef Dwarf_Attribute /*! @typedef Dwarf_Attribute
@ -586,17 +641,19 @@ typedef struct Dwarf_Weak_s* Dwarf_Weak;
typedef struct Dwarf_Attribute_s* Dwarf_Attribute; typedef struct Dwarf_Attribute_s* Dwarf_Attribute;
/*! @typedef Dwarf_Abbrev /*! @typedef Dwarf_Abbrev
Used to reference a Dwarf_Abbrev, though Used to reference a Dwarf_Abbrev.
usually such are handled transparently Usually Dwarf_Abbrev are fully handled inside the library
in the library so one rarely needs to declare the type.
*/ */
typedef struct Dwarf_Abbrev_s* Dwarf_Abbrev; typedef struct Dwarf_Abbrev_s* Dwarf_Abbrev;
/*! @typedef Dwarf_Fde /*! @typedef Dwarf_Fde
Used to reference .debug_frame or .eh_frame FDE. Used to reference .debug_frame or .eh_frame FDE.
*/ */
typedef struct Dwarf_Fde_s* Dwarf_Fde; typedef struct Dwarf_Fde_s* Dwarf_Fde;
/*! @typedef Dwarf_Cie /*! @typedef Dwarf_Cie
Used to reference .debug_frame or .eh_frame CIE. Used to reference .debug_frame or .eh_frame CIE.
*/ */
typedef struct Dwarf_Cie_s* Dwarf_Cie; typedef struct Dwarf_Cie_s* Dwarf_Cie;
@ -628,15 +685,18 @@ typedef struct Dwarf_Line_Context_s *Dwarf_Line_Context;
typedef struct Dwarf_Macro_Context_s *Dwarf_Macro_Context; typedef struct Dwarf_Macro_Context_s *Dwarf_Macro_Context;
/*! @typedef Dwarf_Dnames_Head /*! @typedef Dwarf_Dnames_Head
Used as the general reference to the DWARF5 .debug_names Used as the general reference to the DWARF5 .debug_names
section. section.
*/ */
typedef struct Dwarf_Dnames_Head_s *Dwarf_Dnames_Head; typedef struct Dwarf_Dnames_Head_s *Dwarf_Dnames_Head;
/*! @typedef Dwarf_Handler /*! @typedef Dwarf_Handler
Used in rare cases (mainly tiny programs) Used in rare cases (mainly tiny programs)
with dwarf_init_path() etc with dwarf_init_path() etc
initialization calls. initialization calls to provide a pointer
to a generic-error-handler function you write.
*/ */
typedef void (*Dwarf_Handler)(Dwarf_Error dw_error, typedef void (*Dwarf_Handler)(Dwarf_Error dw_error,
Dwarf_Ptr dw_errarg); Dwarf_Ptr dw_errarg);
@ -658,13 +718,22 @@ struct Dwarf_Macro_Details_s {
Dwarf_Signed dmd_fileindex;/* the source file index */ Dwarf_Signed dmd_fileindex;/* the source file index */
char * dmd_macro; /* macro name string */ char * dmd_macro; /* macro name string */
}; };
/*! @typedef Dwarf_Macro_Details
A handy short name for a Dwarf_Macro_Details_S struct.
*/
typedef struct Dwarf_Macro_Details_s Dwarf_Macro_Details; typedef struct Dwarf_Macro_Details_s Dwarf_Macro_Details;
/*! @typedef Dwarf_Debug_Fission_Per_CU
A handy short name for a Dwarf_Debug_Fission_Per_CU_s struct.
*/
typedef struct Dwarf_Debug_Fission_Per_CU_s typedef struct Dwarf_Debug_Fission_Per_CU_s
Dwarf_Debug_Fission_Per_CU; Dwarf_Debug_Fission_Per_CU;
/* ===== BEGIN Obj_Access data ===== */ /* ===== BEGIN Obj_Access data ===== */
/*! @typedef Dwarf_Obj_Access_Interface_a /*! @typedef Dwarf_Obj_Access_Interface_a
Used for access to and settint up special data Used for access to and setting up special data
allowing access to DWARF even with no object allowing access to DWARF even with no object
files present files present
*/ */
@ -672,7 +741,7 @@ typedef struct Dwarf_Obj_Access_Interface_a_s
Dwarf_Obj_Access_Interface_a; Dwarf_Obj_Access_Interface_a;
/*! @typedef Dwarf_Obj_Access_Methods_a /*! @typedef Dwarf_Obj_Access_Methods_a
Used for access to and settint up special data Used for access to and setting up special data
allowing access to DWARF even with no object allowing access to DWARF even with no object
files present files present
*/ */
@ -767,18 +836,20 @@ typedef struct Dwarf_Rnglists_Head_s * Dwarf_Rnglists_Head;
/*! @} endgroup allstructs */ /*! @} endgroup allstructs */
/*! @defgroup framedefines Default stack frame #defines /*! @defgroup framedefines Default stack frame macros
@{ @{
*/ */
/* Special values for offset_into_exception_table field /* Special values for offset_into_exception_table field
of dwarf fde's. */ of dwarf fde's
/* The following value indicates that there is no The following value indicates that there is no
Exception table offset Exception table offset
associated with a dwarf frame. */ associated with a dwarf frame.
*/
#define DW_DLX_NO_EH_OFFSET (-1LL) #define DW_DLX_NO_EH_OFFSET (-1LL)
/* The following value indicates that the producer /* The following value indicates that the producer
was unable to analyze the was unable to analyze the
source file to generate Exception tables for this function. */ source file to generate Exception tables for this function.
*/
#define DW_DLX_EH_OFFSET_UNAVAILABLE (-2LL) #define DW_DLX_EH_OFFSET_UNAVAILABLE (-2LL)
/* The augmenter string for CIE */ /* The augmenter string for CIE */
@ -1584,9 +1655,7 @@ DW_API int dwarf_init_path_dl_a(const char * dw_path,
unsigned char * dw_dl_path_source, unsigned char * dw_dl_path_source,
Dwarf_Error* dw_error); Dwarf_Error* dw_error);
/*! @brief Initialization based on Unix/Linux (etc) path /*! @brief Initialization based on Unix/Linux (etc) fd
This version allows specifying any number of debuglink
global paths to search on for debuglink targets.
In case DW_DLV_ERROR returned be sure to In case DW_DLV_ERROR returned be sure to
call dwarf_dealloc_error even though call dwarf_dealloc_error even though
@ -1636,6 +1705,10 @@ DW_API int dwarf_init_b(int dw_fd,
May return DW_DLV_NO_ENTRY May return DW_DLV_NO_ENTRY
but no further information is available. but no further information is available.
Normally returns DW_DLV_OK. Normally returns DW_DLV_OK.
There is nothing the caller can do with the return
value except report it somehow. Most callers
ignore the return value.
*/ */
DW_API int dwarf_finish(Dwarf_Debug dw_dbg); DW_API int dwarf_finish(Dwarf_Debug dw_dbg);
@ -1689,20 +1762,33 @@ DW_API int dwarf_object_init_b(Dwarf_Obj_Access_Interface_a* dw_obj,
The init call dw_obj data is not freed The init call dw_obj data is not freed
by the call to dwarf_object_finish. by the call to dwarf_object_finish.
@return @return
The return value DW_DLV_OK etc is pretty useless, there The return value DW_DLV_OK etc is useless,
is not much you can do with it. one could possibly report it somehow. Callers
usually ignore the return value.
*/ */
DW_API int dwarf_object_finish(Dwarf_Debug dw_dbg); DW_API int dwarf_object_finish(Dwarf_Debug dw_dbg);
/*! @brief Use with split dwarf. /*! @brief Use with split dwarf.
@param dw_basedbg In libdwarf usage the object file being reported
Pass in an open dbg, on an object file on [a] is opened with dwarf_init_path() or the like.
with (normally) lots of DWARF.. If that object file [a] is a split-dwarf object
then important data needed to report all of what is
in the object file [a] needs an open Dwarf_Debug on
the base object file [b] (usually the base executable
object). Here we call that executable object file [b]
the @e tied object.
See DWARF5 Appendix F.
@param dw_split_dbg
Pass in an open dbg, on a split-dwarf object file
with (normally) lots of DWARF but no executable code.
@param dw_tied_dbg @param dw_tied_dbg
Pass in an open dbg on an executable Pass in an open dbg on an executable
which has minimal DWARF to save space (we call it a @e tied dbg here)
in the executable. which has minimal DWARF (to save space
in the executable).
@param dw_error @param dw_error
In case return is DW_DLV_ERROR In case return is DW_DLV_ERROR
dw_error is set to point to dw_error is set to point to
@ -1712,7 +1798,7 @@ DW_API int dwarf_object_finish(Dwarf_Debug dw_dbg);
@see example2 @see example2
@see example3 @see example3
*/ */
DW_API int dwarf_set_tied_dbg(Dwarf_Debug dw_basedbg, DW_API int dwarf_set_tied_dbg(Dwarf_Debug dw_split_dbg,
Dwarf_Debug dw_tied_dbg, Dwarf_Debug dw_tied_dbg,
Dwarf_Error* dw_error); Dwarf_Error* dw_error);
@ -1742,6 +1828,17 @@ DW_API int dwarf_get_tied_dbg(Dwarf_Debug dw_dbg,
It returns the CU_DIE pointer through dw_cu_die; It returns the CU_DIE pointer through dw_cu_die;
dwarf_next_cu_header_e() is preferred over
dwarf_next_cu_header_d() as the latter requires
a second (immediate) step to access the CU-DIE
of the CU.
With the CU-DIE returned by dwarf_next_cu_header_e()
one calls dwarf_child() first (the CU-DIE has
no siblings) and then one calls dwarf_siblingof_c() and
dwarf_child() appropriately to descend the tree of
DIEs.
@param dw_dbg @param dw_dbg
The Dwarf_Debug of interest. The Dwarf_Debug of interest.
@param dw_is_info @param dw_is_info
@ -1817,8 +1914,7 @@ DW_API int dwarf_next_cu_header_e(Dwarf_Debug dw_dbg,
libdwarf v0.8.0 and earlier (and it also works libdwarf v0.8.0 and earlier (and it also works
for later versions). for later versions).
This version will evenually be deprecated, but This version will eventually be deprecated.
that won't be for years.
The library keeps track of where it is in the object file The library keeps track of where it is in the object file
and it knows where to find 'next'. and it knows where to find 'next'.
@ -1877,6 +1973,18 @@ DW_API int dwarf_siblingof_c(Dwarf_Die dw_die,
/*! @brief Return the first DIE or the next sibling DIE. /*! @brief Return the first DIE or the next sibling DIE.
This function follows dwarf_next_cu_header_d()
to return the CU-DIE that dwarf_next_cu_header_d()
implies but does not reveal.
Aside from the special case required use
of dwarf_siblingof_b()
immediately following
dwarf_next_cu_header_d(), dwarf_siblingof_c()
is the faster function.
This function will eventually be deprecated.
@param dw_dbg @param dw_dbg
The Dwarf_Debug one is operating on. The Dwarf_Debug one is operating on.
@param dw_die @param dw_die
@ -1964,7 +2072,7 @@ DW_API int dwarf_cu_header_basics(Dwarf_Die dw_die,
@param dw_return_childdie @param dw_return_childdie
Returns the first child through the pointer. Returns the first child through the pointer.
For subsequent dies siblings of the first, use For subsequent dies siblings of the first, use
dwarf_siblingof_b(). dwarf_siblingof_c().
@param dw_error @param dw_error
The usual Dwarf_Error*. The usual Dwarf_Error*.
@return @return
@ -1981,6 +2089,9 @@ DW_API int dwarf_child(Dwarf_Die dw_die,
/*! @brief Deallocate (free) a DIE. /*! @brief Deallocate (free) a DIE.
@param dw_die @param dw_die
Frees (deallocs) memory associated with this Dwarf_Die. Frees (deallocs) memory associated with this Dwarf_Die.
DIEs not freed explicitly will be freed by
dwarf_finish().
*/ */
DW_API void dwarf_dealloc_die( Dwarf_Die dw_die); DW_API void dwarf_dealloc_die( Dwarf_Die dw_die);
@ -2021,8 +2132,8 @@ DW_API int dwarf_die_from_hash_signature(Dwarf_Debug dw_dbg,
The global offset of the DIE in the appropriate The global offset of the DIE in the appropriate
section. section.
@param dw_is_info @param dw_is_info
Pass TRUE if the target is .debug_info, else Pass TRUE if the target is .debug_info.
pass FALSE if the target is .debug_types. Pass FALSE if the target is .debug_types.
@param dw_return_die @param dw_return_die
On success this returns a DIE pointer to On success this returns a DIE pointer to
the found DIE. the found DIE.
@ -2093,7 +2204,7 @@ DW_API Dwarf_Bool dwarf_get_die_infotypes_flag(Dwarf_Die dw_die);
So we can associate a DIE's abbreviations with the contents So we can associate a DIE's abbreviations with the contents
the abbreviations section. the abbreviations section.
Useful for detailed printing and analysis of Useful for detailed printing and analysis of
abbreviations abbreviations.
@param dw_die @param dw_die
The DIE of interest The DIE of interest
@ -2147,6 +2258,9 @@ DW_API int dwarf_dieoffset(Dwarf_Die dw_die,
/*! @brief Extract address given address index. DWARF5 /*! @brief Extract address given address index. DWARF5
Useful for checking for compiler/linker errors
in the creation of DWARF5.
@param dw_die @param dw_die
The DIE of interest The DIE of interest
@param dw_index @param dw_index
@ -2182,6 +2296,10 @@ DW_API Dwarf_Bool dwarf_addr_form_is_indexed(int dw_form);
in the CU containing the given_die in the CU containing the given_die
(the passed in DIE can be any DIE). (the passed in DIE can be any DIE).
This does not identify whether the section is
.debug_info or .debug_types, use
dwarf_get_die_infotypes_flag() to determine the section.
@see dwarf_get_cu_die_offset_given_cu_header_offset_b @see dwarf_get_cu_die_offset_given_cu_header_offset_b
@see example7 @see example7
@ -2229,6 +2347,10 @@ DW_API int dwarf_get_cu_die_offset_given_cu_header_offset_b(
@see dwarf_CU_dieoffset_given_die @see dwarf_CU_dieoffset_given_die
This does not identify whether the section is
.debug_info or .debug_types, use
dwarf_get_die_infotypes_flag() to determine the section.
@param dw_die @param dw_die
The DIE being queried. The DIE being queried.
@param dw_return_offset @param dw_return_offset
@ -2243,6 +2365,11 @@ DW_API int dwarf_die_CU_offset(Dwarf_Die dw_die,
Dwarf_Error* dw_error); Dwarf_Error* dw_error);
/*! @brief Return the offset length of the entire CU of a DIE. /*! @brief Return the offset length of the entire CU of a DIE.
This does not identify whether the section is
.debug_info or .debug_types, use
dwarf_get_die_infotypes_flag() to determine the section.
@param dw_die @param dw_die
The DIE being queried. The DIE being queried.
@param dw_return_CU_header_offset @param dw_return_CU_header_offset
@ -2298,7 +2425,7 @@ DW_API int dwarf_attr(Dwarf_Die dw_die,
Do not free the string. Do not free the string.
Many attributes allow various forms that directly or Many attributes allow various forms that directly or
indirectly contain strings and this indirectly contain strings and this
follows all of them to their string. returns the string.
@param dw_error @param dw_error
The usual error detail return pointer. The usual error detail return pointer.
@return @return
@ -2335,7 +2462,7 @@ DW_API int dwarf_diename(Dwarf_Die dw_die,
/*! @brief Return the DIE abbrev code /*! @brief Return the DIE abbrev code
The Abbrev code for a DIE is a non-negative The Abbrev code for a DIE is a positive
integer assigned by the compiler within a particular CU. integer assigned by the compiler within a particular CU.
For .debug_names abbreviations the For .debug_names abbreviations the
situation is conceptually similar. The code values situation is conceptually similar. The code values
@ -2355,7 +2482,7 @@ DW_API Dwarf_Unsigned dwarf_die_abbrev_code(Dwarf_Die dw_die);
/*! @brief Return TRUE if the DIE has children /*! @brief Return TRUE if the DIE has children
@param dw_die @param dw_die
A DIE. A valid DIE pointer (not NULL).
@param dw_ab_has_child @param dw_ab_has_child
Sets TRUE though the pointer if the DIE Sets TRUE though the pointer if the DIE
has children. has children.
@ -2374,6 +2501,10 @@ DW_API int dwarf_die_abbrev_children_flag(Dwarf_Die dw_die,
dwarfdump is checking for valid DWARF) dwarfdump is checking for valid DWARF)
to try to catch a corrupt DIE tree. to try to catch a corrupt DIE tree.
This does not identify whether the section is
.debug_info or .debug_types, use
dwarf_get_die_infotypes_flag() to determine the section.
@see example_sibvalid @see example_sibvalid
@param dw_sibling @param dw_sibling
@ -2475,6 +2606,11 @@ DW_API int dwarf_get_die_address_size(Dwarf_Die dw_die,
/* Get both offsets (local and global) */ /* Get both offsets (local and global) */
/*! @brief Return section and CU-local offsets of a DIE /*! @brief Return section and CU-local offsets of a DIE
This does not identify whether the section is
.debug_info or .debug_types, use
dwarf_get_die_infotypes_flag() to determine the section.
@param dw_die @param dw_die
The DIE of interest. The DIE of interest.
@param dw_global_offset @param dw_global_offset
@ -2530,12 +2666,6 @@ DW_API int dwarf_lowpc(Dwarf_Die dw_die,
Dwarf_Addr * dw_returned_addr, Dwarf_Addr * dw_returned_addr,
Dwarf_Error* dw_error); Dwarf_Error* dw_error);
/* When the highpc attribute is of class 'constant'
it is not an address, it is an offset from the
base address (such as lowpc) of the function.
This is therefore a required interface for DWARF4
style DW_AT_highpc. */
/*! @brief Return the DW_AT_hipc address value /*! @brief Return the DW_AT_hipc address value
This is accessing the DW_AT_high_pc attribute. This is accessing the DW_AT_high_pc attribute.
@ -2657,6 +2787,7 @@ DW_API int dwarf_bitoffset(Dwarf_Die dw_die,
Dwarf_Half * dw_attrnum, Dwarf_Half * dw_attrnum,
Dwarf_Unsigned * dw_returned_offset, Dwarf_Unsigned * dw_returned_offset,
Dwarf_Error* dw_error); Dwarf_Error* dw_error);
/*! @brief Return the value of the DW_AT_language attribute. /*! @brief Return the value of the DW_AT_language attribute.
The DIE should be a CU DIE. The DIE should be a CU DIE.
@ -2689,8 +2820,8 @@ DW_API int dwarf_srclang(Dwarf_Die dw_die,
DW_API int dwarf_arrayorder(Dwarf_Die dw_die, DW_API int dwarf_arrayorder(Dwarf_Die dw_die,
Dwarf_Unsigned * dw_returned_order, Dwarf_Unsigned * dw_returned_order,
Dwarf_Error* dw_error); Dwarf_Error* dw_error);
/*! @} */ /*! @} */
/*! @defgroup attrform DIE Attribute and Attribute-Form Details /*! @defgroup attrform DIE Attribute and Attribute-Form Details
@{ @{
Access to the details of DIEs Access to the details of DIEs
@ -3326,8 +3457,9 @@ DW_API int dwarf_discr_entry_s(Dwarf_Dsc_Head dw_dsc,
DW_DLV_OK. DW_DLV_OK.
In referencing the array via a file-number from In referencing the array via a file-number from
a DW_AT_decl_file attribute one needs to a <b>DW_AT_decl_file</b> or
know if the CU is DWARF5 or not. <b>DW_AT_call_file</b> attribute one needs
to know if the CU is DWARF5 or not.
Line Table Version numbers match compilation unit Line Table Version numbers match compilation unit
version numbers except that an experimental line table version numbers except that an experimental line table
@ -3335,11 +3467,15 @@ DW_API int dwarf_discr_entry_s(Dwarf_Dsc_Head dw_dsc,
sometimes been used with DWARF4. sometimes been used with DWARF4.
For DWARF5: For DWARF5:
The file-number from a \b DW_AT_decl_file
The file-number from a <b>DW_AT_decl_file</b> or
<b>DW_AT_call_file</b>
is the proper index into the array of string pointers. is the proper index into the array of string pointers.
For DWARF2,3,4, including experimental line table For DWARF2,3,4, including experimental line table
version 0xfe06 and a file-number from a \b DW_AT_decl_file: version 0xfe06 and a file-number from a
<b>DW_AT_decl_file</b> or <b>DW_AT_call_file</b>:
-# If the file-number is zero there is no file name to find. -# If the file-number is zero there is no file name to find.
-# Otherwise subtract one(1) from the file-number and -# Otherwise subtract one(1) from the file-number and
use the new value as the index into the array use the new value as the index into the array
@ -3597,7 +3733,7 @@ DW_API int dwarf_srclines_files_indexes(
Has the md5ptr field so cases where DW_LNCT_MD5 Has the md5ptr field so cases where DW_LNCT_MD5
is present can return pointer to the MD5 value. is present can return pointer to the MD5 value.
With DWARF 5 index starts with 0. With DWARF 5 index starts with 0.
dwarf_srclines_files_indexes makes dwarf_srclines_files_indexes() makes
indexing through the files easy. indexing through the files easy.
@see dwarf_srclines_files_indexes @see dwarf_srclines_files_indexes
@ -3735,7 +3871,7 @@ DW_API int dwarf_srclines_version(Dwarf_Line_Context dw_line_context,
/*! @brief Read Line beginstatement register /*! @brief Read Line beginstatement register
@link dwsec_linetabreg Link to Line Table Registers @endlink @link dwsec_linetabreg Line Table Registers @endlink
@param dw_line @param dw_line
The Dwarf_Line of interest. The Dwarf_Line of interest.
@ -3754,7 +3890,7 @@ DW_API int dwarf_linebeginstatement(Dwarf_Line dw_line,
/*! @brief Read Line endsequence register flag /*! @brief Read Line endsequence register flag
@link dwsec_linetabreg Link to Line Table Registers @endlink @link dwsec_linetabreg Line Table Registers @endlink
@param dw_line @param dw_line
The Dwarf_Line of interest. The Dwarf_Line of interest.
@ -3773,7 +3909,7 @@ DW_API int dwarf_lineendsequence(Dwarf_Line dw_line,
/*! @brief Read Line line register /*! @brief Read Line line register
@link dwsec_linetabreg Link to Line Table Registers @endlink @link dwsec_linetabreg Line Table Registers @endlink
@param dw_line @param dw_line
The Dwarf_Line of interest. The Dwarf_Line of interest.
@ -3791,7 +3927,7 @@ DW_API int dwarf_lineno(Dwarf_Line dw_line,
/*! @brief Read Line file register /*! @brief Read Line file register
@link dwsec_linetabreg Link to Line Table Registers @endlink @link dwsec_linetabreg Line Table Registers @endlink
@param dw_line @param dw_line
The Dwarf_Line of interest. The Dwarf_Line of interest.
@ -3826,7 +3962,7 @@ DW_API int dwarf_line_is_addr_set(Dwarf_Line dw_line,
/*! @brief Return the address of the Dwarf_Line /*! @brief Return the address of the Dwarf_Line
@link dwsec_linetabreg Link to Line Table Registers @endlink @link dwsec_linetabreg Line Table Registers @endlink
@param dw_line @param dw_line
The Dwarf_Line of interest. The Dwarf_Line of interest.
@ -3844,7 +3980,7 @@ DW_API int dwarf_lineaddr(Dwarf_Line dw_line,
/*! @brief Return a column number through the pointer /*! @brief Return a column number through the pointer
@link dwsec_linetabreg Link to Line Table Registers @endlink @link dwsec_linetabreg Line Table Registers @endlink
@param dw_line @param dw_line
The Dwarf_Line of interest. The Dwarf_Line of interest.
@ -3862,7 +3998,7 @@ DW_API int dwarf_lineoff_b(Dwarf_Line dw_line,
/*! @brief Return the file name applicable to the Dwarf_Line /*! @brief Return the file name applicable to the Dwarf_Line
@link dwsec_linetabreg Link to Line Table Registers @endlink @link dwsec_linetabreg Line Table Registers @endlink
@param dw_line @param dw_line
The Dwarf_Line of interest. The Dwarf_Line of interest.
@ -3883,7 +4019,7 @@ DW_API int dwarf_linesrc(Dwarf_Line dw_line,
/*! @brief Return the basic_block line register. /*! @brief Return the basic_block line register.
@link dwsec_linetabreg Link to Line Table Registers @endlink @link dwsec_linetabreg Line Table Registers @endlink
@param dw_line @param dw_line
The Dwarf_Line of interest. The Dwarf_Line of interest.
@ -3903,7 +4039,7 @@ DW_API int dwarf_lineblock(Dwarf_Line dw_line,
will want all or none of them. */ will want all or none of them. */
/*! @brief Return various line table registers in one call /*! @brief Return various line table registers in one call
@link dwsec_linetabreg Link to Line Table Registers @endlink @link dwsec_linetabreg Line Table Registers @endlink
@param dw_line @param dw_line
The Dwarf_Line of interest. The Dwarf_Line of interest.
@ -3983,7 +4119,7 @@ DW_API int dwarf_line_subprog(Dwarf_Line /*line*/,
with the messages (likely just print them). with the messages (likely just print them).
The lines passed back already have newlines. The lines passed back already have newlines.
@see dwarf_check_lineheader @see dwarf_check_lineheader(b)
@see Dwarf_Printf_Callback_Info_s @see Dwarf_Printf_Callback_Info_s
@param dw_cu_die @param dw_cu_die
@ -4007,15 +4143,17 @@ DW_API int dwarf_check_lineheader_b(Dwarf_Die dw_cu_die,
Does not use printf. Does not use printf.
Instead it calls back to the application using a function Instead it calls back to the application using a function
pointer once per line-to-print. The lines passed back pointer once per line-to-print. The lines passed back
already have any needed already have any needed newlines.
newlines.
dwarfdump uses this function for verbose printing
of line table data.
Failing to call the dwarf_register_printf_callback() Failing to call the dwarf_register_printf_callback()
function will prevent the lines from being passed back function will prevent the lines from being passed back
but such omission is not an error. but such omission is not an error.
the same function, but focused on checking for errors The same function, but focused on checking for errors
is is dwarf_check_lineheader_b().
@see dwarf_check_lineheader_b
@see Dwarf_Printf_Callback_Info_s @see Dwarf_Printf_Callback_Info_s
@param dw_cu_die @param dw_cu_die
@ -4032,7 +4170,10 @@ DW_API int dwarf_print_lines(Dwarf_Die dw_cu_die,
/*! @brief For line details this records callback details /*! @brief For line details this records callback details
For the structure you must fill in: Not usually needed. It is a way to check
(while using the library) what callback
data is in use or to update that callback data.
@see Dwarf_Printf_Callback_Info_s @see Dwarf_Printf_Callback_Info_s
@param dw_dbg @param dw_dbg
@ -4840,7 +4981,6 @@ DW_API int dwarf_debug_addr_table(Dwarf_Debug dw_dbg,
/*! @brief Return .debug_addr address given table index /*! @brief Return .debug_addr address given table index
@param dw_dat @param dw_dat
Pass in a Dwarf_Debug_Addr_Table pointer. Pass in a Dwarf_Debug_Addr_Table pointer.
@param dw_entry_index @param dw_entry_index
@ -7080,7 +7220,11 @@ DW_API int dwarf_get_arange_info_b(Dwarf_Arange dw_arange,
This accesses .debug_pubnames and .debug_names sections. This accesses .debug_pubnames and .debug_names sections.
Section .debug_pubnames is defined in DWARF2, DWARF3, Section .debug_pubnames is defined in DWARF2, DWARF3,
and DWARF4. and DWARF4.
Section .debug_names is defined in DWARF5. Section .debug_names is defined in DWARF5 and contains
lots of information, but only the part of the wealth
of information that this interface allows can
be retrieved here. See dwarf_dnames_header() for
access to all. debug_names data.
The code here, as of 0.4.3, September 3 2022, The code here, as of 0.4.3, September 3 2022,
returns data from either section. returns data from either section.
@ -7112,9 +7256,28 @@ DW_API int dwarf_get_globals(Dwarf_Debug dw_dbg,
#define DW_GL_TYPES 3 /* .debug_typenames */ #define DW_GL_TYPES 3 /* .debug_typenames */
#define DW_GL_VARS 4 /* .debug_varnames */ #define DW_GL_VARS 4 /* .debug_varnames */
#define DW_GL_WEAKS 5 /* .debug_weaknames */ #define DW_GL_WEAKS 5 /* .debug_weaknames */
/*! @brief Global debug_types access
/* Same function name as 0.5.0 and earlier, but @param dw_dbg
the data type changes to Dwarf_Global */ The Dwarf_Debug of interest.
@param dw_pubtypes
On success returns an array of pointers to opaque
structs..
@param dw_number_of_pubtypes
On success returns the number of entries in the array.
@param dw_error
On error dw_error is set to point to the error details.
@return
The usual value: DW_DLV_OK etc.
Returns DW_DLV_NO_ENTRY if the section is not present.
Same function name as 0.5.0 and earlier, but
the data type changes to Dwarf_Global
dwarf_get_pubtypes() is an alternate name for
dwarf_globals_by_type(..,DW_GL_PUBTYPES,..).
*/
DW_API int dwarf_get_pubtypes(Dwarf_Debug dw_dbg, DW_API int dwarf_get_pubtypes(Dwarf_Debug dw_dbg,
Dwarf_Global** dw_pubtypes, Dwarf_Global** dw_pubtypes,
Dwarf_Signed * dw_number_of_pubtypes, Dwarf_Signed * dw_number_of_pubtypes,
@ -7359,21 +7522,21 @@ DW_API void dwarf_gnu_index_dealloc(Dwarf_Gnu_Index_Head dw_head);
On success set to the offset, in .debug_info, of On success set to the offset, in .debug_info, of
the data for this block. the data for this block.
The returned offset may be outside the bounds The returned offset may be outside the bounds
of the actual .debug_info section, sucn a possibility of the actual .debug_info section, such a possibility
does not cause the function to return DW_DLV_ERROR. does not cause the function to return DW_DLV_ERROR.
@param dw_size_of_debug_info_area @param dw_size_of_debug_info_area
On success set to the size in bytes, in .debug_info, of On success set to the size in bytes, in .debug_info, of
the area this block refers to. the area this block refers to.
The returned dw_ dw_size_of_debug_info_are The returned dw_ dw_size_of_debug_info_are
plus dw_offset_into_debug_info may be outside the bounds plus dw_offset_into_debug_info may be outside the bounds
of the actual .debug_info section, sucn a possibility of the actual .debug_info section, such a possibility
does not cause the function to return DW_DLV_ERROR. does not cause the function to return DW_DLV_ERROR.
Use dwarf_get_section_max_offsets_d() Use dwarf_get_section_max_offsets_d()
to learn the size of .debug_info and optionally other to learn the size of .debug_info and optionally other
sections as well. sections as well.
@param dw_count_of_index_entries @param dw_count_of_index_entries
On success set to the count of index entries in On success set to the count of index entries in
this particlular block number. this particular block number.
@param dw_error @param dw_error
On error dw_error is set to point to the error details. On error dw_error is set to point to the error details.
@return @return
@ -7537,7 +7700,7 @@ DW_API int dwarf_gdbindex_culist_array(
If dw_entryindex is too large for the array If dw_entryindex is too large for the array
the function returns DW_DLV_NO_ENTRY. the function returns DW_DLV_NO_ENTRY.
@param dw_cu_offset @param dw_cu_offset
On success returns the CU offet for this list entry. On success returns the CU offset for this list entry.
@param dw_cu_length @param dw_cu_length
On success returns the CU length(in bytes) On success returns the CU length(in bytes)
for this list entry. for this list entry.
@ -7580,9 +7743,9 @@ DW_API int dwarf_gdbindex_types_culist_array(
If the value is greater than dw_list_length-1 If the value is greater than dw_list_length-1
the function returns DW_DLV_NO_ENTRY. the function returns DW_DLV_NO_ENTRY.
@param dw_cu_offset @param dw_cu_offset
On success returns the types CU offet for this list entry. On success returns the types CU offset for this list entry.
@param dw_tu_offset @param dw_tu_offset
On success returns the tu offet for this list entry. On success returns the tu offset for this list entry.
@param dw_type_signature @param dw_type_signature
On success returns the type unit offset for this On success returns the type unit offset for this
entry if the type has a signature. entry if the type has a signature.
@ -8007,14 +8170,21 @@ DW_API int dwarf_get_debugfission_for_key(Dwarf_Debug dw_dbg,
Dwarf_Error * dw_error); Dwarf_Error * dw_error);
/* END debugfission dwp .debug_cu_index /* END debugfission dwp .debug_cu_index
and .debug_tu_indexmeaningfumeaningfu operations. */ and .debug_tu_index meaningful operations. */
/*! @} */ /*! @} */
/*! @defgroup gnudebuglink Access GNU .gnu_debuglink, build-id. /*! @defgroup gnudebuglink Access GNU .gnu_debuglink, build-id.
@{ @{
When DWARF is separate from a normal shared object. When DWARF sections are in a differenct object
than the executable or a normal shared object.
The special GNU section provides a way to name
the object file with DWARF.
libdwarf will attempt to use this data to find
the object file with DWARF.
Has nothing to do with split-dwarf/debug-fission. Has nothing to do with split-dwarf/debug-fission.
*/ */
@ -8144,10 +8314,10 @@ DW_API int dwarf_suppress_debuglink_crc(int dw_suppress);
/*! @brief Adding debuglink global paths /*! @brief Adding debuglink global paths
Only really inside dwarfexample/dwdebuglink.c Used inside src/bin/dwarfexample/dwdebuglink.c
so we can show all that is going on. so we can show all that is going on.
The following has the explanation for how debuglink The following has the explanation for how debuglink
and global paths interact. and global paths interact:
@see https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html @see https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html
@param dw_dbg @param dw_dbg
@ -8226,11 +8396,17 @@ DW_API unsigned int dwarf_basic_crc32(const unsigned char * dw_buf,
/*! @defgroup harmless Harmless Error recording /*! @defgroup harmless Harmless Error recording
@{ @{
The harmless error list is a circular buffer of The harmless error list is a fixed size circular buffer of
errors we note but which do not stop us from processing errors we note but which do not stop us from processing
the object. Created so dwarfdump or other tools the object. Created so dwarfdump or other tools
can report such inconsequential errors without causing can report such inconsequential errors without causing
anything to stop early. anything to stop early.
You can change the list size from the default of
DW_HARMLESS_ERROR_CIRCULAR_LIST_DEFAULT_SIZE
at any time for a Dwarf_Debug dbg.
Harmless error data is dealloc'd by dwarf_finish().
*/ */
/*! @brief Default size of the libdwarf-internal circular list */ /*! @brief Default size of the libdwarf-internal circular list */
#define DW_HARMLESS_ERROR_CIRCULAR_LIST_DEFAULT_SIZE 4 #define DW_HARMLESS_ERROR_CIRCULAR_LIST_DEFAULT_SIZE 4
@ -8315,7 +8491,7 @@ DW_API unsigned int dwarf_set_harmless_error_list_size(
@param dw_newerror @param dw_newerror
Pass in a string whose content the function Pass in a string whose content the function
inserts as a harmless error (which inserts as a harmless error (which
dwarf_get_harmless_error_list will retrieve. dwarf_get_harmless_error_list will retrieve).
*/ */
DW_API void dwarf_insert_harmless_error(Dwarf_Debug dw_dbg, DW_API void dwarf_insert_harmless_error(Dwarf_Debug dw_dbg,
char * dw_newerror); char * dw_newerror);
@ -8335,13 +8511,20 @@ DW_API void dwarf_insert_harmless_error(Dwarf_Debug dw_dbg,
through the pointer @b dw_s_out and the value through the pointer @b dw_s_out and the value
returned is DW_DLV_OK. returned is DW_DLV_OK.
The strings are in static storage and must not be freed. The strings returned on sucess are in static storage
and must not be freed.
These functions are generated from information
in dwarf.h, not hand coded functions.
If DW_DLV_NO_ENTRY is returned the @b dw_val_in is not known and If DW_DLV_NO_ENTRY is returned the @b dw_val_in is not known and
@b *s_out is not set. This is unusual. @b *s_out is not set. This is unusual.
DW_DLV_ERROR is never returned. DW_DLV_ERROR is never returned.
The example referred to offers the suggested way
to use functions like these.
@see examplezb @see examplezb
*/ */
@ -8974,9 +9157,8 @@ DW_API int dwarf_machine_architecture(Dwarf_Debug dw_dbg,
/*! @brief Get section count (of object file sections). /*! @brief Get section count (of object file sections).
Return the section count. Returns 0 if the Return the section count. Returns 0 if the
dw_debug argument is improper in any way. dw_dbg argument is improper in any way.
@param dw_dbt
@param dw_dbg @param dw_dbg
Pass in a valid Dwarf_Debug of interest. Pass in a valid Dwarf_Debug of interest.
@return @return
@ -9034,8 +9216,8 @@ DW_API int dwarf_get_section_max_offsets_d(Dwarf_Debug dw_dbg,
@{ @{
Section Groups are defined in the extended Section Groups are defined in the extended
Elf ABI and are usually seen in relocatable Elf ABI and are seen in relocatable
Elf object files. Elf object files, not executables or shared objects.
@link dwsec_sectiongroup Section Groups Overview @endlink @link dwsec_sectiongroup Section Groups Overview @endlink
@ -9345,11 +9527,10 @@ DW_API int dwarf_get_universalbinary_count(
These are crucial for libdwarf itself. These are crucial for libdwarf itself.
The dw_ftype returned is one of The dw_ftype returned is one of
DW_FTYPE_APPLEUNIVERSAL DW_FTYPE_ELF,
DW_FTYPE_MACH_O DW_FTYPE_PE,
DW_FTYPE_ELF DW_FTYPE_MACH_O, or
DW_FTYPE_PE DW_FTYPE_APPLEUNIVERSAL.
*/ */
DW_API int dwarf_object_detector_path_b(const char * dw_path, DW_API int dwarf_object_detector_path_b(const char * dw_path,
char *dw_outpath_buffer, char *dw_outpath_buffer,

View File

@ -11,7 +11,7 @@
#define LIBDWARF_PRIVATE_H #define LIBDWARF_PRIVATE_H
#define DW_PR_XZEROS "08" #define DW_PR_XZEROS "08"
#ifdef _WIN32 #if defined(_WIN32) && defined(_MSC_VER)
#define DW_PR_DUx "I64x" #define DW_PR_DUx "I64x"
#define DW_PR_DSx "I64x" #define DW_PR_DSx "I64x"
#define DW_PR_DUu "I64u" #define DW_PR_DUu "I64u"

View File

@ -142,6 +142,8 @@ libdwarf = declare_dependency(
dependencies : [zlib_deps, libzstd_deps] dependencies : [zlib_deps, libzstd_deps]
) )
meson.override_dependency('libdwarf', libdwarf)
install_headers(libdwarf_header_src, install_headers(libdwarf_header_src,
install_dir : dir_pkginclude + '-' + v_maj install_dir : dir_pkginclude + '-' + v_maj
) )