Create mirror of 6216e185863f41d6f19ab850caabfff7326020d7

This commit is contained in:
Jeremy 2023-11-13 11:24:44 -05:00
commit c78e984f3a
No known key found for this signature in database
GPG Key ID: B4C8300FEC395042
127 changed files with 82542 additions and 0 deletions

3
.gitattributes vendored Normal file
View File

@ -0,0 +1,3 @@
src/** linguist-vendored
cmake/** linguist-vendored
CMakeLists.txt linguist-vendored

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
build
libdwarf-code

366
CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,366 @@
cmake_minimum_required(VERSION 3.5)
project(libdwarf C CXX)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
include_directories( ${PROJECT_BINARY_DIR} )
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
# used to compile on MSVC upto 2013 where snprintf is not available
macro(msvc_posix target)
if(MSVC AND ("${MSVC_VERSION}" LESS 1900))
# under VS 2015
target_compile_definitions(${target} PUBLIC
snprintf=_snprintf)
endif()
endmacro()
set(LIBDWARF_CRT "MD" CACHE STRING "Either MT or MD, specifies whether to use the static or dynamic MSVCRT.")
if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
# Use CMAKE_MSVC_RUNTIME in versions 3.15 and up
if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.15")
cmake_policy(SET CMP0091 NEW)
if (LIBDWARF_CRT STREQUAL "MT")
message(STATUS "Using MT runtime by CMAKE_MSVC_RUNTIME_LIBRARY")
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
elseif(LIBDWARF_CRT STREQUAL "MD")
message(STATUS "Using MD runtime by CMAKE_MSVC_RUNTIME_LIBRARY")
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
else()
message(FATAL_ERROR "LIBDWARF_CRT must be MT or MD")
endif()
# Use regexes in versions before 3.15
else()
if (LIBDWARF_CRT STREQUAL "MT")
message(STATUS "Using MT runtime by compile flag replacement")
# taken from the CMake FAQ
foreach(flag_v
CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG
CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_MINSIZEREL
CMAKE_C_FLAGS_RELWITHDEBINFO
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG
CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_MINSIZEREL
CMAKE_CXX_FLAGS_RELWITHDEBINFO)
if (${flag_v} MATCHES "([\\/\\-]M)D")
string(REGEX REPLACE "([\\/\\-]M)D" "\\1T"
${flag_v} "${${flag_v}}")
endif()
endforeach()
elseif(LIBDWARF_CRT STREQUAL "MD")
message(STATUS "Using MD runtime by cmake default")
else()
message(FATAL_ERROR "LIBDWARF_CRT must be MT or MD")
endif()
endif()
endif()
# message("CMake flags are:")
# message(" CMAKE_C_FLAGS: ${CMAKE_C_FLAGS}")
# message(" CMAKE_C_FLAGS_DEBUG: ${CMAKE_C_FLAGS_DEBUG}")
# message(" CMAKE_C_FLAGS_RELEASE: ${CMAKE_C_FLAGS_RELEASE}")
# message(" CMAKE_C_FLAGS_MINSIZEREL: ${CMAKE_C_FLAGS_MINSIZEREL}")
# message(" CMAKE_C_FLAGS_RELWITHDEBINFO: ${CMAKE_C_FLAGS_RELWITHDEBINFO}")
# message(" CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}")
# message(" CMAKE_CXX_FLAGS_DEBUG: ${CMAKE_CXX_FLAGS_DEBUG}")
# message(" CMAKE_CXX_FLAGS_RELEASE: ${CMAKE_CXX_FLAGS_RELEASE}")
# message(" CMAKE_CXX_FLAGS_MINSIZEREL: ${CMAKE_CXX_FLAGS_MINSIZEREL}")
# message(" CMAKE_CXX_FLAGS_RELWITHDEBINFO: ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
# set target folder on IDE
macro(set_folder target folder)
set_target_properties(${target} PROPERTIES FOLDER ${folder})
endmacro()
# set source groups on IDE
macro(set_source_group list_name group_name)
set(${list_name} ${ARGN})
source_group(${group_name} FILES ${ARGN})
endmacro()
# view folders on supported IDEs
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
# tells cmake to look in 64bit first (cmake
# would probably do this anyway).
set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS TRUE)
enable_testing()
# always include project's folder to includes
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE ON)
### begin what was configure.cmake
# cmake macros
include(TestBigEndian)
include(CheckIncludeFile)
include(CheckCSourceCompiles)
include(CheckCSourceRuns)
include(CheckSymbolExists)
### Version also appears in configure.ac
set(VERSION 0.9.0)
set(PACKAGE_VERSION "\"${VERSION}\"")
set(PACKAGE_NAME "libdwarf" )
set(PACKAGE_STRING "\"${PACKAGE_NAME} ${VERSION}\"")
string(REGEX REPLACE "[\"]" "" tarname1 "${PACKAGE_STRING}" )
string(REGEX REPLACE "[^a-zA-Z0-9_]" "-" tarname "${tarname1}" )
set(PACKAGE_TARNAME "\"${tarname}\"" )
test_big_endian(isBigEndian)
if (${isBigEndian})
set ( WORDS_BIGENDIAN 1 )
endif()
# check_include_file( "sys/types.h" HAVE_SYS_TYPES_H) // Only used by dwarfgen
# check_include_file( "sys/stat.h" HAVE_SYS_STAT_H ) // Only used by dwarfgen
# check_include_file( "inttypes.h" HAVE_INTTYPES_H ) // Unused
# check_include_file( "memory.h" HAVE_MEMORY_H ) // Unused
# check_include_file( "strings.h" HAVE_STRINGS_H ) // Unused
check_include_file( "stdint.h" HAVE_STDINT_H )
check_include_file( "unistd.h" HAVE_UNISTD_H )
# check_include_file( "sgidefs.h" HAVE_SGIDEFS_H ) // Unused
check_include_file( "stdafx.h" HAVE_STDAFX_H )
check_include_file( "fcntl.h" HAVE_FCNTL_H )
### cmake provides no way to guarantee uint32_t present.
### configure does guarantee that.
# HAVE_UINTPTR_T: Unused
# uintptr_t: Unused
# HAVE_INTPTR_T: Unused
# if(HAVE_STDINT_H)
# check_c_source_compiles("
# #include <stdint.h>
# int main()
# {
# uintptr_t i; i = 12;
# return (int)i;
# }" HAVE_UINTPTR_T)
# check_c_source_compiles("
# #include <stdint.h>
# int main()
# {
# intptr_t i; i = 12;
# return (int)i;
# }" HAVE_INTPTR_T)
# endif()
# if (HAVE_UINTPTR_T)
# message(STATUS "HAVE_UINTPTR_T 1: uintptr_t defined in stdint.h... YES")
# else()
# message(STATUS "uintptr_t defined in stdint.h... NO")
# set(uintptr_t "unsigned long long int" )
# message(STATUS "Setting #define uintptr_t " ${uintptr_t})
# endif()
# if (uintptr_t)
# message(STATUS "uintptr_t value considered YES ")
# else()
# message(STATUS "uintptr_t value considered NO ")
# endif()
# if (HAVE_INTPTR_T)
# message(STATUS "HAVE_INTPTR_T 1: intptr_t defined in stdint.h... YES")
# else()
# message(STATUS "intptr_t defined in stdint.h... NO")
# set(uintptr_t "long long int" )
# message(STATUS "Setting #define intptr_t " ${intptr_t})
# endif()
# if (intptr_t)
# message(STATUS "intptr_t value considered YES ")
# else()
# message(STATUS "intptr_t value considered NO ")
# endif()
# Unused
# check_c_source_compiles("
# static unsigned foo( unsigned x,
# __attribute__ ((unused)) int y)
# {
# unsigned x2 = x + 1;
# return x2;
# }
# int main(void) {
# unsigned y = 0;
# y = foo(12,y);
# return 0;
# }" HAVE_UNUSED_ATTRIBUTE)
# message(STATUS "Checking compiler supports __attribute__ unused... ${HAVE_UNUSED_ATTRIBUTE}")
# Redundant
# check_c_source_compiles([=[
# #include "stdafx.h"
# int main()
# {
# int p; p = 27;
# return 0;
# }]=] HAVE_STDAFX_H)
#message(STATUS "Checking have windows stdafx.h... ${HAVE_STDAFX_H}")
set(CMAKE_REQUIRED_LIBRARIES z)
check_c_source_compiles( [=[
#include "zlib.h"
int main()
{
Bytef dest[100];
uLongf destlen = 100;
Bytef *src = 0;
uLong srclen = 3;
int res = uncompress(dest,&destlen,src,srclen);
if (res == Z_OK) {
/* ALL IS WELL */
}
return 0;
} ]=] HAVE_ZLIB )
check_c_source_compiles( [=[
#include "zlib.h"
int main()
{
Bytef dest[100];
uLongf destlen = 100;
Bytef *src = 0;
uLong srclen = 3;
int res = uncompress(dest,&destlen,src,srclen);
if (res == Z_OK) {
/* ALL IS WELL */
}
return 0;
} ]=] HAVE_ZLIB_H )
set(CMAKE_REQUIRED_LIBRARIES)
if (HAVE_ZLIB)
# For linking in libz
set(DW_FZLIB "z")
endif()
set(CMAKE_REQUIRED_LIBRARIES zstd )
check_c_source_compiles( [=[
#include "zstd.h"
int main()
{
char * dest[100];
size_t destlen = 100;
char *src = 0;
size_t srclen = 3;
size_t res = ZSTD_decompress(dest,destlen,src,srclen);
if (res == destlen) {
/* ALL IS WELL */
}
return 0;
} ]=] HAVE_ZSTD )
check_c_source_compiles( [=[
#include "zstd.h"
int main()
{
char * dest[100];
size_t destlen = 100;
char *src = 0;
size_t srclen = 3;
size_t res = ZSTD_decompress(dest,destlen,src,srclen);
if (res == destlen) {
/* ALL IS WELL */
}
return 0;
} ]=] HAVE_ZSTD_H )
set(CMAKE_REQUIRED_LIBRARIES)
if (HAVE_ZSTD)
# For linking in libzstd
set(DW_FZSTD "zstd")
endif()
# Unused
# check_c_source_compiles([=[
# #include <stdint.h>
# int main()
# {
# intptr_t p;
# p = 27;
# return 0;
# }]=] HAVE_INTPTR_T)
message(STATUS "CMAKE_SIZEOF_VOID_P ... " ${CMAKE_SIZEOF_VOID_P} )
# libdwarf
option(BUILD_NON_SHARED "build archive library libdwarf[p].a" TRUE)
option(BUILD_SHARED
"build shared library libdwarf[p].so and use it" FALSE)
# This adds compiler option -Wall (gcc compiler warnings)
option(WALL "Add -Wall" FALSE)
option(LIBDWARF_STATIC "add -DLIBDWARF_STATIC" FALSE)
# DW_FWALLXX are gnu C++ options.
if (WALL)
set(DW_FWALLXX -Wall -Wextra -Wno-unused-private-field -Wpointer-arith -Wmissing-declarations -Wcomment -Wformat -Wpedantic -Wuninitialized -Wshadow -Wno-long-long -Werror)
set(DW_FWALL ${DW_FWALLXX} -Wpointer-arith -Wmissing-declarations -Wmissing-prototypes -Wdeclaration-after-statement -Wextra -Wcomment -Wformat -Wpedantic -Wuninitialized -Wno-long-long -Wshadow -Werror )
message(STATUS "Compiler warning options... YES ${DW_FWALL}")
else()
unset(DW_FWALL )
message(STATUS "Compiler warning options... NO")
endif()
#if (LIBDWARF_STATIC)
# set(DW_LIBDWARF_STATIC -DLIBDWARF_STATIC)
#else()
# unset(DW_LIBDWARF_STATIC)
#endif()
option(BUILD_DWARFDUMP "Build dwarfdump (default is YES)" FALSE)
option(BUILD_DWARFGEN "Build dwarfgen (default is NO)" FALSE)
message(STATUS "Building dwarfgen ... ${BUILD_DWARFGEN}")
option(BUILD_DWARFEXAMPLE "Build dwarfexample (default is NO)" FALSE)
message(STATUS "Building dwarfexample... ${BUILD_DWARFEXAMPLE}")
option(DO_TESTING "Do certain api tests (default is NO)" FALSE)
message(STATUS "Building api tests ... ${DOTESTS}")
### end what was configure.cmake
option(PIC_ALWAYS "Build libdwarf with position-independent code for both static and shared (default is NO)" FALSE)
configure_file(cmake/config.h.cmake config.h)
if(BUILD_NON_SHARED)
set(DW_LIBDWARF_STATIC -DLIBDWARF_STATIC)
set(BUILD_SHARED_LIBS NO)
set(DWARF_TARGETS dwarf-static)
set(DWARF_TYPES STATIC)
set(dwarf-target dwarf-static)
set(DWARFP_TARGETS dwarfp-static)
set(DWARFP_TYPES STATIC)
set(dwarfp-target dwarfp-static)
else()
unset(DW_LIBDWARF_STATIC)
set(BUILD_SHARED_LIBS YES)
set(DWARF_TARGETS dwarf-shared)
set(DWARF_TYPES SHARED)
set(dwarf-target dwarf-shared)
set(DWARFP_TARGETS dwarfp-shared)
set(DWARFP_TYPES SHARED)
set(dwarfp-target dwarfp-shared)
endif()
add_subdirectory(src/lib/libdwarf)
if ( BUILD_DWARFDUMP )
add_subdirectory(src/bin/dwarfdump)
endif()
if ( BUILD_DWARFEXAMPLE )
add_subdirectory(src/bin/dwarfexample)
endif()
if ( BUILD_DWARFGEN )
set(LIBDWARF_INCLUDE_DIR ../libdwarf)
add_subdirectory(src/lib/libdwarfp)
add_subdirectory(src/bin/dwarfgen)
endif()
if (DO_TESTING)
add_subdirectory(test)
endif()
message(STATUS "Install prefix ... ${CMAKE_INSTALL_PREFIX}" )
# installation of libdwarf[p] has to be in
# src/lib/libdwarf[p]/CMakeLists.txt
# so that it works properly for cmake before cmake 3.13.

25
COPYING Normal file
View File

@ -0,0 +1,25 @@
COPYING
August 6 2023
The source code in the libdwarf directory is LGPL version
2.1. See libdwarf/LIBDWARFCOPYRIGHT libdwarf/LGPL.txt A
few of files use the two-clause BSD copyright ("FreeBSD
License").
The source code in the dwarfdump directory is
generally GPL version 2. See dwarfdump/COPYING
dwarfdump/DWARFDUMPCOPYRIGHT dwarfdump/GPL.txt a
A few files in some directories may have the 3-clause
BSD copyright.
The source code in the dwarfgen directory generally has
the two-clause BSD copyright. See dwarfgen/COPYING
Various files begin with a copyright and a notice
saying the file is PUBLIC DOMAIN (sometimes spelled
public domain). Such files can be copied, modified,
and used by anyone for any purpose without attribution
or restriction. Example source code is marked as public
domain as we expect many people will use such as a starting
point in their code.

2
README.md Normal file
View File

@ -0,0 +1,2 @@
This is a minimal mirror of libdwarf from https://github.com/davea42/libdwarf-code. The purpose of this repository is
optimizing clone and configure time.

63
cmake/FindZSTD.cmake vendored Normal file
View File

@ -0,0 +1,63 @@
# Copyright (C) 1995-2019, Rene Brun and Fons Rademakers.
# All rights reserved.
#
# This is licensed as LGPL 2.1 by the authors.
# For the licensing terms see COPYING and
# libdwarf/LIBDWARFCOPYRIGHT
# or https://github.com/root-project/root/blob/master/LICENSE
# For the list of contributors in the project that
# created this cmake file see
# https://github.com/root-project/root/blob/master/README/CREDITS
#.rst:
# FindZSTD
# -----------
#
# Find the ZSTD library header and define variables.
#
# Imported Targets
# ^^^^^^^^^^^^^^^^
#
# This module defines :prop_tgt:`IMPORTED` target ``ZSTD::ZSTD``,
# if ZSTD has been found
#
# Result Variables
# ^^^^^^^^^^^^^^^^
#
# This module defines the following variables:
#
# ::
#
# ZSTD_FOUND - True if ZSTD is found.
# ZSTD_INCLUDE_DIRS - Where to find zstd.h
#
# Finds the Zstandard library. This module defines:
# - ZSTD_INCLUDE_DIR, directory containing headers
# - ZSTD_LIBRARIES, the Zstandard library path
# - ZSTD_FOUND, whether Zstandard has been found
# Find header files
find_path(ZSTD_INCLUDE_DIR zstd.h)
# Find a ZSTD version
if (ZSTD_INCLUDE_DIR AND EXISTS "${ZSTD_INCLUDE_DIR}/zstd.h")
file(READ "${ZSTD_INCLUDE_DIR}/zstd.h" CONTENT)
string(REGEX MATCH ".*define ZSTD_VERSION_MAJOR *([0-9]+).*define ZSTD_VERSION_MINOR *([0-9]+).*define ZSTD_VERSION_RELEASE *([0-9]+)" VERSION_REGEX "${CONTENT}")
set(ZSTD_VERSION_MAJOR ${CMAKE_MATCH_1})
set(ZSTD_VERSION_MINOR ${CMAKE_MATCH_2})
set(ZSTD_VERSION_RELEASE ${CMAKE_MATCH_3})
set(ZSTD_VERSION "${ZSTD_VERSION_MAJOR}.${ZSTD_VERSION_MINOR}.${ZSTD_VERSION_RELEASE}")
endif ()
# Find library
find_library(ZSTD_LIBRARIES NAMES zstd)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(ZSTD REQUIRED_VARS ZSTD_LIBRARIES ZSTD_INCLUDE_DIR ZSTD_VERSION VERSION_VAR ZSTD_VERSION)
if (ZSTD_FOUND)
if (NOT TARGET ZSTD::ZSTD)
add_library(ZSTD::ZSTD UNKNOWN IMPORTED)
set_target_properties(ZSTD::ZSTD PROPERTIES IMPORTED_LOCATION "${ZSTD_LIBRARIES}" INTERFACE_INCLUDE_DIRECTORIES "${ZSTD_INCLUDE_DIRS}")
endif ()
endif ()

120
cmake/config.h.cmake vendored Normal file
View File

@ -0,0 +1,120 @@
/* Define if building universal (internal helper macro) */
#cmakedefine AC_APPLE_UNIVERSAL_BUILD 1
/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
systems. This function is required for `alloca.c' support on those systems.
*/
#cmakedefine CRAY_STACKSEG_END 1
/* Define to 1 if you have the <dlfcn.h> header file. */
#cmakedefine HAVE_DLFCN_H 1
/* Define to 1 if you have the <libelf.h> header file. */
#cmakedefine HAVE_INTTYPES_H 1
/* Define to 1 if you have the <fcntl.h> header file. */
#cmakedefine HAVE_FCNTL_H 1
/* Define to 1 if you have the <malloc.h> header file. */
#cmakedefine HAVE_MALLOC_H 1
/* Define to 1 if you have the <memory.h> header file. */
#cmakedefine HAVE_MEMORY_H 1
/* Set to 1 if big endian . */
#cmakedefine WORDS_BIGENDIAN 1
/* Define to 1 if you have the <sgidefs.h> header file. */
#cmakedefine HAVE_SGIDEFS_H 1
/* Define to 1 if you have the <stdint.h> header file. */
#cmakedefine HAVE_STDINT_H 1
/* Define to 1 if you have the <strings.h> header file. */
#cmakedefine HAVE_STRINGS_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#cmakedefine HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#cmakedefine HAVE_SYS_TYPES_H 1
/* Define to HAVE_UINTPTR_T 1 if the system has the type `uintptr_t'. */
#cmakedefine HAVE_UINTPTR_T 1
/* Define to 1 if the system has the type `intptr_t'. */
#cmakedefine HAVE_INTPTR_T
/* Define to the uintptr_t to the type of an unsigned integer
type wide enough to hold a pointer
if the system does not define it. */
#cmakedefine uintptr_t ${uintptr_t}
#cmakedefine intptr_t ${intptr_t}
/* Define to 1 if you have the <unistd.h> header file. */
#cmakedefine HAVE_UNISTD_H 1
/* Set to 1 if __attribute__ ((unused)) is available. */
#cmakedefine HAVE_UNUSED_ATTRIBUTE 1
/* Set to 1 if zlib decompression is available. */
#cmakedefine HAVE_ZLIB 1
/* Define to 1 if you have the <zlib.h> header file. */
#cmakedefine HAVE_ZLIB_H 1
/* Define to the sub-directory where libtool stores uninstalled libraries. */
#cmakedefine LT_OBJDIR 1
/* Name of package */
#cmakedefine PACKAGE
/* Define to the address where bug reports for this package should be sent. */
#cmakedefine PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#cmakedefine PACKAGE_NAME libdwarf
/* Define to the full name and version of this package. */
#cmakedefine PACKAGE_STRING "${PACKAGE_NAME} ${VERSION}"
/* Define to the one symbol short name of this package. */
#cmakedefine PACKAGE_TARNAME
/* Define to the home page for this package. */
#cmakedefine PACKAGE_URL "${tarname}" )
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at runtime.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown */
#cmakedefine STACK_DIRECTION
/* Define to 1 if you have the ANSI C header files. */
#cmakedefine STDC_HEADERS 1
/* Define to the version of this package. */
#cmakedefine PACKAGE_VERSION ${PACKAGE_VERSION}
/* Version number of package */
#cmakedefine VERSION ${VERSION}
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#if defined AC_APPLE_UNIVERSAL_BUILD
# if defined __BIG_ENDIAN__
# cmakedefine WORDS_BIGENDIAN 1
# endif
#else
# ifndef WORDS_BIGENDIAN
# undef WORDS_BIGENDIAN
# endif
#endif
/* Define to `unsigned int' if <sys/types.h> does not define. */
#undef size_t

5
notes.txt Normal file
View File

@ -0,0 +1,5 @@
Making patch:
diff -Naru CMakeLists.txt CMakeListsUpdated.txt > patches/CMakeLists.patch
Applying:
patch < patches/CMakeLists.patch

239
patches/CMakeLists.patch Normal file
View File

@ -0,0 +1,239 @@
--- CMakeLists.txt 2023-11-13 10:57:07.278246800 -0500
+++ CMakeListsUpdated.txt 2023-11-13 11:11:35.551623300 -0500
@@ -11,7 +11,7 @@
macro(msvc_posix target)
if(MSVC AND ("${MSVC_VERSION}" LESS 1900))
# under VS 2015
- target_compile_definitions(${target} PUBLIC
+ target_compile_definitions(${target} PUBLIC
snprintf=_snprintf)
endif()
endmacro()
@@ -36,7 +36,7 @@
if (LIBDWARF_CRT STREQUAL "MT")
message(STATUS "Using MT runtime by compile flag replacement")
# taken from the CMake FAQ
- foreach(flag_v
+ foreach(flag_v
CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG
CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_MINSIZEREL
CMAKE_C_FLAGS_RELWITHDEBINFO
@@ -102,7 +102,7 @@
include(CheckSymbolExists)
### Version also appears in configure.ac
set(VERSION 0.9.0)
-set(PACKAGE_VERSION "\"${VERSION}\"")
+set(PACKAGE_VERSION "\"${VERSION}\"")
set(PACKAGE_NAME "libdwarf" )
set(PACKAGE_STRING "\"${PACKAGE_NAME} ${VERSION}\"")
string(REGEX REPLACE "[\"]" "" tarname1 "${PACKAGE_STRING}" )
@@ -114,83 +114,87 @@
set ( WORDS_BIGENDIAN 1 )
endif()
-check_include_file( "sys/types.h" HAVE_SYS_TYPES_H)
-check_include_file( "sys/stat.h" HAVE_SYS_STAT_H )
-check_include_file( "inttypes.h" HAVE_INTTYPES_H )
-check_include_file( "memory.h" HAVE_MEMORY_H )
-check_include_file( "strings.h" HAVE_STRINGS_H )
+# check_include_file( "sys/types.h" HAVE_SYS_TYPES_H) // Only used by dwarfgen
+# check_include_file( "sys/stat.h" HAVE_SYS_STAT_H ) // Only used by dwarfgen
+# check_include_file( "inttypes.h" HAVE_INTTYPES_H ) // Unused
+# check_include_file( "memory.h" HAVE_MEMORY_H ) // Unused
+# check_include_file( "strings.h" HAVE_STRINGS_H ) // Unused
check_include_file( "stdint.h" HAVE_STDINT_H )
check_include_file( "unistd.h" HAVE_UNISTD_H )
-check_include_file( "sgidefs.h" HAVE_SGIDEFS_H )
+# check_include_file( "sgidefs.h" HAVE_SGIDEFS_H ) // Unused
check_include_file( "stdafx.h" HAVE_STDAFX_H )
-check_include_file( "fcntl.h" HAVE_FCNTL_H )
+check_include_file( "fcntl.h" HAVE_FCNTL_H )
### cmake provides no way to guarantee uint32_t present.
### configure does guarantee that.
-if(HAVE_STDINT_H)
- check_c_source_compiles("
- #include <stdint.h>
- int main()
- {
- uintptr_t i; i = 12;
- return (int)i;
- }" HAVE_UINTPTR_T)
- check_c_source_compiles("
- #include <stdint.h>
- int main()
- {
- intptr_t i; i = 12;
- return (int)i;
- }" HAVE_INTPTR_T)
-endif()
-if (HAVE_UINTPTR_T)
- message(STATUS "HAVE_UINTPTR_T 1: uintptr_t defined in stdint.h... YES")
-else()
- message(STATUS "uintptr_t defined in stdint.h... NO")
- set(uintptr_t "unsigned long long int" )
- message(STATUS "Setting #define uintptr_t " ${uintptr_t})
-endif()
-if (uintptr_t)
- message(STATUS "uintptr_t value considered YES ")
-else()
- message(STATUS "uintptr_t value considered NO ")
-endif()
-if (HAVE_INTPTR_T)
- message(STATUS "HAVE_INTPTR_T 1: intptr_t defined in stdint.h... YES")
-else()
- message(STATUS "intptr_t defined in stdint.h... NO")
- set(uintptr_t "long long int" )
- message(STATUS "Setting #define intptr_t " ${intptr_t})
-endif()
-if (intptr_t)
- message(STATUS "intptr_t value considered YES ")
-else()
- message(STATUS "intptr_t value considered NO ")
-endif()
-
-
-check_c_source_compiles("
- static unsigned foo( unsigned x,
- __attribute__ ((unused)) int y)
- {
- unsigned x2 = x + 1;
- return x2;
- }
-
- int main(void) {
- unsigned y = 0;
- y = foo(12,y);
- return 0;
- }" HAVE_UNUSED_ATTRIBUTE)
-message(STATUS "Checking compiler supports __attribute__ unused... ${HAVE_UNUSED_ATTRIBUTE}")
-
-check_c_source_compiles([=[
- #include "stdafx.h"
- int main()
- {
- int p; p = 27;
- return 0;
- }]=] HAVE_STDAFX_H)
+# HAVE_UINTPTR_T: Unused
+# uintptr_t: Unused
+# HAVE_INTPTR_T: Unused
+# if(HAVE_STDINT_H)
+# check_c_source_compiles("
+# #include <stdint.h>
+# int main()
+# {
+# uintptr_t i; i = 12;
+# return (int)i;
+# }" HAVE_UINTPTR_T)
+# check_c_source_compiles("
+# #include <stdint.h>
+# int main()
+# {
+# intptr_t i; i = 12;
+# return (int)i;
+# }" HAVE_INTPTR_T)
+# endif()
+# if (HAVE_UINTPTR_T)
+# message(STATUS "HAVE_UINTPTR_T 1: uintptr_t defined in stdint.h... YES")
+# else()
+# message(STATUS "uintptr_t defined in stdint.h... NO")
+# set(uintptr_t "unsigned long long int" )
+# message(STATUS "Setting #define uintptr_t " ${uintptr_t})
+# endif()
+# if (uintptr_t)
+# message(STATUS "uintptr_t value considered YES ")
+# else()
+# message(STATUS "uintptr_t value considered NO ")
+# endif()
+# if (HAVE_INTPTR_T)
+# message(STATUS "HAVE_INTPTR_T 1: intptr_t defined in stdint.h... YES")
+# else()
+# message(STATUS "intptr_t defined in stdint.h... NO")
+# set(uintptr_t "long long int" )
+# message(STATUS "Setting #define intptr_t " ${intptr_t})
+# endif()
+# if (intptr_t)
+# message(STATUS "intptr_t value considered YES ")
+# else()
+# message(STATUS "intptr_t value considered NO ")
+# endif()
+
+# Unused
+# check_c_source_compiles("
+# static unsigned foo( unsigned x,
+# __attribute__ ((unused)) int y)
+# {
+# unsigned x2 = x + 1;
+# return x2;
+# }
+
+# int main(void) {
+# unsigned y = 0;
+# y = foo(12,y);
+# return 0;
+# }" HAVE_UNUSED_ATTRIBUTE)
+# message(STATUS "Checking compiler supports __attribute__ unused... ${HAVE_UNUSED_ATTRIBUTE}")
+
+# Redundant
+# check_c_source_compiles([=[
+# #include "stdafx.h"
+# int main()
+# {
+# int p; p = 27;
+# return 0;
+# }]=] HAVE_STDAFX_H)
#message(STATUS "Checking have windows stdafx.h... ${HAVE_STDAFX_H}")
set(CMAKE_REQUIRED_LIBRARIES z)
@@ -223,7 +227,7 @@
return 0;
} ]=] HAVE_ZLIB_H )
set(CMAKE_REQUIRED_LIBRARIES)
-if (HAVE_ZLIB)
+if (HAVE_ZLIB)
# For linking in libz
set(DW_FZLIB "z")
endif()
@@ -264,21 +268,21 @@
endif()
-
-check_c_source_compiles([=[
-#include <stdint.h>
-int main()
-{
- intptr_t p;
- p = 27;
- return 0;
-}]=] HAVE_INTPTR_T)
+# Unused
+# check_c_source_compiles([=[
+# #include <stdint.h>
+# int main()
+# {
+# intptr_t p;
+# p = 27;
+# return 0;
+# }]=] HAVE_INTPTR_T)
message(STATUS "CMAKE_SIZEOF_VOID_P ... " ${CMAKE_SIZEOF_VOID_P} )
-# libdwarf
+# libdwarf
option(BUILD_NON_SHARED "build archive library libdwarf[p].a" TRUE)
-option(BUILD_SHARED
+option(BUILD_SHARED
"build shared library libdwarf[p].so and use it" FALSE)
# This adds compiler option -Wall (gcc compiler warnings)
@@ -300,7 +304,7 @@
# unset(DW_LIBDWARF_STATIC)
#endif()
-option(BUILD_DWARFDUMP "Build dwarfdump (default is YES)" TRUE)
+option(BUILD_DWARFDUMP "Build dwarfdump (default is YES)" FALSE)
option(BUILD_DWARFGEN "Build dwarfgen (default is NO)" FALSE)
message(STATUS "Building dwarfgen ... ${BUILD_DWARFGEN}")

24
pull.sh Normal file
View File

@ -0,0 +1,24 @@
#!/bin/bash
echo "Removing files"
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
cd ..
echo "Copying files"
mkdir -p src/lib
mv -v libdwarf-code/CMakeLists.txt .
mv -v libdwarf-code/COPYING .
mv -v libdwarf-code/cmake .
mv -v libdwarf-code/src/lib/libdwarf src/lib
echo "Deleting cloned repo"
rm -rf libdwarf-code
echo "Cleaning up src/lib/libdwarf"
cd src/lib/libdwarf
rm -rfv ChangeLog* CHANGES CODINGSTYLE NEWS
cd ../../..
echo "Patching"
patch < patches/CMakeLists.patch
echo "Done"

167
src/lib/libdwarf/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,167 @@
set_source_group(SOURCES "Source Files" dwarf_abbrev.c
dwarf_alloc.c dwarf_crc.c dwarf_crc32.c dwarf_arange.c
dwarf_debug_sup.c
dwarf_debugaddr.c
dwarf_debuglink.c dwarf_die_deliv.c
dwarf_debugnames.c dwarf_dsc.c
dwarf_elf_load_headers.c
dwarf_elfread.c
dwarf_elf_rel_detector.c
dwarf_error.c
dwarf_fill_in_attr_form.c
dwarf_find_sigref.c dwarf_fission_to_cu.c
dwarf_form.c dwarf_form_class_names.c
dwarf_frame.c dwarf_frame2.c
dwarf_gdbindex.c dwarf_global.c
dwarf_gnu_index.c dwarf_groups.c
dwarf_harmless.c dwarf_generic_init.c dwarf_init_finish.c
dwarf_leb.c
dwarf_line.c dwarf_loc.c
dwarf_loclists.c
dwarf_locationop_read.c
dwarf_machoread.c dwarf_macro.c dwarf_macro5.c
dwarf_memcpy_swap.c
dwarf_names.c
dwarf_object_read_common.c dwarf_object_detector.c
dwarf_peread.c
dwarf_query.c dwarf_ranges.c
dwarf_rnglists.c
dwarf_safe_arithmetic.c
dwarf_safe_strcpy.c
dwarf_secname_ck.c
dwarf_setup_sections.c
dwarf_string.h dwarf_string.c
dwarf_stringsection.c
dwarf_tied.c
dwarf_str_offsets.c
dwarf_tsearchhash.c dwarf_util.c
dwarf_xu_index.c
dwarf_print_lines.c )
set_source_group(HEADERS "Header Files" dwarf.h dwarf_abbrev.h
dwarf_alloc.h dwarf_arange.h dwarf_base_types.h
dwarf_debugaddr.h
dwarf_debuglink.h dwarf_die_deliv.h
dwarf_debugnames.h dwarf_dsc.h
dwarf_elf_access.h dwarf_elf_defines.h dwarf_elfread.h
dwarf_elf_rel_detector.h
dwarf_elfstructs.h
dwarf_error.h dwarf_frame.h
dwarf_gdbindex.h dwarf_global.h dwarf_harmless.h
dwarf_gnu_index.h
dwarf_line.h dwarf_loc.h
dwarf_machoread.h dwarf_macro.h dwarf_macro5.h
dwarf_object_detector.h dwarf_opaque.h
dwarf_pe_descr.h dwarf_peread.h
dwarf_reading.h
dwarf_rnglists.h
dwarf_safe_arithmetic.h
dwarf_safe_strcpy.h
dwarf_tied_decls.h
dwarf_tsearch.h
dwarf_setup_sections.h
dwarf_str_offsets.h
dwarf_universal.h
dwarf_util.h
dwarf_xu_index.h libdwarf_private.h
dwarf_macho_loader.h
dwarf_memcpy_swap.h)
set_source_group(CONFIGURATION_FILES "Configuration Files"
${PROJECT_SOURCE_DIR}/cmake/config.h.cmake
${PROJECT_BINARY_DIR}/config.h)
# The -DPIC is so we find the right DW_API value in libdwarf.h
# with cmake with Linux.
# Dwarfgen requires all symbols in .so to be visible, so
# do not say hidden on libdwarf in that case.
if (BUILD_SHARED)
if(NOT BUILD_DWARFGEN)
set(CMAKE_C_VISIBILITY_PRESET hidden)
endif()
set(DEFS LIBDWARF_BUILD PIC)
else()
set(DEFS LIBDWARF_STATIC)
endif()
if (PIC_ALWAYS)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
list(APPEND DEFS PIC)
endif()
include(GNUInstallDirs)
list(LENGTH DWARF_TARGETS targetCount)
math(EXPR targetCount "${targetCount} - 1")
list(APPEND DWARF_LIBS ${LIBELF_LIBRARIES})
if (DW_FZLIB)
list(APPEND DWARF_LIBS z)
endif()
if (DW_FZSTD)
list(APPEND DWARF_LIBS zstd)
endif()
foreach(i RANGE ${targetCount})
list(GET DWARF_TARGETS ${i} target)
list(GET DWARF_TYPES ${i} type)
add_library(${target} ${type} ${SOURCES} ${HEADERS}
${GENNAMES_OUTPUT} ${CONFIGURATION_FILES})
add_library(libdwarf::${target} ALIAS ${target})
set_folder(${target} src/lib/libdwarf)
target_compile_options(${target} PRIVATE ${COMPILER_FLAGS}
${DW_FWALL})
msvc_posix(${target})
target_compile_definitions(${target} PUBLIC ${DEFS})
target_include_directories(
${target}
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
target_link_libraries(${target} PUBLIC ${DW_FZLIB} ${DW_FZSTD} )
set_target_properties(${target} PROPERTIES OUTPUT_NAME dwarf)
set(SUFFIX $<$<EQUAL:${CMAKE_SIZEOF_VOID_P},8>:64>)
set(LIBDIR lib${SUFFIX})
set(BINDIR bin${SUFFIX})
install(TARGETS ${target}
RUNTIME DESTINATION ${BINDIR}
LIBRARY DESTINATION ${LIBDIR}
ARCHIVE DESTINATION ${LIBDIR})
endforeach()
configure_file(libdwarf.pc.cmake libdwarf.pc @ONLY )
# The install has to be here, not in
# another CMakeLists.txt to make install work properly
# for cmake before cmake 3.13. This also works
# for newer cmake.
add_custom_target(dd DEPENDS ${DWARF_TARGETS} dwarfdump)
install(TARGETS ${DWARF_TARGETS} EXPORT libdwarfTargets
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
install(EXPORT libdwarfTargets
FILE libdwarf-targets.cmake
NAMESPACE libdwarf::
DESTINATION lib/cmake/libdwarf
)
install(
FILES cmake/libdwarf-config.cmake
DESTINATION lib/cmake/libdwarf
)
install(
FILES ${CMAKE_CURRENT_SOURCE_DIR}/libdwarf.h
DESTINATION include/libdwarf)
install(
FILES ${CMAKE_CURRENT_SOURCE_DIR}/dwarf.h
DESTINATION include/libdwarf)
install( FILES ${PROJECT_BINARY_DIR}/src/lib/libdwarf/libdwarf.pc
DESTINATION lib/pkgconfig
)

32
src/lib/libdwarf/COPYING vendored Normal file
View File

@ -0,0 +1,32 @@
The files:
libdwarf.h
libdwarfp.h
dwarf.h
and most of the .h and .c files in this implementation of
libdwarf and libdwarfp are copyrighted according to the file
LIBDWARFCOPYRIGHT (which mentions the LGPL version 2.1).
Each file mentions the LGPL.
The full text of the LGPL 2.1 is provided in LGPL.txt
Another copyright used here in some files is the
two-clause BSD license, (FreeBSD license).
The libdwarf documentation:
libdwarf.mm
is based on material submitted to the UI PLSIG as proposed
interfaces for dwarf, but completely rewritten.
Copyright ownership is therefore SGI (but see the
document for details) and it seems clear that the
intent was there was to be free
copying with no fees.
libdwarfp.mm
is documentation of a set of interfaces
(not part of the UI PLSIG proposals)
and the document was written from scratch at SGI.
Copyright ownership is therefore SGI (but see the
document for details) and it seems clear that
the intent was there was to be free
copying with no fees.
13 June 2021 updated to match the new file structure.

504
src/lib/libdwarf/LGPL.txt vendored Normal file
View File

@ -0,0 +1,504 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

42
src/lib/libdwarf/LIBDWARFCOPYRIGHT vendored Normal file
View File

@ -0,0 +1,42 @@
======
Update January 31, 2015:
The SGI postal address and oss.sgi.com address
in the original copyright are no longer correct.
So the final 8 lines of the original copyright
have been deleted from the current copyright.
====== original copyright example.
Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
This program is free software; you can redistribute it
and/or modify it under the terms of version 2.1 of the
GNU Lesser General Public License as published by the Free
Software Foundation.
This program is distributed in the hope that it would be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
Further, this software is distributed without any warranty
that it is free of the rightful claim of any third person
regarding infringement or the like. Any license provided
herein, whether implied or otherwise, applies only to this
software file. Patent licenses, if any, provided herein
do not apply to combinations of this program with other
software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write the
Free Software Foundation, Inc., 51 Franklin Street - Fifth
Floor, Boston MA 02110-1301, USA.
Contact information: Silicon Graphics, Inc., 1500 Crittenden
Lane, Mountain View, CA 94043, or:
http://www.sgi.com
For further information regarding this notice, see:
http://oss.sgi.com/projects/GenInfo/NoticeExplan

162
src/lib/libdwarf/Makefile.am vendored Normal file
View File

@ -0,0 +1,162 @@
###Copyright (C) 2018 Vincent Torri <vincent dot torri at gmail dot com
###This code is public domain and can be freely used or copied.
AUTOMAKE_OPTIONS=subdir-objects
MAINTAINERCLEANFILES = Makefile.in
### libdwarf
lib_LTLIBRARIES = libdwarf.la
libdwarf_la_SOURCES = \
dwarf.h \
dwarf_abbrev.c \
dwarf_abbrev.h \
dwarf_alloc.c \
dwarf_alloc.h \
dwarf_arange.c \
dwarf_arange.h \
dwarf_base_types.h \
dwarf_crc.c \
dwarf_crc32.c \
dwarf_debugaddr.c \
dwarf_debugaddr.h \
dwarf_debuglink.c \
dwarf_debuglink.h \
dwarf_die_deliv.c \
dwarf_die_deliv.h \
dwarf_debugnames.c \
dwarf_debugnames.h \
dwarf_debug_sup.c \
dwarf_dsc.c \
dwarf_dsc.h \
dwarf_elf_access.h \
dwarf_elf_defines.h \
dwarf_elf_load_headers.c \
dwarf_elfread.c \
dwarf_elfread.h \
dwarf_elf_rel_detector.c \
dwarf_elf_rel_detector.h \
dwarf_elfstructs.h \
dwarf_errmsg_list.h \
dwarf_error.c \
dwarf_error.h \
dwarf_fill_in_attr_form.c \
dwarf_find_sigref.c \
dwarf_fission_to_cu.c \
dwarf_form.c \
dwarf_form_class_names.c \
dwarf_frame.c \
dwarf_frame.h \
dwarf_frame2.c \
dwarf_gdbindex.c \
dwarf_gdbindex.h \
dwarf_generic_init.c \
dwarf_global.c \
dwarf_global.h \
dwarf_gnu_index.h \
dwarf_gnu_index.c \
dwarf_groups.c \
dwarf_harmless.c \
dwarf_harmless.h \
dwarf_init_finish.c \
dwarf_leb.c \
dwarf_line.c \
dwarf_line.h \
dwarf_line_table_reader_common.h \
dwarf_loc.c \
dwarf_loc.h \
dwarf_locationop_read.c \
dwarf_loclists.c \
dwarf_macho_loader.h \
dwarf_machoread.c \
dwarf_machoread.h \
dwarf_macro.c \
dwarf_macro.h \
dwarf_macro5.c \
dwarf_macro5.h \
dwarf_memcpy_swap.h \
dwarf_memcpy_swap.c \
dwarf_names.c \
dwarf_object_detector.c \
dwarf_object_detector.h \
dwarf_object_read_common.c \
dwarf_object_read_common.h \
dwarf_opaque.h \
dwarf_pe_descr.h \
dwarf_peread.c \
dwarf_peread.h \
dwarf_print_lines.c \
dwarf_query.c \
dwarf_safe_arithmetic.c \
dwarf_safe_arithmetic.h \
dwarf_safe_strcpy.c \
dwarf_safe_strcpy.h \
dwarf_secname_ck.c \
dwarf_secname_ck.h \
dwarf_setup_sections.c \
dwarf_setup_sections.h \
dwarf_ranges.c \
dwarf_rnglists.c \
dwarf_rnglists.h \
dwarf_reading.h \
dwarf_str_offsets.c \
dwarf_str_offsets.h \
dwarf_string.c \
dwarf_string.h \
dwarf_stringsection.c \
dwarf_tied.c \
dwarf_tied_decls.h \
dwarf_tsearchhash.c \
dwarf_tsearch.h \
dwarf_universal.h \
dwarf_util.c \
dwarf_util.h \
dwarf_xu_index.c \
dwarf_xu_index.h \
libdwarf.h \
libdwarf_private.h
libdwarf_la_CPPFLAGS = -DLIBDWARF_BUILD
libdwarf_la_CFLAGS = @ZLIB_CFLAGS@ @ZSTD_CFLAGS@ $(DWARF_CFLAGS_WARN)
libdwarf_la_LIBADD = @DWARF_LIBS@ @ZLIB_LIBS@ @ZSTD_LIBS@
libdwarf_la_LDFLAGS = -fPIC -no-undefined -version-info @version_info@ @release_info@
libdwarfpkgincludedir = $(pkgincludedir)-@VMAJ@
libdwarfpkginclude_DATA = \
$(top_srcdir)/src/lib/libdwarf/dwarf.h \
$(top_srcdir)/src/lib/libdwarf/libdwarf.h
EXTRA_DIST = \
COPYING \
LGPL.txt \
LIBDWARFCOPYRIGHT \
CHANGES \
ChangeLog \
ChangeLog2006 \
ChangeLog2007 \
ChangeLog2008 \
ChangeLog2009 \
ChangeLog2010 \
ChangeLog2011 \
ChangeLog2012 \
ChangeLog2013 \
ChangeLog2014 \
ChangeLog2015 \
ChangeLog2016 \
ChangeLog2017 \
ChangeLog2018 \
ChangeLog2019 \
ChangeLog2020 \
CODINGSTYLE \
dw-linetableheader.txt \
CMakeLists.txt \
libdwarf.pc.cmake \
cmake/libdwarf-config.cmake \
meson.build \
NEWS \
README \
CODINGSTYLE

238
src/lib/libdwarf/README vendored Normal file
View File

@ -0,0 +1,238 @@
June 22, 2021.
If ./configure is absent type
./autogen.sh
(you will need to have installed autoconf, automake
and libtool for autogen.sh to work)
To build libdwarf.a, type
./configure
make
To build libdwarf.so, type
./configure --enable-shared --disable-static
make
To build both, type
./configure --enable-shared
make
=======
April 16, 2017: Some people have had build problems, getting
errors like:
"dwarf_elf_access.c:238:21: warning: assignment makes
pointer from integer without a cast [enabled by default]
if ((ehdr_ident = elf_getident(elf, NULL)) == NULL) {"
That suggests that the libelf headers needed are missing.
On Ubuntu the command 'sudo apt-get install libelf-dev'
should solve this problem.
January 30, 2013: libdwarf.h is no longer in the distribution,
but libdwarf.h.in is identical to libdwarf.h. 'configure'
copies libdwarf.h.in to libdwarf.h and whether libelf.h defines
'struct _Elf' or 'struct Elf' configure attempts to create
libdwarf.h appropriately.
No real install target is provided here, so 'make install' does
not do much. One can copy either or both of libdwarf.a libdwarf.so
to somewhere fairly standard (but intended for software you build)
like '/usr/local/lib'. Or anywhere else you want to copy it.
To use dwarf or libdwarf, you may want to copy dwarf.h and
a generated libdwarf.h somewhere convenient
(possibly /usr/local/include),
and you may need to copy the libdwarf to a convenient spot
(/usr/local/lib is a traditional place for libraries one builds
oneself on Unix and Linux).
This copying is not needed to build dwarfdump.
Multi Threading, or using threads with libdwarf (Thread Safety):
Nothing in libdwarf does any locking. Every Dwarf_Debug
(such as returned by dwarf_init()) is fully independent
of all other Dwarf_Debug-s. However, calls to libdwarf can
change a Dwarf_Debug. So it is unsafe to have two different
threads accessing a single Dwarf_Debug simultaneously.
It is therefore sufficient to ensure than any one Dwarf_Debug
is only accessed from a single thread.
Warnings like
"warning: cast from pointer to integer of different size"
at compile time are to be expected in dwarf_frame.c and
dwarf_frame2.c. Do not be alarmed.
Warnings like
"warning: passing argument 1 of dbg->de_callback_func_c
discards const qualifier from pointer target type
[enabled by default]" at compile time are to be expected in
some pro*.c source files. Fixing the public prototype could
cause some producer-library user's code to fail to compile
so we live with the warnings.
When cross-compiling, gennames has to be built by the
native compiler. So try
make HOSTCC=cc gennames
as a first step before the normal make.
If your headers are not in the expected places,
use the make command line to add flags and include directories.
For example
./configure
PREINCS="-I /usr/local/share/include" POSTINCS="-I /home/x/include" make
PREINCS content is inserted before CFLAGS as make(1) is running.
POSTINCS content is added after the CFLAGS value.
To set LDFLAGS (which is used when building a .so and
in building gennames to create some source here),
do so at configure time, for example:
./configure LDFLAGS="-L /var/tmp"
Or use PRELIBS and/or POSTLIBS at 'make' time similar to the use
of PREINCS and POSTINCS.
Windows (February 2016): Those wishing to read DWARF2 or
later from Windows PE files (using Mingw) should take a look at
https://github.com/jrfonseca/drmingw/tree/master/src/mgwhelp
which shows simple LGPL code that implements the necessary object
reading interfaces for PE objects. dwarf_pe.cpp
fills out the Dwarf_Obj_Access_Methods
object interface and opens an object
(see dwarf_object_init())
using the PE object access making the full libdwarf API
available.
To enable dection of Windows pathnames as full paths
add --enable-windowspath. Doing this does mean things like
A:foo and \anything are treated as full paths (these are
unlikely path names on a POSIX system but are legal
POSIX partial paths).
Back to Linux/Unix:
It is possible to request a shared library (libdwarf.so) build with
--enable-shared
To turn off the build of the archive library (libdwarf.a) specify
--disable-nonshared
but in this case you must specify --enable-shared or nothing will
build!
TARGET DEPENDENCIES of .debug_frame:
dwarf.h
These should be revised if you have more than the defined
63 'normal' registers. It's not harmful to have these too large!
Too small will lead to errors reading .debug_frame and .eh_frame.
DW_FRAME_HIGHEST_NORMAL_REGISTER
DW_FRAME_LAST_REG_NUM
These you might revise, but can safely ignore if simply
using dwarfdump. If using the producer code you will want
to get these exactly right for your architecture.
DW_FRAME_RA_COL
DW_FRAME_STATIC_LINK
DW_FRAME_CFA_COL
libdwarf.h
The DW_FRAME_REG_INITIAL_VALUE #define should be set to
the value appropriate to your architecture. See libdwarf.h
for details.
If DW_REG_TABLE_SIZE is not set large enough attempts to
fill in the .debug_frame tables will get an error.
Should be at least as large as DW_FRAME_LAST_REG_NUM.
If it's too large nothing is harmed (but some extra space taken
at run time).
If your printf does not support C standard %llx etc,
(such as MSWindows with long long), configure
option --enable-nonstandardprintf
and defines like DW_PR_DUx etc in libdwarf.h
provide a way to configure for that relatively easily.
The .debug_frame is so very architecture dependent
and because the host (where libdwarf/dwarfdump are executed)
and target (the objects read) could be different.
It's currently not supported to have dwarfdump/libdwarf determine
the architecture on-the-fly and do-the-right-thing.
Just setting DW_FRAME_LAST_REG_NUM and DW_FRAME_HIGHEST_NORMAL_REGISTER
and DW_REG_TABLE_SIZE high enough will likely suffice for most
purposes and most compilers/architectures..
See comments in dwarf.h/libdwarf.h.
It's perfectly safe to ignore the above suggestions as long
as libdwarf does not get a DW_DLE_DF_REG_NUM_TOO_HIGH error.
(which would only happen on reading .debug_frame or .eh_frame data).
If you intend to use the libdwarf dwarf-producer code
for .debug_frame information
you must do a thorough analysys and revise dwarf.h
substantially to match the output target architecture.
In general, in the producer code, numbers are copied from and
to integers with memcpy(). In case of endianness problems,
constants set in dwarf_producer_init() can fix the problems.
If one wants to produce a *different-endian* output the best
solution is to change the integer memcpy calls to call thru a
new dbg-based function pointer and have it 'do the right thing'
to adjust endianness. Set the function pointer correctly in
dwarf_producer_init() and the rest of the code will just call
thru the function pointer. Tedious work to find and change the
memcpy calls to be dbg->de_memcpy(), but once done the code is
no longer endian dependent (right now there is no way to ask
for cross-endian: a new flag needed or ?).
leb128 numbers are endian-independent, so nothing need be
done with those for cross-endian support (the storage
of leb128 on disk is always little-endian).
The .ps files are postscript. So those who cannot deal with mm
format files but do have a postscript printer (or have
ghostscript) can print the documents.
This form was chosen before pdf format existed...
libdwarf2.1.pdf documents a way for a debugger to read dwarf information.
libdwarf2p.1.pdf documents a way for a compiler to generate dwarf information.
mips_extensions.ps documents the mips/sgi extensions to dwarf.
See the Makefile for the commands used to build pdf files
libdwarf.2.1.pdf and libdwarf1p.1.pdf.
pic is a picture processing tool (ATT command).
tbl is a table-processing tool.
(part of Documentor's Work Bench on ATT-like systems).
tbl and pic are available on linux.
psroff is a name for a troff-like processor, part of
Documentor's Work Bench on IRIX. Substitute a
troff-like or nroff-like processor (GNU groff works fine).
To use dwarf or libdwarf, you may want to install dwarf.h and
libdwarf.h somewhere convenient.
You will also need libelf (libelf.a and/or libelf.so) and
libelf.h installed. These are available from GNU repositories
and from the normal Linux repositories for Linux releases.
On Ubuntu Linux for example:
sudo apt-get install libelf-dev libelf1
Compiler warnings:
A few Warnings like:
dwarf_frame.c:715:29: warning: cast from pointer to integer of different size [-
Wpointer-to-int-cast]
dwarf_arange.c:113:13: warning: variable local_extension_size set but not used
[-Wunused-but-set-variable]
are considered normal.
As of January 2013 the code compiles with gcc without
problems with -Wall and -Wsign-compare
aside from the warnings hinted at above.
The following gcc/clang options
have not all been tried as of January 2013,
but will be as time permits.
-Wsystem-headers
-Wall -Wsign-compare
-Wno-format-y2k -W
-Wno-unused-parameter -Wstrict-prototypes
-Wmissing-prototypes -Wpointer-arith
-Wreturn-type -Wcast-qual -Wwrite-strings
-Wswitch -Wshadow -Wunused-parameter
-Wcast-align -Wchar-subscripts -Winline
-Wnested-externs -Wredundant-decls
-Wold-style-definition -Wno-pointer-sign

View File

@ -0,0 +1,3 @@
if (NOT TARGET libdwarf::libdwarf)
include(${CMAKE_CURRENT_LIST_DIR}/libdwarf-targets.cmake)
endif()

44
src/lib/libdwarf/dw-linetableheader.txt vendored Normal file
View File

@ -0,0 +1,44 @@
Copyright (C) 2021. David Anderson.
This simple file is hereby placed in the Public Domain.
This file documents the arrangement of line table headers
across all Standard versions of DWARF and some special
experimental line tables.
Line Table Header variations.
The experimental version has a distinct version
number of 0xf006 so cannot be confused with DWARF4 or 5.
DWversion
2,3,4,5 meaning the DWARF standards
x meaning gcc's experimental two level line table.
2345x 1. unit_length (4 or 12 bytes)
2345x 2. version (2 bytes, for x is 0xF006)
5 2.1 address_size
5 2.2 segment_selector_size
2345x 3. header_length (4 or 8 bytes)
2345x 4. minimum_instruction_length (1 byte)
45 x 5. maximum_operations_per_instruction (1 byte)
2345x 6. default_is_stmt (1 byte)
2345x 7. line_base (1 byte)
2345x 8. line_range (1 byte)
2345x 9. opcode_base (1 byte)
2345x 10. standard_opcode_lengths (array of length opcode_base - 1)
234 x 11. include directories (for x just one NUL byte(empty list))
234 x 12. file_names (for x just one NUL byte(empty list))
x 13. fake_extended_op (5 bytes: 00 FF FF 7F 7F)
x 14. logicals_table_offset (4 or 8 bytes)
x 15. actuals_table_offset (4 or 8 bytes)
x5 16. directory_entry_format_count (1 byte)
x5 17. directory_entry_format (sequence of unsigned LEB128 pairs)
x5 18. directories_count (unsigned LEB128)
x5 19. directories (sequence of directory entries)
x5 20. file_name_entry_format_count (1 byte)
x5 21. file_name_entry_format (sequence of unsigned LEB128 pairs)
x5 22. file_names_count (unsigned LEB128)
x5 23. file_names (sequence of directory entries)
x 24. subprogram_entry_format_count (1 byte)
x 25. subprogram_entry_format (sequence of unsigned LEB128 pairs)
x 26. subprograms_count (unsigned LEB128)
x 27. subprograms (sequence of directory entries)

1584
src/lib/libdwarf/dwarf.h vendored Normal file

File diff suppressed because it is too large Load Diff

451
src/lib/libdwarf/dwarf_abbrev.c vendored Normal file
View File

@ -0,0 +1,451 @@
/*
Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
Portions Copyright (C) 2009-2020 David Anderson. All Rights Reserved.
This program is free software; you can redistribute it
and/or modify it under the terms of version 2.1 of the
GNU Lesser General Public License as published by the Free
Software Foundation.
This program is distributed in the hope that it would be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
Further, this software is distributed without any warranty
that it is free of the rightful claim of any third person
regarding infringement or the like. Any license provided
herein, whether implied or otherwise, applies only to this
software file. Patent licenses, if any, provided herein
do not apply to combinations of this program with other
software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write the
Free Software Foundation, Inc., 51 Franklin Street - Fifth
Floor, Boston MA 02110-1301, USA.
*/
#include <config.h>
#include <stddef.h> /* NULL size_t */
#if defined(_WIN32) && defined(HAVE_STDAFX_H)
#include "stdafx.h"
#endif /* HAVE_STDAFX_H */
#include "dwarf.h"
#include "libdwarf.h"
#include "libdwarf_private.h"
#include "dwarf_base_types.h"
#include "dwarf_opaque.h"
#include "dwarf_abbrev.h"
#include "dwarf_alloc.h"
#include "dwarf_error.h"
#include "dwarf_util.h"
#include "dwarf_string.h"
/* For abbrevs we first count the entries.
Actually recording the attr/form/implicit const
values happens later. */
int
_dwarf_count_abbrev_entries(Dwarf_Debug dbg,
Dwarf_Byte_Ptr abbrev_ptr,
Dwarf_Byte_Ptr abbrev_section_end,
Dwarf_Unsigned *abbrev_count_out,
Dwarf_Unsigned *abbrev_implicit_const_count_out,
Dwarf_Byte_Ptr *abbrev_ptr_out,
Dwarf_Error *error)
{
Dwarf_Unsigned abbrev_count = 0;
Dwarf_Unsigned abbrev_implicit_const_count = 0;
Dwarf_Unsigned attr_name = 0;
Dwarf_Unsigned attr_form = 0;
/* The abbreviations table ends with an entry with a single
byte of zero for the abbreviation code.
Padding bytes following that zero are allowed, but
here we simply stop looking past that zero abbrev.
We also stop looking if the block/section ends,
though the DWARF2 and later standards do not specifically
allow section/block end to terminate an abbreviations
list. */
do {
DECODE_LEB128_UWORD_CK(abbrev_ptr, attr_name,
dbg,error,abbrev_section_end);
if (attr_name > DW_AT_hi_user) {
_dwarf_error(dbg, error,DW_DLE_ATTR_CORRUPT);
return DW_DLV_ERROR;
}
DECODE_LEB128_UWORD_CK(abbrev_ptr, attr_form,
dbg,error,abbrev_section_end);
/* If we have attr, form as 0,0, fall through to end */
if (!_dwarf_valid_form_we_know(attr_form,attr_name)) {
dwarfstring m;
dwarfstring_constructor(&m);
dwarfstring_append_printf_u(&m,
"DW_DLE_UNKNOWN_FORM: Abbrev form 0x%"
DW_PR_DUx,
attr_form);
if (attr_name) {
dwarfstring_append_printf_u(&m,
" DW_DLE_UNKNOWN_FORM: Abbrev form 0x%"
DW_PR_DUx,
attr_form);
dwarfstring_append_printf_u(&m,
" with attribute 0x%" DW_PR_DUx,
attr_name);
} else {
dwarfstring_append_printf_u(&m,
" DW_DLE_UNKNOWN_FORM(really unknown attr)"
": Abbrev form 0x%"
DW_PR_DUx,
attr_form);
dwarfstring_append_printf_u(&m,
" with attribute 0x%" DW_PR_DUx,
attr_name);
}
dwarfstring_append(&m," so abbreviations unusable. ");
_dwarf_error_string(dbg, error, DW_DLE_UNKNOWN_FORM,
dwarfstring_string(&m));
dwarfstring_destructor(&m);
return DW_DLV_ERROR;
}
if (attr_form == DW_FORM_implicit_const) {
/* The value is here, not in a DIE. We do
nothing with it, but must read past it. */
abbrev_implicit_const_count++;
SKIP_LEB128_CK(abbrev_ptr,
dbg,error,abbrev_section_end);
}
abbrev_count++;
} while ((abbrev_ptr < abbrev_section_end) &&
(attr_name != 0 || attr_form != 0));
/* We counted one too high,we included the 0,0 */
*abbrev_count_out = abbrev_count-1;
*abbrev_implicit_const_count_out = abbrev_implicit_const_count;
*abbrev_ptr_out = abbrev_ptr;
return DW_DLV_OK;
}
/* dwarf_get_abbrev() is used to print
a .debug_abbrev section without
knowing about the DIEs that use the abbrevs.
When we have a simple .o
there is at least a hope of iterating through
the abbrevs meaningfully without knowing
a CU context.
This often fails or gets incorrect info
because there is no guarantee the .debug_abbrev
section is free of garbage bytes.
In an object with multiple CU/TUs the
output is difficult/impossible to usefully interpret.
In a dwp (Package File) it is really impossible
to associate abbrevs with a CU.
*/
int
dwarf_get_abbrev(Dwarf_Debug dbg,
Dwarf_Unsigned offset,
Dwarf_Abbrev * returned_abbrev,
Dwarf_Unsigned * length,
Dwarf_Unsigned * abbr_count, Dwarf_Error * error)
{
Dwarf_Byte_Ptr abbrev_ptr = 0;
Dwarf_Byte_Ptr abbrev_ptr_out = 0;
Dwarf_Byte_Ptr abbrev_section_end = 0;
Dwarf_Abbrev ret_abbrev = 0;
Dwarf_Unsigned labbr_count = 0;
Dwarf_Unsigned utmp = 0;
Dwarf_Unsigned abbrev_implicit_const_count_out = 0;
int res = 0;
if (!dbg || dbg->de_magic != DBG_IS_VALID) {
_dwarf_error_string(NULL, error, DW_DLE_DBG_NULL,
"DW_DLE_DBG_NULL: "
"calling dwarf_get_abbrev "
"either null or it contains"
"a stale Dwarf_Debug pointer");
return DW_DLV_ERROR;
}
if (dbg->de_debug_abbrev.dss_data == 0) {
/* Loads abbrev section (and .debug_info as we do those
together). */
res = _dwarf_load_debug_info(dbg, error);
if (res != DW_DLV_OK) {
return res;
}
}
if (offset >= dbg->de_debug_abbrev.dss_size) {
return DW_DLV_NO_ENTRY;
}
ret_abbrev = (Dwarf_Abbrev) _dwarf_get_alloc(dbg,
DW_DLA_ABBREV, 1);
if (ret_abbrev == NULL) {
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
return DW_DLV_ERROR;
}
ret_abbrev->dab_dbg = dbg;
if (returned_abbrev == 0 || abbr_count == 0) {
dwarf_dealloc(dbg, ret_abbrev, DW_DLA_ABBREV);
_dwarf_error(dbg, error, DW_DLE_DWARF_ABBREV_NULL);
return DW_DLV_ERROR;
}
*abbr_count = 0;
if (length) {
*length = 1;
}
abbrev_ptr = dbg->de_debug_abbrev.dss_data + offset;
abbrev_section_end =
dbg->de_debug_abbrev.dss_data + dbg->de_debug_abbrev.dss_size;
res = _dwarf_leb128_uword_wrapper(dbg,&abbrev_ptr,
abbrev_section_end,&utmp,error);
if (res == DW_DLV_ERROR) {
dwarf_dealloc(dbg, ret_abbrev, DW_DLA_ABBREV);
return res;
}
ret_abbrev->dab_code = utmp;
if (ret_abbrev->dab_code == 0) {
*returned_abbrev = ret_abbrev;
*abbr_count = 0;
if (length) {
*length = 1;
}
return DW_DLV_OK;
}
res = _dwarf_leb128_uword_wrapper(dbg,&abbrev_ptr,
abbrev_section_end,&utmp,error);
if (res == DW_DLV_ERROR) {
dwarf_dealloc(dbg, ret_abbrev, DW_DLA_ABBREV);
return res;
}
if (utmp > DW_TAG_hi_user) {
dwarf_dealloc(dbg, ret_abbrev, DW_DLA_ABBREV);
return _dwarf_format_TAG_err_msg(dbg,
utmp,"DW_DLE_TAG_CORRUPT",
error);
}
ret_abbrev->dab_tag = utmp;
if (abbrev_ptr >= abbrev_section_end) {
dwarfstring m;
dwarf_dealloc(dbg, ret_abbrev, DW_DLA_ABBREV);
dwarfstring_constructor(&m);
dwarfstring_append_printf_u(&m,
"DW_DLE_ABBREV_DECODE_ERROR: Ran off the end "
"of the abbrev section reading tag, starting at"
" abbrev section offset 0x%x",offset);
_dwarf_error_string(dbg, error,
DW_DLE_ABBREV_DECODE_ERROR,
dwarfstring_string(&m));
dwarfstring_destructor(&m);
return DW_DLV_ERROR;
}
ret_abbrev->dab_has_child = *(abbrev_ptr++);
ret_abbrev->dab_abbrev_ptr = abbrev_ptr;
ret_abbrev->dab_next_ptr = abbrev_ptr;
ret_abbrev->dab_next_index = 0;
res = _dwarf_count_abbrev_entries(dbg,abbrev_ptr,
abbrev_section_end,&labbr_count,
&abbrev_implicit_const_count_out,
&abbrev_ptr_out,error);
if (res == DW_DLV_ERROR) {
dwarf_dealloc(dbg, ret_abbrev, DW_DLA_ABBREV);
return res;
}
abbrev_ptr = abbrev_ptr_out;
/* Global section offset. */
ret_abbrev->dab_goffset = offset;
ret_abbrev->dab_count = labbr_count;
ret_abbrev->dab_implicit_count = abbrev_implicit_const_count_out;
if (abbrev_ptr > abbrev_section_end) {
dwarf_dealloc(dbg, ret_abbrev, DW_DLA_ABBREV);
_dwarf_error_string(dbg, error,
DW_DLE_ABBREV_DECODE_ERROR,
"DW_DLE_ABBREV_DECODE_ERROR: Ran off the end "
"of the abbrev section reading abbrev_entries.");
_dwarf_error(dbg, error, DW_DLE_ABBREV_DECODE_ERROR);
return DW_DLV_ERROR;
}
if (length) {
*length = abbrev_ptr - dbg->de_debug_abbrev.dss_data - offset;
}
*returned_abbrev = ret_abbrev;
*abbr_count = labbr_count;
return DW_DLV_OK;
}
int
dwarf_get_abbrev_code(Dwarf_Abbrev abbrev,
Dwarf_Unsigned * returned_code,
Dwarf_Error * error)
{
if (abbrev == NULL) {
_dwarf_error(NULL, error, DW_DLE_DWARF_ABBREV_NULL);
return DW_DLV_ERROR;
}
*returned_code = abbrev->dab_code;
return DW_DLV_OK;
}
/* DWARF defines DW_TAG_hi_user as 0xffff so no tag should be
over 16 bits. */
int
dwarf_get_abbrev_tag(Dwarf_Abbrev abbrev,
Dwarf_Half * returned_tag, Dwarf_Error * error)
{
if (abbrev == NULL) {
_dwarf_error(NULL, error, DW_DLE_DWARF_ABBREV_NULL);
return DW_DLV_ERROR;
}
*returned_tag = (Dwarf_Half)abbrev->dab_tag;
return DW_DLV_OK;
}
int
dwarf_get_abbrev_children_flag(Dwarf_Abbrev abbrev,
Dwarf_Signed * returned_flag,
Dwarf_Error * error)
{
if (abbrev == NULL) {
_dwarf_error(NULL, error, DW_DLE_DWARF_ABBREV_NULL);
return DW_DLV_ERROR;
}
*returned_flag = abbrev->dab_has_child;
return DW_DLV_OK;
}
/* If filter_outliers is non-zero then
the routine will return DW_DLV_ERROR
if the leb reading generates a number that
is so large it cannot be correct.
If filter_outliers is 0 the uleb/sleb
values read are returned, even if
the values are unreasonable. This is
a useful option if one wishes to
have callers examine the return values
in greater detail than the checking here
provides.
*/
int
dwarf_get_abbrev_entry_b(Dwarf_Abbrev abbrev,
Dwarf_Unsigned indx,
Dwarf_Bool filter_outliers,
Dwarf_Unsigned * returned_attr_num,
Dwarf_Unsigned * returned_form,
Dwarf_Signed * returned_implicitconst,
Dwarf_Off * offset,
Dwarf_Error * error)
{
Dwarf_Byte_Ptr abbrev_ptr = 0;
Dwarf_Byte_Ptr abbrev_end = 0;
Dwarf_Byte_Ptr mark_abbrev_ptr = 0;
Dwarf_Unsigned attr = 0;
Dwarf_Unsigned form = 0;
Dwarf_Unsigned implicitconst = 0;
Dwarf_Debug dbg = 0;
Dwarf_Signed local_indx = (Dwarf_Signed)indx;
if (abbrev == NULL) {
_dwarf_error(NULL, error, DW_DLE_DWARF_ABBREV_NULL);
return DW_DLV_ERROR;
}
if (abbrev->dab_code == 0) {
return DW_DLV_NO_ENTRY;
}
dbg = abbrev->dab_dbg;
if (!dbg || dbg->de_magic != DBG_IS_VALID) {
_dwarf_error_string(NULL, error, DW_DLE_DBG_NULL,
"DW_DLE_DBG_NULL: "
"calling dwarf_get_abbrev_entry_b() "
"either null or it contains"
"a stale Dwarf_Debug pointer");
return DW_DLV_ERROR;
}
abbrev_ptr = abbrev->dab_abbrev_ptr;
abbrev_end = dbg->de_debug_abbrev.dss_data +
dbg->de_debug_abbrev.dss_size;
if ((Dwarf_Unsigned)local_indx >= abbrev->dab_next_index) {
/* We want a part not yet scanned ,
so we can start closer to the desired value. */
abbrev_ptr = abbrev->dab_next_ptr;
local_indx -= abbrev->dab_next_index;
}
for (attr = 1, form = 1;
local_indx >= 0 && abbrev_ptr < abbrev_end &&
(attr != 0 || form != 0);
local_indx--) {
mark_abbrev_ptr = abbrev_ptr;
DECODE_LEB128_UWORD_CK(abbrev_ptr, attr,dbg,
error,abbrev_end);
if (filter_outliers && attr > DW_AT_hi_user) {
_dwarf_error(dbg, error,DW_DLE_ATTR_CORRUPT);
return DW_DLV_ERROR;
}
DECODE_LEB128_UWORD_CK(abbrev_ptr, form,dbg,
error,abbrev_end);
if (filter_outliers &&
!_dwarf_valid_form_we_know(form,attr)) {
_dwarf_error(dbg, error, DW_DLE_UNKNOWN_FORM);
return DW_DLV_ERROR;
}
if (form == DW_FORM_implicit_const) {
/* The value is here, not in a DIE. */
DECODE_LEB128_SWORD_CK( abbrev_ptr, implicitconst,
dbg,error,abbrev_end);
} else {
implicitconst = 0;
}
}
if (abbrev_ptr >= abbrev_end) {
_dwarf_error_string(dbg, error,
DW_DLE_ABBREV_DECODE_ERROR,
"DW_DLE_ABBREV_DECODE_ERROR: Ran off the end "
"of the abbrev section reading abbrev entries..");
return DW_DLV_ERROR;
}
if (local_indx >= 0) {
return DW_DLV_NO_ENTRY;
}
if (returned_form != NULL) {
*returned_form = form;
}
if (offset != NULL) {
*offset = mark_abbrev_ptr - dbg->de_debug_abbrev.dss_data;
}
if (returned_attr_num) {
*returned_attr_num = attr;
}
if (returned_implicitconst) {
/* Callers should only examine implicit const value
if the form is DW_FORM_implicit_const. */
*returned_implicitconst = implicitconst;
}
abbrev->dab_next_ptr = abbrev_ptr;
abbrev->dab_next_index = (Dwarf_Unsigned)local_indx ;
return DW_DLV_OK;
}

82
src/lib/libdwarf/dwarf_abbrev.h vendored Normal file
View File

@ -0,0 +1,82 @@
/*
Copyright (C) 2000 Silicon Graphics, Inc. All Rights Reserved.
Portions Copyright (C) 2008-2023 David Anderson. All Rights Reserved.
This program is free software; you can redistribute it
and/or modify it under the terms of version 2.1 of the
GNU Lesser General Public License as published by the Free
Software Foundation.
This program is distributed in the hope that it would be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
Further, this software is distributed without any warranty
that it is free of the rightful claim of any third person
regarding infringement or the like. Any license provided
herein, whether implied or otherwise, applies only to this
software file. Patent licenses, if any, provided herein
do not apply to combinations of this program with other
software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write
the Free Software Foundation, Inc., 51 Franklin Street -
Fifth Floor, Boston MA 02110-1301, USA.
*/
#ifndef DWARF_ABBREV_H
#define DWARF_ABBREV_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* In a given CU, one of these is (eventually) set up
for every abbreviation we need to find (and for all
those earlier in the abbreviations for that CU).
So we don't want elements needlessly big.
*/
struct Dwarf_Abbrev_s {
/* No TAG should exceed DW_TAG_hi_user, 0xffff, but
we do allow a larger value here. */
Dwarf_Unsigned dab_tag;
/* Abbreviations are numbered (normally sequentially from
1 and so 16 bits is not enough! */
Dwarf_Unsigned dab_code;
Dwarf_Small dab_has_child;
/* dab_abbrev_ptr points to the abbreviations
themselves in memory, the list of attr/form
integers terminated by 0,0. */
Dwarf_Byte_Ptr dab_abbrev_ptr;
Dwarf_Debug dab_dbg;
/* Section global offset of the abbrev. */
Dwarf_Off dab_goffset;
/* dab_count is the number of attr/form uleb pairs */
Dwarf_Off dab_count;
/* The number of DW_FORM_implicit_const in the uleb pairs*/
Dwarf_Unsigned dab_implicit_count;
/* When the caller cycles through attr/form pairs
by index from zero this lets the code read just one
pair to work. */
Dwarf_Byte_Ptr dab_next_ptr;
Dwarf_Unsigned dab_next_index;
};
int _dwarf_count_abbrev_entries(Dwarf_Debug dbg,
Dwarf_Byte_Ptr abbrev_ptr,
Dwarf_Byte_Ptr abbrev_section_end,
Dwarf_Unsigned *abbrev_count_out,
Dwarf_Unsigned *abbrev_implicit_const_count_out,
Dwarf_Byte_Ptr *abbrev_ptr_out,
Dwarf_Error *error);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* DWARF_ABBREV_H */

1201
src/lib/libdwarf/dwarf_alloc.c vendored Normal file

File diff suppressed because it is too large Load Diff

58
src/lib/libdwarf/dwarf_alloc.h vendored Normal file
View File

@ -0,0 +1,58 @@
/*
Copyright (C) 2000,2005 Silicon Graphics, Inc. All Rights Reserved.
Portions Copyright (C) 2008-2023 David Anderson. All Rights Reserved.
This program is free software; you can redistribute it
and/or modify it under the terms of version 2.1 of the
GNU Lesser General Public License as published by the Free
Software Foundation.
This program is distributed in the hope that it would be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
Further, this software is distributed without any warranty
that it is free of the rightful claim of any third person
regarding infringement or the like. Any license provided
herein, whether implied or otherwise, applies only to this
software file. Patent licenses, if any, provided herein
do not apply to combinations of this program with other
software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write
the Free Software Foundation, Inc., 51 Franklin Street -
Fifth Floor, Boston MA 02110-1301, USA.
*/
#ifndef DWARF_ALLOC_H
#define DWARF_ALLOC_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* #define DWARF_SIMPLE_MALLOC 1 */
char * _dwarf_get_alloc(Dwarf_Debug, Dwarf_Small, Dwarf_Unsigned);
Dwarf_Debug _dwarf_get_debug(Dwarf_Unsigned filesize);
int _dwarf_free_all_of_one_debug(Dwarf_Debug);
struct Dwarf_Error_s * _dwarf_special_no_dbg_error_malloc(void);
void _dwarf_error_destructor(void *);
/* ALLOC_AREA_INDEX_TABLE_MAX is the size of the
struct ial_s index_into_allocated array in dwarf_alloc.c
*/
#define ALLOC_AREA_INDEX_TABLE_MAX 66
void _dwarf_add_to_static_err_list(Dwarf_Error err);
void _dwarf_flush_static_error_list(void);
void _dwarf_free_static_errlist(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* DWARF_ALLOC_H */

738
src/lib/libdwarf/dwarf_arange.c vendored Normal file
View File

@ -0,0 +1,738 @@
/*
Copyright (C) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
Portions Copyright (C) 2007-2020 David Anderson. All Rights Reserved.
Portions Copyright 2012 SN Systems Ltd. All rights reserved.
This program is free software; you can redistribute it
and/or modify it under the terms of version 2.1 of the
GNU Lesser General Public License as published by the Free
Software Foundation.
This program is distributed in the hope that it would be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
Further, this software is distributed without any warranty
that it is free of the rightful claim of any third person
regarding infringement or the like. Any license provided
herein, whether implied or otherwise, applies only to this
software file. Patent licenses, if any, provided herein
do not apply to combinations of this program with other
software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write the
Free Software Foundation, Inc., 51 Franklin Street - Fifth
Floor, Boston MA 02110-1301, USA.
*/
#include <config.h>
#include <stddef.h> /* NULL size_t */
#include <stdio.h> /* debug printf */
#if defined(_WIN32) && defined(HAVE_STDAFX_H)
#include "stdafx.h"
#endif /* HAVE_STDAFX_H */
#include "dwarf.h"
#include "libdwarf.h"
#include "libdwarf_private.h"
#include "dwarf_base_types.h"
#include "dwarf_opaque.h"
#include "dwarf_alloc.h"
#include "dwarf_error.h"
#include "dwarf_util.h"
#include "dwarf_arange.h"
#include "dwarf_global.h" /* for _dwarf_fixup_* */
#include "dwarf_string.h"
static void
free_aranges_chain(Dwarf_Debug dbg, Dwarf_Chain head)
{
Dwarf_Chain cur = head;
Dwarf_Chain next = 0;
if (!head) {
return;
}
next = head->ch_next;
for ( ;cur; cur = next) {
void *item = cur->ch_item;
int type = cur->ch_itemtype;
next = cur->ch_next;
if (item && type) {
dwarf_dealloc(dbg,item,type);
cur->ch_item = 0;
dwarf_dealloc(dbg,cur,DW_DLA_CHAIN);
}
}
}
/* Common code for two user-visible routines to share.
Errors here result in memory leaks, but errors here
are serious (making aranges unusable) so we assume
callers will not repeat the error often or mind the leaks.
*/
static int
_dwarf_get_aranges_list(Dwarf_Debug dbg,
Dwarf_Chain * chain_out,
Dwarf_Signed * chain_count_out,
Dwarf_Error * error)
{
/* Sweeps through the arange. */
Dwarf_Small *arange_ptr = 0;
Dwarf_Small *arange_ptr_start = 0;
/* Start of arange header.
Used for rounding offset of arange_ptr
to twice the tuple size. Libdwarf requirement. */
Dwarf_Small *header_ptr = 0;
/* Version of .debug_aranges header. */
Dwarf_Unsigned version = 0;
/* Offset of current set of aranges into .debug_info. */
Dwarf_Off info_offset = 0;
/* Size in bytes of addresses in target. */
Dwarf_Small address_size = 0;
/* Size in bytes of segment offsets in target. */
Dwarf_Small segment_sel_size = 0;
/* Count of total number of aranges. */
Dwarf_Signed arange_count = 0;
Dwarf_Arange arange = 0;
Dwarf_Unsigned section_size = 0;
Dwarf_Byte_Ptr arange_end_section = 0;
/* Used to chain Dwarf_Aranges structs. */
Dwarf_Chain curr_chain = NULL;
Dwarf_Chain head_chain = NULL;
Dwarf_Chain *plast = &head_chain;
if (!dbg->de_debug_aranges.dss_size) {
return DW_DLV_NO_ENTRY;
}
arange_ptr = dbg->de_debug_aranges.dss_data;
arange_ptr_start = arange_ptr;
section_size = dbg->de_debug_aranges.dss_size;
arange_end_section = arange_ptr + section_size;
do {
/* Length of current set of aranges.
This is local length, which begins just
after the length field itself. */
Dwarf_Unsigned area_length = 0;
Dwarf_Unsigned remainder = 0;
Dwarf_Unsigned range_entry_size = 0;
int local_length_size;
int local_extension_size = 0;
Dwarf_Small *end_this_arange = 0;
int res = 0;
header_ptr = arange_ptr;
if (header_ptr >= arange_end_section) {
free_aranges_chain(dbg,head_chain);
_dwarf_error(dbg, error,DW_DLE_ARANGES_HEADER_ERROR);
return DW_DLV_ERROR;
}
res = _dwarf_read_area_length_ck_wrapper(dbg,&area_length,
&arange_ptr,&local_length_size,&local_extension_size,
section_size,arange_end_section,error);
if (res != DW_DLV_OK) {
free_aranges_chain(dbg,head_chain);
return res;
}
/* arange_ptr has been incremented appropriately past
the length field by READ_AREA_LENGTH. */
if (area_length > dbg->de_debug_aranges.dss_size ||
(area_length +local_length_size+local_extension_size)
> dbg->de_debug_aranges.dss_size ) {
free_aranges_chain(dbg,head_chain);
_dwarf_error(dbg, error,DW_DLE_ARANGES_HEADER_ERROR);
return DW_DLV_ERROR;
}
if ((area_length + local_length_size + local_extension_size) >
dbg->de_debug_aranges.dss_size) {
free_aranges_chain(dbg,head_chain);
_dwarf_error(dbg, error, DW_DLE_ARANGES_HEADER_ERROR);
return DW_DLV_ERROR;
}
end_this_arange = arange_ptr + area_length;
if (end_this_arange > arange_end_section) {
free_aranges_chain(dbg,head_chain);
_dwarf_error(dbg, error,DW_DLE_ARANGES_HEADER_ERROR);
return DW_DLV_ERROR;
}
if (!area_length) {
/* We read 4 bytes of zero, so area-length zero.
Keep scanning. First seen Nov 27, 2018
in GNU-cc in windows dll. */
continue;
}
res = _dwarf_read_unaligned_ck_wrapper(dbg,&version,
arange_ptr,DWARF_HALF_SIZE,end_this_arange,error);
if (res != DW_DLV_OK) {
free_aranges_chain(dbg,head_chain);
return res;
}
arange_ptr += DWARF_HALF_SIZE;
if (arange_ptr >= end_this_arange) {
free_aranges_chain(dbg,head_chain);
_dwarf_error(dbg, error, DW_DLE_ARANGES_HEADER_ERROR);
return DW_DLV_ERROR;
}
if (version != DW_ARANGES_VERSION2) {
free_aranges_chain(dbg,head_chain);
_dwarf_error(dbg, error, DW_DLE_VERSION_STAMP_ERROR);
return DW_DLV_ERROR;
}
res = _dwarf_read_unaligned_ck_wrapper(dbg,&info_offset,
arange_ptr,local_length_size,end_this_arange,error);
if (res != DW_DLV_OK) {
free_aranges_chain(dbg,head_chain);
return res;
}
arange_ptr += local_length_size;
if (arange_ptr >= end_this_arange) {
free_aranges_chain(dbg,head_chain);
_dwarf_error(dbg, error, DW_DLE_ARANGES_HEADER_ERROR);
return DW_DLV_ERROR;
}
/* This applies to debug_info only, not to debug_types. */
if (info_offset >= dbg->de_debug_info.dss_size) {
FIX_UP_OFFSET_IRIX_BUG(dbg, info_offset,
"arange info offset.a");
if (info_offset >= dbg->de_debug_info.dss_size) {
free_aranges_chain(dbg,head_chain);
_dwarf_error(dbg, error, DW_DLE_ARANGE_OFFSET_BAD);
return DW_DLV_ERROR;
}
}
address_size = *(Dwarf_Small *) arange_ptr;
if (address_size > sizeof(Dwarf_Addr)) {
free_aranges_chain(dbg,head_chain);
_dwarf_error(dbg, error, DW_DLE_ADDRESS_SIZE_ERROR);
return DW_DLV_ERROR;
}
if (address_size == 0) {
free_aranges_chain(dbg,head_chain);
_dwarf_error(dbg, error, DW_DLE_ADDRESS_SIZE_ZERO);
return DW_DLV_ERROR;
}
/* It is not an error if the sizes differ.
Unusual, but not an error. */
arange_ptr = arange_ptr + sizeof(Dwarf_Small);
/* The following deref means we better
check the pointer for off-end. */
if (arange_ptr >= end_this_arange) {
free_aranges_chain(dbg,head_chain);
_dwarf_error(dbg, error, DW_DLE_ARANGE_OFFSET_BAD);
return DW_DLV_ERROR;
}
/* Even DWARF2 had a segment_sel_size field here,
meaning
size in bytes of a segment selector/descriptor
on the target system.
In reality it is unlikely any non-zero
value will work sensibly for the user. */
segment_sel_size = *(Dwarf_Small *) arange_ptr;
if (segment_sel_size > 0) {
free_aranges_chain(dbg,head_chain);
_dwarf_error_string(dbg, error,
DW_DLE_SEGMENT_SIZE_BAD,
"DW_DLE_SEGMENT_SIZE_BAD: "
"segment selector size > 0 is not supported");
return DW_DLV_ERROR;
}
arange_ptr = arange_ptr + sizeof(Dwarf_Small);
/* Code below will check for == end_this_arange
as appropriate. */
if (arange_ptr > end_this_arange) {
free_aranges_chain(dbg,head_chain);
_dwarf_error(dbg, error, DW_DLE_ARANGE_OFFSET_BAD);
return DW_DLV_ERROR;
}
range_entry_size = 2*address_size + segment_sel_size;
/* Round arange_ptr offset to next multiple of
address_size. */
remainder = (Dwarf_Unsigned) ((arange_ptr - header_ptr) %
(range_entry_size));
if (remainder != 0) {
arange_ptr = arange_ptr + (2 * address_size) - remainder;
}
do {
Dwarf_Addr range_address = 0;
Dwarf_Unsigned segment_selector = 0;
Dwarf_Unsigned range_length = 0;
/* For segmented address spaces, the first field to
read is a segment selector (new in DWARF4).
The version number DID NOT CHANGE from 2, which
is quite surprising.
Also surprising since the segment_sel_size
was always there
in the table header! */
/* We want to test cu_version here
and segment_sel_size, but
currently with no way segment_sel_size
can be other than zero.
We just hope no one using
segment_selectors, really. FIXME */
res = _dwarf_read_unaligned_ck_wrapper(dbg,&range_address,
arange_ptr,address_size,end_this_arange,error);
if (res != DW_DLV_OK) {
free_aranges_chain(dbg,head_chain);
return res;
}
arange_ptr += address_size;
res = _dwarf_read_unaligned_ck_wrapper(dbg,&range_length,
arange_ptr,address_size,end_this_arange,error);
if (res != DW_DLV_OK) {
free_aranges_chain(dbg,head_chain);
return res;
}
arange_ptr += address_size;
{
/* We used to suppress all-zero entries, but
now we return all aranges entries so we show
the entire content. March 31, 2010. */
arange = (Dwarf_Arange)
_dwarf_get_alloc(dbg, DW_DLA_ARANGE, 1);
if (arange == NULL) {
free_aranges_chain(dbg,head_chain);
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
return DW_DLV_ERROR;
}
arange->ar_segment_selector = segment_selector;
arange->ar_segment_selector_size =
segment_sel_size;
arange->ar_address = range_address;
arange->ar_length = range_length;
arange->ar_info_offset = info_offset;
arange->ar_dbg = dbg;
arange_count++;
curr_chain = (Dwarf_Chain)
_dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
if (curr_chain == NULL) {
dwarf_dealloc(dbg,arange,DW_DLA_ARANGE);
free_aranges_chain(dbg,head_chain);
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
return DW_DLV_ERROR;
}
curr_chain->ch_item = arange;
curr_chain->ch_itemtype = DW_DLA_ARANGE;
(*plast) = curr_chain;
plast = &(curr_chain->ch_next);
}
/* The current set of ranges is terminated by
range_address 0 and range_length 0, but that
does not necessarily terminate the ranges for this CU!
There can be multiple sets in that DWARF
does not explicitly forbid multiple sets.
DWARF2,3,4 section 7.20
We stop short to avoid overrun of the
end of the CU. */
} while (end_this_arange >= (arange_ptr + range_entry_size));
/* A compiler could emit some padding bytes here. dwarf2/3
(dwarf4 sec 7.20) does not clearly make extra padding
bytes illegal. */
if (end_this_arange < arange_ptr) {
Dwarf_Unsigned pad_count = arange_ptr - end_this_arange;
Dwarf_Unsigned offset = arange_ptr - arange_ptr_start;
dwarfstring aramsg;
dwarfstring_constructor(&aramsg);
/* Safe. Length strictly limited. */
dwarfstring_append_printf_u(&aramsg,
"DW_DLE_ARANGE_LENGTH_BAD."
" 0x%" DW_PR_XZEROS DW_PR_DUx,
pad_count);
dwarfstring_append_printf_u(&aramsg,
" pad bytes at offset 0x%" DW_PR_XZEROS DW_PR_DUx
" in .debug_aranges",
offset);
dwarf_insert_harmless_error(dbg,
dwarfstring_string(&aramsg));
dwarfstring_destructor(&aramsg);
}
/* For most compilers, arange_ptr == end_this_arange at
this point. But not if there were padding bytes */
arange_ptr = end_this_arange;
} while (arange_ptr < arange_end_section);
if (arange_ptr != arange_end_section) {
free_aranges_chain(dbg,head_chain);
_dwarf_error(dbg, error, DW_DLE_ARANGE_DECODE_ERROR);
return DW_DLV_ERROR;
}
*chain_out = head_chain;
*chain_count_out = arange_count;
return DW_DLV_OK;
}
/*
This function returns the count of the number of
aranges in the .debug_aranges section. It sets
aranges to point to a block of Dwarf_Arange's
describing the arange's. It returns DW_DLV_ERROR
on error.
Must be identical in most aspects to
dwarf_get_aranges_addr_offsets!
*/
int
dwarf_get_aranges(Dwarf_Debug dbg,
Dwarf_Arange ** aranges,
Dwarf_Signed * returned_count, Dwarf_Error * error)
{
/* Count of total number of aranges. */
Dwarf_Signed arange_count = 0;
Dwarf_Arange *arange_block = 0;
/* Used to chain Dwarf_Aranges structs. */
Dwarf_Chain curr_chain = NULL;
Dwarf_Chain head_chain = NULL;
Dwarf_Signed i = 0;
int res = DW_DLV_ERROR;
/* ***** BEGIN CODE ***** */
if (dbg == NULL) {
_dwarf_error(NULL, error, DW_DLE_DBG_NULL);
return DW_DLV_ERROR;
}
res = _dwarf_load_section(dbg, &dbg->de_debug_aranges, error);
if (res != DW_DLV_OK) {
return res;
}
/* aranges points in to info, so if info needs expanding
we have to load it. */
res = _dwarf_load_debug_info(dbg, error);
if (res != DW_DLV_OK) {
return res;
}
res = _dwarf_get_aranges_list(dbg,&head_chain,
&arange_count,error);
if (res != DW_DLV_OK) {
free_aranges_chain(dbg,head_chain);
return res;
}
arange_block = (Dwarf_Arange *)
_dwarf_get_alloc(dbg, DW_DLA_LIST, arange_count);
if (arange_block == NULL) {
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
free_aranges_chain(dbg,head_chain);
return DW_DLV_ERROR;
}
/* See also free_aranges_chain() above */
curr_chain = head_chain;
for (i = 0; i < arange_count; i++) {
Dwarf_Chain prev = 0;
/* Copies pointers. No dealloc of ch_item, */
*(arange_block + i) = curr_chain->ch_item;
curr_chain->ch_item = 0;
prev = curr_chain;
curr_chain = curr_chain->ch_next;
dwarf_dealloc(dbg, prev, DW_DLA_CHAIN);
}
*aranges = arange_block;
*returned_count = (arange_count);
return DW_DLV_OK;
}
#if 0
/*
This function returns DW_DLV_OK if it succeeds
and DW_DLV_ERR or DW_DLV_OK otherwise.
count is set to the number of addresses in the
.debug_aranges section.
For each address, the corresponding element in
an array is set to the address itself(aranges) and
the section offset (offsets).
Must be identical in most aspects to
dwarf_get_aranges!
*/
int
_dwarf_get_aranges_addr_offsets(Dwarf_Debug dbg,
Dwarf_Addr ** addrs,
Dwarf_Off ** offsets,
Dwarf_Signed * count,
Dwarf_Error * error)
{
Dwarf_Signed i = 0;
/* Used to chain Dwarf_Aranges structs. */
Dwarf_Chain curr_chain = NULL;
Dwarf_Chain head_chain = NULL;
Dwarf_Signed arange_count = 0;
Dwarf_Addr *arange_addrs = 0;
Dwarf_Off *arange_offsets = 0;
int res = DW_DLV_ERROR;
/* ***** BEGIN CODE ***** */
if (error != NULL)
*error = NULL;
if (dbg == NULL) {
_dwarf_error(NULL, error, DW_DLE_DBG_NULL);
return DW_DLV_ERROR;
}
res = _dwarf_load_section(dbg, &dbg->de_debug_aranges,error);
if (res != DW_DLV_OK) {
return res;
}
/* aranges points in to info, so if info needs expanding
we have to load it. */
res = _dwarf_load_debug_info(dbg, error);
if (res != DW_DLV_OK) {
return res;
}
res = _dwarf_get_aranges_list(dbg,&head_chain,
&arange_count,error);
if (res != DW_DLV_OK) {
return res;
}
arange_addrs = (Dwarf_Addr *)
_dwarf_get_alloc(dbg, DW_DLA_ADDR, arange_count);
if (arange_addrs == NULL) {
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
return DW_DLV_ERROR;
}
arange_offsets = (Dwarf_Off *)
_dwarf_get_alloc(dbg, DW_DLA_ADDR, arange_count);
if (arange_offsets == NULL) {
free_aranges_chain(dbg,head_chain);
dwarf_dealloc(dbg,arange_addrs,DW_DLA_ADDR);
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
return DW_DLV_ERROR;
}
curr_chain = head_chain;
for (i = 0; i < arange_count; i++) {
Dwarf_Arange ar = curr_chain->ch_item;
int itemtype = curr_chain->ch_itemtype;
Dwarf_Chain prev = 0;
if (!ar) {
arange_addrs[i] = 0;
arange_offsets[i] = 0;
continue;
}
curr_chain->ch_item = 0;
arange_addrs[i] = ar->ar_address;
arange_offsets[i] = ar->ar_info_offset;
prev = curr_chain;
curr_chain = curr_chain->ch_next;
if (itemtype) {
dwarf_dealloc(dbg, ar, itemtype);
}
dwarf_dealloc(dbg, prev, DW_DLA_CHAIN);
}
*count = arange_count;
*offsets = arange_offsets;
*addrs = arange_addrs;
return DW_DLV_OK;
}
#endif /* 0 */
/*
This function takes a pointer to a block
of Dwarf_Arange's, and a count of the
length of the block. It checks if the
given address is within the range of an
address range in the block. If yes, it
returns the appropriate Dwarf_Arange.
If no, it returns DW_DLV_NO_ENTRY;
On error it returns DW_DLV_ERROR.
*/
int
dwarf_get_arange(Dwarf_Arange * aranges,
Dwarf_Unsigned arange_count,
Dwarf_Addr address,
Dwarf_Arange * returned_arange, Dwarf_Error * error)
{
Dwarf_Arange curr_arange = 0;
Dwarf_Unsigned i = 0;
if (!aranges) {
_dwarf_error(NULL, error, DW_DLE_ARANGES_NULL);
return DW_DLV_ERROR;
}
for (i = 0; i < arange_count; i++) {
curr_arange = *(aranges + i);
if (address >= curr_arange->ar_address &&
address <
curr_arange->ar_address + curr_arange->ar_length) {
*returned_arange = curr_arange;
return DW_DLV_OK;
}
}
return DW_DLV_NO_ENTRY;
}
/*
This function takes an Dwarf_Arange,
and returns the offset of the first
die in the compilation-unit that the
arange belongs to. Returns DW_DLV_ERROR
on error.
For an arange, the cu_die can only be from debug_info,
not debug_types, it seems.
*/
int
dwarf_get_cu_die_offset(Dwarf_Arange arange,
Dwarf_Off * returned_offset,
Dwarf_Error * error)
{
Dwarf_Debug dbg = 0;
Dwarf_Off offset = 0;
Dwarf_Unsigned headerlen = 0;
int cres = 0;
if (arange == NULL) {
_dwarf_error(NULL, error, DW_DLE_ARANGE_NULL);
return DW_DLV_ERROR;
}
dbg = arange->ar_dbg;
offset = arange->ar_info_offset;
/* This applies to debug_info only, not to debug_types. */
if (!dbg->de_debug_info.dss_data) {
int res = _dwarf_load_debug_info(dbg, error);
if (res != DW_DLV_OK) {
return res;
}
}
cres = _dwarf_length_of_cu_header(dbg, offset,
true, &headerlen,error);
if (cres != DW_DLV_OK) {
return cres;
}
*returned_offset = headerlen + offset;
return DW_DLV_OK;
}
/* This function takes an Dwarf_Arange,
and returns the offset of the CU header
in the compilation-unit that the
arange belongs to. Returns DW_DLV_ERROR
on error.
Ensures .debug_info loaded so
the cu_offset is meaningful. */
int
dwarf_get_arange_cu_header_offset(Dwarf_Arange arange,
Dwarf_Off * cu_header_offset_returned,
Dwarf_Error * error)
{
Dwarf_Debug dbg = 0;
if (arange == NULL) {
_dwarf_error(NULL, error, DW_DLE_ARANGE_NULL);
return DW_DLV_ERROR;
}
dbg = arange->ar_dbg;
/* This applies to debug_info only, not to debug_types. */
/* Like dwarf_get_arange_info_b() this ensures debug_info loaded:
the cu_header is in debug_info and will be used else
we would not call dwarf_get_arange_cu_header_offset. */
if (!dbg->de_debug_info.dss_data) {
int res = _dwarf_load_debug_info(dbg, error);
if (res != DW_DLV_OK) {
return res;
}
}
*cu_header_offset_returned = arange->ar_info_offset;
return DW_DLV_OK;
}
/*
This function takes a Dwarf_Arange, and returns
true if it is not NULL. It also stores the start
address of the range in *start, the length of the
range in *length, and the offset of the first die
in the compilation-unit in *cu_die_offset. It
returns false on error.
If cu_die_offset returned ensures .debug_info loaded so
the cu_die_offset is meaningful.
New for DWARF4, entries may have segment information.
*segment is only meaningful
if *segment_entry_size is non-zero.
But segment_selectors are not fully defined so
a non-zero segment_entry_size is not actually
usable. */
int
dwarf_get_arange_info_b(Dwarf_Arange arange,
Dwarf_Unsigned* segment,
Dwarf_Unsigned* segment_entry_size,
Dwarf_Addr * start,
Dwarf_Unsigned* length,
Dwarf_Off * cu_die_offset,
Dwarf_Error * error)
{
if (arange == NULL) {
_dwarf_error(NULL, error, DW_DLE_ARANGE_NULL);
return DW_DLV_ERROR;
}
if (segment != NULL) {
*segment = arange->ar_segment_selector;
}
if (segment_entry_size != NULL) {
*segment_entry_size = arange->ar_segment_selector_size;
}
if (start != NULL)
*start = arange->ar_address;
if (length != NULL)
*length = arange->ar_length;
if (cu_die_offset != NULL) {
Dwarf_Debug dbg = arange->ar_dbg;
Dwarf_Off offset = arange->ar_info_offset;
Dwarf_Unsigned headerlen = 0;
int cres = 0;
/* This applies to debug_info only, not to debug_types. */
if (!dbg->de_debug_info.dss_data) {
int res = _dwarf_load_debug_info(dbg, error);
if (res != DW_DLV_OK) {
return res;
}
}
cres = _dwarf_length_of_cu_header(dbg, offset,
true, &headerlen,error);
if (cres != DW_DLV_OK) {
return cres;
}
*cu_die_offset = offset + headerlen;
}
return DW_DLV_OK;
}

60
src/lib/libdwarf/dwarf_arange.h vendored Normal file
View File

@ -0,0 +1,60 @@
/*
Copyright (C) 2000 Silicon Graphics, Inc. All Rights Reserved.
Portions Copyright (C) 2011-2023 David Anderson. All Rights Reserved.
This program is free software; you can redistribute it
and/or modify it under the terms of version 2.1 of the
GNU Lesser General Public License as published by the Free
Software Foundation.
This program is distributed in the hope that it would be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
Further, this software is distributed without any warranty
that it is free of the rightful claim of any third person
regarding infringement or the like. Any license provided
herein, whether implied or otherwise, applies only to this
software file. Patent licenses, if any, provided herein
do not apply to combinations of this program with other
software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write the
Free Software Foundation, Inc., 51 Franklin Street - Fifth
Floor, Boston MA 02110-1301, USA.
*/
/* This structure is used to read an arange into. */
struct Dwarf_Arange_s {
/* The segment selector. Only non-zero if Dwarf4, only
meaningful if ar_segment_selector_size non-zero */
Dwarf_Unsigned ar_segment_selector;
/* Starting address of the arange, ie low-pc. */
Dwarf_Addr ar_address;
/* Length of the arange. */
Dwarf_Unsigned ar_length;
/* Offset into .debug_info of the start of the compilation-unit
containing this set of aranges.
Applies only to .debug_info, not .debug_types. */
Dwarf_Off ar_info_offset;
/* Corresponding Dwarf_Debug. */
Dwarf_Debug ar_dbg;
Dwarf_Half ar_segment_selector_size;
};
int
_dwarf_get_aranges_addr_offsets(Dwarf_Debug dbg,
Dwarf_Addr ** addrs,
Dwarf_Off ** offsets,
Dwarf_Signed * count,
Dwarf_Error * error);

137
src/lib/libdwarf/dwarf_base_types.h vendored Normal file
View File

@ -0,0 +1,137 @@
/*
Copyright (C) 2000,2005 Silicon Graphics, Inc. All Rights Reserved.
Portions Copyright (C) 2008-2023 David Anderson. All Rights Reserved.
This program is free software; you can redistribute it
and/or modify it under the terms of version 2.1 of the
GNU Lesser General Public License as published by the Free
Software Foundation.
This program is distributed in the hope that it would be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
Further, this software is distributed without any warranty
that it is free of the rightful claim of any third person
regarding infringement or the like. Any license provided
herein, whether implied or otherwise, applies only to this
software file. Patent licenses, if any, provided herein
do not apply to combinations of this program with other
software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write the
Free Software Foundation, Inc., 51 Franklin Street - Fifth
Floor, Boston MA 02110-1301, USA.
*/
#ifndef DWARF_BASE_TYPES_H
#define DWARF_BASE_TYPES_H
#define true 1
#define false 0
/* .debug_addr new in DWARF5 */
#define DW_ADDR_VERSION5 5
/* To identify a cie. That is, for .debug_frame */
#define DW_CIE_ID ~(0x0)
#define DW_CIE_VERSION 1 /* DWARF2 */
#define DW_CIE_VERSION3 3 /* DWARF3 */
#define DW_CIE_VERSION4 4 /* DWARF4 */
#define DW_CIE_VERSION5 5 /* DWARF5 */
/* For .debug_info DWARF2,3,4,5.
.debug_types in DWARF4 only, and gets DW_CU_VERSION4. */
#define DW_CU_VERSION2 2
#define DW_CU_VERSION3 3
#define DW_CU_VERSION4 4
#define DW_CU_VERSION5 5
/* For .debug_macro: DWARF 4 (extension) or DWARF5 */
#define DW_MACRO_VERSION4 4
#define DW_MACRO_VERSION5 5
/* DWARF2,3, 4 and 5.*/
#define DW_ARANGES_VERSION2 2
#define DW_LINE_VERSION2 2
#define DW_LINE_VERSION3 3
#define DW_LINE_VERSION4 4
#define DW_LINE_VERSION5 5
/* .debug_line_str (and .dwo) new in DWARF5. */
#define DW_LINE_STR_VERSION5 5
/* Experimental two-level line tables */
#define EXPERIMENTAL_LINE_TABLES_VERSION 0xf006
/* .debug_loc (and .dwo) First header version number is DWARF5. */
#define DW_LOC_VERSION5 5
/* .debug_names new in DWARF5. */
#define DW_NAMES_VERSION5 5
/* .debug_pubnames in DWARF2,3,4. */
#define DW_PUBNAMES_VERSION2 2
/* .debug_pubnames in DWARF3,4. */
#define DW_PUBTYPES_VERSION2 2
/* .debug_ranges gets a version number in header in DWARF5. */
#define DW_RANGES_VERSION5 5
/* .debug_str_offsets (and .dwo) new in DWARF5. */
#define DW_STR_OFFSETS_VERSION5 5
#define DW_STR_OFFSETS_VERSION4 4 /* GNU extension in DW4 */
/* .debug_sup new in DWARF5. */
#define DW_SUP_VERSION5 5
/* .debug_cu_index new in DWARF5. */
#define DW_CU_INDEX_VERSION5 5
/* .debug_tu_index new in DWARF5. */
#define DW_TU_INDEX_VERSION5 5
/* These are allocation type codes for structs that
are internal to the Libdwarf Consumer library. */
#define DW_DLA_ABBREV_LIST 0x1e
#define DW_DLA_CHAIN 0x1f
#define DW_DLA_CU_CONTEXT 0x20
#define DW_DLA_FRAME 0x21
#define DW_DLA_GLOBAL_CONTEXT 0x22
#define DW_DLA_FILE_ENTRY 0x23
#define DW_DLA_LINE_CONTEXT 0x24
#define DW_DLA_LOC_CHAIN 0x25
#define DW_DLA_HASH_TABLE 0x26
#define DW_DLA_FUNC_CONTEXT 0x27
#define DW_DLA_TYPENAME_CONTEXT 0x28
#define DW_DLA_VAR_CONTEXT 0x29
#define DW_DLA_WEAK_CONTEXT 0x2a
#define DW_DLA_PUBTYPES_CONTEXT 0x2b /* DWARF3 */
#define DW_DLA_HASH_TABLE_ENTRY 0x2c
#define DW_DLA_FISSION_PERCU 0x2d
#define DW_DLA_CHAIN_2 0x3d
/* Thru 0x36 reserved for internal future use. */
/* Maximum number of allocation types for allocation routines.
Only used with malloc_check.c and that is basically obsolete. */
#define MAX_DW_DLA 0x3a
typedef signed char Dwarf_Sbyte;
typedef unsigned char Dwarf_Ubyte;
typedef signed short Dwarf_Shalf;
typedef Dwarf_Small *Dwarf_Byte_Ptr;
#define DWARF_HALF_SIZE 2
#define DWARF_32BIT_SIZE 4
#define DWARF_64BIT_SIZE 8
typedef struct Dwarf_Abbrev_List_s *Dwarf_Abbrev_List;
typedef struct Dwarf_File_Entry_s *Dwarf_File_Entry;
typedef struct Dwarf_CU_Context_s *Dwarf_CU_Context;
typedef struct Dwarf_Hash_Table_s *Dwarf_Hash_Table;
typedef struct Dwarf_Alloc_Hdr_s *Dwarf_Alloc_Hdr;
#endif /* DWARF_BASE_TYPES_H */

137
src/lib/libdwarf/dwarf_crc.c vendored Normal file
View File

@ -0,0 +1,137 @@
/*
Copyright 2020 David Anderson. All Rights Reserved.
This program is free software; you can redistribute it
and/or modify it under the terms of version 2.1 of the
GNU Lesser General Public License as published by the Free
Software Foundation.
This program is distributed in the hope that it would be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
Further, this software is distributed without any warranty
that it is free of the rightful claim of any third person
regarding infringement or the like. Any license provided
herein, whether implied or otherwise, applies only to this
software file. Patent licenses, if any, provided herein
do not apply to combinations of this program with other
software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write the
Free Software Foundation, Inc., 51 Franklin Street - Fifth
Floor, Boston MA 02110-1301, USA.
*/
#include <config.h>
#include <stddef.h> /* size_t */
#include "dwarf.h"
#include "libdwarf.h"
#include "libdwarf_private.h"
#include "dwarf_base_types.h"
#include "dwarf_opaque.h" /* For the function prototype */
#define uint32_t unsigned int
/* Table computed by David Anderson
with Mark Adler's table builder
logic on October 20,2020
with pattern from polynomial (0xedb88320) */
static const uint32_t crc32_table[256] =
{
0x00000000,0x77073096,0xee0e612c,0x990951ba,
0x076dc419,0x706af48f,0xe963a535,0x9e6495a3,
0x0edb8832,0x79dcb8a4,0xe0d5e91e,0x97d2d988,
0x09b64c2b,0x7eb17cbd,0xe7b82d07,0x90bf1d91,
0x1db71064,0x6ab020f2,0xf3b97148,0x84be41de,
0x1adad47d,0x6ddde4eb,0xf4d4b551,0x83d385c7,
0x136c9856,0x646ba8c0,0xfd62f97a,0x8a65c9ec,
0x14015c4f,0x63066cd9,0xfa0f3d63,0x8d080df5,
0x3b6e20c8,0x4c69105e,0xd56041e4,0xa2677172,
0x3c03e4d1,0x4b04d447,0xd20d85fd,0xa50ab56b,
0x35b5a8fa,0x42b2986c,0xdbbbc9d6,0xacbcf940,
0x32d86ce3,0x45df5c75,0xdcd60dcf,0xabd13d59,
0x26d930ac,0x51de003a,0xc8d75180,0xbfd06116,
0x21b4f4b5,0x56b3c423,0xcfba9599,0xb8bda50f,
0x2802b89e,0x5f058808,0xc60cd9b2,0xb10be924,
0x2f6f7c87,0x58684c11,0xc1611dab,0xb6662d3d,
0x76dc4190,0x01db7106,0x98d220bc,0xefd5102a,
0x71b18589,0x06b6b51f,0x9fbfe4a5,0xe8b8d433,
0x7807c9a2,0x0f00f934,0x9609a88e,0xe10e9818,
0x7f6a0dbb,0x086d3d2d,0x91646c97,0xe6635c01,
0x6b6b51f4,0x1c6c6162,0x856530d8,0xf262004e,
0x6c0695ed,0x1b01a57b,0x8208f4c1,0xf50fc457,
0x65b0d9c6,0x12b7e950,0x8bbeb8ea,0xfcb9887c,
0x62dd1ddf,0x15da2d49,0x8cd37cf3,0xfbd44c65,
0x4db26158,0x3ab551ce,0xa3bc0074,0xd4bb30e2,
0x4adfa541,0x3dd895d7,0xa4d1c46d,0xd3d6f4fb,
0x4369e96a,0x346ed9fc,0xad678846,0xda60b8d0,
0x44042d73,0x33031de5,0xaa0a4c5f,0xdd0d7cc9,
0x5005713c,0x270241aa,0xbe0b1010,0xc90c2086,
0x5768b525,0x206f85b3,0xb966d409,0xce61e49f,
0x5edef90e,0x29d9c998,0xb0d09822,0xc7d7a8b4,
0x59b33d17,0x2eb40d81,0xb7bd5c3b,0xc0ba6cad,
0xedb88320,0x9abfb3b6,0x03b6e20c,0x74b1d29a,
0xead54739,0x9dd277af,0x04db2615,0x73dc1683,
0xe3630b12,0x94643b84,0x0d6d6a3e,0x7a6a5aa8,
0xe40ecf0b,0x9309ff9d,0x0a00ae27,0x7d079eb1,
0xf00f9344,0x8708a3d2,0x1e01f268,0x6906c2fe,
0xf762575d,0x806567cb,0x196c3671,0x6e6b06e7,
0xfed41b76,0x89d32be0,0x10da7a5a,0x67dd4acc,
0xf9b9df6f,0x8ebeeff9,0x17b7be43,0x60b08ed5,
0xd6d6a3e8,0xa1d1937e,0x38d8c2c4,0x4fdff252,
0xd1bb67f1,0xa6bc5767,0x3fb506dd,0x48b2364b,
0xd80d2bda,0xaf0a1b4c,0x36034af6,0x41047a60,
0xdf60efc3,0xa867df55,0x316e8eef,0x4669be79,
0xcb61b38c,0xbc66831a,0x256fd2a0,0x5268e236,
0xcc0c7795,0xbb0b4703,0x220216b9,0x5505262f,
0xc5ba3bbe,0xb2bd0b28,0x2bb45a92,0x5cb36a04,
0xc2d7ffa7,0xb5d0cf31,0x2cd99e8b,0x5bdeae1d,
0x9b64c2b0,0xec63f226,0x756aa39c,0x026d930a,
0x9c0906a9,0xeb0e363f,0x72076785,0x05005713,
0x95bf4a82,0xe2b87a14,0x7bb12bae,0x0cb61b38,
0x92d28e9b,0xe5d5be0d,0x7cdcefb7,0x0bdbdf21,
0x86d3d2d4,0xf1d4e242,0x68ddb3f8,0x1fda836e,
0x81be16cd,0xf6b9265b,0x6fb077e1,0x18b74777,
0x88085ae6,0xff0f6a70,0x66063bca,0x11010b5c,
0x8f659eff,0xf862ae69,0x616bffd3,0x166ccf45,
0xa00ae278,0xd70dd2ee,0x4e048354,0x3903b3c2,
0xa7672661,0xd06016f7,0x4969474d,0x3e6e77db,
0xaed16a4a,0xd9d65adc,0x40df0b66,0x37d83bf0,
0xa9bcae53,0xdebb9ec5,0x47b2cf7f,0x30b5ffe9,
0xbdbdf21c,0xcabac28a,0x53b39330,0x24b4a3a6,
0xbad03605,0xcdd70693,0x54de5729,0x23d967bf,
0xb3667a2e,0xc4614ab8,0x5d681b02,0x2a6f2b94,
0xb40bbe37,0xc30c8ea1,0x5a05df1b,0x2d02ef8d
};
/* The following is essentially identical
to every crc32 anyone uses up to trivial
differences in starting conditions.
The algorithm appears on
https://en.wikipedia.org/wiki/Cyclic_redundancy_check
in a simple logic loop (written in no actual
language but English) and the following is a translation
into C. Just like every other crc calculation.
The unsigned int return will not get the same CRC as
Linux/Macos if int/unsigned-int is 16 bits (Windows),
but there the crc does not matter in practice.
The results on big-endian are not the same
as little-endian machines.*/
unsigned int
dwarf_basic_crc32 (const unsigned char *buf,
unsigned long len,
unsigned int crc)
{
const unsigned char *end = 0;
crc = ~crc;
for (end = buf + len; buf < end; ++buf)
crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);
return ~crc;
}

153
src/lib/libdwarf/dwarf_crc32.c vendored Normal file
View File

@ -0,0 +1,153 @@
/*
Copyright (C) 2020 David Anderson. All Rights Reserved.
This program is free software; you can redistribute it
and/or modify it under the terms of version 2.1 of the
GNU Lesser General Public License as published by the Free
Software Foundation.
This program is distributed in the hope that it would be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
Further, this software is distributed without any warranty
that it is free of the rightful claim of any third person
regarding infringement or the like. Any license provided
herein, whether implied or otherwise, applies only to this
software file. Patent licenses, if any, provided herein
do not apply to combinations of this program with other
software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write
the Free Software Foundation, Inc., 51 Franklin Street -
Fifth Floor, Boston MA 02110-1301, USA.
*/
#include <config.h>
#include <stddef.h> /* size_t */
#include <stdio.h> /* SEEK_END SEEK_SET */
#include <stdlib.h> /* free() malloc() */
#include <string.h> /* memcpy() */
#ifdef _WIN32
#ifdef HAVE_STDAFX_H
#include "stdafx.h"
#endif /* HAVE_STDAFX_H */
#include <io.h> /* lseek() off_t ssize_t */
#elif defined HAVE_UNISTD_H
#include <unistd.h> /* lseek() off_t */
#endif /* _WIN32 */
#include "dwarf.h"
#include "libdwarf.h"
#include "libdwarf_private.h"
#include "dwarf_base_types.h"
#include "dwarf_opaque.h"
#include "dwarf_error.h"
/* Returns DW_DLV_OK DW_DLV_NO_ENTRY or DW_DLV_ERROR
crc32 used for debuglink crc calculation.
Caller passes pointer to an
uninitialized array of 4 unsigned char
and if this returns DW_DLV_OK that is filled in.
The crc is calculated based on reading
the entire current open
Dwarf_Debug dbg object file and all bytes in
the file are read to create the crc. */
int
dwarf_crc32 (Dwarf_Debug dbg,unsigned char *crcbuf,
Dwarf_Error *error)
{
/* off_t is signed, defined by POSIX */
/* ssize_t is signed, defined in POSIX */
/* size_t is unsigned, defined in C89. */
off_t size_left = 0;
off_t fsize = 0;
off_t lsval = 0;
/* Named with u to remind the reader that this is
an unsigned value. */
size_t readlenu = 1000;
unsigned char *readbuf = 0;
unsigned int tcrc = 0;
unsigned int init = 0;
int fd = -1;
if (!dbg) {
_dwarf_error_string(dbg,error,DW_DLE_DBG_NULL,
"DW_DLE_DBG_NULL: Bad call to dwarf_crc32");
return DW_DLV_ERROR;
}
if (!crcbuf) {
return DW_DLV_NO_ENTRY;
}
if (!dbg->de_owns_fd) {
return DW_DLV_NO_ENTRY;
}
fd = dbg->de_fd;
if (fd < 0) {
return DW_DLV_NO_ENTRY;
}
fd = dbg->de_fd;
if (dbg->de_filesize) {
fsize = size_left = (off_t)dbg->de_filesize;
} else {
fsize = size_left = lseek(fd,0L,SEEK_END);
if (fsize == (off_t)-1) {
_dwarf_error_string(dbg,error,DW_DLE_SEEK_ERROR,
"DW_DLE_SEEK_ERROR: dwarf_crc32 seek "
"to end fails");
return DW_DLV_ERROR;
}
}
if (fsize <= (off_t)500) {
/* Not a real object file.
A random length check. */
return DW_DLV_NO_ENTRY;
}
lsval = lseek(fd,0L,SEEK_SET);
if (lsval < 0) {
_dwarf_error_string(dbg,error,DW_DLE_SEEK_ERROR,
"DW_DLE_SEEK_ERROR: dwarf_crc32 seek "
"to start fails");
return DW_DLV_ERROR;
}
readbuf = (unsigned char *)malloc(readlenu);
if (!readbuf) {
_dwarf_error_string(dbg,error,DW_DLE_ALLOC_FAIL,
"DW_DLE_ALLOC_FAIL: dwarf_crc32 read buffer"
" alloc fails");
return DW_DLV_ERROR;
}
while (size_left > 0) {
ssize_t readreturnv = 0;
if (size_left < (off_t)readlenu) {
readlenu = (size_t)size_left;
}
/* Fix warning on Windows: read()'s
3rd parameter is a unsigned const */
#ifdef _WIN32
readreturnv = read(fd,readbuf,(unsigned const)readlenu);
#else
readreturnv = read(fd,readbuf,readlenu);
#endif
if (readreturnv != (ssize_t)readlenu) {
_dwarf_error_string(dbg,error,DW_DLE_READ_ERROR,
"DW_DLE_READ_ERROR: dwarf_crc32 read fails ");
free(readbuf);
return DW_DLV_ERROR;
}
/* Call the public API function so it gets tested too. */
tcrc = dwarf_basic_crc32(readbuf,readlenu,
(unsigned long)init);
init = tcrc;
size_left -= (off_t)readlenu;
}
/* endianness issues? */
free(readbuf);
memcpy(crcbuf,(void *)&tcrc,4);
return DW_DLV_OK;
}

206
src/lib/libdwarf/dwarf_debug_sup.c vendored Normal file
View File

@ -0,0 +1,206 @@
/*
Copyright (c) 2020, David Anderson
All rights reserved.
Redistribution and use in source and binary forms, with
or without modification, are permitted provided that the
following conditions are met:
Redistributions of source code must retain the above
copyright notice, this list of conditions and the following
disclaimer.
Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* This provides access to the DWARF5 .debug_sup section. */
#include <config.h>
#include <string.h> /* strlen() */
#if defined(_WIN32) && defined(HAVE_STDAFX_H)
#include "stdafx.h"
#endif /* HAVE_STDAFX_H */
#include "dwarf.h"
#include "libdwarf.h"
#include "libdwarf_private.h"
#include "dwarf_base_types.h"
#include "dwarf_opaque.h"
#include "dwarf_alloc.h"
#include "dwarf_error.h"
#include "dwarf_util.h"
#include "dwarf_global.h"
#include "dwarf_string.h"
static void
get_sup_fields(Dwarf_Debug dbg,
struct Dwarf_Section_s **sec_out)
{
if (!dbg) {
return;
}
*sec_out = &dbg->de_debug_sup;
}
static int
load_sup(Dwarf_Debug dbg,
Dwarf_Error *error)
{
struct Dwarf_Section_s * sec = 0;
int res;
get_sup_fields(dbg,&sec);
if (!sec) {
return DW_DLV_NO_ENTRY;
}
res = _dwarf_load_section(dbg,sec,error);
return res;
}
/* New for DWARF5 in July 2020. */
int
dwarf_get_debug_sup(Dwarf_Debug dbg,
Dwarf_Half * version_out,
Dwarf_Small * is_supplementary_out,
char ** filename_out,
Dwarf_Unsigned * checksum_len_out,
Dwarf_Small ** checksum_out,
Dwarf_Error * error)
{
Dwarf_Unsigned version = 0;
Dwarf_Small is_supp = 0;
char *filename = 0;
Dwarf_Unsigned checksum_len = 0;
Dwarf_Small *checksum_ptr = 0;
int res = 0;
Dwarf_Small *data = 0;
Dwarf_Small *enddata = 0;
Dwarf_Unsigned size = 0;
res = load_sup(dbg,error);
if (res != DW_DLV_OK) {
return res;
}
data = dbg->de_debug_sup.dss_data;
size = dbg->de_debug_sup.dss_size;
if (dbg->de_filesize && size > dbg->de_filesize) {
dwarfstring m;
dwarfstring_constructor(&m);
dwarfstring_append_printf_u(&m, "DW_DLE_DEBUG_SUP_ERROR: "
".debug_sup section size 0x%x bigger than file "
"size! Corrupt",
size);
_dwarf_error_string(dbg,error,
DW_DLE_DEBUG_SUP_ERROR,
dwarfstring_string(&m));
dwarfstring_destructor(&m);
return DW_DLV_ERROR;
}
enddata = data + size;
res = _dwarf_read_unaligned_ck_wrapper(dbg,
&version,
data,DWARF_HALF_SIZE,
enddata,error);
if (res != DW_DLV_OK) {
return res;
}
data+= DWARF_HALF_SIZE;
if ((data+4) > enddata) {
dwarfstring m;
dwarfstring_constructor(&m);
dwarfstring_append_printf_u(&m, "DW_DLE_DEBUG_SUP_ERROR: "
" .debug_sup section size 0x%x"
" too small to be correct! Corrupt",
size);
_dwarf_error_string(dbg,error,
DW_DLE_DEBUG_SUP_ERROR,
dwarfstring_string(&m));
dwarfstring_destructor(&m);
return DW_DLV_ERROR;
}
is_supp = (Dwarf_Small)*data;
++data;
res = _dwarf_check_string_valid(dbg,data,data,enddata,
DW_DLE_DEBUG_SUP_STRING_ERROR,error);
if (res != DW_DLV_OK) {
return res;
}
filename = (char *)data;
data += strlen((char *)data) +1;
res = _dwarf_leb128_uword_wrapper(dbg, &data,enddata,
&checksum_len,error);
if (res != DW_DLV_OK) {
return res;
}
if (checksum_len >= size) {
dwarfstring m;
dwarfstring_constructor(&m);
dwarfstring_append_printf_u(&m, "DW_DLE_DEBUG_SUP_ERROR: "
" .debug_sup checksum length 0x%x"
" too large to be correct! Corrupt",
checksum_len);
_dwarf_error_string(dbg,error,
DW_DLE_DEBUG_SUP_ERROR,
dwarfstring_string(&m));
dwarfstring_destructor(&m);
return DW_DLV_ERROR;
}
if ((data +checksum_len) > enddata) {
dwarfstring m;
dwarfstring_constructor(&m);
dwarfstring_append_printf_u(&m, "DW_DLE_DEBUG_SUP_ERROR: "
" .debug_sup checksum (length 0x%x) "
" runs off the end of the section, Corrupt data",
checksum_len);
_dwarf_error_string(dbg,error,
DW_DLE_DEBUG_SUP_ERROR,
dwarfstring_string(&m));
dwarfstring_destructor(&m);
return DW_DLV_ERROR;
}
checksum_ptr = data;
if (version_out) {
*version_out = (Dwarf_Half)version;
}
if (is_supp) {
*is_supplementary_out = is_supp;
}
if (filename_out) {
*filename_out = filename;
}
if (checksum_len_out) {
*checksum_len_out = checksum_len;
}
if (checksum_out) {
*checksum_out = checksum_ptr;
}
return DW_DLV_OK;
}

342
src/lib/libdwarf/dwarf_debugaddr.c vendored Normal file
View File

@ -0,0 +1,342 @@
/*
Copyright (C) 2022 David Anderson. All Rights Reserved.
Redistribution and use in source and binary forms, with
or without modification, are permitted provided that the
following conditions are met:
Redistributions of source code must retain the above
copyright notice, this list of conditions and the following
disclaimer.
Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <stddef.h> /* NULL size_t */
#include <stdio.h> /* debug printf */
#include <string.h> /* memset() strlen() */
#if defined(_WIN32) && defined(HAVE_STDAFX_H)
#include "stdafx.h"
#endif /* HAVE_STDAFX_H */
#include "dwarf.h"
#include "libdwarf.h"
#include "libdwarf_private.h"
#include "dwarf_base_types.h"
#include "dwarf_opaque.h"
#include "dwarf_alloc.h"
#include "dwarf_error.h"
#include "dwarf_util.h"
#include "dwarf_debugaddr.h"
#include "dwarf_string.h"
#if 0
static void
dump_bytes(const char *msg,Dwarf_Small * start, long len)
{
Dwarf_Small *end = start + len;
Dwarf_Small *cur = start;
int linelim=16;
int lineb = 0;
printf("dump_bytes: %s %ld starting %p \n",msg,len,
(void *)start);
fflush(stdout);
for (; cur < end; cur++, ++lineb) {
if (lineb == linelim) {
printf("\n");
lineb = 0;
}
printf("%02x",*cur);
}
printf("\n");
fflush(stdout);
}
#endif /* 0 */
int
dwarf_debug_addr_table(Dwarf_Debug dbg,
Dwarf_Unsigned dw_section_offset,
Dwarf_Debug_Addr_Table *dw_table_header,
Dwarf_Unsigned *dw_length,
Dwarf_Half *dw_version,
Dwarf_Small *dw_address_size,
Dwarf_Unsigned *dw_at_addr_base,
Dwarf_Unsigned *dw_entry_count,
Dwarf_Unsigned *dw_next_table_offset,
Dwarf_Error *error)
{
int res = 0;
struct Dwarf_Debug_Addr_Table_s tab;
Dwarf_Unsigned section_size = 0;
Dwarf_Small *end_data = 0;
Dwarf_Small *data = 0;
Dwarf_Small *section_start = 0;
Dwarf_Unsigned arealen = 0;
Dwarf_Unsigned tablelen = 0;
int offset_size = 0;
int exten_size = 0;
Dwarf_Small address_size = 0;
Dwarf_Small segment_selector_size = 0;
Dwarf_Half version = 0;
Dwarf_Unsigned curlocaloffset = 0;
Dwarf_Unsigned offset_one_past_end = 0;
/* we will instantiate this below */
Dwarf_Debug_Addr_Table newad = 0;
res = _dwarf_load_section(dbg, &dbg->de_debug_addr,error);
if (res == DW_DLV_NO_ENTRY) {
return res;
}
if (res == DW_DLV_ERROR) {
if (error) {
Dwarf_Error e = *error;
/* Lets append info to the error string! */
if (e->er_static_alloc != DE_STATIC) {
dwarfstring *em = (dwarfstring*)(e->er_msg);
dwarfstring_append(em, "Unable to open "
".debug_addr section, serious error");
}
}
return DW_DLV_ERROR;
}
memset(&tab,0,sizeof(tab));
tab.da_magic = DW_ADDR_TABLE_MAGIC;
section_size = dbg->de_debug_addr.dss_size;
section_start = dbg->de_debug_addr.dss_data;
end_data = section_start + section_size;
tab.da_section_size = section_size;
if (dw_section_offset >= section_size) {
return DW_DLV_NO_ENTRY;
}
curlocaloffset = 0;
data = section_start + dw_section_offset;
READ_AREA_LENGTH_CK(dbg,arealen,Dwarf_Unsigned,
data,offset_size,exten_size,
error,
section_size,end_data);
if (arealen > section_size ||
(arealen + offset_size +exten_size) > section_size) {
dwarfstring m;
dwarfstring_constructor(&m);
dwarfstring_append_printf_u(&m,
"DW_DLE_SECTION_SIZE_ERROR: A .debug_addr "
"area size of 0x%x ",arealen);
dwarfstring_append_printf_u(&m,
"at offset 0x%x ",dw_section_offset);
dwarfstring_append_printf_u(&m,
"is larger than the entire section size of "
"0x%x. Corrupt DWARF.",section_size);
_dwarf_error_string(dbg,error,
DW_DLE_SECTION_SIZE_ERROR,
dwarfstring_string(&m));
dwarfstring_destructor(&m);
return DW_DLV_ERROR;
}
tab.da_dbg = dbg;
tablelen = arealen - 4; /* 4: the rest of the header */
tab.da_length = tablelen;
curlocaloffset = offset_size + exten_size;
offset_one_past_end = dw_section_offset
+ curlocaloffset + 4 /*rest of header */
+ tablelen;
end_data = section_start + offset_one_past_end;
tab.da_end_table = end_data;
READ_UNALIGNED_CK(dbg,version,Dwarf_Half,data,
SIZEOFT16,error,end_data);
if (version != DW_CU_VERSION5) {
dwarfstring m;
dwarfstring_constructor(&m);
dwarfstring_append_printf_u(&m,
"DW_DLE_VERSION_STAMP_ERROR: "
"The .debug_addr version should be 5 "
"but we find %u instead.",version);
_dwarf_error_string(dbg,error,
DW_DLE_VERSION_STAMP_ERROR,
dwarfstring_string(&m));
dwarfstring_destructor(&m);
return DW_DLV_ERROR;
}
tab.da_version = version;
data += SIZEOFT16;
curlocaloffset += SIZEOFT16;
READ_UNALIGNED_CK(dbg,address_size,Dwarf_Small,data,
1,error,end_data);
if (address_size != 4 && address_size != 8 &&
address_size != 2) {
dwarfstring m;
dwarfstring_constructor(&m);
dwarfstring_append_printf_u(&m,
" DW_DLE_ADDRESS_SIZE_ERROR: The "
" .debug_addr address size "
"of %u is not supported.",address_size);
_dwarf_error_string(dbg,error,DW_DLE_ADDRESS_SIZE_ERROR,
dwarfstring_string(&m));
dwarfstring_destructor(&m);
return DW_DLV_ERROR;
}
tab.da_address_size = address_size;
data++;
curlocaloffset++;
READ_UNALIGNED_CK(dbg,segment_selector_size,Dwarf_Small,data,
1,error,end_data);
if (segment_selector_size != 0) {
dwarfstring m;
dwarfstring_constructor(&m);
dwarfstring_append(&m,
" DW_DLE_DEBUG_ADDR_ERROR: The "
" .debug_addr segment selector size "
"of non-zero is not supported.");
_dwarf_error_string(dbg,error,DW_DLE_DEBUG_ADDR_ERROR,
dwarfstring_string(&m));
dwarfstring_destructor(&m);
return DW_DLV_ERROR;
}
/* We do not record segment selector size,
as it is not supported. */
curlocaloffset++;
data++;
tab.da_data_entries = data;
/* Now we are at the beginning of the actual table */
{
Dwarf_Unsigned entry_count = 0;
/* Two byte version and two byte flags preceed the
actual table */
Dwarf_Unsigned table_len_bytes = tab.da_length;
if (table_len_bytes%(Dwarf_Unsigned)address_size) {
dwarfstring m;
dwarfstring_constructor(&m);
dwarfstring_append_printf_u(&m,
" DW_DLE_DEBUG_ADDR_ERROR: The "
" .debug_addr address array "
"length of %u not a multiple of "
"address_size.",table_len_bytes);
_dwarf_error_string(dbg,error,
DW_DLE_DEBUG_ADDR_ERROR,
dwarfstring_string(&m));
dwarfstring_destructor(&m);
return DW_DLV_ERROR;
}
entry_count = table_len_bytes/address_size;
tab.da_entry_count = entry_count;
}
tab.da_table_section_offset = dw_section_offset;
tab.da_addr_base = dw_section_offset + curlocaloffset;
/* Do alloc as late as possible to avoid
any concern about missing a dealloc in
case of error. */
newad = (Dwarf_Debug_Addr_Table)
_dwarf_get_alloc(dbg,DW_DLA_DEBUG_ADDR,1);
if (!newad) {
_dwarf_error_string(dbg, error,
DW_DLE_ALLOC_FAIL,
"DW_DLE_ALLOC_FAIL: "
"allocating a Dwarf_Debug_Addr_Table "
"record.");
return DW_DLV_ERROR;
}
/* Copy structure itself */
*newad = tab;
*dw_table_header = newad;
if (dw_length) {
*dw_length = newad->da_length;
}
if (dw_version) {
*dw_version = newad->da_version;
}
if (dw_address_size) {
*dw_address_size = newad->da_address_size;
}
if (dw_at_addr_base) {
*dw_at_addr_base = newad->da_addr_base;
}
if (dw_entry_count) {
*dw_entry_count = newad->da_entry_count;
}
if (dw_next_table_offset) {
*dw_next_table_offset = offset_one_past_end;
}
return DW_DLV_OK;
}
int
dwarf_debug_addr_by_index(Dwarf_Debug_Addr_Table dw_dat,
Dwarf_Unsigned dw_entry_index,
Dwarf_Unsigned *dw_address,
Dwarf_Error *dw_error)
{
Dwarf_Small *data = 0;
Dwarf_Unsigned addr = 0;
if (!dw_dat) {
_dwarf_error_string(NULL,dw_error,
DW_DLE_DEBUG_ADDR_ERROR,
"DW_DLE_DEBUG_ADDR_ERROR: "
"NULL dw_dat passed in.");
return DW_DLV_ERROR;
}
if (dw_dat->da_magic != DW_ADDR_TABLE_MAGIC) {
_dwarf_error_string(NULL,dw_error,
DW_DLE_DEBUG_ADDR_ERROR,
"DW_DLE_DEBUG_ADDR_ERROR: "
"Bad debug addr table magic number. ");
return DW_DLV_ERROR;
}
if (dw_entry_index >= dw_dat->da_entry_count) {
return DW_DLV_NO_ENTRY;
}
data = dw_dat->da_data_entries+
dw_dat->da_address_size * dw_entry_index;
if ((data+ dw_dat->da_address_size) > dw_dat->da_end_table) {
_dwarf_error_string(NULL,dw_error,
DW_DLE_DEBUG_ADDR_ERROR,
"DW_DLE_DEBUG_ADDR_ERROR: "
"Bad debug addr table: miscount, too short. ");
return DW_DLV_ERROR;
}
READ_UNALIGNED_CK(dw_dat->da_dbg,
addr,Dwarf_Unsigned, data,
dw_dat->da_address_size,dw_error,
dw_dat->da_end_table);
*dw_address = addr;
return DW_DLV_OK;
}
void
dwarf_dealloc_debug_addr_table(Dwarf_Debug_Addr_Table dw_dat)
{
Dwarf_Debug dbg = 0;
if (!dw_dat) {
return;
}
if (dw_dat->da_magic != DW_ADDR_TABLE_MAGIC) {
return;
}
dbg = dw_dat->da_dbg;
dw_dat->da_magic = 0;
dwarf_dealloc(dbg,dw_dat,DW_DLA_DEBUG_ADDR);
}

75
src/lib/libdwarf/dwarf_debugaddr.h vendored Normal file
View File

@ -0,0 +1,75 @@
/*
Copyright (C) 2022-2023 David Anderson. All Rights Reserved.
Redistribution and use in source and binary forms, with
or without modification, are permitted provided that the
following conditions are met:
Redistributions of source code must retain the above
copyright notice, this list of conditions and the following
disclaimer.
Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef DWARF_DEBUGADDR_H
#define DWARF_DEBUGADDR_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define DW_ADDR_TABLE_MAGIC 0xfade
struct Dwarf_Debug_Addr_Table_s {
Dwarf_Unsigned da_magic;
Dwarf_Debug da_dbg;
/* Length includes the table header and
the length-field of the header and
the array of addresses. */
Dwarf_Unsigned da_length;
Dwarf_Small da_length_size; /* 4 or 8 */
Dwarf_Small da_extension_size; /* 4 or 0 */
Dwarf_Unsigned da_table_section_offset;
/* Whole section size. >= this table length */
Dwarf_Unsigned da_section_size ;
/* pointer to entry[0] */
Dwarf_Small *da_data_entries;
Dwarf_Unsigned da_entry_count;
/* One past end of this Debug Addr Table */
Dwarf_Small *da_end_table;
/* The value appearing in some DW_AT_addr_base:
da_table_section_offset+da_local_offset_entry0. */
Dwarf_Unsigned da_addr_base;
Dwarf_Half da_version;
Dwarf_Small da_address_size;
#if 0
/* this is not really handled anywhere by any compiler
so we do not remember it. Must be zero. */
Dwarf_Small da_segment_selector_size;
#endif
};
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* DWARF_DEBUGADDR_H */

1085
src/lib/libdwarf/dwarf_debuglink.c vendored Normal file

File diff suppressed because it is too large Load Diff

60
src/lib/libdwarf/dwarf_debuglink.h vendored Normal file
View File

@ -0,0 +1,60 @@
/*
Copyright (c) 2019-2023, David Anderson
All rights reserved.
Redistribution and use in source and binary forms, with
or without modification, are permitted provided that the
following conditions are met:
Redistributions of source code must retain the above
copyright notice, this list of conditions and the following
disclaimer.
Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
#ifndef DWARF_DEBUGLINK_H
#define DWARF_DEBUGLINK_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define DW_BUILDID_SANE_SIZE (8*1024)
int _dwarf_pathjoinl(dwarfstring *target,dwarfstring * input);
int _dwarf_construct_linkedto_path(
char **global_prefixes_in,
unsigned length_global_prefixes_in,
char *pathname_in,
char *link_string_in, /* from debug link */
dwarfstring *link_string_fullpath,
#if 0
unsigned char *crc_in, /* from debug_link, 4 bytes */
#endif
unsigned char *buildid, /* from gnu buildid */
unsigned buildid_length, /* from gnu buildid */
char ***paths_out,
unsigned *paths_out_length,
int *errcode);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* DWARF_DEBUGLINK_H */

1915
src/lib/libdwarf/dwarf_debugnames.c vendored Normal file

File diff suppressed because it is too large Load Diff

121
src/lib/libdwarf/dwarf_debugnames.h vendored Normal file
View File

@ -0,0 +1,121 @@
/*
Copyright (C) 2017-2023 David Anderson. All Rights Reserved.
This program is free software; you can redistribute it
and/or modify it under the terms of version 2.1 of the
GNU Lesser General Public License as published by the Free
Software Foundation.
This program is distributed in the hope that it would be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
Further, this software is distributed without any warranty
that it is free of the rightful claim of any third person
regarding infringement or the like. Any license provided
herein, whether implied or otherwise, applies only to this
software file. Patent licenses, if any, provided herein
do not apply to combinations of this program with other
software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write the
Free Software Foundation, Inc., 51 Franklin Street - Fifth
Floor, Boston MA 02110-1301, USA.
*/
/* Adjust this number to hope for best space and time efficiency. */
#define ABB_PAIRS_MAX 10
/* The unused attr/form entries are zero. */
struct Dwarf_D_Abbrev_s {
struct Dwarf_D_Abbrev_s * da_next;
Dwarf_Unsigned da_abbrev_offset;
Dwarf_Unsigned da_abbrev_code;
Dwarf_Unsigned da_tag;
Dwarf_Unsigned da_pairs_count;
Dwarf_Half da_idxattr[ABB_PAIRS_MAX];
Dwarf_Half da_form[ABB_PAIRS_MAX];
};
struct Dwarf_DN_Bucket_s {
Dwarf_Unsigned db_nameindex;
Dwarf_Unsigned db_collisioncount;
};
#define DWARF_DNAMES_VERSION5 5
#define DWARF_DNAMES_MAGIC 0xabcd
/* All offsets section global */
struct Dwarf_Dnames_Head_s {
Dwarf_Unsigned dn_magic;
Dwarf_Debug dn_dbg;
/* For entire section */
Dwarf_Small * dn_section_data;
Dwarf_Small * dn_section_end;
Dwarf_Unsigned dn_section_size;
/* For this names table set of data */
Dwarf_Unsigned dn_section_offset; /* unit length offset*/
Dwarf_Small * dn_indextable_data; /* unit length ptr */
Dwarf_Unsigned dn_unit_length;
Dwarf_Small * dn_indextable_data_end;
Dwarf_Unsigned dn_next_set_offset;
Dwarf_Half dn_offset_size;
Dwarf_Half dn_version;
Dwarf_Unsigned dn_comp_unit_count;
Dwarf_Unsigned dn_local_type_unit_count;
Dwarf_Unsigned dn_foreign_type_unit_count;
Dwarf_Unsigned dn_bucket_count;
/* Once set, this is a single array of entries. */
struct Dwarf_DN_Bucket_s * dn_bucket_array;
/* dn_name_count gives the size of
the dn_string_offsets and dn_entry_offsets arrays,
and if hashes present, the size of the
dn_hash_table array. */
Dwarf_Unsigned dn_name_count;
Dwarf_Unsigned dn_abbrev_table_size; /* bytes */
Dwarf_Unsigned dn_entry_pool_size; /* bytes */
Dwarf_Unsigned dn_augmentation_string_size;
char * dn_augmentation_string; /* local copy */
/*Offsets are non-decreasing (even empty tables */
Dwarf_Unsigned dn_cu_list_offset;
Dwarf_Unsigned dn_local_tu_list_offset;
Dwarf_Unsigned dn_foreign_tu_list_offset;
Dwarf_Unsigned dn_buckets_offset;
Dwarf_Unsigned dn_hash_table_offset;
Dwarf_Unsigned dn_string_offsets_offset;
Dwarf_Unsigned dn_entry_offsets_offset;
Dwarf_Unsigned dn_abbrevs_offset;
Dwarf_Unsigned dn_entry_pool_offset;
/* pointers non-decreasing (even empty tables) */
Dwarf_Small * dn_cu_list;
Dwarf_Small * dn_local_tu_list;
Dwarf_Small * dn_foreign_tu_list;
Dwarf_Small * dn_buckets;
Dwarf_Small * dn_hash_table;
Dwarf_Small * dn_string_offsets;
Dwarf_Small * dn_entry_offsets;
Dwarf_Small * dn_abbrevs;
Dwarf_Small * dn_entry_pool;
/* Array of structs*/
struct Dwarf_D_Abbrev_s *dn_abbrev_instances;
Dwarf_Unsigned dn_abbrev_instance_count;
/* If this is a single-CU entry the next two are set
for later return. */
Dwarf_Bool dn_single_cu;
Dwarf_Unsigned dn_single_cu_offset;
Dwarf_Unsigned b_value;
Dwarf_Unsigned b_orig_bucket_index;
Dwarf_Unsigned b_sorted_bucket_index;
};
void _dwarf_dnames_destructor(void *m);

3263
src/lib/libdwarf/dwarf_die_deliv.c vendored Normal file

File diff suppressed because it is too large Load Diff

78
src/lib/libdwarf/dwarf_die_deliv.h vendored Normal file
View File

@ -0,0 +1,78 @@
/*
Copyright (C) 2000 Silicon Graphics, Inc. All Rights Reserved.
Portions Copyright (C) 2008-2023 David Anderson. All Rights Reserved.
This program is free software; you can redistribute it
and/or modify it under the terms of version 2.1 of the
GNU Lesser General Public License as published by the Free
Software Foundation.
This program is distributed in the hope that it would be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
Further, this software is distributed without any warranty
that it is free of the rightful claim of any third person
regarding infringement or the like. Any license provided
herein, whether implied or otherwise, applies only to this
software file. Patent licenses, if any, provided herein
do not apply to combinations of this program with other
software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write the
Free Software Foundation, Inc., 51 Franklin Street - Fifth
Floor, Boston MA 02110-1301, USA.
*/
/*
This struct holds information about an abbreviation.
It is put in the hash table for abbreviations for
a compile-unit. Typically the list contains
exactly one item (except with somewhat
pathological abbrev codes, and that likely
never happens).
It is dealloced by dwarf_finish().
*/
struct Dwarf_Abbrev_List_s {
Dwarf_Unsigned abl_code;
Dwarf_Half abl_tag;
Dwarf_Half abl_has_child;
/* This reference count is just for
analysis, does not affect size
or correctness. */
Dwarf_Unsigned abl_reference_count;
/* Section global offset of this abbrev entry. */
Dwarf_Off abl_goffset;
/* Singly linked synonym list in case of duplicate
hash. */
Dwarf_Abbrev_List abl_next;
/* Points to start of attribute/form pairs in
the .debug_abbrev section for the abbrev. */
Dwarf_Byte_Ptr abl_abbrev_ptr;
/* The number of at/form[/implicitvalue] pairs
in this abbrev. */
Dwarf_Unsigned abl_abbrev_count;
Dwarf_Unsigned abl_implicit_const_count;
/* For indirect can only be completed at a real
point in the program, not just on the
.debug_abbrev content, and we want to know
of it at the first encounter. */
Dwarf_Bool abl_has_form_indirect;
/* The following are the decoded attribte and
FORM pairs, abl_abbrev_count of them. */
Dwarf_Half *abl_attr;
Dwarf_Half *abl_form;
/* If there are any DW_FORM_implicit_const
in *abl_form array the following is
an array of abl_abbrev_count slots
for an implicit const value. */
Dwarf_Signed *abl_implicit_const;
};

331
src/lib/libdwarf/dwarf_dsc.c vendored Normal file
View File

@ -0,0 +1,331 @@
/*
Copyright (C) 2016-2020 David Anderson. All Rights Reserved.
This program is free software; you can redistribute it
and/or modify it under the terms of version 2.1 of the
GNU Lesser General Public License as published by the Free
Software Foundation.
This program is distributed in the hope that it would be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
Further, this software is distributed without any warranty
that it is free of the rightful claim of any third person
regarding infringement or the like. Any license provided
herein, whether implied or otherwise, applies only to this
software file. Patent licenses, if any, provided herein
do not apply to combinations of this program with other
software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write the
Free Software Foundation, Inc., 51 Franklin Street - Fifth
Floor, Boston MA 02110-1301, USA.
*/
#include <config.h>
#include <stdlib.h> /* calloc() free() */
#include <string.h> /* memcpy() */
#if defined(_WIN32) && defined(HAVE_STDAFX_H)
#include "stdafx.h"
#endif /* HAVE_STDAFX_H */
#include "dwarf.h"
#include "libdwarf.h"
#include "libdwarf_private.h"
#include "dwarf_base_types.h"
#include "dwarf_opaque.h"
#include "dwarf_alloc.h"
#include "dwarf_error.h"
#include "dwarf_util.h"
#include "dwarf_dsc.h"
/* When called with ary and *arraycount 0
this just counts the elements found.
Otherwise it records the values in ary and
recounts. The arraycount pointer must be
passed-in non-null always. */
static int
get_dsc_leb_entries(Dwarf_Debug dbg,
Dwarf_Small * blockpointer,
Dwarf_Unsigned blocklen,
int dounsigned,
struct Dwarf_Dsc_Entry_s *ary,
size_t * arraycount,
Dwarf_Error * error)
{
Dwarf_Small *p = blockpointer;
Dwarf_Small *endp = blockpointer + blocklen;
size_t larraycount = 0;
size_t iarraycount = *arraycount;
if (!ary) {
if (iarraycount) {
/* Internal botch calling this static function. */
_dwarf_error(dbg, error, DW_DLE_DISCR_ARRAY_ERROR);
return DW_DLV_ERROR;
} else {}
} else {
if (!iarraycount) {
/* Internal botch calling this static function. */
_dwarf_error(dbg, error, DW_DLE_DISCR_ARRAY_ERROR);
return DW_DLV_ERROR;
} else {}
}
if (dounsigned) {
while (p < endp) {
Dwarf_Unsigned dsc = 0;
Dwarf_Unsigned low = 0;
Dwarf_Unsigned high = 0;
if (ary && (larraycount >= iarraycount)) {
_dwarf_error(dbg, error, DW_DLE_DISCR_ARRAY_ERROR);
return DW_DLV_ERROR;
}
DECODE_LEB128_UWORD_CK(p,dsc,
dbg,error,endp);
if (!dsc) {
DECODE_LEB128_UWORD_CK(p,low,
dbg,error,endp);
} else {
DECODE_LEB128_UWORD_CK(p,low,
dbg,error,endp);
DECODE_LEB128_UWORD_CK(p,high,
dbg,error,endp);
}
if (ary) {
struct Dwarf_Dsc_Entry_s *arye =
ary+larraycount;
/* type reads the same as uleb and leb because
it is only zero or one. */
arye->dsc_type = (Dwarf_Half)dsc;
arye->dsc_low_u = low;
arye->dsc_high_u = high;
}
larraycount++;
}
} else {
while (p < endp) {
Dwarf_Signed dsc = 0;
Dwarf_Signed low = 0;
Dwarf_Signed high = 0;
Dwarf_Unsigned leblen = 0;
(void)leblen;
if (ary && (larraycount >= iarraycount)) {
_dwarf_error(dbg, error, DW_DLE_DISCR_ARRAY_ERROR);
return DW_DLV_ERROR;
}
DECODE_LEB128_SWORD_LEN_CK(p,dsc,
leblen,dbg,error,endp);
if (!dsc) {
DECODE_LEB128_SWORD_LEN_CK(p,low,
leblen,dbg,error,endp);
} else {
DECODE_LEB128_SWORD_LEN_CK(p,low,
leblen,dbg,error,endp);
DECODE_LEB128_SWORD_LEN_CK(p,high,
leblen,dbg,error,endp);
}
if (ary) {
struct Dwarf_Dsc_Entry_s *arye =
ary+larraycount;
/* type reads the same as uleb and leb because
it is only zero or one. */
arye->dsc_type = (Dwarf_Half)dsc;
arye->dsc_low_s = low;
arye->dsc_high_s = high;
}
larraycount++;
}
}
if (ary) {
/* Just verify this recount matches original */
if (iarraycount != larraycount) {
_dwarf_error(dbg, error, DW_DLE_DISCR_ARRAY_ERROR);
return DW_DLV_ERROR;
}
} else {
/* This matters for first call with
ary 0 and iarraycount 0 as we are generating the
count. */
*arraycount = larraycount;
}
return DW_DLV_OK;
}
int dwarf_discr_list(Dwarf_Debug dbg,
Dwarf_Small * blockpointer,
Dwarf_Unsigned blocklen,
Dwarf_Dsc_Head * dsc_head_out,
Dwarf_Unsigned * dsc_array_length_out,
Dwarf_Error * error)
{
Dwarf_Dsc_Head h = 0;
int res = 0;
size_t arraycount = 0;
struct Dwarf_Dsc_Entry_s *ary = 0;
Dwarf_Small * dscblockp = 0;
Dwarf_Unsigned dscblocklen = 0;
if (!dbg){
_dwarf_error(NULL, error, DW_DLE_DBG_NULL); \
return DW_DLV_ERROR;
}
if (blocklen == 0) {
return DW_DLV_NO_ENTRY;
}
dscblockp = (Dwarf_Small *)calloc(blocklen,sizeof(Dwarf_Small));
if (!dscblockp) {
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
return DW_DLV_ERROR;
}
dscblocklen = blocklen;
memcpy(dscblockp,blockpointer,blocklen);
res = get_dsc_leb_entries(dbg,dscblockp,dscblocklen,
/* TRUE or FALSE here is not important, the arraycount
returned to us will be identical either way. */
FALSE, 0, &arraycount,error);
if (res != DW_DLV_OK) {
free(dscblockp);
return res;
}
h = (Dwarf_Dsc_Head)_dwarf_get_alloc(dbg,DW_DLA_DSC_HEAD,1);
if (!h) {
free(dscblockp);
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
return DW_DLV_ERROR;
}
h->dsh_block = dscblockp;
h->dsh_block_len = dscblocklen;
h->dsh_debug = dbg;
/* Now the destructor for h will deal with block malloc space. */
ary = (struct Dwarf_Dsc_Entry_s *)calloc(arraycount,
sizeof(struct Dwarf_Dsc_Entry_s));
if (!ary) {
dwarf_dealloc(dbg,h,DW_DLA_DSC_HEAD);
_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
return DW_DLV_ERROR;
}
h->dsh_count = arraycount;
h->dsh_array = ary;
h->dsh_set_unsigned = 0;
h->dsh_set_signed = 0;
*dsc_head_out = h;
*dsc_array_length_out = arraycount;
return DW_DLV_OK;
}
/* NEW September 2016. Allows easy access to DW_AT_discr_list
entry. Callers must know which is the appropriate
one of the following two interfaces, though both
will work. */
int
dwarf_discr_entry_u(Dwarf_Dsc_Head dsh ,
Dwarf_Unsigned entrynum,
Dwarf_Half * out_type,
Dwarf_Unsigned * out_discr_low,
Dwarf_Unsigned * out_discr_high,
Dwarf_Error * error)
{
struct Dwarf_Dsc_Entry_s *dse = 0;
(void)error;
if (entrynum >= dsh->dsh_count) {
return DW_DLV_NO_ENTRY;
}
if (!dsh->dsh_set_unsigned) {
int res =0;
int dounsigned = 1;
size_t count = dsh->dsh_count;
res = get_dsc_leb_entries(dsh->dsh_debug,
dsh->dsh_block,
dsh->dsh_block_len,
dounsigned,
dsh->dsh_array,
&count,
error);
if (res != DW_DLV_OK) {
return res;
}
dsh->dsh_set_unsigned = TRUE;
}
if (!dsh->dsh_array) {
_dwarf_error(dsh->dsh_debug, error, DW_DLE_DISCR_ARRAY_ERROR);
return DW_DLV_ERROR;
}
dse = dsh->dsh_array + entrynum;
*out_type = dse->dsc_type;
*out_discr_low = dse->dsc_low_u;
*out_discr_high = dse->dsc_high_u;
return DW_DLV_OK;
}
/* NEW September 2016. Allows easy access to DW_AT_discr_list
entry. */
int
dwarf_discr_entry_s(Dwarf_Dsc_Head dsh,
Dwarf_Unsigned entrynum,
Dwarf_Half * out_type,
Dwarf_Signed * out_discr_low,
Dwarf_Signed * out_discr_high,
Dwarf_Error * error)
{
struct Dwarf_Dsc_Entry_s *dse = 0;
(void)error;
if (entrynum >= dsh->dsh_count) {
return DW_DLV_NO_ENTRY;
}
if (!dsh->dsh_set_signed) {
int res =0;
int dounsigned = 0;
size_t count = dsh->dsh_count;
res = get_dsc_leb_entries(dsh->dsh_debug,
dsh->dsh_block,
dsh->dsh_block_len,
dounsigned,
dsh->dsh_array,
&count,
error);
if (res != DW_DLV_OK) {
return res;
}
dsh->dsh_set_signed = TRUE;
}
if (!dsh->dsh_array) {
_dwarf_error(dsh->dsh_debug, error, DW_DLE_DISCR_ARRAY_ERROR);
return DW_DLV_ERROR;
}
dse = dsh->dsh_array + entrynum;
*out_type = dse->dsc_type;
*out_discr_low = dse->dsc_low_s;
*out_discr_high = dse->dsc_high_s;
return DW_DLV_OK;
}
void
_dwarf_dsc_destructor(void *m)
{
Dwarf_Dsc_Head h = (Dwarf_Dsc_Head) m;
free(h->dsh_array);
h->dsh_array = 0;
free(h->dsh_block);
h->dsh_block = 0;
h->dsh_count = 0;
}

59
src/lib/libdwarf/dwarf_dsc.h vendored Normal file
View File

@ -0,0 +1,59 @@
/*
Copyright (C) 2016-2023 David Anderson. All Rights Reserved.
This program is free software; you can redistribute it
and/or modify it under the terms of version 2.1 of the
GNU Lesser General Public License as published by the Free
Software Foundation.
This program is distributed in the hope that it would be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
Further, this software is distributed without any warranty
that it is free of the rightful claim of any third person
regarding infringement or the like. Any license provided
herein, whether implied or otherwise, applies only to this
software file. Patent licenses, if any, provided herein
do not apply to combinations of this program with other
software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write the
Free Software Foundation, Inc., 51 Franklin Street - Fifth
Floor, Boston MA 02110-1301, USA.
*/
/* dsc_type: if 0, then dsc_low is a single discriminant value
and dsc_high is zero..
If 1, then dsc_low, dsc_high are a discriminant range
All the messy complexity here is so we can have both
a set of values read as uleb and as sleb.
We make our own copy of the block for the same reason.
*/
struct Dwarf_Dsc_Entry_s {
/* Type is a 1 byte leb that reads the same as sleb or uleb
because its value can only be zero or one. */
Dwarf_Half dsc_type;
Dwarf_Unsigned dsc_low_u;
Dwarf_Unsigned dsc_high_u;
Dwarf_Signed dsc_low_s;
Dwarf_Signed dsc_high_s;
};
struct Dwarf_Dsc_Head_s {
Dwarf_Debug dsh_debug;
Dwarf_Unsigned dsh_count;
Dwarf_Small *dsh_block;
Dwarf_Unsigned dsh_block_len;
/* Following two are flags to tell us whether
lebs already read in a given signedness. */
Dwarf_Bool dsh_set_unsigned;
Dwarf_Bool dsh_set_signed;
struct Dwarf_Dsc_Entry_s *dsh_array;
};
void _dwarf_dsc_destructor(void *m);

47
src/lib/libdwarf/dwarf_elf_access.h vendored Normal file
View File

@ -0,0 +1,47 @@
#ifndef _DWARF_ELF_PORT_H
#define _DWARF_ELF_PORT_H
/*
Copyright (C) 2008-2023 David Anderson. All rights reserved.
Portions Copyright 2008-2010 Arxan Technologies, Inc. All rights reserved.
This program is free software; you can redistribute it
and/or modify it under the terms of version 2.1 of the
GNU Lesser General Public License as published by the Free
Software Foundation.
This program is distributed in the hope that it would be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
Further, this software is distributed without any warranty
that it is free of the rightful claim of any third person
regarding infringement or the like. Any license provided
herein, whether implied or otherwise, applies only to this
software file. Patent licenses, if any, provided herein
do not apply to combinations of this program with other
software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write the
Free Software Foundation, Inc., 51 Franklin Street - Fifth
Floor, Boston MA 02110-1301, USA.
*/
/* libelf) object access for the generic
object file interface */
int
dwarf_elf_object_access_init(void * elf ,
int libdwarf_owns_elf,
Dwarf_Obj_Access_Interface** ret_obj,
int *err );
void
dwarf_elf_object_access_finish(Dwarf_Obj_Access_Interface* obj );
/* End ELF object access for the generic object file interface */
#endif

1118
src/lib/libdwarf/dwarf_elf_defines.h vendored Normal file

File diff suppressed because it is too large Load Diff

2230
src/lib/libdwarf/dwarf_elf_load_headers.c vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,368 @@
/*
Copyright (c) 2019, David Anderson
All rights reserved.
cc
Redistribution and use in source and binary forms, with
or without modification, are permitted provided that the
following conditions are met:
Redistributions of source code must retain the above
copyright notice, this list of conditions and the following
disclaimer.
Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include "dwarf_elf_defines.h"
#include "dwarf_elf_rel_detector.h"
unsigned
_dwarf_is_32bit_abs_reloc(unsigned int type, unsigned machine)
{
unsigned r = 0;
switch (machine) {
#if defined(EM_MIPS) && defined (R_MIPS_32)
case EM_MIPS:
r = (0
#if defined (R_MIPS_32)
| (type == R_MIPS_32)
#endif
#if defined (R_MIPS_TLS_DTPREL32)
| (type == R_MIPS_TLS_DTPREL32)
#endif /* DTPREL32 */
);
break;
#endif /* MIPS case */
#if defined(EM_SPARC32PLUS) && defined (R_SPARC_UA32)
case EM_SPARC32PLUS:
r = (0
#if defined(R_SPARC_UA32)
| (type == R_SPARC_UA32)
#endif
#if defined(R_SPARC_TLS_DTPOFF32)
| (type == R_SPARC_TLS_DTPOFF32)
#endif
);
break;
#endif
#if defined(EM_SPARCV9) && defined (R_SPARC_UA32)
case EM_SPARCV9:
r = (type == R_SPARC_UA32);
break;
#endif
#if defined(EM_SPARC) && defined (R_SPARC_UA32)
case EM_SPARC:
r = (0
#if defined(R_SPARC_UA32)
| (type == R_SPARC_UA32)
#endif
#if (R_SPARC_TLS_DTPOFF32)
| (type == R_SPARC_TLS_DTPOFF32)
#endif
);
break;
#endif /* EM_SPARC */
#if defined(EM_386) && defined (R_386_32) && defined (R_386_PC32)
case EM_386:
r = (0
#if defined (R_386_32)
| (type == R_386_32)
#endif
#if defined (R_386_GOTPC)
| (type == R_386_GOTPC)
#endif
#if defined (R_386_PC32)
| (type == R_386_PC32)
#endif
#if defined (R_386_TLS_LDO_32)
| (type == R_386_TLS_LDO_32)
#endif
#if defined (R_386_TLS_DTPOFF32)
| (type == R_386_TLS_DTPOFF32)
#endif
);
break;
#endif /* EM_386 */
#if defined (EM_SH) && defined (R_SH_DIR32)
case EM_SH:
r = (0
#if defined (R_SH_DIR32)
| (type == R_SH_DIR32)
#endif
#if defined (R_SH_DTPOFF32)
| (type == R_SH_TLS_DTPOFF32)
#endif
);
break;
#endif /* SH */
#if defined(EM_IA_64) && defined (R_IA64_SECREL32LSB)
case EM_IA_64: /* 32bit? ! */
r = (0
#if defined (R_IA64_SECREL32LSB)
| (type == R_IA64_SECREL32LSB)
#endif
#if defined (R_IA64_DIR32LSB)
| (type == R_IA64_DIR32LSB)
#endif
#if defined (R_IA64_DTPREL32LSB)
| (type == R_IA64_DTPREL32LSB)
#endif
);
break;
#endif /* EM_IA_64 */
#if defined(EM_ARM) && defined (R_ARM_ABS32)
case EM_ARM:
case EM_AARCH64:
r = (0
#if defined (R_ARM_ABS32)
| ( type == R_ARM_ABS32)
#endif
#if defined (R_AARCH64_ABS32)
| ( type == R_AARCH64_ABS32)
#endif
#if defined (R_ARM_TLS_LDO32)
| ( type == R_ARM_TLS_LDO32)
#endif
);
break;
#endif /* EM_ARM */
/* On FreeBSD xR_PPC64_ADDR32 not defined
so we use the xR_PPC_ names which
have the proper value.
Our headers have:
xR_PPC64_ADDR64 38
xR_PPC_ADDR32 1 so we use this one
xR_PPC64_ADDR32 R_PPC_ADDR32
xR_PPC64_DTPREL32 110 which may be wrong/unavailable
xR_PPC64_DTPREL64 78
xR_PPC_DTPREL32 78
*/
#if defined(EM_PPC64) && defined (R_PPC_ADDR32)
case EM_PPC64:
r = (0
#if defined(R_PPC_ADDR32)
| (type == R_PPC_ADDR32)
#endif
#if defined(R_PPC64_DTPREL32)
| (type == R_PPC64_DTPREL32)
#endif
);
break;
#endif /* EM_PPC64 */
#if defined(EM_PPC) && defined (R_PPC_ADDR32)
case EM_PPC:
r = (0
#if defined (R_PPC_ADDR32)
| (type == R_PPC_ADDR32)
#endif
#if defined (R_PPC_DTPREL32)
| (type == R_PPC_DTPREL32)
#endif
);
break;
#endif /* EM_PPC */
#if defined(EM_S390) && defined (R_390_32)
case EM_S390:
r = (0
#if defined (R_390_32)
| (type == R_390_32)
#endif
#if defined (R_390_TLS_LDO32)
| (type == R_390_TLS_LDO32)
#endif
);
break;
#endif /* EM_S390 */
#if defined(EM_X86_64) && \
( defined(R_X86_64_32) || defined(R_X86_64_PC32) ||\
defined(R_X86_64_DTPOFF32) )
#if defined(EM_K10M)
case EM_K10M:
#endif
#if defined(EM_L10M)
case EM_L10M:
#endif
case EM_X86_64:
r = (0
#if defined (R_X86_64_PC32)
| (type == R_X86_64_PC32)
#endif
#if defined (R_X86_64_32)
| (type == R_X86_64_32)
#endif
#if defined (R_X86_64_DTPOFF32)
| (type == R_X86_64_DTPOFF32)
#endif
);
break;
#endif /* EM_X86_64 */
case EM_QUALCOMM_DSP6:
r = (type == R_QUALCOMM_REL32);
break;
default: break;
}
return r;
}
unsigned
_dwarf_is_64bit_abs_reloc(unsigned int type, unsigned machine)
{
unsigned r = 0;
switch (machine) {
#if defined(EM_MIPS) && defined (R_MIPS_64)
case EM_MIPS:
r = (0
#if defined (R_MIPS_64)
| (type == R_MIPS_64)
#endif
#if defined (R_MIPS_32)
| (type == R_MIPS_32)
#endif
#if defined(R_MIPS_TLS_DTPREL64)
| (type == R_MIPS_TLS_DTPREL64)
#endif
);
break;
#endif /* EM_MIPS */
#if defined(EM_SPARC32PLUS) && defined (R_SPARC_UA64)
case EM_SPARC32PLUS:
r = (type == R_SPARC_UA64);
break;
#endif
#if defined(EM_SPARCV9) && defined (R_SPARC_UA64)
case EM_SPARCV9:
r = (0
#if defined (R_SPARC_UA64)
| (type == R_SPARC_UA64)
#endif
#if defined (R_SPARC_TLS_DTPOFF64)
| (type == R_SPARC_TLS_DTPOFF64)
#endif
);
break;
#endif
#if defined(EM_SPARC) && defined (R_SPARC_UA64)
case EM_SPARC:
r = (0
#if defined(R_SPARC_UA64)
| (type == R_SPARC_UA64)
#endif
#if defined (R_SPARC_TLS_DTPOFF64)
| (type == R_SPARC_TLS_DTPOFF64)
#endif
);
break;
#endif /* EM_SPARC */
#if defined(EM_IA_64) && defined (R_IA64_SECREL64LSB)
case EM_IA_64: /* 64bit */
r = (0
#if defined (R_IA64_SECREL64LSB)
| (type == R_IA64_SECREL64LSB)
#endif
#if defined (R_IA64_SECREL32LSB)
| (type == R_IA64_SECREL32LSB)
#endif
#if defined (R_IA64_DIR64LSB)
| (type == R_IA64_DIR64LSB)
#endif
#if defined (R_IA64_DTPREL64LSB)
| (type == R_IA64_DTPREL64LSB)
#endif
#if defined (R_IA64_REL32LSB)
| (type == R_IA64_REL32LSB)
#endif
);
break;
#endif /* EM_IA_64 */
#if defined(EM_PPC64) && defined (R_PPC64_ADDR64)
case EM_PPC64:
r = (0
#if defined(R_PPC64_ADDR64)
| (type == R_PPC64_ADDR64)
#endif
#if defined(R_PPC64_DTPREL64)
| (type == R_PPC64_DTPREL64)
#endif
);
break;
#endif /* EM_PPC64 */
#if defined(EM_S390) && defined (R_390_64)
case EM_S390:
r = (0
#if defined(R_390_64)
| (type == R_390_64)
#endif
#if defined(R_390_TLS_LDO64)
| (type == R_390_TLS_LDO64)
#endif
);
break;
#endif /* EM_390 */
#if defined(EM_X86_64) && defined (R_X86_64_64)
#if defined(EM_K10M)
case EM_K10M:
#endif
#if defined(EM_L10M)
case EM_L10M:
#endif
case EM_X86_64:
r = (0
#if defined (R_X86_64_64)
| (type == R_X86_64_64)
#endif
#if defined (R_X86_64_PC64)
| (type == R_X86_64_PC64)
#endif
#if defined (R_X86_64_DTPOFF32)
| (type == R_X86_64_DTPOFF64)
#endif
);
break;
#endif /* EM_X86_64 */
#if defined(EM_AARCH64) && defined (R_AARCH64_ABS64)
case EM_AARCH64:
r = (0
#if defined (R_AARCH64_ABS64)
| ( type == R_AARCH64_ABS64)
#endif
);
break;
#endif /* EM_AARCH64 */
default: break;
}
return r;
}

View File

@ -0,0 +1,48 @@
/* Copyright (c) 2019-2023, David Anderson
All rights reserved.
Redistribution and use in source and binary forms, with
or without modification, are permitted provided that the
following conditions are met:
Redistributions of source code must retain the above
copyright notice, this list of conditions and the following
disclaimer.
Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef DWARF_ELF_REL_DETECTOR_H
#define DWARF_ELF_REL_DETECTOR_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
unsigned _dwarf_is_32bit_abs_reloc(unsigned int type,
unsigned machine);
unsigned _dwarf_is_64bit_abs_reloc(unsigned int type,
unsigned machine);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* DWARF_ELF_REL_DETECTOR_H */

809
src/lib/libdwarf/dwarf_elfread.c vendored Normal file
View File

@ -0,0 +1,809 @@
/*
Copyright (c) 2019, David Anderson
All rights reserved.
cc
Redistribution and use in source and binary forms, with
or without modification, are permitted provided that the
following conditions are met:
Redistributions of source code must retain the above
copyright notice, this list of conditions and the following
disclaimer.
Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* This file reads the parts of an Elf
file appropriate to reading DWARF debugging data.
Overview:
_dwarf_elf_nlsetup() Does all elf setup.
calls _dwarf_elf_access_init()
calls _dwarf_elf_object_access_internals_init()
Creates internals record 'M',
dwarf_elf_object_access_internals_t
Sets flags/data in internals record
Loads elf object data needed later.
Sets methods struct to access elf object.
calls _dwarf_object_init_b() Creates Dwarf_Debug, independent
of any elf code.
Sets internals record into dbg.
----------------------
_dwarf_destruct_elf_nlaccess(). This frees
the elf internals record created in
_dwarf_elf_object_access_internals_init()
in case of errors during setup or when
dwarf_finish() is called. Works safely for
partially or fully set-up elf internals record.
Other than in _dwarf_elf_nlsetup() the elf code
knows nothing about Dwarf_Debug, and the rest of
libdwarf knows nothing about the content of the
object-type-specific (for Elf here)
internals record.
*/
#include <config.h>
#include <stddef.h> /* size_t */
#include <stdlib.h> /* free() malloc() */
#include <stdio.h> /* debug printf */
#include <string.h> /* memset() strdup() strncmp() */
#ifdef _WIN32
#ifdef HAVE_STDAFX_H
#include "stdafx.h"
#endif /* HAVE_STDAFX_H */
#include <io.h> /* close() off_t */
#elif defined HAVE_UNISTD_H
#include <unistd.h> /* close() off_t */
#endif /* _WIN32*/
#include "dwarf.h"
#include "libdwarf.h"
#include "libdwarf_private.h"
#include "dwarf_base_types.h"
#include "dwarf_opaque.h"
#include "dwarf_error.h" /* for _dwarf_error() declaration */
#include "dwarf_reading.h"
#include "dwarf_memcpy_swap.h"
#include "dwarf_object_read_common.h"
#include "dwarf_object_detector.h"
#include "dwarf_elfstructs.h"
#include "dwarf_elf_defines.h"
#include "dwarf_elf_rel_detector.h"
#include "dwarf_elfread.h"
#ifndef TYP
#define TYP(n,l) char (n)[(l)]
#endif /* TYPE */
#ifdef WORDS_BIGENDIAN
#define READ_UNALIGNED_SAFE(dbg,dest, source, length) \
do { \
Dwarf_Unsigned _ltmp = 0; \
(dbg)->de_copy_word( (((char *)(&_ltmp)) + \
sizeof(_ltmp) - length),(source),(length)); \
dest = _ltmp; \
} while (0)
#define WRITE_UNALIGNED_LOCAL(dbg,dest,source, srclength,len_out) \
{ \
(dbg)->de_copy_word((dest), \
((char *)(source)) +(srclength)-(len_out), \
(len_out)) ; \
}
#else /* LITTLE ENDIAN */
#define READ_UNALIGNED_SAFE(dbg,dest, source, srclength) \
do { \
Dwarf_Unsigned _ltmp = 0; \
dbg->de_copy_word( (char *)(&_ltmp), \
(source), (srclength)) ; \
dest = _ltmp; \
} while (0)
#define WRITE_UNALIGNED_LOCAL(dbg,dest,source, srclength,len_out) \
{ \
dbg->de_copy_word( (dest) , \
((char *)(source)) , \
(len_out)) ; \
}
#endif /* *-ENDIAN */
static int
_dwarf_elf_object_access_init(
int fd,
unsigned ftype,
unsigned endian,
unsigned offsetsize,
size_t filesize,
Dwarf_Obj_Access_Interface_a **binary_interface,
int *localerrnum);
static Dwarf_Small elf_get_nolibelf_byte_order (void *obj)
{
dwarf_elf_object_access_internals_t *elf =
(dwarf_elf_object_access_internals_t*)(obj);
return (Dwarf_Small)elf->f_endian;
}
static Dwarf_Small elf_get_nolibelf_length_size (void *obj)
{
dwarf_elf_object_access_internals_t *elf =
(dwarf_elf_object_access_internals_t*)(obj);
return elf->f_offsetsize/8;
}
static Dwarf_Small elf_get_nolibelf_pointer_size (void *obj)
{
dwarf_elf_object_access_internals_t *elf =
(dwarf_elf_object_access_internals_t*)(obj);
return elf->f_pointersize/8;
}
static Dwarf_Unsigned elf_get_nolibelf_file_size(void *obj)
{
dwarf_elf_object_access_internals_t *elf =
(dwarf_elf_object_access_internals_t*)(obj);
return elf->f_filesize;
}
static Dwarf_Unsigned elf_get_nolibelf_section_count (void *obj)
{
dwarf_elf_object_access_internals_t *elf =
(dwarf_elf_object_access_internals_t*)(obj);
return elf->f_loc_shdr.g_count;
}
static int elf_get_nolibelf_section_info(void *obj,
Dwarf_Unsigned section_index,
Dwarf_Obj_Access_Section_a *return_section,
int *error)
{
dwarf_elf_object_access_internals_t *elf =
(dwarf_elf_object_access_internals_t*)(obj);
(void)error;
if (section_index < elf->f_loc_shdr.g_count) {
struct generic_shdr *sp = 0;
sp = elf->f_shdr + section_index;
return_section->as_addr = sp->gh_addr;
return_section->as_type = sp->gh_type;
return_section->as_size = sp->gh_size;
return_section->as_name = sp->gh_namestring;
return_section->as_link = sp->gh_link;
return_section->as_info = sp->gh_info;
return_section->as_flags = sp->gh_flags;
return_section->as_entrysize = sp->gh_entsize;
return_section->as_offset = sp->gh_offset;
return DW_DLV_OK;
}
return DW_DLV_NO_ENTRY;
}
static int
elf_load_nolibelf_section (void *obj, Dwarf_Unsigned section_index,
Dwarf_Small **return_data, int *error)
{
/* Linux kernel read size limit 0x7ffff000,
Without any good reason, limit our reads
to a bit less. */
const Dwarf_Unsigned read_size_limit = 0x7ff00000;
Dwarf_Unsigned read_offset = 0;
Dwarf_Unsigned read_size = 0;
Dwarf_Unsigned remaining_bytes = 0;
Dwarf_Small * read_target = 0;
dwarf_elf_object_access_internals_t *elf =
(dwarf_elf_object_access_internals_t*)(obj);
if (0 < section_index &&
section_index < elf->f_loc_shdr.g_count) {
int res = 0;
struct generic_shdr *sp =
elf->f_shdr + section_index;
if (sp->gh_content) {
*return_data = (Dwarf_Small *)sp->gh_content;
return DW_DLV_OK;
}
if (!sp->gh_size) {
return DW_DLV_NO_ENTRY;
}
/* Guarding against bad values and
against overflow */
if (sp->gh_size > elf->f_filesize ||
sp->gh_offset > elf->f_filesize ||
(sp->gh_size + sp->gh_offset) >
elf->f_filesize) {
*error = DW_DLE_ELF_SECTION_ERROR;
return DW_DLV_ERROR;
}
sp->gh_content = malloc((size_t)sp->gh_size);
if (!sp->gh_content) {
*error = DW_DLE_ALLOC_FAIL;
return DW_DLV_ERROR;
}
/* Linux has a 2GB limit on read size.
So break this into 2gb pieces. */
remaining_bytes = sp->gh_size;
read_size = remaining_bytes;
read_offset = sp->gh_offset;
read_target = (Dwarf_Small*)sp->gh_content;
for ( ; remaining_bytes > 0; read_size = remaining_bytes ) {
if (read_size > read_size_limit) {
read_size = read_size_limit;
}
res = RRMOA(elf->f_fd,
(void *)read_target, (off_t)read_offset,
(size_t)read_size,
(off_t)elf->f_filesize, error);
if (res != DW_DLV_OK) {
free(sp->gh_content);
sp->gh_content = 0;
return res;
}
remaining_bytes -= read_size;
read_offset += read_size;
read_target += read_size;
}
*return_data = (Dwarf_Small *)sp->gh_content;
return DW_DLV_OK;
}
return DW_DLV_NO_ENTRY;
}
#define MATCH_REL_SEC(i_,s_,r_) \
if ((i_) == (s_).dss_index) { \
*(r_) = &(s_); \
return DW_DLV_OK; \
}
static int
find_section_to_relocate(Dwarf_Debug dbg,Dwarf_Unsigned section_index,
struct Dwarf_Section_s **relocatablesec, int *error)
{
MATCH_REL_SEC(section_index,dbg->de_debug_info,relocatablesec);
MATCH_REL_SEC(section_index,dbg->de_debug_abbrev,relocatablesec);
MATCH_REL_SEC(section_index,dbg->de_debug_line,relocatablesec);
MATCH_REL_SEC(section_index,dbg->de_debug_loc,relocatablesec);
MATCH_REL_SEC(section_index,dbg->de_debug_aranges,relocatablesec);
MATCH_REL_SEC(section_index,dbg->de_debug_macinfo,relocatablesec);
MATCH_REL_SEC(section_index,dbg->de_debug_pubnames,
relocatablesec);
MATCH_REL_SEC(section_index,dbg->de_debug_names,
relocatablesec);
MATCH_REL_SEC(section_index,dbg->de_debug_ranges,relocatablesec);
MATCH_REL_SEC(section_index,dbg->de_debug_frame,
relocatablesec);
MATCH_REL_SEC(section_index,dbg->de_debug_frame_eh_gnu,
relocatablesec);
MATCH_REL_SEC(section_index,dbg->de_debug_pubtypes,
relocatablesec);
MATCH_REL_SEC(section_index,dbg->de_debug_funcnames,
relocatablesec);
MATCH_REL_SEC(section_index,dbg->de_debug_typenames,
relocatablesec);
MATCH_REL_SEC(section_index,dbg->de_debug_varnames,
relocatablesec);
MATCH_REL_SEC(section_index,dbg->de_debug_weaknames,
relocatablesec);
MATCH_REL_SEC(section_index,dbg->de_debug_types,relocatablesec);
MATCH_REL_SEC(section_index,dbg->de_debug_macro,relocatablesec);
MATCH_REL_SEC(section_index,dbg->de_debug_rnglists,
relocatablesec);
MATCH_REL_SEC(section_index,dbg->de_debug_loclists,
relocatablesec);
MATCH_REL_SEC(section_index,dbg->de_debug_aranges,
relocatablesec);
MATCH_REL_SEC(section_index,dbg->de_debug_sup,
relocatablesec);
MATCH_REL_SEC(section_index,dbg->de_debug_str_offsets,
relocatablesec);
MATCH_REL_SEC(section_index,dbg->de_debug_addr,relocatablesec);
MATCH_REL_SEC(section_index,dbg->de_debug_gnu_pubnames,
relocatablesec);
MATCH_REL_SEC(section_index,dbg->de_debug_gnu_pubtypes,
relocatablesec);
/* dbg-> de_debug_tu_index,reloctablesec); */
/* dbg-> de_debug_cu_index,reloctablesec); */
/* dbg-> de_debug_gdbindex,reloctablesec); */
/* dbg-> de_debug_str,syms); */
/* de_elf_symtab,syms); */
/* de_elf_strtab,syms); */
*error = DW_DLE_RELOC_SECTION_MISMATCH;
return DW_DLV_ERROR;
}
/* Returns DW_DLV_OK if it works, else DW_DLV_ERROR.
The caller may decide to ignore the errors or report them. */
static int
update_entry(Dwarf_Debug dbg,
dwarf_elf_object_access_internals_t*obj,
struct generic_rela *rela,
Dwarf_Small *target_section,
Dwarf_Unsigned target_section_size,
int *error)
{
unsigned int type = 0;
unsigned int sym_idx = 0;
Dwarf_Unsigned offset = 0;
Dwarf_Signed addend = 0;
Dwarf_Half reloc_size = 0;
Dwarf_Half machine = (Dwarf_Half)obj->f_machine;
struct generic_symentry *symp = 0;
int is_rela = rela->gr_is_rela;
offset = rela->gr_offset;
addend = rela->gr_addend;
type = (unsigned int)rela->gr_type;
sym_idx = (unsigned int)rela->gr_sym;
if (sym_idx >= obj->f_loc_symtab.g_count) {
*error = DW_DLE_RELOC_SECTION_SYMBOL_INDEX_BAD;
return DW_DLV_ERROR;
}
symp = obj->f_symtab + sym_idx;
if (offset >= target_section_size) {
/* If offset really big, any add will overflow.
So lets stop early if offset is corrupt. */
*error = DW_DLE_RELOC_INVALID;
return DW_DLV_ERROR;
}
/* Determine relocation size */
if (_dwarf_is_32bit_abs_reloc(type, machine)) {
reloc_size = 4;
} else if (_dwarf_is_64bit_abs_reloc(type, machine)) {
reloc_size = 8;
} else if (!type) {
/* There is nothing to do. , this is the case such as
R_AARCH64_NONE and R_X86_64_NONE and the other machine
cases have it too. Most object files do not have
any relocation records of type R_<machine>_NONE. */
return DW_DLV_OK;
} else {
*error = DW_DLE_RELOC_SECTION_RELOC_TARGET_SIZE_UNKNOWN;
return DW_DLV_ERROR;
}
if ( (offset + reloc_size) < offset) {
/* Another check for overflow. */
*error = DW_DLE_RELOC_INVALID;
return DW_DLV_ERROR;
}
if ( (offset + reloc_size) > target_section_size) {
*error = DW_DLE_RELOC_INVALID;
return DW_DLV_ERROR;
}
/* Assuming we do not need to do a READ_UNALIGNED here
at target_section + offset and add its value to
outval. Some ABIs say no read (for example MIPS),
but if some do then which ones? */
{ /* .rel. (addend is 0), or .rela. */
Dwarf_Small *targ = target_section+offset;
Dwarf_Unsigned presentval = 0;
Dwarf_Unsigned outval = 0;
if (!is_rela) {
READ_UNALIGNED_SAFE(dbg,presentval,
targ,(unsigned long)reloc_size);
}
/* There is no addend in .rel.
Normally presentval is correct
and st_value will be zero.
But a few compilers have
presentval zero and st_value set. */
outval = presentval + symp->gs_value + addend;
WRITE_UNALIGNED_LOCAL(dbg,targ,
&outval,sizeof(outval),(unsigned long)reloc_size);
}
return DW_DLV_OK;
}
/* Somewhat arbitrarily, we attempt to apply all the
relocations we can
and still notify the caller of at least one error if we found
any errors. */
static int
apply_rela_entries(
Dwarf_Debug dbg,
/* Section_index of the relocation section, .rela entries */
Dwarf_Unsigned r_section_index,
dwarf_elf_object_access_internals_t*obj,
/* relocatablesec is the .debug_info(etc) in Dwarf_Debug */
struct Dwarf_Section_s * relocatablesec,
int *error)
{
int return_res = DW_DLV_OK;
struct generic_shdr * rels_shp = 0;
Dwarf_Unsigned relcount;
Dwarf_Unsigned i = 0;
if (r_section_index >= obj->f_loc_shdr.g_count) {
*error = DW_DLE_SECTION_INDEX_BAD;
return DW_DLV_ERROR;
}
rels_shp = obj->f_shdr + r_section_index;
relcount = rels_shp->gh_relcount;
if (obj->f_ehdr->ge_type != ET_REL) {
/* No relocations to do */
return DW_DLV_OK;
}
if (!relcount) {
/* Nothing to do. */
return DW_DLV_OK;
}
if (!rels_shp->gh_rels) {
/* something wrong. */
*error = DW_DLE_RELOCS_ERROR;
return DW_DLV_ERROR;
}
for (i = 0; i < relcount; i++) {
int res = update_entry(dbg,obj,
rels_shp->gh_rels+i,
relocatablesec->dss_data,
relocatablesec->dss_size,
error);
if (res != DW_DLV_OK) {
/* We try to keep going, not stop. */
return_res = res;
}
}
return return_res;
}
/* Find the section data in dbg and find all the relevant
sections. Then do relocations.
section_index is the index of a .debug_info (for example)
so we have to find the section(s) with relocations
targeting section_index.
Normally there is exactly one such, though.
*/
static int
elf_relocations_nolibelf(void* obj_in,
Dwarf_Unsigned section_index,
Dwarf_Debug dbg,
int* error)
{
int res = DW_DLV_ERROR;
dwarf_elf_object_access_internals_t*obj = 0;
struct Dwarf_Section_s * relocatablesec = 0;
Dwarf_Unsigned section_with_reloc_records = 0;
if (section_index == 0) {
return DW_DLV_NO_ENTRY;
}
obj = (dwarf_elf_object_access_internals_t*)obj_in;
/* The section to relocate must already be loaded into memory.
This just turns section_index into a pointer
to a de_debug_info or other section record in
Dwarf_Debug. */
res = find_section_to_relocate(dbg, section_index,
&relocatablesec, error);
if (res != DW_DLV_OK) {
return res;
}
/* Now we know the Dwarf_Section_s section
we need to relocate.
So lets find the rela section(s) targeting this.
*/
/* Sun and possibly others do not always set
sh_link in .debug_* sections.
So we cannot do full consistency checks.
FIXME: This approach assumes there is only one
relocation section applying to section section_index! */
section_with_reloc_records = relocatablesec->dss_reloc_index;
if (!section_with_reloc_records) {
/* Something is wrong. */
*error = DW_DLE_RELOC_SECTION_MISSING_INDEX;
return DW_DLV_ERROR;
}
/* The relocations, if they exist, have been loaded. */
/* The symtab was already loaded. */
if (!obj->f_symtab || !obj->f_symtab_sect_strings) {
*error = DW_DLE_DEBUG_SYMTAB_ERR;
return DW_DLV_ERROR;
}
if (obj->f_symtab_sect_index != relocatablesec->dss_reloc_link) {
/* Something is wrong. */
*error = DW_DLE_RELOC_MISMATCH_RELOC_INDEX;
return DW_DLV_ERROR;
}
/* We have all the data we need in memory. */
/* Now we apply the relocs in section_with_reloc_records to the
target, relocablesec */
res = apply_rela_entries(dbg,
section_with_reloc_records,
obj, relocatablesec,error);
return res;
}
void
_dwarf_destruct_elf_nlaccess(
struct Dwarf_Obj_Access_Interface_a_s *aip)
{
dwarf_elf_object_access_internals_t *ep = 0;
struct generic_shdr *shp = 0;
Dwarf_Unsigned shcount = 0;
Dwarf_Unsigned i = 0;
ep = (dwarf_elf_object_access_internals_t *)aip->ai_object;
free(ep->f_ehdr);
shp = ep->f_shdr;
shcount = ep->f_loc_shdr.g_count;
for (i = 0; i < shcount; ++i,++shp) {
free(shp->gh_rels);
shp->gh_rels = 0;
free(shp->gh_content);
shp->gh_content = 0;
free(shp->gh_sht_group_array);
shp->gh_sht_group_array = 0;
shp->gh_sht_group_array_count = 0;
}
free(ep->f_shdr);
ep->f_loc_shdr.g_count = 0;
free(ep->f_phdr);
free(ep->f_elf_shstrings_data);
free(ep->f_dynamic);
free(ep->f_symtab_sect_strings);
free(ep->f_dynsym_sect_strings);
free(ep->f_symtab);
free(ep->f_dynsym);
/* if TRUE close f_fd on destruct.*/
if (ep->f_destruct_close_fd) {
close(ep->f_fd);
}
ep->f_ident[0] = 'X';
free(ep->f_path);
free(ep);
free(aip);
}
int
_dwarf_elf_nlsetup(int fd,
char *true_path,
unsigned ftype,
unsigned endian,
unsigned offsetsize,
size_t filesize,
unsigned groupnumber,
Dwarf_Handler errhand,
Dwarf_Ptr errarg,
Dwarf_Debug *dbg,Dwarf_Error *error)
{
Dwarf_Obj_Access_Interface_a *binary_interface = 0;
dwarf_elf_object_access_internals_t *intfc = 0;
int res = DW_DLV_OK;
int localerrnum = 0;
res = _dwarf_elf_object_access_init(
fd,
ftype,endian,offsetsize,filesize,
&binary_interface,
&localerrnum);
if (res != DW_DLV_OK) {
if (res == DW_DLV_NO_ENTRY) {
return res;
}
_dwarf_error(NULL, error, localerrnum);
return DW_DLV_ERROR;
}
/* allocates and initializes Dwarf_Debug,
generic code */
res = dwarf_object_init_b(binary_interface, errhand, errarg,
groupnumber, dbg, error);
if (res != DW_DLV_OK){
_dwarf_destruct_elf_nlaccess(binary_interface);
return res;
}
intfc = binary_interface->ai_object;
intfc->f_path = strdup(true_path);
return res;
}
/* dwarf_elf_access method table for use with non-libelf.
See also the methods table in dwarf_elf_access.c for libelf.
*/
static Dwarf_Obj_Access_Methods_a const elf_nlmethods = {
elf_get_nolibelf_section_info,
elf_get_nolibelf_byte_order,
elf_get_nolibelf_length_size,
elf_get_nolibelf_pointer_size,
elf_get_nolibelf_file_size,
elf_get_nolibelf_section_count,
elf_load_nolibelf_section,
elf_relocations_nolibelf
};
/* On any error this frees internals argument. */
static int
_dwarf_elf_object_access_internals_init(
dwarf_elf_object_access_internals_t * internals,
int fd,
unsigned ftype,
unsigned endian,
unsigned offsetsize,
size_t filesize,
int *errcode)
{
dwarf_elf_object_access_internals_t * intfc = internals;
Dwarf_Unsigned i = 0;
struct Dwarf_Obj_Access_Interface_a_s *localdoas;
int res = 0;
/* Must malloc as _dwarf_destruct_elf_access()
forces that due to other uses. */
localdoas = (struct Dwarf_Obj_Access_Interface_a_s *)
malloc(sizeof(struct Dwarf_Obj_Access_Interface_a_s));
if (!localdoas) {
free(internals);
*errcode = DW_DLE_ALLOC_FAIL;
return DW_DLV_ERROR;
}
memset(localdoas,0,sizeof(struct Dwarf_Obj_Access_Interface_a_s));
/* E is used with libelf. F with this elf reader. */
intfc->f_ident[0] = 'F';
intfc->f_ident[1] = '1';
intfc->f_fd = fd;
intfc->f_is_64bit = ((offsetsize==64)?TRUE:FALSE);
intfc->f_offsetsize = (Dwarf_Small)offsetsize;
intfc->f_pointersize = (Dwarf_Small)offsetsize;
intfc->f_filesize = filesize;
intfc->f_ftype = ftype;
intfc->f_destruct_close_fd = FALSE;
#ifdef WORDS_BIGENDIAN
if (endian == DW_END_little ) {
intfc->f_copy_word = _dwarf_memcpy_swap_bytes;
intfc->f_endian = DW_END_little;
} else {
intfc->f_copy_word = _dwarf_memcpy_noswap_bytes;
intfc->f_endian = DW_END_big;
}
#else /* LITTLE ENDIAN */
if (endian == DW_END_little ) {
intfc->f_copy_word = _dwarf_memcpy_noswap_bytes;
intfc->f_endian = DW_END_little;
} else {
intfc->f_copy_word = _dwarf_memcpy_swap_bytes;
intfc->f_endian = DW_END_big;
}
#endif /* LITTLE- BIG-ENDIAN */
/* The following sets f_machine. */
res = _dwarf_load_elf_header(intfc,errcode);
if (res != DW_DLV_OK) {
localdoas->ai_object = intfc;
localdoas->ai_methods = 0;
_dwarf_destruct_elf_nlaccess(localdoas);
localdoas = 0;
return res;
}
/* Not loading progheaders */
res = _dwarf_load_elf_sectheaders(intfc,errcode);
if (res != DW_DLV_OK) {
localdoas->ai_object = intfc;
localdoas->ai_methods = 0;
_dwarf_destruct_elf_nlaccess(localdoas);
localdoas = 0;
return res;
}
/* We are not looking at symbol strings for now. */
res = _dwarf_load_elf_symstr(intfc,errcode);
if (res == DW_DLV_ERROR) {
localdoas->ai_object = intfc;
localdoas->ai_methods = 0;
_dwarf_destruct_elf_nlaccess(localdoas);
localdoas = 0;
return res;
}
res = _dwarf_load_elf_symtab_symbols(intfc,errcode);
if (res == DW_DLV_ERROR) {
localdoas->ai_object = intfc;
localdoas->ai_methods = 0;
_dwarf_destruct_elf_nlaccess(localdoas);
localdoas = 0;
return res;
}
for ( i = 1; i < intfc->f_loc_shdr.g_count; ++i) {
struct generic_shdr *shp = 0;
Dwarf_Unsigned section_type = 0;
enum RelocRela localrel = RelocIsRela;
shp = intfc->f_shdr +i;
section_type = shp->gh_type;
if (!shp->gh_namestring) {
/* A serious error which we ignore here
as it will be caught elsewhere
if necessary. */
continue;
} else if (section_type == SHT_REL ||
(!strncmp(".rel.",shp->gh_namestring,5))) {
localrel = RelocIsRel;
} else if (section_type == SHT_RELA ||
(!strncmp(".rela.",shp->gh_namestring,6))) {
localrel = RelocIsRela;
} else {
continue;
}
/* ASSERT: local rel is either RelocIsRel or
RelocIsRela. Never any other value. */
/* Possibly we should check if the target section
is one we care about before loading rela
FIXME */
res = _dwarf_load_elf_relx(intfc,i,localrel,errcode);
if (res == DW_DLV_ERROR) {
localdoas->ai_object = intfc;
localdoas->ai_methods = 0;
_dwarf_destruct_elf_nlaccess(localdoas);
localdoas = 0;
return res;
}
}
free(localdoas);
localdoas = 0;
return DW_DLV_OK;
}
static int
_dwarf_elf_object_access_init(
int fd,
unsigned ftype,
unsigned endian,
unsigned offsetsize,
size_t filesize,
Dwarf_Obj_Access_Interface_a **binary_interface,
int *localerrnum)
{
int res = 0;
dwarf_elf_object_access_internals_t *internals = 0;
Dwarf_Obj_Access_Interface_a *intfc = 0;
internals = malloc(sizeof(dwarf_elf_object_access_internals_t));
if (!internals) {
*localerrnum = DW_DLE_ALLOC_FAIL;
/* Impossible case, we hope. Give up. */
return DW_DLV_ERROR;
}
memset(internals,0,sizeof(*internals));
res = _dwarf_elf_object_access_internals_init(internals,
fd,
ftype, endian, offsetsize, filesize,
localerrnum);
if (res != DW_DLV_OK){
return res;
}
intfc = malloc(sizeof(Dwarf_Obj_Access_Interface_a));
if (!intfc) {
/* Impossible case, we hope. Give up. */
free(internals);
*localerrnum = DW_DLE_ALLOC_FAIL;
return DW_DLV_ERROR;
}
/* Initialize the interface struct */
intfc->ai_object = internals;
intfc->ai_methods = &elf_nlmethods;
*binary_interface = intfc;
return DW_DLV_OK;
}

288
src/lib/libdwarf/dwarf_elfread.h vendored Normal file
View File

@ -0,0 +1,288 @@
/* Copyright (c) 2013-2023, David Anderson All rights reserved.
Redistribution and use in source and binary forms, with
or without modification, are permitted provided that the
following conditions are met:
Redistributions of source code must retain the above
copyright notice, this list of conditions and the following
disclaimer.
Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef READELFOBJ_H
#define READELFOBJ_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* Use this for .rel. too. */
struct generic_rela {
Dwarf_Unsigned gr_offset;
Dwarf_Unsigned gr_info;
Dwarf_Unsigned gr_sym; /* From info */
Dwarf_Unsigned gr_type; /* From info */
Dwarf_Signed gr_addend;
unsigned char gr_type2; /*MIPS64*/
unsigned char gr_type3; /*MIPS64*/
/* The following TRUE if .rela. and FALSE if .rel.
if FALSE, gr_addend will be zero. */
int gr_is_rela;
};
/* The following are generic to simplify handling
Elf32 and Elf64. Some fields added where
the two sizes have different extraction code. */
struct generic_ehdr {
unsigned char ge_ident[EI_NIDENT];
Dwarf_Unsigned ge_type;
Dwarf_Unsigned ge_machine;
Dwarf_Unsigned ge_version;
Dwarf_Unsigned ge_entry;
Dwarf_Unsigned ge_phoff;
Dwarf_Unsigned ge_shoff;
Dwarf_Unsigned ge_flags;
Dwarf_Unsigned ge_ehsize;
Dwarf_Unsigned ge_phentsize;
Dwarf_Unsigned ge_phnum;
Dwarf_Unsigned ge_shentsize;
Dwarf_Unsigned ge_shnum;
/* if ge_shnum >= 0xff00 SHN_LORESERVE
Once section zero is read we put the sh_size
member as the true count and set ge_shnum_in_shnum TRUE.
ge_shnum_extended is TRUE if the object used the extension
mechanism */
Dwarf_Bool ge_shnum_in_shnum;
Dwarf_Bool ge_shnum_extended;
/* if section num of sec strings >= 0xff SHN_LORESERVE
this member holds SHN_XINDEX (0xffff) and the real
section string index is the sh_link value of section
0. ge_sstrndx_extended is TRUE if the object used
the extension mechanism */
Dwarf_Unsigned ge_shstrndx;
Dwarf_Bool ge_strndx_in_strndx;
Dwarf_Bool ge_strndx_extended;
};
struct generic_phdr {
Dwarf_Unsigned gp_type;
Dwarf_Unsigned gp_flags;
Dwarf_Unsigned gp_offset;
Dwarf_Unsigned gp_vaddr;
Dwarf_Unsigned gp_paddr;
Dwarf_Unsigned gp_filesz;
Dwarf_Unsigned gp_memsz;
Dwarf_Unsigned gp_align;
};
struct generic_shdr {
Dwarf_Unsigned gh_secnum;
Dwarf_Unsigned gh_name;
const char * gh_namestring;
Dwarf_Unsigned gh_type;
Dwarf_Unsigned gh_flags;
Dwarf_Unsigned gh_addr;
Dwarf_Unsigned gh_offset;
Dwarf_Unsigned gh_size;
Dwarf_Unsigned gh_link;
/* Section index (in an SHT_REL or SHT_RELA section)
of the target section from gh_link. Otherwise 0. */
Dwarf_Unsigned gh_reloc_target_secnum;
Dwarf_Unsigned gh_info;
Dwarf_Unsigned gh_addralign;
Dwarf_Unsigned gh_entsize;
/* Zero unless content read in. Malloc space
of size gh_size, in bytes. For dwarf
and strings mainly. free() this if not null*/
char * gh_content;
/* If a .rel or .rela section this will point
to generic relocation records if such
have been loaded.
free() this if not null. */
Dwarf_Unsigned gh_relcount;
struct generic_rela * gh_rels;
/* For SHT_GROUP based grouping, which
group is this section in. 0 unknown,
1 DW_GROUP_NUMBER_BASE base DWARF,
2 DW_GROUPNUMBER_DWO dwo sections, 3+
are in an SHT_GROUP. GNU uses this.
set with group number (3+) from SHT_GROUP
and the flags should have SHF_GROUP set
if in SHT_GROUP. Must only be in one group? */
Dwarf_Unsigned gh_section_group_number;
/* Content of an SHT_GROUP section as an array
of integers. [0] is the version, which
can only be one(1) . */
Dwarf_Unsigned * gh_sht_group_array;
/* Number of elements in the gh_sht_group_array. */
Dwarf_Unsigned gh_sht_group_array_count;
/* TRUE if .debug_info .eh_frame etc. */
char gh_is_dwarf;
};
struct generic_dynentry {
Dwarf_Unsigned gd_tag;
/* gd_val stands in for d_ptr and d_val union,
the union adds nothing in practice since
we expect ptrsize <= ulongest. */
Dwarf_Unsigned gd_val;
Dwarf_Unsigned gd_dyn_file_offset;
};
struct generic_symentry {
Dwarf_Unsigned gs_name;
Dwarf_Unsigned gs_value;
Dwarf_Unsigned gs_size;
Dwarf_Unsigned gs_info;
Dwarf_Unsigned gs_other;
Dwarf_Unsigned gs_shndx;
/* derived */
Dwarf_Unsigned gs_bind;
Dwarf_Unsigned gs_type;
};
struct location {
const char *g_name;
Dwarf_Unsigned g_offset;
Dwarf_Unsigned g_count;
Dwarf_Unsigned g_entrysize;
Dwarf_Unsigned g_totalsize;
};
typedef struct elf_filedata_s {
/* f_ident[0] == 'E' means it is elf and
elf_filedata_s is the struct involved.
Other means error/corruption of some kind.
f_ident[1] is a version number.
Only version 1 is defined. */
char f_ident[8];
char * f_path; /* non-null if known. Must be freed */
int f_fd;
unsigned f_machine; /* EM_* */
int f_destruct_close_fd;
int f_is_64bit;
unsigned f_endian;
Dwarf_Unsigned f_filesize;
/* Elf size, not DWARF. 32 or 64 */
Dwarf_Small f_offsetsize;
Dwarf_Small f_pointersize;
int f_ftype;
Dwarf_Unsigned f_max_secdata_offset;
Dwarf_Unsigned f_max_progdata_offset;
void (*f_copy_word) (void *, const void *, unsigned long);
struct location f_loc_ehdr;
struct generic_ehdr* f_ehdr;
struct location f_loc_shdr;
struct generic_shdr* f_shdr;
struct location f_loc_phdr;
struct generic_phdr* f_phdr;
char *f_elf_shstrings_data; /* section name strings */
/* length of currentsection. Might be zero..*/
Dwarf_Unsigned f_elf_shstrings_length;
/* size of malloc-d space */
Dwarf_Unsigned f_elf_shstrings_max;
/* This is the .dynamic section */
struct location f_loc_dynamic;
struct generic_dynentry * f_dynamic;
Dwarf_Unsigned f_dynamic_sect_index;
/* .dynsym, .dynstr */
struct location f_loc_dynsym;
struct generic_symentry* f_dynsym;
char *f_dynsym_sect_strings;
Dwarf_Unsigned f_dynsym_sect_strings_max;
Dwarf_Unsigned f_dynsym_sect_strings_sect_index;
Dwarf_Unsigned f_dynsym_sect_index;
/* .symtab .strtab */
struct location f_loc_symtab;
struct generic_symentry* f_symtab;
char * f_symtab_sect_strings;
Dwarf_Unsigned f_symtab_sect_strings_max;
Dwarf_Unsigned f_symtab_sect_strings_sect_index;
Dwarf_Unsigned f_symtab_sect_index;
/* Starts at 3. 0,1,2 used specially. */
Dwarf_Unsigned f_sg_next_group_number;
/* Both the following will be zero unless there
are explicit Elf groups. */
Dwarf_Unsigned f_sht_group_type_section_count;
Dwarf_Unsigned f_shf_group_flag_section_count;
Dwarf_Unsigned f_dwo_group_section_count;
} dwarf_elf_object_access_internals_t;
int dwarf_construct_elf_access(int fd,
const char *path,
dwarf_elf_object_access_internals_t **ep,int *errcode);
int dwarf_destruct_elf_access(
dwarf_elf_object_access_internals_t *ep,int *errcode);
int _dwarf_load_elf_header(
dwarf_elf_object_access_internals_t *ep,int *errcode);
int _dwarf_load_elf_sectheaders(
dwarf_elf_object_access_internals_t* ep,int *errcode);
int _dwarf_load_elf_symtab_symbols(
dwarf_elf_object_access_internals_t *ep,int *errcode);
int _dwarf_load_elf_symstr(
dwarf_elf_object_access_internals_t *ep, int *errcode);
/* These two enums used for type safety in passing
values. */
enum RelocRela {
RelocIsRela = 1,
RelocIsRel = 2
};
enum RelocOffsetSize {
RelocOffset32 = 4,
RelocOffset64 = 8
};
int _dwarf_load_elf_relx(dwarf_elf_object_access_internals_t *ep,
Dwarf_Unsigned secnum,enum RelocRela,int *errcode);
#ifndef EI_NIDENT
#define EI_NIDENT 16
#endif /* EI_NIDENT */
#ifndef SHN_XINDEX
#define SHN_XINDEX 0xffff
#endif /* SHN_XINDEX */
#ifndef SHN_lORESERVE
#define SHN_LORESERVE 0xff00
#endif /* SHN_lORESERVE */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* READELFOBJ_H */

213
src/lib/libdwarf/dwarf_elfstructs.h vendored Normal file
View File

@ -0,0 +1,213 @@
/*
Copyright (c) 2021-2023, David Anderson
All rights reserved.
or without modification, are permitted provided that the
following conditions are met:
Redistributions of source code must retain the above
copyright notice, this list of conditions and the following
disclaimer.
Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* Typed in from the SystemV Application Binary Interface
but using char arrays instead of variables as
for reading we don't need the struct members to be
variables. This simplifies configure.
https://www.uclibc.org/docs/elf-64-gen.pdf used as source
of Elf64 fields.
It is expected code including this will have included
an official <elf.h> (for various definitions needed)
before including this. But that is not strictly necessary
given other headers.
The structs were all officially defined so files
could be mapped in. Fields are arranged so
there will not be gaps and we need not deal with
alignment-gaps.
*/
#ifndef DW_ELFSTRUCTS_H
#define DW_ELFSTRUCTS_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#ifndef EI_NIDENT
#define EI_NIDENT 16
#endif
#ifndef TYP
#define TYP(n,l) char (n)[(l)]
#endif
typedef struct
{
unsigned char e_ident[EI_NIDENT];
TYP(e_type,2);
TYP(e_machine,2);
TYP(e_version,4);
TYP(e_entry,4);
TYP(e_phoff,4);
TYP(e_shoff,4);
TYP(e_flags,4);
TYP(e_ehsize,2);
TYP(e_phentsize,2);
TYP(e_phnum,2);
TYP(e_shentsize,2);
TYP(e_shnum,2);
TYP(e_shstrndx,2);
} dw_elf32_ehdr;
typedef struct
{
unsigned char e_ident[EI_NIDENT];
TYP(e_type,2);
TYP(e_machine,2);
TYP(e_version,4);
TYP(e_entry,8);
TYP(e_phoff,8);
TYP(e_shoff,8);
TYP(e_flags,4);
TYP(e_ehsize,2);
TYP(e_phentsize,2);
TYP(e_phnum,2);
TYP(e_shentsize,2);
TYP(e_shnum,2);
TYP(e_shstrndx,2);
} dw_elf64_ehdr;
typedef struct
{
TYP(p_type,4);
TYP(p_offset,4);
TYP(p_vaddr,4);
TYP(p_paddr,4);
TYP(p_filesz,4);
TYP(p_memsz,4);
TYP(p_flags,4);
TYP(p_align,4);
} dw_elf32_phdr;
typedef struct
{
TYP(p_type,4);
TYP(p_flags,4);
TYP(p_offset,8);
TYP(p_vaddr,8);
TYP(p_paddr,8);
TYP(p_filesz,8);
TYP(p_memsz,8);
TYP(p_align,8);
} dw_elf64_phdr;
typedef struct
{
TYP(sh_name,4);
TYP(sh_type,4);
TYP(sh_flags,4);
TYP(sh_addr,4);
TYP(sh_offset,4);
TYP(sh_size,4);
TYP(sh_link,4);
TYP(sh_info,4);
TYP(sh_addralign,4);
TYP(sh_entsize,4);
} dw_elf32_shdr;
typedef struct
{
TYP(sh_name,4);
TYP(sh_type,4);
TYP(sh_flags,8);
TYP(sh_addr,8);
TYP(sh_offset,8);
TYP(sh_size,8);
TYP(sh_link,4);
TYP(sh_info,4);
TYP(sh_addralign,8);
TYP(sh_entsize,8);
} dw_elf64_shdr;
typedef struct
{
TYP(r_offset,4);
TYP(r_info,4);
} dw_elf32_rel;
typedef struct
{
TYP(r_offset,8);
TYP(r_info,8);
} dw_elf64_rel;
typedef struct
{
TYP(r_offset,4);
TYP(r_info,4);
TYP(r_addend,4); /* signed */
} dw_elf32_rela;
typedef struct
{
TYP(r_offset,8);
TYP(r_info,8);
TYP(r_addend,8); /* signed */
} dw_elf64_rela;
typedef struct {
TYP(st_name,4);
TYP(st_value,4);
TYP(st_size,4);
unsigned char st_info[1];
unsigned char st_other[1];
TYP(st_shndx,2);
} dw_elf32_sym;
typedef struct {
TYP(st_name,4);
unsigned char st_info[1];
unsigned char st_other[1];
TYP(st_shndx,2);
TYP(st_value,8);
TYP(st_size,8);
} dw_elf64_sym;
typedef struct
{
TYP(d_tag,4); /* signed */
TYP(d_val,4); /* Union in original */
} dw_elf32_dyn;
typedef struct
{
TYP(d_tag,8); /* signed */
TYP(d_val,8); /* Union in original */
} dw_elf64_dyn;
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* DW_ELFSTRUCTS_H */

691
src/lib/libdwarf/dwarf_errmsg_list.h vendored Normal file
View File

@ -0,0 +1,691 @@
/*
Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
Portions Copyright (C) 2008-2023 David Anderson. All Rights Reserved.
This program is free software; you can redistribute it
and/or modify it under the terms of version 2.1 of the
GNU Lesser General Public License as published by the Free
Software Foundation.
This program is distributed in the hope that it would be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
Further, this software is distributed without any warranty
that it is free of the rightful claim of any third person
regarding infringement or the like. Any license provided
herein, whether implied or otherwise, applies only to this
software file. Patent licenses, if any, provided herein
do not apply to combinations of this program with other
software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write the
Free Software Foundation, Inc., 51 Franklin Street - Fifth
Floor, Boston MA 02110-1301, USA.
*/
#ifndef DWARF_ERRMSG_LIST_H
#define DWARF_ERRMSG_LIST_H
/* Array to hold string representation of errors. Any time a
define is added to the list in libdwarf.h, a string should be
added to this Array
Errors in the list (missing a comma, for example)
happen too often. Making this a separate little file
simplifies testing for missing-commas/extra-strings.
Using an array table instead of
pointers saves DW_DLE_LAST+1 relocations at runtime
for libdwarf as DSO (libdwarf.so).
*/
#define DW_MAX_MSG_LEN 111
static const char _dwarf_errmsgs[DW_DLE_LAST+1][DW_MAX_MSG_LEN] = {
{"DW_DLE_No error (0)\n"},
{"DW_DLE_VMM (1) dwarf format/library version mismatch"},
{"DW_DLE_MAP (2) memory map failure"},
{"DW_DLE_LEE (3) libelf error"},
{"DW_DLE_NDS (4) no debug section"},
{"DW_DLE_NLS (5) no line section "},
{"DW_DLE_ID (6) invalid descriptor for query "},
{"DW_DLE_IOF (7) I/O failure "},
{"DW_DLE_MAF (8) memory allocation failure "},
{"DW_DLE_IA (9) invalid argument "},
{"DW_DLE_MDE (10) mangled debugging entry:libelf detected error"},
{"DW_DLE_MLE (11) mangled line number entry "},
{"DW_DLE_FNO (12) file not open "},
{"DW_DLE_FNR (13) file not a regular file "},
{"DW_DLE_FWA (14) file open with wrong access "},
{"DW_DLE_NOB (15) not an object file "},
{"DW_DLE_MOF (16) mangled object file header "},
{"DW_DLE_EOLL (17) end of location list entries "},
{"DW_DLE_NOLL (18) no location list section "},
{"DW_DLE_BADOFF (19) Invalid offset "},
{"DW_DLE_EOS (20) end of section "},
{"DW_DLE_ATRUNC (21) abbreviations section appears truncated"},
{"DW_DLE_BADBITC (22) Address size passed to dwarf bad"},
{"DW_DLE_DBG_ALLOC (23) Unable to malloc a Dwarf_Debug structure"},
{"DW_DLE_FSTAT_ERROR (24) The file fd passed to dwarf_init "
"cannot be fstat()ed"},
{"DW_DLE_FSTAT_MODE_ERROR (25) The file mode bits say not "
"a normal file"},
{"DW_DLE_INIT_ACCESS_WRONG (26) A call to dwarf_init failed,"
" this error impossible as of July 2021"},
{"DW_DLE_ELF_BEGIN_ERROR (27) a call to "
"elf_begin(... ELF_C_READ_MMAP... ) failed"},
{"DW_DLE_ELF_GETEHDR_ERROR (28) a call to "
"elf32_getehdr() or elf64_getehdr() failed"},
{"DW_DLE_ELF_GETSHDR_ERROR (29) a call to "
"elf32_getshdr() or elf64_getshdr() failed"},
{"DW_DLE_ELF_STRPTR_ERROR (30) a call to "
"elf_strptr() failed trying to get a section name"},
{"DW_DLE_DEBUG_INFO_DUPLICATE (31) Only one .debug_info "
"section is allowed"},
{"DW_DLE_DEBUG_INFO_NULL (32) .debug_info section present but "
"elf_getdata() failed"},
{"DW_DLE_DEBUG_ABBREV_DUPLICATE (33) Only one .debug_abbrev "
"section is allowed"},
{"DW_DLE_DEBUG_ABBREV_NULL (34) .debug_abbrev section present but "
"elf_getdata() failed"},
{"DW_DLE_DEBUG_ARANGES_DUPLICATE (35) Only one .debug_aranges "
"section is allowed"},
{"DW_DLE_DEBUG_ARANGES_NULL (36) .debug_aranges section present but "
"elf_getdata() failed"},
{"DW_DLE_DEBUG_LINE_DUPLICATE (37) Only one .debug_line "
"section is allowed"},
{"DW_DLE_DEBUG_LINE_NULL (38) .debug_line section 0-size. Corrupt."},
{"DW_DLE_DEBUG_LOC_DUPLICATE (39) Only one .debug_loc "
"section is allowed"},
{"DW_DLE_DEBUG_LOC_NULL (40) .debug_loc section present but "
"elf_getdata() failed"},
{"DW_DLE_DEBUG_MACINFO_DUPLICATE (41) Only one .debug_macinfo "
"section is allowed"},
{"DW_DLE_DEBUG_MACINFO_NULL (42) .debug_macinfo section present but "
"elf_getdata() failed"},
{"DW_DLE_DEBUG_PUBNAMES_DUPLICATE (43) Only one .debug_pubnames "
"section is allowed"},
{"DW_DLE_DEBUG_PUBNAMES_NULL (44) .debug_pubnames section "
"present but elf_getdata() failed"},
{"DW_DLE_DEBUG_STR_DUPLICATE (45) Only one .debug_str "
"section is allowed"},
{"DW_DLE_DEBUG_STR_NULL (46) .debug_str section present but "
"elf_getdata() failed"},
{"DW_DLE_CU_LENGTH_ERROR (47) Corrupted DWARF or corrupted object"},
{"DW_DLE_VERSION_STAMP_ERROR (48) Corrupted DWARF "
"or corrupted object"},
{"DW_DLE_ABBREV_OFFSET_ERROR (49) Corrupted DWARF or "
"corrupted object"},
{"DW_DLE_ADDRESS_SIZE_ERROR (50) size too large"},
{"DW_DLE_DEBUG_INFO_PTR_NULL (51)"},
{"DW_DLE_DIE_NULL (52)"},
{"DW_DLE_STRING_OFFSET_BAD (53) Corrupted DWARF or corrupted object"},
{"DW_DLE_DEBUG_LINE_LENGTH_BAD (54)"},
{"DW_DLE_LINE_PROLOG_LENGTH_BAD (55)"},
{"DW_DLE_LINE_NUM_OPERANDS_BAD (56)"},
{"DW_DLE_LINE_SET_ADDR_ERROR (57)"},
{"DW_DLE_LINE_EXT_OPCODE_BAD (58)"},
{"DW_DLE_DWARF_LINE_NULL (59)"},
{"DW_DLE_INCL_DIR_NUM_BAD (60)"},
{"DW_DLE_LINE_FILE_NUM_BAD (61)"},
{"DW_DLE_ALLOC_FAIL (62) Out of memory or corrupted object"},
{"DW_DLE_NO_CALLBACK_FUNC (63)"},
{"DW_DLE_SECT_ALLOC (64)"},
{"DW_DLE_FILE_ENTRY_ALLOC (65)"},
{"DW_DLE_LINE_ALLOC (66)"},
{"DW_DLE_FPGM_ALLOC (67)"},
{"DW_DLE_INCDIR_ALLOC (68)"},
{"DW_DLE_STRING_ALLOC (69)"},
{"DW_DLE_CHUNK_ALLOC (70)"},
{"DW_DLE_BYTEOFF_ERR (71)"},
{"DW_DLE_CIE_ALLOC (72)"},
{"DW_DLE_FDE_ALLOC (73)"},
{"DW_DLE_REGNO_OVFL (74)"},
{"DW_DLE_CIE_OFFS_ALLOC (75)"},
{"DW_DLE_WRONG_ADDRESS (76)"},
{"DW_DLE_EXTRA_NEIGHBORS (77)"},
{"DW_DLE_WRONG_TAG (78)"},
{"DW_DLE_DIE_ALLOC (79)"},
{"DW_DLE_PARENT_EXISTS (80)"},
{"DW_DLE_DBG_NULL (81)"},
{"DW_DLE_DEBUGLINE_ERROR (82)"},
{"DW_DLE_DEBUGFRAME_ERROR (83)"},
{"DW_DLE_DEBUGINFO_ERROR (84)"},
{"DW_DLE_ATTR_ALLOC (85)"},
{"DW_DLE_ABBREV_ALLOC (86)"},
{"DW_DLE_OFFSET_UFLW (87)"},
{"DW_DLE_ELF_SECT_ERR (88)"},
{"DW_DLE_DEBUG_FRAME_LENGTH_BAD (89)"},
{"DW_DLE_FRAME_VERSION_BAD (90)"},
{"DW_DLE_CIE_RET_ADDR_REG_ERROR (91)"},
{"DW_DLE_FDE_NULL (92)"},
{"DW_DLE_FDE_DBG_NULL (93)"},
{"DW_DLE_CIE_NULL (94)"},
{"DW_DLE_CIE_DBG_NULL (95)"},
{"DW_DLE_FRAME_TABLE_COL_BAD (96)"},
{"DW_DLE_PC_NOT_IN_FDE_RANGE (97)"},
{"DW_DLE_CIE_INSTR_EXEC_ERROR (98)"},
{"DW_DLE_FRAME_INSTR_EXEC_ERROR (99)"},
{"DW_DLE_FDE_PTR_NULL (100)"},
{"DW_DLE_RET_OP_LIST_NULL (101)"},
{"DW_DLE_LINE_CONTEXT_NULL (102)"},
{"DW_DLE_DBG_NO_CU_CONTEXT (103)"},
{"DW_DLE_DIE_NO_CU_CONTEXT (104)"},
{"DW_DLE_FIRST_DIE_NOT_CU (105)"},
{"DW_DLE_NEXT_DIE_PTR_NULL (106)"},
{"DW_DLE_DEBUG_FRAME_DUPLICATE (107) Only one .debug_frame "
"section is allowed"},
{"DW_DLE_DEBUG_FRAME_NULL (108) .debug_frame section present but "
"elf_getdata() failed"},
{"DW_DLE_ABBREV_DECODE_ERROR (109)"},
{"DW_DLE_DWARF_ABBREV_NULL (110)"},
{"DW_DLE_ATTR_NULL (111)"},
{"DW_DLE_DIE_BAD (112)"},
{"DW_DLE_DIE_ABBREV_BAD (113)"},
{"DW_DLE_ATTR_FORM_BAD (114)"},
{"DW_DLE_ATTR_NO_CU_CONTEXT (115)"},
{"DW_DLE_ATTR_FORM_SIZE_BAD (116)"},
{"DW_DLE_ATTR_DBG_NULL (117)"},
{"DW_DLE_BAD_REF_FORM (118)"},
{"DW_DLE_ATTR_FORM_OFFSET_BAD (119)"},
{"DW_DLE_LINE_OFFSET_BAD (120)"},
{"DW_DLE_DEBUG_STR_OFFSET_BAD (121)"},
{"DW_DLE_STRING_PTR_NULL (122)"},
{"DW_DLE_PUBNAMES_VERSION_ERROR (123)"},
{"DW_DLE_PUBNAMES_LENGTH_BAD (124)"},
{"DW_DLE_GLOBAL_NULL (125)"},
{"DW_DLE_GLOBAL_CONTEXT_NULL (126)"},
{"DW_DLE_DIR_INDEX_BAD (127)"},
{"DW_DLE_LOC_EXPR_BAD (128)"},
{"DW_DLE_DIE_LOC_EXPR_BAD (129)"},
{"DW_DLE_ADDR_ALLOC (130)"},
{"DW_DLE_OFFSET_BAD (131)"},
{"DW_DLE_MAKE_CU_CONTEXT_FAIL (132)"},
{"DW_DLE_REL_ALLOC (133)"},
{"DW_DLE_ARANGE_OFFSET_BAD (134)"},
{"DW_DLE_SEGMENT_SIZE_BAD (135) Size of a segment selector "
"should usually be less than 8 (bytes)."},
{"DW_DLE_ARANGE_LENGTH_BAD (136)"},
{"DW_DLE_ARANGE_DECODE_ERROR (137)"},
{"DW_DLE_ARANGES_NULL (138)"},
{"DW_DLE_ARANGE_NULL (139)"},
{"DW_DLE_NO_FILE_NAME (140)"},
{"DW_DLE_NO_COMP_DIR (141)"},
{"DW_DLE_CU_ADDRESS_SIZE_BAD (142)"},
{"DW_DLE_INPUT_ATTR_BAD (143)"},
{"DW_DLE_EXPR_NULL (144)"},
{"DW_DLE_BAD_EXPR_OPCODE (145)"},
{"DW_DLE_EXPR_LENGTH_BAD (146)"},
{"DW_DLE_MULTIPLE_RELOC_IN_EXPR (147)"},
{"DW_DLE_ELF_GETIDENT_ERROR (148)"},
{"DW_DLE_NO_AT_MIPS_FDE (149)"},
{"DW_DLE_NO_CIE_FOR_FDE (150)"},
{"DW_DLE_DIE_ABBREV_LIST_NULL (151) No abbrev exists for "
"the requested abbrev code"},
{"DW_DLE_DEBUG_FUNCNAMES_DUPLICATE (152)"},
{"DW_DLE_DEBUG_FUNCNAMES_NULL (153) .debug_funcnames section "
"present but elf_getdata() bad"},
{"DW_DLE_DEBUG_FUNCNAMES_VERSION_ERROR (154)"},
{"DW_DLE_DEBUG_FUNCNAMES_LENGTH_BAD (155)"},
{"DW_DLE_FUNC_NULL (156)"},
{"DW_DLE_FUNC_CONTEXT_NULL (157)"},
{"DW_DLE_DEBUG_TYPENAMES_DUPLICATE (158)"},
{"DW_DLE_DEBUG_TYPENAMES_NULL (159) .debug_typenames section "
"present but elf_getdata() failed"},
{"DW_DLE_DEBUG_TYPENAMES_VERSION_ERROR (160)"},
{"DW_DLE_DEBUG_TYPENAMES_LENGTH_BAD (161)"},
{"DW_DLE_TYPE_NULL (162)"},
{"DW_DLE_TYPE_CONTEXT_NULL (163)"},
{"DW_DLE_DEBUG_VARNAMES_DUPLICATE (164)"},
{"DW_DLE_DEBUG_VARNAMES_NULL (165) .debug_varnames section present "
"but elf_getdata() failed"},
{"DW_DLE_DEBUG_VARNAMES_VERSION_ERROR (166)"},
{"DW_DLE_DEBUG_VARNAMES_LENGTH_BAD (167)"},
{"DW_DLE_VAR_NULL (168)"},
{"DW_DLE_VAR_CONTEXT_NULL (169)"},
{"DW_DLE_DEBUG_WEAKNAMES_DUPLICATE (170)"},
{"DW_DLE_DEBUG_WEAKNAMES_NULL (171) .debug_weaknames section "
"present but elf_getdata() failed"},
{"DW_DLE_DEBUG_WEAKNAMES_VERSION_ERROR (172)"},
{"DW_DLE_DEBUG_WEAKNAMES_LENGTH_BAD (173)"},
{"DW_DLE_WEAK_NULL (174)"},
{"DW_DLE_WEAK_CONTEXT_NULL (175)"},
{"DW_DLE_LOCDESC_COUNT_WRONG (176)"},
{"DW_DLE_MACINFO_STRING_NULL (177)"},
{"DW_DLE_MACINFO_STRING_EMPTY (178)"},
{"DW_DLE_MACINFO_INTERNAL_ERROR_SPACE (179)"},
{"DW_DLE_MACINFO_MALLOC_FAIL (180)"},
{"DW_DLE_DEBUGMACINFO_ERROR (181)"},
{"DW_DLE_DEBUG_MACRO_LENGTH_BAD (182) in .debug_macinfo"},
{"DW_DLE_DEBUG_MACRO_MAX_BAD (183) in .debug_macinfo"},
{"DW_DLE_DEBUG_MACRO_INTERNAL_ERR (184) in .debug_macinfo"},
{"DW_DLE_DEBUG_MACRO_MALLOC_SPACE (185) in .debug_macinfo"},
{"DW_DLE_DEBUG_MACRO_INCONSISTENT (186) in .debug_macinfo"},
{"DW_DLE_DF_NO_CIE_AUGMENTATION(187)"},
{"DW_DLE_DF_REG_NUM_TOO_HIGH(188)"},
{"DW_DLE_DF_MAKE_INSTR_NO_INIT(189)"},
{"DW_DLE_DF_NEW_LOC_LESS_OLD_LOC(190)"},
{"DW_DLE_DF_POP_EMPTY_STACK(191)"},
{"DW_DLE_DF_ALLOC_FAIL(192)"},
{"DW_DLE_DF_FRAME_DECODING_ERROR(193)"},
{"DW_DLE_DEBUG_LOC_SECTION_SHORT(194)"},
{"DW_DLE_FRAME_AUGMENTATION_UNKNOWN(195)"},
{"DW_DLE_PUBTYPE_CONTEXT(196)"},
{"DW_DLE_DEBUG_PUBTYPES_LENGTH_BAD(197)"},
{"DW_DLE_DEBUG_PUBTYPES_VERSION_ERROR(198)"},
{"DW_DLE_DEBUG_PUBTYPES_DUPLICATE(199)"},
{"DW_DLE_FRAME_CIE_DECODE_ERROR(200)"},
{"DW_DLE_FRAME_REGISTER_UNREPRESENTABLE(201)"},
{"DW_DLE_FRAME_REGISTER_COUNT_MISMATCH(202)"},
{"DW_DLE_LINK_LOOP(203)"},
{"DW_DLE_STRP_OFFSET_BAD(204)"},
{"DW_DLE_DEBUG_RANGES_DUPLICATE(205)"},
{"DW_DLE_DEBUG_RANGES_OFFSET_BAD(206)"},
{"DW_DLE_DEBUG_RANGES_MISSING_END(207)"},
{"DW_DLE_DEBUG_RANGES_OUT_OF_MEM(208)"},
{"DW_DLE_DEBUG_SYMTAB_ERR(209)"},
{"DW_DLE_DEBUG_STRTAB_ERR(210)"},
{"DW_DLE_RELOC_MISMATCH_INDEX(211)"},
{"DW_DLE_RELOC_MISMATCH_RELOC_INDEX(212)"},
{"DW_DLE_RELOC_MISMATCH_STRTAB_INDEX(213)"},
{"DW_DLE_RELOC_SECTION_MISMATCH(214)"},
{"DW_DLE_RELOC_SECTION_MISSING_INDEX(215)"},
{"DW_DLE_RELOC_SECTION_LENGTH_ODD(216)"},
{"DW_DLE_RELOC_SECTION_PTR_NULL(217)"},
{"DW_DLE_RELOC_SECTION_MALLOC_FAIL(218)"},
{"DW_DLE_NO_ELF64_SUPPORT(219)"},
{"DW_DLE_MISSING_ELF64_SUPPORT(220)"},
{"DW_DLE_ORPHAN_FDE(221)"},
{"DW_DLE_DUPLICATE_INST_BLOCK(222)"},
{"DW_DLE_BAD_REF_SIG8_FORM(223)"},
{"DW_DLE_ATTR_EXPRLOC_FORM_BAD(224)"},
{"DW_DLE_FORM_SEC_OFFSET_LENGTH_BAD(225)"},
{"DW_DLE_NOT_REF_FORM(226)"},
{"DW_DLE_DEBUG_FRAME_LENGTH_NOT_MULTIPLE(227)"},
{"DW_DLE_REF_SIG8_NOT_HANDLED (228)"},
{"DW_DLE_DEBUG_FRAME_POSSIBLE_ADDRESS_BOTCH (229)"},
{"DW_DLE_LOC_BAD_TERMINATION (230) location operator "
"in expression missing data"},
{"DW_DLE_SYMTAB_SECTION_LENGTH_ODD (231) so doing "
"relocations seems unsafe"},
{"DW_DLE_RELOC_SECTION_SYMBOL_INDEX_BAD (232) so doing a "
"relocation seems unsafe"},
{"DW_DLE_RELOC_SECTION_RELOC_TARGET_SIZE_UNKNOWN (233) so "
"doing a relocation is unsafe"},
{"DW_DLE_SYMTAB_SECTION_ENTRYSIZE_ZERO(234)"},
{"DW_DLE_LINE_NUMBER_HEADER_ERROR (235), a line number "
"program header seems incomplete"},
{"DW_DLE_DEBUG_TYPES_NULL (236)"},
{"DW_DLE_DEBUG_TYPES_DUPLICATE (237)"},
{"DW_DLE_DEBUG_TYPES_ONLY_DWARF4 (238) DW4 and DW5 have types CUs"},
{"DW_DLE_DEBUG_TYPEOFFSET_BAD (239)"},
{"DW_DLE_GNU_OPCODE_ERROR (240)"},
{"DW_DLE_DEBUGPUBTYPES_ERROR (241), could not create "
"pubtypes section"},
{"DW_DLE_AT_FIXUP_NULL (242)"},
{"DW_DLE_AT_FIXUP_DUP (243)"},
{"DW_DLE_BAD_ABINAME (244)"},
{"DW_DLE_TOO_MANY_DEBUG(245), too many .debug_* sections "
"present somehow"},
{"DW_DLE_DEBUG_STR_OFFSETS_DUPLICATE(246)"},
{"DW_DLE_SECTION_DUPLICATION(247)"},
{"DW_DLE_SECTION_ERROR(248)"},
{"DW_DLE_DEBUG_ADDR_DUPLICATE(249)"},
{"DW_DLE_DEBUG_CU_UNAVAILABLE_FOR_FORM(250)"},
{"DW_DLE_DEBUG_FORM_HANDLING_INCOMPLETE(251)"},
{"DW_DLE_NEXT_DIE_PAST_END(252)"},
{"DW_DLE_NEXT_DIE_WRONG_FORM(253)"},
{"DW_DLE_NEXT_DIE_NO_ABBREV_LIST(254)"},
{"DW_DLE_NESTED_FORM_INDIRECT_ERROR(255)"},
{"DW_DLE_CU_DIE_NO_ABBREV_LIST(256)"},
{"DW_DLE_MISSING_NEEDED_DEBUG_ADDR_SECTION(257)"},
{"DW_DLE_ATTR_FORM_NOT_ADDR_INDEX(258)"},
{"DW_DLE_ATTR_FORM_NOT_STR_INDEX(259)"},
{"DW_DLE_DUPLICATE_GDB_INDEX(260)"},
{"DW_DLE_ERRONEOUS_GDB_INDEX_SECTION(261) The section is too small"},
{"DW_DLE_GDB_INDEX_COUNT_ERROR(262)"},
{"DW_DLE_GDB_INDEX_COUNT_ADDR_ERROR(263)"},
{"DW_DLE_GDB_INDEX_CUVEC_ERROR(264)"},
{"DW_DLE_GDB_INDEX_INDEX_ERROR(265)"},
{"DW_DLE_DUPLICATE_CU_INDEX(266)"},
{"DW_DLE_DUPLICATE_TU_INDEX(267)"},
{"DW_DLE_XU_TYPE_ARG_ERROR(268) XU means dwarf_cu_ or "
"tu_ index section"},
{"DW_DLE_XU_IMPOSSIBLE_ERROR(269) XU means dwarf_cu_ or "
"tu_ index section"},
{"DW_DLE_XU_NAME_COL_ERROR(270) XU means dwarf_cu_ or "
"tu_ index section"},
{"DW_DLE_XU_HASH_ROW_ERROR(271) XU means dwarf_cu_ or "
"tu_ index section"},
{"DW_DLE_XU_HASH_INDEX_ERROR(272) XU means dwarf_cu_ or "
"tu_ index section"},
{"DW_DLE_FAILSAFE_ERRVAL(273)"},
{"DW_DLE_ARANGE_ERROR(274) producer problem in object generation"},
{"DW_DLE_PUBNAMES_ERROR(275) producer problem in object generation"},
{"DW_DLE_FUNCNAMES_ERROR(276) producer problem in object generation"},
{"DW_DLE_TYPENAMES_ERROR(277) producer problem in object generation"},
{"DW_DLE_VARNAMES_ERROR(278) producer problem in object generation"},
{"DW_DLE_WEAKNAMES_ERROR(279) producer problem in object generation"},
{"DW_DLE_RELOCS_ERROR(280) producer problem in object generation"},
{"DW_DLE_DW_DLE_ATTR_OUTSIDE_SECTION(281)"},
{"DW_DLE_FISSION_INDEX_WRONG(282)"},
{"DW_DLE_FISSION_VERSION_ERROR(283)"},
{"DW_DLE_NEXT_DIE_LOW_ERROR(284) corrupted DIE tree"},
{"DW_DLE_CU_UT_TYPE_ERROR(285) bad DW_UT_* value, corrupt DWARF5"},
{"DW_DLE_NO_SUCH_SIGNATURE_FOUND(286) CU signature not in the index"},
{"DW_DLE_SIGNATURE_SECTION_NUMBER_WRONG(287) "
"libdwarf software error"},
{"DW_DLE_ATTR_FORM_NOT_DATA8(288) wanted an 8 byte signature"},
{"DW_DLE_SIG_TYPE_WRONG_STRING (289) expected tu or cu"},
{"DW_DLE_MISSING_REQUIRED_TU_OFFSET_HASH(290) is a "
"broken dwp package file"},
{"DW_DLE_MISSING_REQUIRED_CU_OFFSET_HASH(291) is a "
"broken dwp package file"},
{"DW_DLE_DWP_MISSING_DWO_ID(292)"},
{"DW_DLE_DWP_SIBLING_ERROR(293)"},
{"DW_DLE_DEBUG_FISSION_INCOMPLETE(294)"},
{"DW_DLE_FISSION_SECNUM_ERR(295) internal libdwarf error"},
{"DW_DLE_DEBUG_MACRO_DUPLICATE(296)"},
{"DW_DLE_DEBUG_NAMES_DUPLICATE(297)"},
{"DW_DLE_DEBUG_LINE_STR_DUPLICATE(298)"},
{"DW_DLE_DEBUG_SUP_DUPLICATE(299)"},
{"DW_DLE_NO_SIGNATURE_TO_LOOKUP(300)"},
{"DW_DLE_NO_TIED_ADDR_AVAILABLE(301)"},
{"DW_DLE_NO_TIED_SIG_AVAILABLE(302)"},
{"DW_DLE_STRING_NOT_TERMINATED(303) section data may be corrupted"},
{"DW_DLE_BAD_LINE_TABLE_OPERATION(304) two-level line table botch"},
{"DW_DLE_LINE_CONTEXT_BOTCH(305) call is wrong or memory corruption"},
{"DW_DLE_LINE_CONTEXT_INDEX_WRONG(306)"},
{"DW_DLE_NO_TIED_STRING_AVAILABLE(307) tied file does not "
"have the string"},
{"DW_DLE_NO_TIED_FILE_AVAILABLE(308) see dwarf_set_tied_dbg()"},
{"DW_DLE_CU_TYPE_MISSING(309) libdwarf bug or data corruption"},
{"DW_DLE_LLE_CODE_UNKNOWN (310) libdwarf bug or data corruption"},
{"DW_DLE_LOCLIST_INTERFACE_ERROR (311) interface cannot do "
"location or DW_OP*"},
{"DW_DLE_LOCLIST_INDEX_ERROR (312)"},
{"DW_DLE_INTERFACE_NOT_SUPPORTED (313)"},
{"DW_DLE_ZDEBUG_REQUIRES_ZLIB (314) Unable to decompress .zdebug "
"as zlib missing"},
{"DW_DLE_ZDEBUG_INPUT_FORMAT_ODD(315)"},
{"DW_DLE_ZLIB_BUF_ERROR (316) Z_BUF_ERROR buffer size small"},
{"DW_DLE_ZLIB_DATA_ERROR (317) Z_DATA_ERROR compressed "
"data corrupted"},
{"DW_DLE_MACRO_OFFSET_BAD (318)"},
{"DW_DLE_MACRO_OPCODE_BAD (319)"},
{"DW_DLE_MACRO_OPCODE_FORM_BAD (320)"},
{"DW_DLE_UNKNOWN_FORM (321) Possibly corrupt DWARF data"},
{"DW_DLE_BAD_MACRO_HEADER_POINTER(322)"},
{"DW_DLE_BAD_MACRO_INDEX(323)"},
{"DW_DLE_MACRO_OP_UNHANDLED(324) Possibly an implementation "
"extension"},
{"DW_DLE_MACRO_PAST_END(325)"},
{"DW_DLE_LINE_STRP_OFFSET_BAD(326)"},
{"DW_DLE_STRING_FORM_IMPROPER(327) An internal libdwarf logic error"},
{"DW_DLE_ELF_FLAGS_NOT_AVAILABLE(328) elf/non-elf object confusion?"},
{"DW_DLE_LEB_IMPROPER (329) Runs off end of section or CU"},
{"DW_DLE_DEBUG_LINE_RANGE_ZERO (330) Corrupted line section"},
{"DW_DLE_READ_LITTLEENDIAN_ERROR (331) Corrupted dwarfdata "
"littleendian host"},
{"DW_DLE_READ_BIGENDIAN_ERROR (332) Corrupted dwarf data "
"bigendian host"},
{"DW_DLE_RELOC_INVALID (333) relocation corruption"},
{"DW_DLE_INFO_HEADER_ERROR(334) Corrupt dwarf"},
{"DW_DLE_ARANGES_HEADER_ERROR(335) Corrupt dwarf"},
{"DW_DLE_LINE_OFFSET_WRONG_FORM(336) Corrupt dwarf"},
{"DW_DLE_FORM_BLOCK_LENGTH_ERROR(337) Corrupt dwarf"},
{"DW_DLE_ZLIB_SECTION_SHORT (338) Corrupt dwarf"},
{"DW_DLE_CIE_INSTR_PTR_ERROR (339)"},
{"DW_DLE_FDE_INSTR_PTR_ERROR (340)"},
{"DW_DLE_FISSION_ADDITION_ERROR (341) Corrupt dwarf"},
{"DW_DLE_HEADER_LEN_BIGGER_THAN_SECSIZE (342) Corrupt dwarf"},
{"DW_DLE_LOCEXPR_OFF_SECTION_END (343) Corrupt dwarf"},
{"DW_DLE_POINTER_SECTION_UNKNOWN (344)"},
{"DW_DLE_ERRONEOUS_XU_INDEX_SECTION(345) XU means cu_ or tu_ index"},
{"DW_DLE_DIRECTORY_FORMAT_COUNT_VS_DIRECTORIES_MISMATCH(346) "
"Inconsistent line table, corrupted."},
{"DW_DLE_COMPRESSED_EMPTY_SECTION(347) corrupt section data"},
{"DW_DLE_SIZE_WRAPAROUND(348) Impossible string length"},
{"DW_DLE_ILLOGICAL_TSEARCH(349) Impossible situation. "
"Corrupted data?"},
{"DW_DLE_BAD_STRING_FORM(350) Not a currently allowed form"},
{"DW_DLE_DEBUGSTR_ERROR(351) problem generating .debug_str section"},
{"DW_DLE_DEBUGSTR_UNEXPECTED_REL(352) string relocation "
"will be wrong."},
{"DW_DLE_DISCR_ARRAY_ERROR(353) Internal error in "
"dwarf_discr_list()"},
{"DW_DLE_LEB_OUT_ERROR(354) Insufficient buffer to turn "
"integer to leb"},
{"DW_DLE_SIBLING_LIST_IMPROPER(355) Runs off end of section. "
"Corrupt dwarf"},
{"DW_DLE_LOCLIST_OFFSET_BAD(356) Corrupt dwarf"},
{"DW_DLE_LINE_TABLE_BAD(357) Corrupt line table"},
{"DW_DLE_DEBUG_LOClISTS_DUPLICATE(358)"},
{"DW_DLE_DEBUG_RNGLISTS_DUPLICATE(359)"},
{"DW_DLE_ABBREV_OFF_END(360)"},
{"DW_DLE_FORM_STRING_BAD_STRING(361) string runs off end of data"},
{"DW_DLE_AUGMENTATION_STRING_OFF_END(362) augmentation runs off "
"of its section"},
{"DW_DLE_STRING_OFF_END_PUBNAMES_LIKE(363) one of the global "
"sections, string bad"},
{"DW_DLE_LINE_STRING_BAD(364) runs off end of line data"},
{"DW_DLE_DEFINE_FILE_STRING_BAD(365) runs off end of section"},
{"DW_DLE_MACRO_STRING_BAD(366) DWARF5 macro def/undef string "
"runs off section data"},
{"DW_DLE_MACINFO_STRING_BAD(367) DWARF2..4 macro def/undef "
"string runs off section data"},
{"DW_DLE_ZLIB_UNCOMPRESS_ERROR(368) Surely an invalid "
"uncompress length"},
{"DW_DLE_IMPROPER_DWO_ID(369)"},
{"DW_DLE_GROUPNUMBER_ERROR(370) An error determining default "
"target group number"},
{"DW_DLE_ADDRESS_SIZE_ZERO(371)"},
{"DW_DLE_DEBUG_NAMES_HEADER_ERROR(372)"},
{"DW_DLE_DEBUG_NAMES_AUG_STRING_ERROR(373) corrupt dwarf"},
{"DW_DLE_DEBUG_NAMES_PAD_NON_ZERO(374) corrupt dwarf"},
{"DW_DLE_DEBUG_NAMES_OFF_END(375) corrupt dwarf"},
{"DW_DLE_DEBUG_NAMES_ABBREV_OVERFLOW(376) Surprising "
"overrun of fixed size array"},
{"DW_DLE_DEBUG_NAMES_ABBREV_CORRUPTION(377)"},
{"DW_DLE_DEBUG_NAMES_NULL_POINTER(378) null argument"},
{"DW_DLE_DEBUG_NAMES_BAD_INDEX_ARG(379) index outside valid range"},
{"DW_DLE_DEBUG_NAMES_ENTRYPOOL_OFFSET(380) offset outside entrypool"},
{"DW_DLE_DEBUG_NAMES_UNHANDLED_FORM(381) Might be corrupt "
"dwarf or incomplete DWARF support"},
{"DW_DLE_LNCT_CODE_UNKNOWN(382)"},
{"DW_DLE_LNCT_FORM_CODE_NOT_HANDLED(383) Might be bad form "
"or just not implemented"},
{"DW_DLE_LINE_HEADER_LENGTH_BOTCH(384) Internal libdwarf error"},
{"DW_DLE_STRING_HASHTAB_IDENTITY_ERROR(385) Internal libdwarf error"},
{"DW_DLE_UNIT_TYPE_NOT_HANDLED(386) Possibly incomplete "
"dwarf5 support"},
{"DW_DLE_GROUP_MAP_ALLOC(387) Out of malloc space"},
{"DW_DLE_GROUP_MAP_DUPLICATE(388) Each section # should appear once"},
{"DW_DLE_GROUP_COUNT_ERROR(389) An inconsistency in map entry count"},
{"DW_DLE_GROUP_INTERNAL_ERROR(390) libdwarf data corruption"},
{"DW_DLE_GROUP_LOAD_ERROR(391) corrupt data?"},
{"DW_DLE_GROUP_LOAD_READ_ERROR(392)"},
{"DW_DLE_AUG_DATA_LENGTH_BAD(393) Data does not fit in section"},
{"DW_DLE_ABBREV_MISSING(394) Unable to find abbrev for DIE"},
{"DW_DLE_NO_TAG_FOR_DIE(395)"},
{"DW_DLE_LOWPC_WRONG_CLASS(396) found in dwarf_lowpc()"},
{"DW_DLE_HIGHPC_WRONG_FORM(397) found in dwarf_highpc()"},
{"DW_DLE_STR_OFFSETS_BASE_WRONG_FORM(398)"},
{"DW_DLE_DATA16_OUTSIDE_SECTION(399)"},
{"DW_DLE_LNCT_MD5_WRONG_FORM(400)"},
{"DW_DLE_LINE_HEADER_CORRUPT(401) possible data corruption"},
{"DW_DLE_STR_OFFSETS_NULLARGUMENT(402) improper call"},
{"DW_DLE_STR_OFFSETS_NULL_DBG(403) improper call"},
{"DW_DLE_STR_OFFSETS_NO_MAGIC(404) improper call"},
{"DLE_STR_OFFSETS_ARRAY_SIZE(405) Not a multiple of entry size"},
{"DW_DLE_STR_OFFSETS_VERSION_WRONG(406) Must be 5 "},
{"DW_DLE_STR_OFFSETS_ARRAY_INDEX_WRONG(407) Requested outside bound"},
{"DW_DLE_STR_OFFSETS_EXTRA_BYTES(408) .debug_str_offsets "
"section problem"},
{"DW_DLE_DUP_ATTR_ON_DIE(409) Compiler error, object improper DWARF"},
{"DW_DLE_SECTION_NAME_BIG(410) Caller provided insufficient "
"room for section name"},
{"DW_DLE_FILE_UNAVAILABLE(411). Unable find/read object file"},
{"DW_DLE_FILE_WRONG_TYPE(412). Not an object type we recognize."},
{"DW_DLE_SIBLING_OFFSET_WRONG(413). Corrupt dwarf."},
{"DW_DLE_OPEN_FAIL(414) Unable to open, possibly a bad filename"},
{"DW_DLE_OFFSET_SIZE(415) Offset size is neither 32 nor 64"},
{"DW_DLE_MACH_O_SEGOFFSET_BAD(416) corrupt object"},
{"DW_DLE_FILE_OFFSET_BAD(417) corrupt object"},
{"DW_DLE_SEEK_ERROR(418). Seek failed, corrupt object"},
{"DW_DLE_READ_ERROR(419). Read failed, corrupt object"},
{"DW_DLE_ELF_CLASS_BAD(420) Corrupt object."},
{"DW_DLE_ELF_ENDIAN_BAD(421) Corrupt object."},
{"DW_DLE_ELF_VERSION_BAD(422) Corrupt object."},
{"DW_DLE_FILE_TOO_SMALL(423) File is too small to be an "
"object file."},
{"DW_DLE_PATH_SIZE_TOO_SMALL(424) buffer passed to "
"dwarf_object_detector_path is too small."},
{"DW_DLE_BAD_TYPE_SIZE(425) At compile time the build "
"configured itself improperly."},
{"DW_DLE_PE_SIZE_SMALL(426) File too small to be valid PE object."},
{"DW_DLE_PE_OFFSET_BAD(427) Calculated offset too large. "
"Corrupt object."},
{"DW_DLE_PE_STRING_TOO_LONG(428) Increase size for call."},
{"DW_DLE_IMAGE_FILE_UNKNOWN_TYPE(429) a PE object has an "
"unknown machine type, not 0x14c, 0x200 or 0x8664"},
{"DLE_LINE_TABLE_LINENO_ERROR(430) Negative line number "
"impossible. Corrupted line table."},
{"DW_DLE_PRODUCER_CODE_NOT_AVAILABLE(431) Without elf.h "
"the producer code is not available."},
{"DW_DLE_NO_ELF_SUPPORT(432) libdwarf was compiled without "
"Elf object support."},
{"DW_DLE_NO_STREAM_RELOC_SUPPORT(433) no elf.h so cannot "
"generate STREAM relocations"},
{"DW_DLE_RETURN_EMPTY_PUBNAMES_ERROR(434) Flag value passed "
"in not allowed."},
{"DW_DLE_SECTION_SIZE_ERROR(435) Corrupt Elf. Section size: "
"> file size or not a multiple of entry size"},
{"DW_DLE_INTERNAL_NULL_POINTER(436) Internal libdwarf "
"call:null pointer"},
{"DW_DLE_SECTION_STRING_OFFSET_BAD(437) Corrupt Elf, an "
"offset to section name is invalid"},
{"DW_DLE_SECTION_INDEX_BAD(438) Corrupt Elf, a section "
"index is incorrect"},
{"DW_DLE_INTEGER_TOO_SMALL(439) Build does not allow reading Elf64"},
{"DW_DLE_ELF_SECTION_LINK_ERROR(440) Corrupt Elf, section "
"links in error"},
{"DW_DLE_ELF_SECTION_GROUP_ERROR(441) Corrupt Elf, section "
"group information problem"},
{"DW_DLE_ELF_SECTION_COUNT_MISMATCH(442) Corrupt Elf or "
"libdwarf bug."},
{"DW_DLE_ELF_STRING_SECTION_MISSING(443) Corrupt Elf, "
"string section wrong type"},
{"DW_DLE_SEEK_OFF_END(444) Corrupt Elf. Seek past the end "
"not allowed"},
{"DW_DLE_READ_OFF_END(445) Corrupt Elf. A read would read past "
"end of object"},
{"DW_DLE_ELF_SECTION_ERROR(446) Section offset or size is too large. "
"Corrupt elf object."},
{"DW_DLE_ELF_STRING_SECTION_ERROR(447) String section missing. "
"Corrupt Elf"},
{"DW_DLE_MIXING_SPLIT_DWARF_VERSIONS(448) DWARF5 header "
"signature and DWARF4 DW_AT_[GNU]_dwo_id both present"},
{"DW_DLE_TAG_CORRUPT(449) DW_TAG outside allowed range. "
"Corrupt DWARF."},
{"DW_DLE_FORM_CORRUPT(450) DW_FORM unknown, too large a value. "
"Corrupt DWARF?"},
{"DW_DLE_ATTR_CORRUPT(451) DW_AT outside allowed range. "
"Corrupt DWARF."},
{"DW_DLE_ABBREV_ATTR_DUPLICATION(452) Abbreviation list corruption."},
{"DW_DLE_DWP_SIGNATURE_MISMATCH(453) Impossible signature "
"mismatch. Corrupted Dwarf?"},
{"DW_DLE_CU_UT_TYPE_VALUE(454) Internal libdwarf data corruption"},
{"DW_DLE_DUPLICATE_GNU_DEBUGLINK(455) Duplicated section "
".gnu_debuglink"},
{"DW_DLE_CORRUPT_GNU_DEBUGLINK(456) Section length wrong"},
{"DW_DLE_CORRUPT_NOTE_GNU_DEBUGID(457) Data corruption in "
".note.gnu.debugid section"},
{"DW_DLE_CORRUPT_GNU_DEBUGID_SIZE(458) Section .note.gnu.debugid "
"size incorrect"},
{"DW_DLE_CORRUPT_GNU_DEBUGID_STRING(459) Section .note.gnu.debugid "
"owner string not terminated properly"},
{"DW_DLE_HEX_STRING_ERROR(460). dwarf_producer_init() "
"extras string has a bad hex string"},
{"DW_DLE_DECIMAL_STRING_ERROR(461) dwarf_producer_init() extras "
"string has a bad decimal string"},
{"DW_DLE_PRO_INIT_EXTRAS_UNKNOWN(462) dwarf_producer_init() extras "
"string has an unknown string"},
{"DW_DLE_PRO_INIT_EXTRAS_ERR(463) dwarf_producer_init() extras "
"string has an unexpected space character"},
{"DW_DLE_NULL_ARGS_DWARF_ADD_PATH(464) obsolete error code"},
{"DW_DLE_DWARF_INIT_DBG_NULL(465) a dwarf_init*() call "
"the return-dbg argument is null"},
{"DW_DLE_ELF_RELOC_SECTION_ERROR(466) A relocation section header "
"link field is incorrect."},
{"DW_DLE_USER_DECLARED_ERROR(467) library user created this."},
{"DW_DLE_RNGLISTS_ERROR(468) Corrupt dwarf. Bad .debug_rnglists "
"data."},
{"DW_DLE_LOCLISTS_ERROR(469) Corrupt dwarf. Bad .debug_loclists "
"data."},
{"DW_DLE_SECTION_SIZE_OR_OFFSET_LARGE(470) corrupt section header."},
{"DW_DLE_GDBINDEX_STRING_ERROR(471) .gdb_index section string error"},
{"DW_DLE_GNU_PUBNAMES_ERROR(472) A problem with .debug_gnu_pubnames"},
{"DW_DLE_GNU_PUBTYPES_ERROR(473) A problem with .debug_gnu_pubtypes"},
{"DW_DLE_DUPLICATE_GNU_DEBUG_PUBNAMES(474) Duplicated section "
".debug_gnu_pubnames"},
{"DW_DLE_DUPLICATE_GNU_DEBUG_PUBTYPES(475) Duplicated section "
".debug_gnu_pubtypes"},
{"DW_DLE_DEBUG_SUP_STRING_ERROR(476) String in .debug_sup head "
"runs off the end of the section."},
{"DW_DLE_DEBUG_SUP_ERROR(477). .debug_sup data corruption"},
{"DW_DLE_LOCATION_ERROR(478). A location processing libdwarf error"},
{"DW_DLE_DEBUGLINK_PATH_SHORT(479) Buffer provided for GNU "
"debuglink is too small"},
{"DW_DLE_SIGNATURE_MISMATCH(480) DWARF4 extension dwo_id and "
"dwarf5signature present but they do not match!"},
{"DW_DLE_MACRO_VERSION_ERROR(481) Unknown DWARF5 macro version."
" Corrupt data."},
{"DW_DLE_NEGATIVE_SIZE(482) A size < 0 "
"(from DW_FORM_implicit_const) is not appropriate"},
{"DW_DLE_UDATA_VALUE_NEGATIVE(483) Reading a negative value from "
"dwarf_formudata() is not allowed."},
{"DW_DLE_DEBUG_NAMES_ERROR(484) Error reading .debug_names"},
{"DW_DLE_CFA_INSTRUCTION_ERROR(485) Error accessing "
"frame instructions"},
{"DW_DLE_MACHO_CORRUPT_HEADER(486) Incorrect header content."
" Corrupt DWARF"},
{"DW_DLE_MACHO_CORRUPT_COMMAND(487) Incorrect Macho Command "
"data. Corrupt DWARF"},
{"DW_DLE_MACHO_CORRUPT_SECTIONDETAILS(488) Incorrect Macho "
"section data. Corrupt DWARF"},
{"DW_DLE_RELOCATION_SECTION_SIZE_ERROR(489) Corrupt Elf. "
"Reloc section size impossible."},
{"DW_DLE_SYMBOL_SECTION_SIZE_ERROR(490) Corrupt Elf. "
"Symbols section size bad"},
{"DW_DLE_PE_SECTION_SIZE_ERROR(491) Corrupt PE object. "
"Section size too large."},
{"DW_DLE_DEBUG_ADDR_ERROR(492) Problem reading .debug_addr"},
{"DW_DLE_NO_SECT_STRINGS(493) Section strings section "
"number from header "
"is incorrect. Unusable object"},
{"DW_DLE_TOO_FEW_SECTIONS(494) Sections incomplete, corrupted. "
"Unusable object"},
{"DW_DLE_BUILD_ID_DESCRIPTION_SIZE(495) .note.gnu.build-id section"
" corrupt. Unusable object"},
{"DW_DLE_BAD_SECTION_FLAGS(496) Some section flags are incorrect."
" Unusable object"},
{"DW_DLE_IMPROPER_SECTION_ZERO(497) Section zero header contents "
"incorrect. See Elf ABI. Unsafe object."},
{"DW_DLE_INVALID_NULL_ARGUMENT(498) Argument must be a valid "
"pointer and non-null"},
{"DW_DLE_LINE_INDEX_WRONG(499) An index into a line table is "
"not valid. Corrupt data."},
{"DW_DLE_LINE_COUNT_WRONG(500) A count in a line table is "
"not valid. Corrupt data."},
{"DW_DLE_ARITHMETIC_OVERFLOW(501) Arithmetic overflow. "
" Corrupt Dwarf." },
{"DW_DLE_UNIVERSAL_BINARY_ERROR(502) Error reading Mach-O "
"uninversal binary head. Corrupt Mach-O object." },
{"DW_DLE_UNIV_BIN_OFFSET_SIZE_ERROR(503) Offset/size from "
"a Mach-O universal binary has an impossible value"}
};
#endif /* DWARF_ERRMSG_LIST_H */

230
src/lib/libdwarf/dwarf_error.c vendored Normal file
View File

@ -0,0 +1,230 @@
/*
Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
Portions Copyright (C) 2008-2020 David Anderson. All Rights Reserved.
This program is free software; you can redistribute it
and/or modify it under the terms of version 2.1 of the
GNU Lesser General Public License as published by the Free
Software Foundation.
This program is distributed in the hope that it would be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
Further, this software is distributed without any warranty
that it is free of the rightful claim of any third person
regarding infringement or the like. Any license provided
herein, whether implied or otherwise, applies only to this
software file. Patent licenses, if any, provided herein
do not apply to combinations of this program with other
software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write the
Free Software Foundation, Inc., 51 Franklin Street - Fifth
Floor, Boston MA 02110-1301, USA.
*/
#include <config.h>
#include <stdio.h> /* stderr fflush() fprintf() */
#include <stdlib.h> /* calloc() */
#if defined(_WIN32) && defined(HAVE_STDAFX_H)
#include "stdafx.h"
#endif /* HAVE_STDAFX_H */
#include "dwarf.h"
#include "libdwarf.h"
#include "libdwarf_private.h"
#include "dwarf_base_types.h"
#include "dwarf_opaque.h"
#include "dwarf_alloc.h"
#include "dwarf_string.h"
#include "dwarf_error.h"
#undef DEBUG
/* Array to hold string representation of errors. Any time a
define is added to the list in libdwarf.h, a string should be
added to this Array
*/
#include "dwarf_errmsg_list.h"
/* This function performs error handling as described in the
libdwarf consumer document section 3. Dbg is the Dwarf_debug
structure being processed. Error is a pointer to the pointer
to the error descriptor that will be returned. Errval is an
error code listed in dwarf_error.h.
If the malloc arena is exhausted we return a pointer to
a special static error record. This special singleton
is mostly ignored by dwarf_dealloc().
Users should not be storing Dwarf_Error pointers
for long so this singleton is only going to cause
confusion when callers try to save an out-of-memory
Dwarf_Error pointer.
If the call provides no way to handle the error
the function simply returns, whereas it used
(before July 2021) to abort in that case.
*/
/* The user provides an explanatory string, the error
number itself explains little.
This prepends DW_DLE_USER_DECLARED_ERROR to the
caller-provided string.
New in April, 2020 . Used by dwarfdump in a few
circumstances. */
void
dwarf_error_creation(Dwarf_Debug dbg,
Dwarf_Error *err,
char *errmsg)
{
dwarfstring m;
if (!dbg) {
return;
}
dwarfstring_constructor(&m);
dwarfstring_append(&m,"DW_DLE_USER_DECLARED_ERROR: ");
dwarfstring_append(&m,errmsg);
_dwarf_error_string(dbg,err,
DW_DLE_USER_DECLARED_ERROR,
dwarfstring_string(&m));
dwarfstring_destructor(&m);
}
/* In rare cases (bad object files) an error is created
via malloc with no dbg to attach it to.
We record a few of those and dealloc and flush
on any dwarf_finish()
We do not expect this except on corrupt objects. */
void
_dwarf_error(Dwarf_Debug dbg, Dwarf_Error * error,
Dwarf_Signed errval)
{
_dwarf_error_string(dbg,error,errval,0);
}
void
_dwarf_error_string(Dwarf_Debug dbg, Dwarf_Error * error,
Dwarf_Signed errval,char *msg)
{
Dwarf_Error errptr = 0;
/* Allow NULL dbg on entry, since sometimes that
can happen and we want to report the upper-level
error, not the null dbg error. */
if (error) {
/* If dbg is NULL, use the alternate error struct. However,
this will overwrite the earlier error. */
if (dbg) {
errptr =
(Dwarf_Error) _dwarf_get_alloc(dbg, DW_DLA_ERROR, 1);
if (!errptr) {
errptr = &_dwarf_failsafe_error;
errptr->er_static_alloc = DE_STATIC;
} else {
errptr->er_static_alloc = DE_STANDARD;
}
} else {
/* We have no dbg to work with. dwarf_init
failed. We hack
up a special area. */
errptr = _dwarf_special_no_dbg_error_malloc();
if (!errptr) {
errptr = &_dwarf_failsafe_error;
errptr->er_static_alloc = DE_STATIC;
#ifdef DEBUG
printf("libdwarf no dbg, fullystatic, "
"using DE_STATIC alloc, addr"
" 0x%lx line %d %s\n",
(unsigned long)errptr,
__LINE__,__FILE__);
#endif /* DEBUG */
} else {
errptr->er_static_alloc = DE_MALLOC;
#ifdef DEBUG
printf("libdwarf no dbg,leaks, "
"static DE_MALLOC alloc, addr"
" 0x%lx line %d %s\n",
(unsigned long)errptr,
__LINE__,__FILE__);
#endif /* DEBUG */
_dwarf_add_to_static_err_list(errptr);
}
}
errptr->er_errval = errval;
if (msg && errptr->er_static_alloc != DE_STATIC) {
dwarfstring *em = 0;
#ifdef DEBUG
printf("libdwarf ALLOC creating error string"
" %s errval %ld errptr 0x%lx \n",
msg,(long)errval,(unsigned long)errptr);
#endif /* DEBUG */
em = (dwarfstring *)calloc(1,sizeof(dwarfstring));
if (em) {
dwarfstring_constructor(em);
dwarfstring_append(em,msg);
errptr->er_msg = (void*)em;
}
}
*error = errptr;
return;
}
if (dbg && dbg->de_errhand != NULL) {
errptr = (Dwarf_Error) _dwarf_get_alloc(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);
return;
}
fflush(stderr);
fprintf(stderr,
"\nlibdwarf is unable to record error %s "
"No error argument or handler available\n",
dwarf_errmsg_by_number(errval));
fflush(stderr);
return;
}
Dwarf_Unsigned
dwarf_errno(Dwarf_Error error)
{
if (!error) {
return (0);
}
return (error->er_errval);
}
char*
dwarf_errmsg_by_number(Dwarf_Unsigned errornum )
{
if (errornum > DW_DLE_LAST) {
return "Dwarf_Error value out of range";
}
return ((char *) &_dwarf_errmsgs[errornum][0]);
}
/*
*/
char *
dwarf_errmsg(Dwarf_Error error)
{
if (!error) {
return "Dwarf_Error is NULL";
}
if (error->er_msg) {
return dwarfstring_string(error->er_msg);
}
return dwarf_errmsg_by_number(error->er_errval);
}

71
src/lib/libdwarf/dwarf_error.h vendored Normal file
View File

@ -0,0 +1,71 @@
/*
Copyright (C) 2000 Silicon Graphics, Inc. All Rights Reserved.
Portions Copyright (C) 2011-2023 David Anderson. All Rights Reserved.
This program is free software; you can redistribute it
and/or modify it under the terms of version 2.1 of the
GNU Lesser General Public License as published by the Free
Software Foundation.
This program is distributed in the hope that it would be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
Further, this software is distributed without any warranty
that it is free of the rightful claim of any third person
regarding infringement or the like. Any license provided
herein, whether implied or otherwise, applies only to this
software file. Patent licenses, if any, provided herein
do not apply to combinations of this program with other
software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write the
Free Software Foundation, Inc., 51 Franklin Street - Fifth
Floor, Boston MA 02110-1301, USA.
*/
#ifndef DWARF_ERROR_H
#define DWARF_ERROR_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void _dwarf_error(Dwarf_Debug dbg, Dwarf_Error * error,
Dwarf_Signed errval);
void _dwarf_error_string(Dwarf_Debug dbg, Dwarf_Error * error,
Dwarf_Signed errval, char *msg);
#define DWARF_DBG_ERROR(dbg,errval,retval) \
_dwarf_error((dbg), error, (errval)); return(retval);
#define DE_STANDARD 0 /* Normal alloc attached to dbg. */
#define DE_STATIC 1 /* Using global static var */
#define DE_MALLOC 2 /* Using malloc space */
struct Dwarf_Error_s {
Dwarf_Signed er_errval;
void * er_msg;
/* If non-zero the Dwarf_Error_s struct is not malloc'd.
To aid when malloc returns NULL.
If zero a normal dwarf_dealloc will work.
er_static_alloc only accessed by dwarf_alloc.c.
If er_static_alloc is 1 in a Dwarf_Error_s
struct (set by libdwarf) and client code accidentally
turns that 0 to zero through a wild
pointer reference (the field is hidden
from clients...) then chaos will
eventually follow.
*/
int er_static_alloc;
};
extern struct Dwarf_Error_s _dwarf_failsafe_error;
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* DWARF_ERROR_H */

View File

@ -0,0 +1,195 @@
/*
Copyright (C) 2022 David Anderson. All Rights Reserved.
Redistribution and use in source and binary forms, with
or without modification, are permitted provided that the
following conditions are met:
Redistributions of source code must retain the above
copyright notice, this list of conditions and the following
disclaimer.
Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <stddef.h> /* NULL size_t */
#include <stdlib.h> /* calloc() free() malloc() */
#if defined(_WIN32) && defined(HAVE_STDAFX_H)
#include "stdafx.h"
#endif /* HAVE_STDAFX_H */
#include "dwarf.h"
#include "libdwarf.h"
#include "libdwarf_private.h"
#include "dwarf_base_types.h"
#include "dwarf_opaque.h"
#include "dwarf_alloc.h"
#include "dwarf_die_deliv.h"
#include "dwarf_abbrev.h"
#include "dwarf_error.h"
#include "dwarf_util.h"
#include "dwarf_string.h"
/*
This is a pre-scan of the abbrev/form list.
We will not handle DW_FORM_indirect here as that
accesses data outside of the abbrev section.
*/
int
_dwarf_fill_in_attr_form_abtable(Dwarf_CU_Context context,
Dwarf_Byte_Ptr abbrev_ptr,
Dwarf_Byte_Ptr abbrev_end,
Dwarf_Abbrev_List abbrev_list,
Dwarf_Error *error)
{
Dwarf_Debug dbg = 0;
Dwarf_Unsigned i = 0;
dbg = context->cc_dbg;
abbrev_list->abl_attr = (Dwarf_Half*)
calloc(abbrev_list->abl_abbrev_count,
SIZEOFT16);
abbrev_list->abl_form = (Dwarf_Half *)
calloc(abbrev_list->abl_abbrev_count,
SIZEOFT16);
if (abbrev_list->abl_implicit_const_count > 0) {
abbrev_list->abl_implicit_const = (Dwarf_Signed *)
calloc(abbrev_list->abl_abbrev_count,
sizeof(Dwarf_Signed));
if (!abbrev_list->abl_implicit_const) {
dwarfstring m;
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;
}
}
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) {
Dwarf_Unsigned attr = 0;
Dwarf_Unsigned attr_form = 0;
Dwarf_Signed implicit_const = 0;
int res = 0;
res = _dwarf_leb128_uword_wrapper(dbg,
&abbrev_ptr,abbrev_end,&attr,error);
if (res == DW_DLV_ERROR) {
return res;
}
if (attr > 0xffff) {
dwarfstring m;
dwarfstring_constructor(&m);
dwarfstring_append(&m,
"DW_DLE_ATTR_FORM_SIZE_BAD :"
" reading Attribute number ");
dwarfstring_append(&m," for abbrev list entry"
" the ULEB number is too large. Corrupt Dwarf.");
_dwarf_error_string(dbg,error,DW_DLE_ATTR_FORM_SIZE_BAD,
dwarfstring_string(&m));
dwarfstring_destructor(&m);
return DW_DLV_ERROR;
}
abbrev_list->abl_attr[i] = (Dwarf_Half)attr;
if (attr > DW_AT_hi_user) {
_dwarf_error(dbg, error,DW_DLE_ATTR_CORRUPT);
return DW_DLV_ERROR;
}
res = _dwarf_leb128_uword_wrapper(dbg,
&abbrev_ptr,abbrev_end,&attr_form,error);
if (res == DW_DLV_ERROR) {
return res;
}
if (attr_form > 0xffff) {
dwarfstring m;
dwarfstring_constructor(&m);
dwarfstring_append(&m,
"DW_DLE_ATTR_FORM_SIZE_BAD :"
" reading attr_form");
dwarfstring_append(&m,"an abbrev list entry "
"the ULEB form number is too large. "
"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;
}
if (!_dwarf_valid_form_we_know(attr_form,attr)) {
dwarfstring m;
dwarfstring_constructor(&m);
dwarfstring_append(&m,"Reading an abbreviation list "
" we find the attribute form pair to be "
" impossible or unknown.");
dwarfstring_append_printf_u(&m," attr 0x%x ",attr);
dwarfstring_append_printf_u(&m," attrform 0x%x ",
attr_form);
_dwarf_error_string(dbg, error, DW_DLE_UNKNOWN_FORM,
dwarfstring_string(&m));
dwarfstring_destructor(&m);
return DW_DLV_ERROR;
}
abbrev_list->abl_attr[i] = (Dwarf_Half)attr;
abbrev_list->abl_form[i] = (Dwarf_Half)attr_form;
if (attr_form == DW_FORM_implicit_const) {
res = _dwarf_leb128_sword_wrapper(dbg,
&abbrev_ptr,abbrev_end,&implicit_const,error);
if (res == DW_DLV_ERROR) {
return res;
}
abbrev_list->abl_implicit_const_count++;
abbrev_list->abl_implicit_const[i] = implicit_const;
}
#if 0
if (attr_form == DW_FORM_indirect) {
/* Do nothing special here. Do not read
from the DIE till reading for
a specific DIE, which we are not
intending here, we do not know
where the DIE is. */
}
#endif
}
return DW_DLV_OK;
}

222
src/lib/libdwarf/dwarf_find_sigref.c vendored Normal file
View File

@ -0,0 +1,222 @@
/*
Copyright (C) 2021 David Anderson. All Rights Reserved.
This program is free software; you can redistribute it
and/or modify it under the terms of version 2.1 of the
GNU Lesser General Public License as published by the Free
Software Foundation.
This program is distributed in the hope that it would be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
Further, this software is distributed without any warranty
that it is free of the rightful claim of any third person
regarding infringement or the like. Any license provided
herein, whether implied or otherwise, applies only to this
software file. Patent licenses, if any, provided herein
do not apply to combinations of this program with other
software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write the
Free Software Foundation, Inc., 51 Franklin Street - Fifth
Floor, Boston MA 02110-1301, USA.
*/
#include <config.h>
#include <string.h> /* memcmp() */
#include <stdio.h> /* printf() debugging */
#if defined(_WIN32) && defined(HAVE_STDAFX_H)
#include "stdafx.h"
#endif /* HAVE_STDAFX_H */
#include "dwarf.h"
#include "libdwarf.h"
#include "libdwarf_private.h"
#include "dwarf_base_types.h"
#include "dwarf_opaque.h"
#include "dwarf_alloc.h"
#include "dwarf_error.h"
#include "dwarf_util.h"
#include "dwarf_string.h"
#if 0
static void
dump_bytes(const char *msg,int line,
Dwarf_Small * start, long len)
{
Dwarf_Small *end = start + len;
Dwarf_Small *cur = start;
printf("%s (0x%lx) line %d\n ",msg,(unsigned long)start,line);
for (; cur < end; cur++) {
printf("%02x", *cur);
}
printf("\n");
}
#endif /*0*/
static int
_dwarf_find_CU_Context_given_sig(Dwarf_Debug dbg,
int context_level,
Dwarf_Sig8 *sig_in,
Dwarf_CU_Context *cu_context_out,
Dwarf_Bool *is_info_out,
Dwarf_Error *error)
{
Dwarf_CU_Context cu_context = 0;
Dwarf_Bool is_info = FALSE;
int loopcount = 0;
int lres = 0;
Dwarf_Debug_InfoTypes dis = 0;
struct Dwarf_Section_s *secdp = 0;
/* Loop once with is_info, once with !is_info.
Then stop. */
for ( ; loopcount < 2; ++loopcount) {
Dwarf_CU_Context prev_cu_context = 0;
Dwarf_Unsigned section_size = 0;
Dwarf_Unsigned new_cu_offset = 0;
is_info = !is_info;
if (is_info) {
dis = &dbg->de_info_reading;
secdp = &dbg->de_debug_info;
} else {
dis = &dbg->de_types_reading;
secdp = &dbg->de_debug_types;
}
lres = _dwarf_load_die_containing_section(dbg,is_info,error);
if (lres == DW_DLV_ERROR) {
return lres;
}
if (lres == DW_DLV_NO_ENTRY ) {
continue;
}
/* Lets see if we already have the CU we need. */
for (cu_context = dis->de_cu_context_list;
cu_context; cu_context = cu_context->cc_next) {
prev_cu_context = cu_context;
if (memcmp(sig_in,&cu_context->cc_signature,
sizeof(Dwarf_Sig8))) {
continue;
}
if (cu_context->cc_unit_type == DW_UT_split_type||
cu_context->cc_unit_type == DW_UT_type) {
*cu_context_out = cu_context;
*is_info_out = cu_context->cc_is_info;
return DW_DLV_OK;
}
}
if (context_level > 0) {
/* Make no attempt to create new context,
we are finishing cu die base fields
on one already.
Just look for the other context,
DWARF4 debug_types */
continue;
}
if (prev_cu_context) {
Dwarf_CU_Context lcu_context = prev_cu_context;
new_cu_offset =
_dwarf_calculate_next_cu_context_offset(
lcu_context);
} else {
new_cu_offset = 0;
}
section_size = secdp->dss_size;
for ( ; new_cu_offset < section_size;
new_cu_offset =
_dwarf_calculate_next_cu_context_offset(
cu_context)) {
#if 0
lres = _dwarf_load_die_containing_section(dbg,
is_info,error);
if (lres == DW_DLV_ERROR) {
return lres;
}
if (lres == DW_DLV_NO_ENTRY) {
continue;
}
#endif /*0*/
lres = _dwarf_create_a_new_cu_context_record_on_list(
dbg, dis,is_info,section_size,new_cu_offset,
&cu_context,error);
if (lres == DW_DLV_ERROR) {
return lres;
}
if (lres == DW_DLV_NO_ENTRY) {
break;
}
if (memcmp(sig_in,&cu_context->cc_signature,
sizeof(Dwarf_Sig8))) {
continue;
}
if (cu_context->cc_unit_type == DW_UT_split_type||
cu_context->cc_unit_type == DW_UT_type) {
*cu_context_out = cu_context;
*is_info_out = cu_context->cc_is_info;
return DW_DLV_OK;
}
}
} /* Loop-end. */
/* Not found */
return DW_DLV_NO_ENTRY;
}
/* We will search to find a CU with the indicated signature
The attribute leading us here is often
We are looking for a DW_UT_split_type or DW_UT_type
CU.
DW_AT_type and if DWARF4 that means our first look is
to !is_info */
int
dwarf_find_die_given_sig8(Dwarf_Debug dbg,
Dwarf_Sig8 *ref,
Dwarf_Die *die_out,
Dwarf_Bool *is_info,
Dwarf_Error *error)
{
int res = 0;
res = _dwarf_internal_find_die_given_sig8(
dbg,0,ref,die_out,is_info,error);
return res;
}
/* If context level > 0 restrict what we will do
to avoid recursion creating CU Contexts */
int
_dwarf_internal_find_die_given_sig8(Dwarf_Debug dbg,
int context_level,
Dwarf_Sig8 *ref,
Dwarf_Die *die_out,
Dwarf_Bool *is_info,
Dwarf_Error *error)
{
int res = 0;
Dwarf_Die ndi = 0;
Dwarf_CU_Context context = 0;
Dwarf_Bool result_is_info = FALSE;
Dwarf_Unsigned dieoffset = 0;
res =_dwarf_find_CU_Context_given_sig(dbg,
context_level,
ref, &context, &result_is_info,error);
if (res != DW_DLV_OK) {
return res;
}
dieoffset = context->cc_debug_offset +
context->cc_signature_offset;
res = dwarf_offdie_b(dbg,dieoffset,result_is_info,
&ndi,error);
if (res == DW_DLV_OK) {
*die_out = ndi;
*is_info = result_is_info;
}
return res;
}

367
src/lib/libdwarf/dwarf_fission_to_cu.c vendored Normal file
View File

@ -0,0 +1,367 @@
/*
Copyright (C) 2018-2020 David Anderson. All Rights Reserved.
This program is free software; you can redistribute it
and/or modify it under the terms of version 2.1 of the
GNU Lesser General Public License as published by the
Free Software Foundation.
This program is distributed in the hope that it would
be useful, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Further, this software is distributed without any warranty
that it is free of the rightful claim of any third person
regarding infringement or the like. Any license provided
herein, whether implied or otherwise, applies only to
this software file. Patent licenses, if any, provided
herein do not apply to combinations of this program with
other software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write
the Free Software Foundation, Inc., 51 Franklin Street -
Fifth Floor, Boston MA 02110-1301, USA.
*/
#include <config.h>
#include <string.h> /* memset() */
#if defined(_WIN32) && defined(HAVE_STDAFX_H)
#include "stdafx.h"
#endif /* HAVE_STDAFX_H */
#include "dwarf.h"
#include "libdwarf.h"
#include "libdwarf_private.h"
#include "dwarf_base_types.h"
#include "dwarf_opaque.h"
#include "dwarf_alloc.h"
#include "dwarf_error.h"
#include "dwarf_util.h"
#include "dwarf_string.h"
#include "dwarf_str_offsets.h"
#include "dwarf_loc.h"
#include "dwarf_rnglists.h"
/* ASSERT: dbg,cu_context, and fsd are non-NULL
as the caller ensured that. */
const struct Dwarf_Loclists_Context_s localcontxt_zero;
static int
load_xu_loclists_into_cucontext(Dwarf_Debug dbg,
Dwarf_CU_Context cu_context,
struct Dwarf_Debug_Fission_Per_CU_s*fsd,
int fsd_index,
Dwarf_Error *error)
{
Dwarf_Unsigned size = 0;
Dwarf_Unsigned soff_hdroffset = 0;
Dwarf_Unsigned soff_size = 0;
struct Dwarf_Loclists_Context_s localcontxt;
Dwarf_Loclists_Context buildhere = &localcontxt;
Dwarf_Unsigned nextset = 0;
int res = 0;
if (!fsd) {
_dwarf_error_string(dbg, error, DW_DLE_XU_TYPE_ARG_ERROR,
"DW_DLE_XU_TYPE_ARG_ERROR: a required argument to"
"load_xu_loclists_into_cucontext() is NULL");
return DW_DLV_ERROR;
}
localcontxt = localcontxt_zero;
size = fsd->pcu_size[fsd_index];
soff_hdroffset = fsd->pcu_offset[fsd_index];
soff_size = dbg->de_debug_loclists.dss_size;
if (!soff_size) {
return DW_DLV_NO_ENTRY;
}
if (soff_hdroffset >= soff_size) {
/* Something is badly wrong. Ignore it here. */
return DW_DLV_NO_ENTRY;
}
memset(buildhere,0,sizeof(localcontxt));
res = _dwarf_internal_read_loclists_header(dbg,
0,soff_size,
dbg->de_debug_loclists.dss_data,
dbg->de_debug_loclists.dss_data +soff_size,
soff_hdroffset,
buildhere,
&nextset,error);
if (res != DW_DLV_OK) {
return res;
}
cu_context->cc_loclists_base_present = TRUE;
cu_context->cc_loclists_base_contr_size = size;
cu_context->cc_loclists_base =
buildhere->lc_offsets_off_in_sect;
return DW_DLV_OK;
}
/*
ASSERT: dbg,cu_context, and fsd are non-NULL
as the caller ensured that.
If .debug_cu_index or
.debug_tu_index is present it might help us find
the offset for this CU's .debug_str_offsets.
*/
static int
load_xu_str_offsets_into_cucontext(Dwarf_Debug dbg,
Dwarf_CU_Context cu_context,
struct Dwarf_Debug_Fission_Per_CU_s*fsd,
int fsd_index,
Dwarf_Error *error )
{
Dwarf_Small *soff_secptr = 0;
Dwarf_Unsigned soff_hdroffset = 0;
Dwarf_Unsigned soff_size = 0;
Dwarf_Small *soff_eptr = 0;
int res = 0;
res = _dwarf_load_section(dbg, &dbg->de_debug_str_offsets,
error);
if (res != DW_DLV_OK) {
return res;
}
soff_hdroffset = fsd->pcu_offset[fsd_index];
soff_secptr = dbg->de_debug_str_offsets.dss_data;
soff_size = dbg->de_debug_str_offsets.dss_size;
if (soff_hdroffset >= soff_size) {
/* Something is badly wrong. Ignore it here. */
return DW_DLV_NO_ENTRY;
}
{
Dwarf_Unsigned length = 0;
Dwarf_Half offset_size = 0;
Dwarf_Half extension_size = 0;
Dwarf_Half version = 0;
Dwarf_Half padding = 0;
Dwarf_Unsigned local_offset_to_array=0;
Dwarf_Unsigned total_table_length =0;
struct Dwarf_Str_Offsets_Table_s sotstr;
memset(&sotstr,0,sizeof(sotstr));
sotstr.so_dbg = dbg;
sotstr.so_section_start_ptr = soff_secptr;
sotstr.so_section_end_ptr = soff_eptr;
sotstr.so_section_size = soff_size;
sotstr.so_next_table_offset = soff_hdroffset;
res = _dwarf_read_str_offsets_header(&sotstr,
cu_context,
&length,&offset_size,
&extension_size,&version,&padding,
&local_offset_to_array,
&total_table_length,
error);
if (res != DW_DLV_OK) {
if (res == DW_DLV_ERROR && error) {
dwarf_dealloc_error(dbg,*error);
*error = 0;
}
return DW_DLV_NO_ENTRY;
}
/* See dwarf_opaque.h for comments. */
cu_context->cc_str_offsets_tab_present = TRUE;
cu_context->cc_str_offsets_header_offset = soff_hdroffset;
cu_context->cc_str_offsets_tab_to_array =
local_offset_to_array;
cu_context->cc_str_offsets_table_size = total_table_length;
cu_context->cc_str_offsets_version = version;
cu_context->cc_str_offsets_offset_size = offset_size;
}
return DW_DLV_OK;
}
/* ASSERT: dbg,cu_context, and fsd are non-NULL
as the caller ensured that. */
static int
load_xu_debug_macro_into_cucontext(Dwarf_Debug dbg,
Dwarf_CU_Context cu_context,
struct Dwarf_Debug_Fission_Per_CU_s*fsd,
int fsd_index,
Dwarf_Error *error )
{
Dwarf_Unsigned size = 0;
Dwarf_Unsigned soff_hdroffset = 0;
Dwarf_Unsigned soff_size = 0;
int res = 0;
res = _dwarf_load_section(dbg, &dbg->de_debug_macro,
error);
if (res != DW_DLV_OK) {
return res;
}
size = fsd->pcu_size[fsd_index];
soff_hdroffset = fsd->pcu_offset[fsd_index];
soff_size = dbg->de_debug_macro.dss_size;
if (!soff_size) {
return DW_DLV_NO_ENTRY;
}
if (soff_hdroffset >= soff_size) {
/* Something is badly wrong. Ignore it here. */
return DW_DLV_NO_ENTRY;
}
/* Presently assuming that DW_AT_macros
and the fission entry both
indicate the beginning
of a .debug_macro sectiom macro header.
(not true for str_offsets or for loclists!)
*/
cu_context->cc_macro_base_present = TRUE;
cu_context->cc_macro_base_contr_size = size;
cu_context->cc_macro_base = soff_hdroffset;
/* FIXME cc_macro_header_length_present? */
return DW_DLV_OK;
}
/* ASSERT: dbg,cu_context, and fsd are non-NULL
as the caller ensured that. */
const struct Dwarf_Rnglists_Context_s builddata_zero;
static int
load_xu_rnglists_into_cucontext(Dwarf_Debug dbg,
Dwarf_CU_Context cu_context,
struct Dwarf_Debug_Fission_Per_CU_s*fsd,
int fsd_index,
Dwarf_Error *error )
{
Dwarf_Unsigned size = 0;
Dwarf_Unsigned soff_hdroffset = 0;
Dwarf_Unsigned soff_size = 0;
struct Dwarf_Rnglists_Context_s builddata;
Dwarf_Rnglists_Context buildhere = &builddata;
Dwarf_Unsigned nextoffset = 0;
int res = 0;
builddata = builddata_zero;
res = _dwarf_load_section(dbg, &dbg->de_debug_rnglists,
error);
if (res != DW_DLV_OK) {
return res;
}
size = fsd->pcu_size[fsd_index];
soff_hdroffset = fsd->pcu_offset[fsd_index];
soff_size = dbg->de_debug_rnglists.dss_size;
if (!soff_size) {
return DW_DLV_NO_ENTRY;
}
if (soff_hdroffset >= soff_size) {
/* Something is badly wrong. Ignore it here. */
return DW_DLV_NO_ENTRY;
}
memset(buildhere,0,sizeof(builddata));
res = _dwarf_internal_read_rnglists_header(dbg,
0,soff_size,
dbg->de_debug_rnglists.dss_data,
dbg->de_debug_rnglists.dss_data+soff_size,
soff_hdroffset,buildhere,
&nextoffset,error);
if (res != DW_DLV_OK) {
return res;
}
cu_context->cc_rnglists_base =
buildhere->rc_offsets_off_in_sect;
cu_context->cc_rnglists_base_present = TRUE;
cu_context->cc_rnglists_base_contr_size = size;
/* FIXME cc_rnglists_header_length_present? */
return DW_DLV_OK;
}
static const char *keylist[2] = {
"cu",
"tu"
};
/* ASSERT: The context has a signature.
ASSERT: dbg and cu_context are non-NULL
as the caller tested them.
_dwarf_make_CU_Context() calls
finish_up_cu_context_from_cudie() which calls
us here.
Then, _dwarf_make_CU_Context() calls
_dwarf_merge_all_base_attrs_of_cu_die() if there
is a tied (executable) object known.
Called by dwarf_die_deliv.c
*/
const struct Dwarf_Debug_Fission_Per_CU_s fission_data_zero;
int
_dwarf_find_all_offsets_via_fission(Dwarf_Debug dbg,
Dwarf_CU_Context cu_context,
Dwarf_Error *error)
{
struct Dwarf_Debug_Fission_Per_CU_s fission_data;
struct Dwarf_Debug_Fission_Per_CU_s*fsd = 0;
int si = 0;
int smax = 2;
int fdres = 0;
int res = 0;
fission_data = fission_data_zero;
fsd = &fission_data;
for (si = 0; si < smax ; ++si) {
int sec_index = 0;
memset(&fission_data,0,sizeof(fission_data));
fdres = dwarf_get_debugfission_for_key(dbg,
&cu_context->cc_signature,
keylist[si],
fsd,error);
if (fdres == DW_DLV_NO_ENTRY) {
continue;
}
if (fdres == DW_DLV_ERROR) {
if (error) {
dwarf_dealloc_error(dbg,*error);
*error = 0;
}
continue;
}
for (sec_index = 1; sec_index < DW_FISSION_SECT_COUNT;
++sec_index) {
if (!fsd->pcu_size[sec_index]) {
continue;
}
res = DW_DLV_OK;
switch(sec_index) {
/* these handled elsewhere, such
as by _dwarf_get_dwp_extra_offset()
_dwarf_get_fission_addition_die()
case DW_SECT_INFO:
case DW_SECT_ABBREV:
case DW_SECT_LINE:
*/
case DW_SECT_LOCLISTS:
res = load_xu_loclists_into_cucontext(dbg,
cu_context,
fsd,sec_index,error);
break;
case DW_SECT_STR_OFFSETS:
res = load_xu_str_offsets_into_cucontext(dbg,
cu_context,
fsd,sec_index,error);
break;
case DW_SECT_MACRO:
res = load_xu_debug_macro_into_cucontext(dbg,
cu_context,
fsd,sec_index,error);
break;
case DW_SECT_RNGLISTS:
res = load_xu_rnglists_into_cucontext(dbg,
cu_context,
fsd,sec_index,error);
break;
default:
res = DW_DLV_OK;
break;
}
if (res == DW_DLV_ERROR) {
return res;
}
}
}
return DW_DLV_OK;
}

2263
src/lib/libdwarf/dwarf_form.c vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,110 @@
/*
Copyright (c) 2021, David Anderson All rights reserved.
Redistribution and use in source and binary forms, with
or without modification, are permitted provided that the
following conditions are met:
Redistributions of source code must retain the above
copyright notice, this list of conditions and the following
disclaimer.
Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include "libdwarf.h"
/* FORM_CLASS is created by libdwarf, it is
not a part of Standard Dwarf. Dwarf_Form_Class attempts
to allow convenient processing of FORMs
across DWARF2,3,4, and 5 for libdwarf,
dwarfdump, and other clients and ensures
type-safe referencing. */
int
dwarf_get_FORM_CLASS_name (enum Dwarf_Form_Class fc,
const char ** s_out)
{
switch (fc) {
case DW_FORM_CLASS_UNKNOWN:
*s_out = "DW_FORM_CLASS_UNKNOWN";
return DW_DLV_OK;
case DW_FORM_CLASS_ADDRESS:
*s_out = "DW_FORM_CLASS_ADDRESS";
return DW_DLV_OK;
case DW_FORM_CLASS_BLOCK:
*s_out = "DW_FORM_CLASS_BLOCK";
return DW_DLV_OK;
case DW_FORM_CLASS_CONSTANT:
*s_out = "DW_FORM_CLASS_CONSTANT";
return DW_DLV_OK;
case DW_FORM_CLASS_EXPRLOC:
*s_out = "DW_FORM_CLASS_EXPRLOC";
return DW_DLV_OK;
case DW_FORM_CLASS_FLAG:
*s_out = "DW_FORM_CLASS_FLAG";
return DW_DLV_OK;
case DW_FORM_CLASS_LINEPTR:
*s_out = "DW_FORM_CLASS_LINEPTR";
return DW_DLV_OK;
case DW_FORM_CLASS_LOCLISTPTR:
*s_out = "DW_FORM_CLASS_LOCLISTPTR";
return DW_DLV_OK;
case DW_FORM_CLASS_MACPTR:
*s_out = "DW_FORM_CLASS_MACPTR";
return DW_DLV_OK;
case DW_FORM_CLASS_RANGELISTPTR:
*s_out = "DW_FORM_CLASS_RANGELISTPTR";
return DW_DLV_OK;
case DW_FORM_CLASS_REFERENCE:
*s_out = "DW_FORM_CLASS_REFERENCE";
return DW_DLV_OK;
case DW_FORM_CLASS_STRING:
*s_out = "DW_FORM_CLASS_STRING";
return DW_DLV_OK;
case DW_FORM_CLASS_FRAMEPTR:
*s_out = "DW_FORM_CLASS_FRAMEPTR";
return DW_DLV_OK;
case DW_FORM_CLASS_MACROPTR:
*s_out = "DW_FORM_CLASS_MAXCROPTR";
return DW_DLV_OK;
case DW_FORM_CLASS_ADDRPTR:
*s_out = "DW_FORM_CLASS_ADDRPTR";
return DW_DLV_OK;
case DW_FORM_CLASS_LOCLIST:
*s_out = "DW_FORM_CLASS_LOCLIST";
return DW_DLV_OK;
case DW_FORM_CLASS_LOCLISTSPTR:
*s_out = "DW_FORM_CLASS_LOCLISTSPTR";
return DW_DLV_OK;
case DW_FORM_CLASS_RNGLIST:
*s_out = "DW_FORM_CLASS_RNGLIST";
return DW_DLV_OK;
case DW_FORM_CLASS_RNGLISTSPTR:
*s_out = "DW_FORM_CLASS_RNGLISTSPTR";
return DW_DLV_OK;
case DW_FORM_CLASS_STROFFSETSPTR:
*s_out = "DW_FORM_CLASS_STROFFSETSPTR";
return DW_DLV_OK;
default: break;
}
return DW_DLV_NO_ENTRY;
}

3503
src/lib/libdwarf/dwarf_frame.c vendored Normal file

File diff suppressed because it is too large Load Diff

509
src/lib/libdwarf/dwarf_frame.h vendored Normal file
View File

@ -0,0 +1,509 @@
/*
Copyright (C) 2000, 2004, 2006 Silicon Graphics, Inc. All Rights Reserved.
Portions Copyright (C) 2021-2023 David Anderson. All Rights Reserved.
This program is free software; you can redistribute it
and/or modify it under the terms of version 2.1 of the
GNU Lesser General Public License as published by the Free
Software Foundation.
This program is distributed in the hope that it would be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
Further, this software is distributed without any warranty
that it is free of the rightful claim of any third person
regarding infringement or the like. Any license provided
herein, whether implied or otherwise, applies only to this
software file. Patent licenses, if any, provided herein
do not apply to combinations of this program with other
software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write the
Free Software Foundation, Inc., 51 Franklin Street - Fifth
Floor, Boston MA 02110-1301, USA.
*/
/* The dwarf 2.0 standard dictates that only the following
fields can be read when an unexpected augmentation string
(in the cie) is encountered: CIE length, CIE_id, version and
augmentation; FDE: length, CIE pointer, initial location and
address range. Unfortunately, with the above restrictions, it
is impossible to read the instruction table from a CIE or a FDE
when a new augmentation string is encountered.
To fix this problem, the following layout is used, if the
augmentation string starts with the string "z".
CIE FDE
length length
CIE_id CIE_pointer
version initial_location
augmentation address_range
- length_of_augmented_fields (*NEW*)
code_alignment_factor Any new fields as necessary
data_alignment_factor instruction_table
return_address
length_of_augmented fields
Any new fields as necessary
initial_instructions
The type of all the old data items are the same as what is
described in dwarf 2.0 standard. The length_of_augmented_fields
is an LEB128 data item that denotes the size (in bytes) of
the augmented fields (not including the size of
"length_of_augmented_fields" itself).
Handling of cie augmentation strings is necessarily a heuristic.
See dwarf_frame.c for the currently known augmentation strings.
---START SGI-ONLY COMMENT:
SGI-IRIX versions of cie or fde were intended
to use "z1", "z2" as the
augmenter strings if required for new augmentation.
However, that never happened (as of March 2005).
The fde's augmented by the string "z" have a new field
(signed constant, 4 byte field)
called offset_into_exception_tables, following the
length_of_augmented field. This field contains an offset
into the "_MIPS_eh_region", which describes
the IRIX CC exception handling tables.
---END SGI-ONLY COMMENT
GNU .eh_frame has an augmentation string of z[RLP]* (gcc 3.4)
The similarity to IRIX 'z' (and proposed but never
implemented IRIX z1, z2 etc) was confusing things.
If the section is .eh_frame then 'z' means GNU exception
information 'Augmentation Data' not IRIX 'z'.
See The Linux Standard Base Core Specification version 3.0
*/
#define DW_DEBUG_FRAME_VERSION 1 /* DWARF2 */
#define DW_DEBUG_FRAME_VERSION3 3 /* DWARF3 */
#define DW_DEBUG_FRAME_VERSION4 4 /* DWARF4 */
/* The following is SGI/IRIX specific, and probably no longer
in use anywhere. */
#define DW_DEBUG_FRAME_AUGMENTER_STRING "mti v1"
/* The value of the offset field for Cie's. */
#define DW_CIE_OFFSET ~(0x0)
/* The augmentation string may be NULL. */
#define DW_EMPTY_STRING ""
#define DW_FRAME_INSTR_OPCODE_SHIFT 6
#define DW_FRAME_INSTR_OFFSET_MASK 0x3f
/* Frame description instructions expanded.
Accessed via a function.
*/
struct Dwarf_Frame_Instr_s {
/* fp_op, if a base op, has the low 6 bits set zero here */
Dwarf_Small fi_op;
/* fp_instr_offset is within instructions */
Dwarf_Unsigned fi_instr_offset;
Dwarf_Unsigned fi_offset; /* frame offset */
/* A string like "u","r", or "rsd" denoting the field
meanings. See the entire list of possibilities.
Never free. */
const char *fi_fields;
/* letter r and u both use u struct elements. */
Dwarf_Unsigned fi_u0;
Dwarf_Unsigned fi_u1;
Dwarf_Unsigned fi_u2; /* LLVM extension */
Dwarf_Signed fi_s0;
Dwarf_Signed fi_s1;
Dwarf_Unsigned fi_code_align_factor;
Dwarf_Signed fi_data_align_factor;
Dwarf_Block fi_expr;
/* Used to prepare a list, which
is then turned into array and this zeroed. */
struct Dwarf_Frame_Instr_s *fi_next;
};
typedef struct Dwarf_Frame_Instr_s * Dwarf_Frame_Instr;
struct Dwarf_Frame_Instr_Head_s {
/* fp_op, if a base op, has the low 6 bits set zero here */
Dwarf_Debug fh_dbg;
Dwarf_Cie fh_cie;
/* array of pointers to Dwarf_Frame_Instr_s */
Dwarf_Frame_Instr *fh_array;
Dwarf_Unsigned fh_array_count;
};
/*
This struct denotes the rule for a register in a row of
the frame table. In other words, it is one element of
the table.
*/
struct Dwarf_Reg_Rule_s {
/* Is a flag indicating whether the rule includes the offset
field, ie whether the ru_soffset field is valid or not.
Applies only if DW_EXPR_OFFSET or DW_EXPR_VAL_OFFSET.
It is important, since reg+offset (offset of 0)
is different from
just 'register' since the former means 'read memory at address
given by the sum of register contents plus offset to get the
value'. whereas the latter
means 'the value is in the register'.
*/
Dwarf_Sbyte ru_is_offset;
/* This has to do with evaluating register
instructions, not with printing frame instruction.
DW_EXPR_OFFSET 0 ( DWARF2)
DW_EXPR_VAL_OFFSET 1 (dwarf2/3)
DW_EXPR_EXPRESSION 2 (dwarf2/3)
DW_EXPR_VAL_EXPRESSION 3 (dwarf2/3)
DW_EXPR_ARGS_SIZE 4 (GNU)
*/
Dwarf_Sbyte ru_value_type;
/* Register involved in this rule, real or non-real-register.
ru_value_type is DW_EXPR_OFFSET or DW_EXPR_VAL_OFFSET.
*/
Dwarf_Unsigned ru_register;
/* Offset to add to register, if indicated by ru_is_offset.
ru_value_type is DW_EXPR_OFFSET */
Dwarf_Signed ru_offset;
Dwarf_Unsigned ru_args_size; /* DW_CFA_GNU_args_size */
/* If ru_value_type is DW_EXPR_EXPRESSION
or DW_EXPR_VAL_EXPRESSION this is filled in. */
Dwarf_Block ru_block;
};
/* Internal use only */
typedef struct Dwarf_Regtable_Entry3_s_i {
Dwarf_Small dw_offset_relevant;
Dwarf_Small dw_value_type;
Dwarf_Unsigned dw_regnum;
Dwarf_Unsigned dw_offset;
Dwarf_Unsigned dw_args_size; /* Not dealt with. */
Dwarf_Block dw_block;
} Dwarf_Regtable_Entry3_i;
/* Internal use only */
typedef struct Dwarf_Regtable3_s_i {
Dwarf_Regtable_Entry3_i rt3_cfa_rule;
Dwarf_Unsigned rt3_reg_table_size;
Dwarf_Regtable_Entry3_i *rt3_rules;
} Dwarf_Regtable3_i;
typedef struct Dwarf_Frame_s *Dwarf_Frame;
/*
This structure represents a row of the frame table.
Fr_loc is the pc value for this row, and Fr_reg
contains the rule for each column.
Entry DW_FRAME_CFA_COL of fr_reg was the traditional MIPS
way of setting CFA. cfa_rule is the new one.
*/
struct Dwarf_Frame_s {
/* Pc value corresponding to this row of the frame table. */
Dwarf_Addr fr_loc;
/* Rules for all the registers in this row. */
struct Dwarf_Reg_Rule_s fr_cfa_rule;
/* fr_reg_count is the the number of
entries of the fr_reg array. */
Dwarf_Unsigned fr_reg_count;
struct Dwarf_Reg_Rule_s *fr_reg;
Dwarf_Frame fr_next;
};
/* See dwarf_frame.c for the heuristics used to set the
Dwarf_Cie ci_augmentation_type.
This succinctly helps interpret the size and
meaning of .debug_frame
and (for gcc) .eh_frame.
In the case of gcc .eh_frame (gcc 3.3, 3.4)
z may be followed by one or more of
L R P.
*/
enum Dwarf_augmentation_type {
aug_empty_string, /* Default empty augmentation string. */
aug_irix_exception_table, /* IRIX plain "z",
for exception handling, IRIX CC compiler.
Proposed z1 z2 ... never implemented. */
aug_gcc_eh_z, /* gcc z augmentation, (including
L R P variations). gcc 3.3 3.4 exception
handling in eh_frame. */
aug_irix_mti_v1, /* IRIX "mti v1" augmentation string. Probably
never in any released SGI-IRIX compiler. */
aug_eh, /* For gcc .eh_frame, "eh" is the string.,
gcc 1,2, egcs. Older values. */
aug_armcc, /* "armcc+" meaning the cfa calculation
is corrected to be standard (output by
Arm C RVCT 3.0 SP1 and later). See
http://sourceware.org/ml/gdb-patches/2006-12/msg00249.html
for details. */
aug_unknown, /* Unknown augmentation, we cannot do much. */
/* HC, From http://sourceforge.net/p/elftoolchain/tickets/397/ */
aug_metaware,
aug_past_last
};
/*
This structure contains all the pertinent info for a Cie. Most
of the fields are taken straight from the definition of a Cie.
Ci_cie_start points to the address (in .debug_frame) where this
Cie begins. Ci_cie_instr_start points to the first byte of the
frame instructions for this Cie. Ci_dbg points to the associated
Dwarf_Debug structure. Ci_initial_table is a pointer to the table
row generated by the instructions for this Cie.
*/
struct Dwarf_Cie_s {
Dwarf_Unsigned ci_length;
char *ci_augmentation;
Dwarf_Unsigned ci_code_alignment_factor;
Dwarf_Signed ci_data_alignment_factor;
Dwarf_Small ci_return_address_register;
Dwarf_Small *ci_cie_start;
Dwarf_Small *ci_cie_instr_start;
Dwarf_Small *ci_cie_end;
Dwarf_Debug ci_dbg;
Dwarf_Frame ci_initial_table;
Dwarf_Cie ci_next;
Dwarf_Small ci_length_size;
Dwarf_Small ci_extension_size;
Dwarf_Half ci_cie_version_number;
enum Dwarf_augmentation_type ci_augmentation_type;
/* The following 2 for GNU .eh_frame exception handling
Augmentation Data. Set if ci_augmentation_type
is aug_gcc_eh_z. Zero if unused. */
Dwarf_Unsigned ci_gnu_eh_augmentation_len;
Dwarf_Ptr ci_gnu_eh_augmentation_bytes;
/* These are extracted from the gnu eh_frame
augmentation if the
augmentation begins with 'z'. See Linux LSB documents.
Otherwize these are zero. */
unsigned char ci_gnu_personality_handler_encoding;
unsigned char ci_gnu_lsda_encoding;
unsigned char ci_gnu_fde_begin_encoding;
/* If 'P' augmentation present, is handler addr. Else
is zero. */
Dwarf_Addr ci_gnu_personality_handler_addr;
/* In creating list of cie's (which will become an array)
record the position so fde can get it on fde creation. */
Dwarf_Unsigned ci_index;
Dwarf_Small * ci_section_ptr;
Dwarf_Unsigned ci_section_length;
Dwarf_Small * ci_section_end;
/* DWARF4 adds address size and segment size to the CIE:
the .debug_info
section may not always be present to allow libdwarf to
find address_size from the compilation-unit. */
Dwarf_Half ci_address_size;
Dwarf_Half ci_segment_size;
};
/*
This structure contains all the pertinent info for a Fde.
Most of the fields are taken straight from the definition.
fd_cie_index is the index of the Cie associated with this
Fde in the list of Cie's for this debug_frame. Fd_cie
points to the corresponding Dwarf_Cie structure. Fd_fde_start
points to the start address of the Fde. Fd_fde_instr_start
points to the start of the instructions for this Fde. Fd_dbg
points to the associated Dwarf_Debug structure.
*/
struct Dwarf_Fde_s {
Dwarf_Unsigned fd_length;
Dwarf_Addr fd_cie_offset;
Dwarf_Unsigned fd_cie_index;
Dwarf_Cie fd_cie;
Dwarf_Addr fd_initial_location;
Dwarf_Small *fd_initial_loc_pos;
Dwarf_Addr fd_address_range;
Dwarf_Small *fd_fde_start;
Dwarf_Small *fd_fde_instr_start;
Dwarf_Small *fd_fde_end;
Dwarf_Debug fd_dbg;
/* fd_offset_into_exception_tables is SGI/IRIX exception table
offset. Unused and zero if not IRIX .debug_frame. */
Dwarf_Signed fd_offset_into_exception_tables;
Dwarf_Fde fd_next;
Dwarf_Small fd_length_size;
Dwarf_Small fd_extension_size;
/* So we know from an fde which 'count' of fde-s in
Dwarf_Debug applies: eh or standard. */
Dwarf_Small fd_is_eh;
/* The following 2 for GNU .eh_frame exception handling
Augmentation Data. Set if CIE ci_augmentation_type
is aug_gcc_eh_z. Zero if unused. */
Dwarf_Unsigned fd_gnu_eh_augmentation_len;
Dwarf_Bool fd_gnu_eh_aug_present;
Dwarf_Ptr fd_gnu_eh_augmentation_bytes;
Dwarf_Addr fd_gnu_eh_lsda; /* If 'L' augmentation letter
present: is address of the
Language Specific Data Area (LSDA). If not 'L" is zero. */
/* The following 3 are about the Elf section the FDEs come from.*/
Dwarf_Small *fd_section_ptr;
Dwarf_Unsigned fd_section_length;
Dwarf_Unsigned fd_section_index;
Dwarf_Small *fd_section_end;
/* If fd_eh_table_value_set is true, then fd_eh_table_value is
meaningful. Never meaningful for .debug_frame, is
part of .eh_frame. */
Dwarf_Unsigned fd_eh_table_value;
Dwarf_Bool fd_eh_table_value_set;
/* The following are memoization to save recalculation. */
struct Dwarf_Frame_s fd_fde_table;
Dwarf_Addr fd_fde_pc_requested;
Dwarf_Bool fd_have_fde_tab;
/* Set by dwarf_get_fde_for_die() */
Dwarf_Bool fd_fde_owns_cie;
};
int
_dwarf_validate_register_numbers(Dwarf_Debug dbg,Dwarf_Error *error);
int
_dwarf_frame_address_offsets(Dwarf_Debug dbg, Dwarf_Addr ** addrlist,
Dwarf_Off ** offsetlist,
Dwarf_Signed * returncount,
Dwarf_Error * err);
int
_dwarf_get_fde_list_internal(Dwarf_Debug dbg,
Dwarf_Cie ** cie_data,
Dwarf_Signed * cie_element_count,
Dwarf_Fde ** fde_data,
Dwarf_Signed * fde_element_count,
Dwarf_Small * section_ptr,
Dwarf_Unsigned section_index,
Dwarf_Unsigned section_length,
Dwarf_Unsigned cie_id_value,
int use_gnu_cie_calc, /* If non-zero,
this is gcc eh_frame. */
Dwarf_Error * error);
enum Dwarf_augmentation_type
_dwarf_get_augmentation_type(Dwarf_Debug dbg,
Dwarf_Small *augmentation_string,
int is_gcc_eh_frame);
int _dwarf_fde_section_offset(Dwarf_Debug /*dbg*/,
Dwarf_Fde /*in_fde*/,
Dwarf_Off * /*fde_off*/,
Dwarf_Off * /*cie_off*/,
Dwarf_Error * /*err*/);
int _dwarf_cie_section_offset(Dwarf_Debug /*dbg*/,
Dwarf_Cie /*in_cie*/,
Dwarf_Off * /*cie_off */,
Dwarf_Error * /*err*/);
int _dwarf_get_return_address_reg(Dwarf_Small *frame_ptr,
int version,
Dwarf_Debug dbg,
Dwarf_Byte_Ptr section_end,
unsigned long *size,
Dwarf_Unsigned *return_address_register,
Dwarf_Error *error);
/* Temporary recording of crucial cie/fde prefix data.
Vastly simplifies some argument lists. */
struct cie_fde_prefix_s {
/* cf_start_addr is a pointer to the first byte
of this fde/cie (meaning the length field itself) */
Dwarf_Small * cf_start_addr;
/* cf_addr_after_prefix is a pointer
to the first byte of this fde/cie
we are reading now, immediately following
the length field read by READ_AREA_LENGTH. */
Dwarf_Small * cf_addr_after_prefix;
/* cf_length is the length field value from the cie/fde
header. */
Dwarf_Unsigned cf_length;
int cf_local_length_size;
int cf_local_extension_size;
Dwarf_Unsigned cf_cie_id;
Dwarf_Small * cf_cie_id_addr; /*used for eh_frame calculations.*/
/* Simplifies passing around these values to create fde having
these here. */
/* cf_section_ptr is a pointer to the first byte
of the object section the prefix is read from. */
Dwarf_Small * cf_section_ptr;
Dwarf_Unsigned cf_section_index;
Dwarf_Unsigned cf_section_length;
};
int
_dwarf_exec_frame_instr(Dwarf_Bool make_instr,
Dwarf_Bool search_pc,
Dwarf_Addr search_pc_val,
Dwarf_Addr initial_loc,
Dwarf_Small * start_instr_ptr,
Dwarf_Small * final_instr_ptr,
Dwarf_Frame table,
Dwarf_Cie cie,
Dwarf_Debug dbg,
Dwarf_Unsigned reg_num_of_cfa,
Dwarf_Bool * has_more_rows,
Dwarf_Addr * subsequent_pc,
Dwarf_Frame_Instr_Head *ret_frame_instr_head,
Dwarf_Unsigned * returned_frame_instr_count,
Dwarf_Error *error);
int _dwarf_read_cie_fde_prefix(Dwarf_Debug dbg,
Dwarf_Small *frame_ptr_in,
Dwarf_Small *section_ptr_in,
Dwarf_Unsigned section_index_in,
Dwarf_Unsigned section_length_in,
struct cie_fde_prefix_s *prefix_out,
Dwarf_Error *error);
int _dwarf_create_fde_from_after_start(Dwarf_Debug dbg,
struct cie_fde_prefix_s * prefix,
Dwarf_Small *section_pointer,
Dwarf_Unsigned section_length,
Dwarf_Small *frame_ptr,
Dwarf_Small *section_ptr_end,
int use_gnu_cie_calc,
Dwarf_Cie cie_ptr_in,
Dwarf_Small address_size_in,
Dwarf_Fde *fde_ptr_out,
Dwarf_Error *error);
int _dwarf_create_cie_from_after_start(Dwarf_Debug dbg,
struct cie_fde_prefix_s *prefix,
Dwarf_Small* section_pointer,
Dwarf_Small* frame_ptr,
Dwarf_Small *section_ptr_end,
Dwarf_Unsigned cie_count,
int use_gnu_cie_calc,
Dwarf_Cie *cie_ptr_out,
Dwarf_Error *error);
int _dwarf_frame_constructor(Dwarf_Debug dbg,void * );
void _dwarf_frame_destructor (void *);
void _dwarf_fde_destructor (void *);
void _dwarf_frame_instr_destructor(void *);

2049
src/lib/libdwarf/dwarf_frame2.c vendored Normal file

File diff suppressed because it is too large Load Diff

850
src/lib/libdwarf/dwarf_gdbindex.c vendored Normal file
View File

@ -0,0 +1,850 @@
/*
Copyright (C) 2014-2020 David Anderson. All Rights Reserved.
This program is free software; you can redistribute it
and/or modify it under the terms of version 2.1 of the
GNU Lesser General Public License as published by the Free
Software Foundation.
This program is distributed in the hope that it would be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
Further, this software is distributed without any warranty
that it is free of the rightful claim of any third person
regarding infringement or the like. Any license provided
herein, whether implied or otherwise, applies only to this
software file. Patent licenses, if any, provided herein
do not apply to combinations of this program with other
software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write the
Free Software Foundation, Inc., 51 Franklin Street - Fifth
Floor, Boston MA 02110-1301, USA.
*/
/* see
https://sourceware.org/gdb/onlinedocs/gdb/\
Index-Section-Format.html#Index-Section-Format
*/
#include <config.h>
#include <string.h> /* memcpy() */
#if defined(_WIN32) && defined(HAVE_STDAFX_H)
#include "stdafx.h"
#endif /* HAVE_STDAFX_H */
#ifdef HAVE_STDINT_H
#include <stdint.h> /* uintptr_t */
#endif /* HAVE_STDINT_H */
#include "dwarf.h"
#include "libdwarf.h"
#include "libdwarf_private.h"
#include "dwarf_base_types.h"
#include "dwarf_opaque.h"
#include "dwarf_alloc.h"
#include "dwarf_error.h"
#include "dwarf_util.h"
#include "dwarf_string.h"
#include "dwarf_memcpy_swap.h"
#include "dwarf_gdbindex.h"
/* The dwarf_util macro READ_UNALIGNED
cannot be directly used because
gdb defines the section contents of
.gdb_index as little-endian always.
*/
#if WORDS_BIGENDIAN /* meaning on this host */
#define READ_GDBINDEX(dest,desttype, source, length) \
do { \
BIGGEST_UINT _ltmp = 0; \
_dwarf_memcpy_swap_bytes((((char *)(&_ltmp)) \
+ sizeof(_ltmp) - (length)), \
(source), (length)) ; \
(dest) = (desttype)_ltmp; \
} while (0)
#else /* little-endian on this host */
#define READ_GDBINDEX(dest,desttype, source, length) \
do { \
BIGGEST_UINT _ltmp = 0; \
memcpy(((char *)(&_ltmp)) , \
(source), (length)) ; \
(dest) = (desttype)_ltmp; \
} while (0)
#endif
struct dwarf_64bitpair {
gdbindex_64 offset;
gdbindex_64 length;
};
static void
emit_no_value_msg(Dwarf_Debug dbg,
int errnum,
const char * errstr_text,
Dwarf_Error *error)
{
_dwarf_error_string(dbg,error,errnum,
(char *)errstr_text);
}
static void
emit_one_value_msg(Dwarf_Debug dbg,
int errnum,
const char * errstr_text,
Dwarf_Unsigned value,
Dwarf_Error *error)
{
dwarfstring m;
dwarfstring_constructor(&m);
dwarfstring_append_printf_u(&m,
(char *)errstr_text,value);
_dwarf_error_string(dbg,error,errnum,
dwarfstring_string(&m));
dwarfstring_destructor(&m);
}
static int
set_base(Dwarf_Debug dbg,
struct Dwarf_Gdbindex_array_instance_s * hdr,
Dwarf_Small *start,
Dwarf_Small *end,
/* entrylen is the length of a single struct as seen
in the object. */
Dwarf_Unsigned entrylen,
/* The size of each field in the struct in the object. */
Dwarf_Unsigned fieldlen,
enum gdbindex_type_e type,
Dwarf_Error * error)
{
if (type == git_std || type == git_cuvec) {
/* cuvec is sort of a fake as a simple
section, but a useful one. */
Dwarf_Unsigned count = 0;
if ( end < start) {
_dwarf_error(dbg, error,DW_DLE_GDB_INDEX_COUNT_ERROR);
return DW_DLV_ERROR;
}
count = end - start;
count = count / entrylen;
hdr->dg_type = type;
hdr->dg_base = start;
hdr->dg_count = count;
hdr->dg_entry_length = entrylen;
hdr->dg_fieldlen = (unsigned)fieldlen;
} else {
/* address area. */
/* 64bit, 64bit, offset. Then 32bit pad. */
Dwarf_Unsigned count = 0;
hdr->dg_base = start;
if ( end < start) {
_dwarf_error(dbg, error,
DW_DLE_GDB_INDEX_COUNT_ADDR_ERROR);
return DW_DLV_ERROR;
}
/* entry length includes pad. */
hdr->dg_entry_length = 2*sizeof(gdbindex_64) +
DWARF_32BIT_SIZE;
count = end - start;
count = count / hdr->dg_entry_length;
hdr->dg_count = count;
/* The dg_fieldlen is a fake, the fields are not
all the same length. */
hdr->dg_fieldlen = DWARF_32BIT_SIZE;
hdr->dg_type = type;
}
return DW_DLV_OK;
}
int
dwarf_gdbindex_header(Dwarf_Debug dbg,
Dwarf_Gdbindex * gdbindexptr,
Dwarf_Unsigned * version,
Dwarf_Unsigned * cu_list_offset,
Dwarf_Unsigned * types_cu_list_offset,
Dwarf_Unsigned * address_area_offset,
Dwarf_Unsigned * symbol_table_offset,
Dwarf_Unsigned * constant_pool_offset,
Dwarf_Unsigned * section_size,
const char ** section_name,
Dwarf_Error * error)
{
Dwarf_Gdbindex indexptr = 0;
int res = DW_DLV_ERROR;
Dwarf_Small *data = 0;
Dwarf_Small *startdata = 0;
Dwarf_Unsigned version_in = 0;
if (!dbg) {
_dwarf_error_string(NULL, error,
DW_DLE_GDB_INDEX_INDEX_ERROR,
"DW_DLE_GDB_INDEX_INDEX_ERROR:"
" passed in NULL Dwarf_Debut to"
" dwarf_gdbindex_header");
return DW_DLV_ERROR;
}
if (!dbg->de_debug_gdbindex.dss_size) {
return DW_DLV_NO_ENTRY;
}
if (!dbg->de_debug_gdbindex.dss_data) {
res = _dwarf_load_section(dbg, &dbg->de_debug_gdbindex,error);
if (res != DW_DLV_OK) {
return res;
}
}
data = dbg->de_debug_gdbindex.dss_data;
startdata = data;
if (dbg->de_debug_gdbindex.dss_size < (DWARF_32BIT_SIZE*6)) {
_dwarf_error(dbg, error, DW_DLE_ERRONEOUS_GDB_INDEX_SECTION);
return DW_DLV_ERROR;
}
indexptr = (Dwarf_Gdbindex)_dwarf_get_alloc(dbg,
DW_DLA_GDBINDEX,1);
if (indexptr == NULL) {
_dwarf_error_string(dbg, error, DW_DLE_ALLOC_FAIL,
"DW_DLE_ALLOC_FAIL: allocating Dwarf_Gdbindex");
return DW_DLV_ERROR;
}
READ_GDBINDEX(version_in,Dwarf_Unsigned,
data, DWARF_32BIT_SIZE);
indexptr->gi_version = version_in;
indexptr->gi_dbg = dbg;
indexptr->gi_section_data = startdata;
indexptr->gi_section_length = dbg->de_debug_gdbindex.dss_size;
/* 7 and lower are different format in some way */
if (indexptr->gi_version != 8 &&
indexptr->gi_version != 7) {
emit_one_value_msg(dbg, DW_DLE_ERRONEOUS_GDB_INDEX_SECTION,
"DW_DLE_ERRONEOUS_GDB_INDEX_SECTION: "
" version number %u is not"
" supported",
indexptr->gi_version,error);
dwarf_dealloc(dbg,indexptr,DW_DLA_GDBINDEX);
return DW_DLV_ERROR;
}
data += DWARF_32BIT_SIZE;
READ_GDBINDEX(indexptr->gi_cu_list_offset ,Dwarf_Unsigned,
data, DWARF_32BIT_SIZE);
if (indexptr->gi_cu_list_offset > indexptr->gi_section_length) {
emit_one_value_msg(dbg, DW_DLE_ERRONEOUS_GDB_INDEX_SECTION,
"DW_DLE_ERRONEOUS_GDB_INDEX_SECTION"
" cu list offset of %u is too large for the section",
indexptr->gi_cu_list_offset,error);
dwarf_dealloc(dbg,indexptr,DW_DLA_GDBINDEX);
return DW_DLV_ERROR;
}
data += DWARF_32BIT_SIZE;
READ_GDBINDEX(indexptr->gi_types_cu_list_offset ,Dwarf_Unsigned,
data, DWARF_32BIT_SIZE);
if (indexptr->gi_types_cu_list_offset >
indexptr->gi_section_length) {
emit_one_value_msg(dbg, DW_DLE_ERRONEOUS_GDB_INDEX_SECTION,
"DW_DLE_ERRONEOUS_GDB_INDEX_SECTION"
" types cu list offset of %u is too "
"large for the section",
indexptr->gi_cu_list_offset,error);
dwarf_dealloc(dbg,indexptr,DW_DLA_GDBINDEX);
return DW_DLV_ERROR;
}
data += DWARF_32BIT_SIZE;
READ_GDBINDEX(indexptr->gi_address_area_offset ,Dwarf_Unsigned,
data, DWARF_32BIT_SIZE);
if (indexptr->gi_address_area_offset >
indexptr->gi_section_length) {
emit_one_value_msg(dbg, DW_DLE_ERRONEOUS_GDB_INDEX_SECTION,
"DW_DLE_ERRONEOUS_GDB_INDEX_SECTION"
" address area offset of %u is too "
"large for the section",
indexptr->gi_address_area_offset ,error);
dwarf_dealloc(dbg,indexptr,DW_DLA_GDBINDEX);
return DW_DLV_ERROR;
}
data += DWARF_32BIT_SIZE;
READ_GDBINDEX(indexptr->gi_symbol_table_offset ,Dwarf_Unsigned,
data, DWARF_32BIT_SIZE);
if (indexptr->gi_symbol_table_offset >
indexptr->gi_section_length) {
emit_one_value_msg(dbg, DW_DLE_ERRONEOUS_GDB_INDEX_SECTION,
"DW_DLE_ERRONEOUS_GDB_INDEX_SECTION"
" symbol table offset of %u is too "
"large for the section",
indexptr->gi_symbol_table_offset,error);
dwarf_dealloc(dbg,indexptr,DW_DLA_GDBINDEX);
return DW_DLV_ERROR;
}
data += DWARF_32BIT_SIZE;
READ_GDBINDEX(indexptr->gi_constant_pool_offset ,Dwarf_Unsigned,
data, DWARF_32BIT_SIZE);
if (indexptr->gi_constant_pool_offset >
indexptr->gi_section_length) {
emit_one_value_msg(dbg, DW_DLE_ERRONEOUS_GDB_INDEX_SECTION,
"DW_DLE_ERRONEOUS_GDB_INDEX_SECTION"
" constant pool offset of %u is too "
"large for the section",
indexptr->gi_constant_pool_offset,error);
dwarf_dealloc(dbg,indexptr,DW_DLA_GDBINDEX);
return DW_DLV_ERROR;
}
data += DWARF_32BIT_SIZE;
res = set_base(dbg,&indexptr->gi_culisthdr,
startdata + indexptr->gi_cu_list_offset,
startdata + indexptr->gi_types_cu_list_offset,
2*sizeof(gdbindex_64),
sizeof(gdbindex_64),
git_std,error);
if (res == DW_DLV_ERROR) {
dwarf_dealloc(dbg,indexptr,DW_DLA_GDBINDEX);
return res;
}
res = set_base(dbg,&indexptr->gi_typesculisthdr,
startdata+ indexptr->gi_types_cu_list_offset,
startdata+ indexptr->gi_address_area_offset,
3*sizeof(gdbindex_64),
sizeof(gdbindex_64),
git_std,error);
if (res == DW_DLV_ERROR) {
dwarf_dealloc(dbg,indexptr,DW_DLA_GDBINDEX);
return res;
}
res = set_base(dbg,&indexptr->gi_addressareahdr,
startdata + indexptr->gi_address_area_offset,
startdata + indexptr->gi_symbol_table_offset,
3*sizeof(gdbindex_64),
sizeof(gdbindex_64),
git_address,error);
if (res == DW_DLV_ERROR) {
dwarf_dealloc(dbg,indexptr,DW_DLA_GDBINDEX);
return res;
}
res = set_base(dbg,&indexptr->gi_symboltablehdr,
startdata + indexptr->gi_symbol_table_offset,
startdata + indexptr->gi_constant_pool_offset,
2*DWARF_32BIT_SIZE,
DWARF_32BIT_SIZE,
git_std,error);
if (res == DW_DLV_ERROR) {
dwarf_dealloc(dbg,indexptr,DW_DLA_GDBINDEX);
return res;
}
res = set_base(dbg,&indexptr->gi_cuvectorhdr,
startdata + indexptr->gi_constant_pool_offset,
/* There is no real single vector size.
but we'll use the entire rest as if there was. */
startdata + indexptr->gi_section_length,
DWARF_32BIT_SIZE,
DWARF_32BIT_SIZE,
git_cuvec,error);
if (res == DW_DLV_ERROR) {
dwarf_dealloc(dbg,indexptr,DW_DLA_GDBINDEX);
return res;
}
*gdbindexptr = indexptr;
*version = indexptr->gi_version;
*cu_list_offset = indexptr->gi_cu_list_offset;
*types_cu_list_offset = indexptr->gi_types_cu_list_offset;
*address_area_offset = indexptr->gi_address_area_offset;
*symbol_table_offset = indexptr->gi_symbol_table_offset;
*constant_pool_offset = indexptr->gi_constant_pool_offset;
*section_size = indexptr->gi_section_length;
*section_name = dbg->de_debug_gdbindex.dss_name;
return DW_DLV_OK;
}
int
dwarf_gdbindex_culist_array(Dwarf_Gdbindex gdbindexptr,
Dwarf_Unsigned * list_length,
Dwarf_Error * error)
{
if (!gdbindexptr || !gdbindexptr->gi_dbg) {
_dwarf_error_string(NULL, error,
DW_DLE_GDB_INDEX_INDEX_ERROR,
"DW_DLE_GDB_INDEX_INDEX_ERROR:"
" passed in NULL inindexptr to"
" dwarf_gdbindex_culist_array");
return DW_DLV_ERROR;
}
(void)error;
*list_length = gdbindexptr->gi_culisthdr.dg_count;
return DW_DLV_OK;
}
/* entryindex: 0 to list_length-1 */
int
dwarf_gdbindex_culist_entry(Dwarf_Gdbindex gdbindexptr,
Dwarf_Unsigned entryindex,
Dwarf_Unsigned * cu_offset,
Dwarf_Unsigned * cu_length,
Dwarf_Error * error)
{
Dwarf_Small * base = 0;
Dwarf_Small * endptr = 0;
Dwarf_Unsigned offset = 0;
Dwarf_Unsigned length = 0;
Dwarf_Unsigned max = 0;
unsigned fieldlen = 0;
if (!gdbindexptr || !gdbindexptr->gi_dbg) {
_dwarf_error_string(NULL, error,
DW_DLE_GDB_INDEX_INDEX_ERROR,
"DW_DLE_GDB_INDEX_INDEX_ERROR:"
" passed in NULL inindexptr to"
" dwarf_gdbindex_culist_entry");
return DW_DLV_ERROR;
}
max = gdbindexptr->gi_culisthdr.dg_count;
fieldlen = gdbindexptr->gi_culisthdr.dg_fieldlen;
if (entryindex >= max) {
return DW_DLV_NO_ENTRY;
}
endptr = gdbindexptr->gi_section_data +
gdbindexptr->gi_section_length;
base = gdbindexptr->gi_culisthdr.dg_base;
base += entryindex*gdbindexptr->gi_culisthdr.dg_entry_length;
if ((base + 2*fieldlen) >endptr) {
Dwarf_Debug dbg = 0;
dbg = gdbindexptr->gi_dbg;
emit_one_value_msg(dbg, DW_DLE_GDB_INDEX_INDEX_ERROR,
"DW_DLE_GDB_INDEX_INDEX_ERROR:"
" end offset of data for index %u is past the"
" end of the section",
entryindex,error);
return DW_DLV_ERROR;
}
READ_GDBINDEX(offset ,Dwarf_Unsigned,
base,
fieldlen);
READ_GDBINDEX(length ,Dwarf_Unsigned,
base+ fieldlen,
fieldlen);
*cu_offset = offset;
*cu_length = length;
return DW_DLV_OK;
}
int
dwarf_gdbindex_types_culist_array(Dwarf_Gdbindex gdbindexptr,
Dwarf_Unsigned * list_length,
Dwarf_Error * error)
{
if (!gdbindexptr || !gdbindexptr->gi_dbg) {
_dwarf_error_string(NULL, error,
DW_DLE_GDB_INDEX_INDEX_ERROR,
"DW_DLE_GDB_INDEX_INDEX_ERROR:"
" passed in NULL inindexptr to"
" dwarf_types_culist_entry");
return DW_DLV_ERROR;
}
(void)error;
*list_length = gdbindexptr->gi_typesculisthdr.dg_count;
return DW_DLV_OK;
}
/* entryindex: 0 to list_length-1 */
int
dwarf_gdbindex_types_culist_entry(Dwarf_Gdbindex gdbindexptr,
Dwarf_Unsigned entryindex,
Dwarf_Unsigned * t_offset,
Dwarf_Unsigned * t_length,
Dwarf_Unsigned * t_signature,
Dwarf_Error * error)
{
Dwarf_Unsigned max = 0;
Dwarf_Small * base = 0;
Dwarf_Small * endptr = 0;
Dwarf_Unsigned offset = 0;
Dwarf_Unsigned length = 0;
Dwarf_Unsigned signature = 0;
unsigned fieldlen = 0;
if (!gdbindexptr || !gdbindexptr->gi_dbg) {
_dwarf_error_string(NULL, error,
DW_DLE_GDB_INDEX_INDEX_ERROR,
"DW_DLE_GDB_INDEX_INDEX_ERROR:"
" passed in NULL inindexptr to"
" dwarf_gdbindex_types_culist_entry");
return DW_DLV_ERROR;
}
fieldlen = gdbindexptr->gi_typesculisthdr.dg_fieldlen;
max = gdbindexptr->gi_typesculisthdr.dg_count;
endptr = gdbindexptr->gi_section_data +
gdbindexptr->gi_section_length;
if (entryindex >= max) {
return DW_DLV_NO_ENTRY;
}
base = gdbindexptr->gi_typesculisthdr.dg_base;
base += entryindex*gdbindexptr->gi_typesculisthdr.dg_entry_length;
if ((base + 3*fieldlen) >endptr) {
Dwarf_Debug dbg = gdbindexptr->gi_dbg;
emit_one_value_msg(dbg, DW_DLE_GDB_INDEX_INDEX_ERROR,
"DW_DLE_GDB_INDEX_INDEX_ERROR:"
" end offset of data for type index %u is past the"
" end of the section",
entryindex,error);
return DW_DLV_ERROR;
}
READ_GDBINDEX(offset ,Dwarf_Unsigned,
base,
fieldlen);
READ_GDBINDEX(length ,Dwarf_Unsigned,
base+ (1*fieldlen),
fieldlen);
READ_GDBINDEX(signature ,Dwarf_Unsigned,
base+ (2*fieldlen),
fieldlen);
*t_offset = offset;
*t_length = length;
*t_signature = signature;
return DW_DLV_OK;
}
int
dwarf_gdbindex_addressarea(Dwarf_Gdbindex gdbindexptr,
Dwarf_Unsigned * list_length,
Dwarf_Error * error)
{
if (!gdbindexptr || !gdbindexptr->gi_dbg) {
_dwarf_error_string(NULL, error,
DW_DLE_GDB_INDEX_INDEX_ERROR,
"DW_DLE_GDB_INDEX_INDEX_ERROR:"
" passed in NULL inindexptr to"
" dwarf_gdbindex_addressarea");
return DW_DLV_ERROR;
}
(void)error;
*list_length = gdbindexptr->gi_addressareahdr.dg_count;
return DW_DLV_OK;
}
/* entryindex: 0 to addressarea_list_length-1 */
int
dwarf_gdbindex_addressarea_entry(
Dwarf_Gdbindex gdbindexptr,
Dwarf_Unsigned entryindex,
Dwarf_Unsigned * low_address,
Dwarf_Unsigned * high_address,
Dwarf_Unsigned * cu_index,
Dwarf_Error * error)
{
Dwarf_Unsigned max = 0;
Dwarf_Small * base = 0;
Dwarf_Small * endptr = 0;
Dwarf_Unsigned lowaddr = 0;
Dwarf_Unsigned highaddr = 0;
Dwarf_Unsigned cuindex = 0;
Dwarf_Unsigned fieldslen = 0;
if (!gdbindexptr || !gdbindexptr->gi_dbg) {
_dwarf_error_string(NULL, error,
DW_DLE_GDB_INDEX_INDEX_ERROR,
"DW_DLE_GDB_INDEX_INDEX_ERROR:"
" passed in NULL inindexptr to"
" dwarf_gdbindex_addressarea_entry");
return DW_DLV_ERROR;
}
max = gdbindexptr->gi_addressareahdr.dg_count;
if (entryindex >= max) {
_dwarf_error(gdbindexptr->gi_dbg, error,
DW_DLE_GDB_INDEX_INDEX_ERROR);
return DW_DLV_ERROR;
}
base = gdbindexptr->gi_addressareahdr.dg_base;
base += entryindex*gdbindexptr->gi_addressareahdr.dg_entry_length;
endptr = gdbindexptr->gi_section_data +
gdbindexptr->gi_section_length;
fieldslen = 2*sizeof(gdbindex_64) + DWARF_32BIT_SIZE;
if ((base + fieldslen) > endptr) {
Dwarf_Debug dbg = gdbindexptr->gi_dbg;
emit_one_value_msg(dbg, DW_DLE_GDB_INDEX_INDEX_ERROR,
"DW_DLE_GDB_INDEX_INDEX_ERROR:"
" end offset of data for "
" dwarf_gdbindex_addressarea_entry %u is past the"
" end of the section",
entryindex,error);
return DW_DLV_ERROR;
}
READ_GDBINDEX(lowaddr ,Dwarf_Unsigned,
base,
sizeof(gdbindex_64));
READ_GDBINDEX(highaddr ,Dwarf_Unsigned,
base+ (1*sizeof(gdbindex_64)),
sizeof(gdbindex_64));
READ_GDBINDEX(cuindex ,Dwarf_Unsigned,
base+ (2*sizeof(gdbindex_64)),
DWARF_32BIT_SIZE);
*low_address = lowaddr;
*high_address = highaddr;
*cu_index = cuindex;
return DW_DLV_OK;
}
int
dwarf_gdbindex_symboltable_array(Dwarf_Gdbindex gdbindexptr,
Dwarf_Unsigned * list_length,
Dwarf_Error * error)
{
if (!gdbindexptr || !gdbindexptr->gi_dbg) {
_dwarf_error_string(NULL, error,
DW_DLE_GDB_INDEX_INDEX_ERROR,
"DW_DLE_GDB_INDEX_INDEX_ERROR:"
" passed in NULL inindexptr to"
" dwarf_gdbindex_symboltable_array");
return DW_DLV_ERROR;
}
(void)error;
*list_length = gdbindexptr->gi_symboltablehdr.dg_count;
return DW_DLV_OK;
}
/* entryindex: 0 to symtab_list_length-1 */
int
dwarf_gdbindex_symboltable_entry(
Dwarf_Gdbindex gdbindexptr,
Dwarf_Unsigned entryindex,
Dwarf_Unsigned * string_offset,
Dwarf_Unsigned * cu_vector_offset,
Dwarf_Error * error)
{
Dwarf_Unsigned max = 0;
Dwarf_Small * base = 0;
Dwarf_Small * endptr = 0;
Dwarf_Unsigned symoffset = 0;
Dwarf_Unsigned cuoffset = 0;
unsigned fieldlen = 0;
if (!gdbindexptr || !gdbindexptr->gi_dbg) {
_dwarf_error_string(NULL, error,
DW_DLE_GDB_INDEX_INDEX_ERROR,
"DW_DLE_GDB_INDEX_INDEX_ERROR:"
" passed in NULL inindexptr to"
" dwarf_gdbindex_symboltable_entry");
return DW_DLV_ERROR;
}
max = gdbindexptr->gi_symboltablehdr.dg_count;
fieldlen = gdbindexptr->gi_symboltablehdr.dg_fieldlen;
if (entryindex >= max) {
return DW_DLV_NO_ENTRY;
}
base = gdbindexptr->gi_symboltablehdr.dg_base;
base += entryindex*gdbindexptr->gi_symboltablehdr.dg_entry_length;
endptr = gdbindexptr->gi_section_data +
gdbindexptr->gi_section_length;
if (( base + 2*fieldlen) >endptr) {
Dwarf_Debug dbg = gdbindexptr->gi_dbg;
emit_one_value_msg(dbg, DW_DLE_GDB_INDEX_INDEX_ERROR,
"DW_DLE_GDB_INDEX_INDEX_ERROR:"
" end offset of data for symboltable entry "
"%u is past the"
" end of the section",
entryindex,error);
return DW_DLV_ERROR;
}
READ_GDBINDEX(symoffset ,Dwarf_Unsigned,
base,
fieldlen);
READ_GDBINDEX(cuoffset ,Dwarf_Unsigned,
base + fieldlen,
fieldlen);
*string_offset = symoffset;
*cu_vector_offset = cuoffset;
return DW_DLV_OK;
}
int
dwarf_gdbindex_cuvector_length(Dwarf_Gdbindex gdbindexptr,
Dwarf_Unsigned cuvector_offset,
Dwarf_Unsigned * innercount,
Dwarf_Error * error)
{
Dwarf_Small *base = 0;
Dwarf_Small *endptr = 0;
Dwarf_Unsigned fieldlen = 0;
Dwarf_Unsigned val = 0;
if (!gdbindexptr || !gdbindexptr->gi_dbg) {
_dwarf_error_string(NULL, error,
DW_DLE_GDB_INDEX_INDEX_ERROR,
"DW_DLE_GDB_INDEX_INDEX_ERROR:"
" passed in NULL indexptr to"
" dwarf_gdbindex_cuvector_length");
return DW_DLV_ERROR;
}
base = gdbindexptr->gi_cuvectorhdr.dg_base;
endptr = gdbindexptr->gi_section_data +
gdbindexptr->gi_section_length;
fieldlen = gdbindexptr->gi_cuvectorhdr.dg_entry_length;
base += cuvector_offset;
if (( base + fieldlen) >endptr) {
Dwarf_Debug dbg = gdbindexptr->gi_dbg;
emit_no_value_msg(dbg, DW_DLE_GDB_INDEX_INDEX_ERROR,
"DW_DLE_GDB_INDEX_INDEX_ERROR:"
" end offset of count of gdbindex cuvector "
" is past the"
" end of the section",
error);
return DW_DLV_ERROR;
}
READ_GDBINDEX(val,Dwarf_Unsigned,
base,
fieldlen);
*innercount = val;
return DW_DLV_OK;
}
int
dwarf_gdbindex_cuvector_inner_attributes(Dwarf_Gdbindex gdbindexptr,
Dwarf_Unsigned cuvector_offset,
Dwarf_Unsigned innerindex,
/* The attr_value is a field of bits. For expanded version
use dwarf_gdbindex_instance_expand_value() */
Dwarf_Unsigned * attributes,
Dwarf_Error * error)
{
Dwarf_Small *base = 0;
Dwarf_Small *endptr = 0;
Dwarf_Unsigned fieldlen = 0;
Dwarf_Unsigned val = 0;
if (!gdbindexptr || !gdbindexptr->gi_dbg) {
_dwarf_error_string(NULL, error,
DW_DLE_GDB_INDEX_INDEX_ERROR,
"DW_DLE_GDB_INDEX_INDEX_ERROR:"
" passed in NULL indexptr to"
" dwarf_gdbindex_cuvector_length");
return DW_DLV_ERROR;
}
base = gdbindexptr->gi_cuvectorhdr.dg_base;
base += cuvector_offset;
endptr = gdbindexptr->gi_section_data +
gdbindexptr->gi_section_length;
fieldlen = gdbindexptr->gi_cuvectorhdr.dg_entry_length;
/* The initial 4 bytes is not part of the array,
it is some sort of count. Get past it.*/
base += fieldlen;
base += fieldlen*innerindex;
if ((base+fieldlen) >= endptr) {
Dwarf_Debug dbg = gdbindexptr->gi_dbg;
emit_one_value_msg(dbg, DW_DLE_GDB_INDEX_INDEX_ERROR,
"DW_DLE_GDB_INDEX_INDEX_ERROR:"
" end offset of data for cuvector_inner_attribute "
"%u is past the"
" end of the section",
innerindex,error);
return DW_DLV_ERROR;
}
READ_GDBINDEX(val ,Dwarf_Unsigned,
base,
fieldlen);
*attributes = val;
return DW_DLV_OK;
}
int
dwarf_gdbindex_cuvector_instance_expand_value(
Dwarf_Gdbindex gdbindexptr,
Dwarf_Unsigned value,
Dwarf_Unsigned * cu_index,
Dwarf_Unsigned * symbol_kind,
Dwarf_Unsigned * is_static,
Dwarf_Error * error)
{
if (!gdbindexptr || !gdbindexptr->gi_dbg) {
_dwarf_error_string(NULL, error, DW_DLE_DBG_NULL,
"DW_DLE_DBG_NULL: The call to "
"dwarf_gdbindex_cuvector_instance_expand_value"
" provides no dbg pointer");
return DW_DLV_ERROR;
}
*cu_index = value & 0xffffff;
*symbol_kind = (value >> 28) & 0x7;
*is_static = (value >> 31) & 1;
return DW_DLV_OK;
}
/* The strings in the pool follow (in memory) the cu index
set and are NUL terminated. */
int
dwarf_gdbindex_string_by_offset(Dwarf_Gdbindex gdbindexptr,
Dwarf_Unsigned stringoffsetinpool,
const char ** string_ptr,
Dwarf_Error * error)
{
Dwarf_Small *pooldata = 0;
Dwarf_Small *section_end = 0;
Dwarf_Small *stringitself = 0;
Dwarf_Debug dbg = 0;
Dwarf_Unsigned fulloffset = 0;
int res = 0;
if (!gdbindexptr || !gdbindexptr->gi_dbg) {
emit_no_value_msg(NULL,DW_DLE_GDB_INDEX_INDEX_ERROR,
"DW_DLE_GDB_INDEX_INDEX_ERROR: "
"The gdbindex pointer to "
"dwarf_gdbindex_string_by_offset()"
" is NULL",error);
return DW_DLV_ERROR;
}
dbg = gdbindexptr->gi_dbg;
if (!dbg) {
emit_no_value_msg(NULL,DW_DLE_GDB_INDEX_INDEX_ERROR,
"DW_DLE_GDB_INDEX_INDEX_ERROR: "
"The gdbindex Dwarf_Debug in"
"dwarf_gdbindex_string_by_offset()"
" is NULL",error);
return DW_DLV_ERROR;
}
section_end = gdbindexptr->gi_section_data +
gdbindexptr->gi_section_length;
fulloffset = gdbindexptr->gi_constant_pool_offset
+ stringoffsetinpool;
stringitself = gdbindexptr->gi_section_data + fulloffset;
if (stringitself > section_end) {
emit_one_value_msg(dbg,DW_DLE_GDBINDEX_STRING_ERROR,
"DW_DLE_GDBINDEX_STRING_ERROR: "
"The dwarf_gdbindex_string_by_offset() "
"string starts past the end of the "
"section at section_offset 0x%"
DW_PR_XZEROS DW_PR_DUx ".",
fulloffset,
error);
return DW_DLV_ERROR;
}
res = _dwarf_check_string_valid(dbg,pooldata,
stringitself, section_end,
DW_DLE_GDBINDEX_STRING_ERROR,
error);
if (res != DW_DLV_OK) {
return res;
}
*string_ptr = (const char *)stringitself;
return DW_DLV_OK;
}
void
dwarf_dealloc_gdbindex(Dwarf_Gdbindex indexptr)
{
if (indexptr) {
Dwarf_Debug dbg = indexptr->gi_dbg;
dwarf_dealloc(dbg,indexptr,DW_DLA_GDBINDEX);
}
}

84
src/lib/libdwarf/dwarf_gdbindex.h vendored Normal file
View File

@ -0,0 +1,84 @@
/*
Copyright (C) 2014-2023 David Anderson. All Rights Reserved.
This program is free software; you can redistribute it
and/or modify it under the terms of version 2.1 of the
GNU Lesser General Public License as published by the Free
Software Foundation.
This program is distributed in the hope that it would be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
Further, this software is distributed without any warranty
that it is free of the rightful claim of any third person
regarding infringement or the like. Any license provided
herein, whether implied or otherwise, applies only to this
software file. Patent licenses, if any, provided herein
do not apply to combinations of this program with other
software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write the
Free Software Foundation, Inc., 51 Franklin Street - Fifth
Floor, Boston MA 02110-1301, USA.
*/
/* The following is based on
The gdb online documentation at
https://sourceware.org/gdb/onlinedocs/gdb/
Appendix J, ".gdb_index section format".
*/
/* These are the two types .gdb_index uses.
the offset_type (32 bits) and other fields
defined 64 bits. We use our own Dwarf_Unsigned
for all the interfaces, these are just for reading
the section data.
The section data is defined to be in little-endian regardless of
the target machine.
We use our host endianness in all interfaces.
We simply assume unsigned int is 32 bits FIXME.
*/
typedef Dwarf_Unsigned gdbindex_64;
enum gdbindex_type_e {
git_unknown,
git_std,
git_address,
git_cuvec
};
struct Dwarf_Gdbindex_array_instance_s {
Dwarf_Small * dg_base;
Dwarf_Unsigned dg_count;
/* the in_object struct size. */
Dwarf_Unsigned dg_entry_length;
/* The size of a single field in the in-object struct */
unsigned dg_fieldlen;
/* The address_area type is a bit irregular. */
enum gdbindex_type_e dg_type;
};
struct Dwarf_Gdbindex_s {
Dwarf_Debug gi_dbg;
Dwarf_Small * gi_section_data; /* dss_data */
Dwarf_Unsigned gi_section_length; /* dss_size */
Dwarf_Unsigned gi_version;
Dwarf_Unsigned gi_cu_list_offset;
Dwarf_Unsigned gi_types_cu_list_offset;
Dwarf_Unsigned gi_address_area_offset;
Dwarf_Unsigned gi_symbol_table_offset;
Dwarf_Unsigned gi_constant_pool_offset;
struct Dwarf_Gdbindex_array_instance_s gi_culisthdr;
struct Dwarf_Gdbindex_array_instance_s gi_typesculisthdr;
struct Dwarf_Gdbindex_array_instance_s gi_addressareahdr;
struct Dwarf_Gdbindex_array_instance_s gi_symboltablehdr;
struct Dwarf_Gdbindex_array_instance_s gi_cuvectorhdr;
};

557
src/lib/libdwarf/dwarf_generic_init.c vendored Normal file
View File

@ -0,0 +1,557 @@
/*
Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
Portions Copyright 2008-2010 Arxan Technologies, Inc. All rights reserved.
Portions Copyright 2011-2020 David Anderson. All rights reserved.
Portions Copyright 2012 SN Systems Ltd. All rights reserved.
This program is free software; you can redistribute it
and/or modify it under the terms of version 2.1 of the
GNU Lesser General Public License as published by the Free
Software Foundation.
This program is distributed in the hope that it would be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
Further, this software is distributed without any warranty
that it is free of the rightful claim of any third person
regarding infringement or the like. Any license provided
herein, whether implied or otherwise, applies only to this
software file. Patent licenses, if any, provided herein
do not apply to combinations of this program with other
software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write the
Free Software Foundation, Inc., 51 Franklin Street - Fifth
Floor, Boston MA 02110-1301, USA.
*/
/*
Here is the deepest routes through dwarf_init_path_dl(),
depending on arguments.
It is called by dwarfdump to open an fd and return Dwarf_Debug.
Much of this is to handle GNU debuglink.
dwarf_init_path_dl(path true_path and globals, dbg1
dwarf_object_detector_path_dSYM (dsym only(
if returns DW_DLV_OK itis dSYM
dwarf_object_detector_path_b( &debuglink with global paths.
dwarf_object_detector_path_b ftype
check for dSYM if found it is the object to run on.
dwarf_object_detector_fd (gets size ftype)
return
_dwarf_debuglink_finder_internal(TRUE passing
in globals paths listr)
new local dbg
dwarf_init_path(path no dysm or debuglink
no global paths)
dwarf_object_detector_path_b( path no dsym
or debuglink no global paths
dwarf_object_detector (path
dwarf_object_detector_fd (gets size ftype)
for each global pathin list, add to dbg
dwarf_gnu_debuglink(dbg
for each global path in debuglink list
_dwarf_debuglink_finder_internal(FALSE
no global paths)
if crc match return OK with
pathname and fd returned
else return NO_ENTRY
*/
#include <config.h>
#include <stddef.h> /* size_t */
#include <stdlib.h> /* free() */
#include <string.h> /* strdup() */
#include <stdio.h> /* debugging */
#ifdef _WIN32
#ifdef HAVE_STDAFX_H
#include "stdafx.h"
#endif /* HAVE_STDAFX_H */
#include <io.h> /* close() open() */
#elif defined HAVE_UNISTD_H
#include <unistd.h> /* close() */
#endif /* _WIN32 */
#ifdef HAVE_FCNTL_H
#include <fcntl.h> /* open() O_RDONLY */
#endif /* HAVE_FCNTL_H */
#include "dwarf.h"
#include "libdwarf.h"
#include "libdwarf_private.h"
#include "dwarf_base_types.h"
#include "dwarf_opaque.h"
#include "dwarf_alloc.h"
#include "dwarf_error.h"
#include "dwarf_object_detector.h"
#ifndef O_BINARY
#define O_BINARY 0
#endif /* O_BINARY */
#ifndef O_CLOEXEC
#define O_CLOEXEC 0
#endif /* O_CLOEXEC */
/* This is the initialization set intended to
handle multiple object formats.
Created September 2018
The init functions here cannot process archives.
Archives cannot be read by libdwarf.
*/
static int
open_a_file(const char * name)
{
/* Set to a file number that cannot be legal. */
int fd = -1;
fd = open(name, O_RDONLY | O_BINARY|O_CLOEXEC);
return fd;
}
static int
set_global_paths_init(Dwarf_Debug dbg, Dwarf_Error* error)
{
int res = 0;
res = dwarf_add_debuglink_global_path(dbg,
"/usr/lib/debug",error);
return res;
}
/* New in September 2023. */
int dwarf_init_path_a(const char *path,
char * true_path_out_buffer,
unsigned true_path_bufferlen,
unsigned groupnumber,
unsigned universalnumber,
Dwarf_Handler errhand,
Dwarf_Ptr errarg,
Dwarf_Debug * ret_dbg,
Dwarf_Error * error)
{
return dwarf_init_path_dl_a(path,
true_path_out_buffer,true_path_bufferlen,
groupnumber,universalnumber,
errhand,errarg,ret_dbg,
0,0,0,
error);
}
int dwarf_init_path(const char *path,
char * true_path_out_buffer,
unsigned true_path_bufferlen,
unsigned groupnumber,
Dwarf_Handler errhand,
Dwarf_Ptr errarg,
Dwarf_Debug * ret_dbg,
Dwarf_Error * error)
{
unsigned int universalnumber = 0;
return dwarf_init_path_dl_a(path,
true_path_out_buffer,true_path_bufferlen,
groupnumber,universalnumber,
errhand,errarg,ret_dbg,
0,0,0,
error);
}
static void
final_common_settings(Dwarf_Debug dbg,
const char *file_path,
int fd,
unsigned char lpath_source,
unsigned char *path_source,
Dwarf_Error *error)
{
int res = 0;
dbg->de_path = strdup(file_path);
dbg->de_fd = fd;
dbg->de_owns_fd = TRUE;
dbg->de_path_source = lpath_source;
if (path_source) {
*path_source = lpath_source;
}
dbg->de_owns_fd = TRUE;
res = set_global_paths_init(dbg,error);
if (res == DW_DLV_ERROR && error) {
dwarf_dealloc_error(dbg,*error);
*error = 0;
}
return;
}
/* New October 2020
Given true_path_out_buffer (and true_path_bufferlen)
non-zero this finds a dSYM (if such exists) with the
file name in true_path_out_buffer
If not a dSYM it follows debuglink rules to try to find a file
that matches requirements. If found returns DW_DLV_OK and
copies the name to true_path_out_buffer;
If none of the above found, it copies path into true_path
and returns DW_DLV_OK, we know the name is good;
The pathn_fd is owned by libdwarf and is in the created dbg->de_fd
field.
*/
int
dwarf_init_path_dl(const char *path,
char * true_path_out_buffer,
unsigned true_path_bufferlen,
unsigned groupnumber,
Dwarf_Handler errhand,
Dwarf_Ptr errarg,
Dwarf_Debug * ret_dbg,
char ** dl_path_array,
unsigned int dl_path_count,
unsigned char * path_source,
Dwarf_Error * error)
{
unsigned int universalnumber = 0;
int res = 0;
res = dwarf_init_path_dl_a(path,
true_path_out_buffer, true_path_bufferlen,
groupnumber,universalnumber,
errhand,errarg,ret_dbg, dl_path_array,
dl_path_count,path_source,error);
return res;
}
int
dwarf_init_path_dl_a(const char *path,
char * true_path_out_buffer,
unsigned true_path_bufferlen,
unsigned groupnumber,
unsigned universalnumber,
Dwarf_Handler errhand,
Dwarf_Ptr errarg,
Dwarf_Debug * ret_dbg,
char ** dl_path_array,
unsigned int dl_path_count,
unsigned char * path_source,
Dwarf_Error * error)
{
unsigned ftype = 0;
unsigned endian = 0;
unsigned offsetsize = 0;
Dwarf_Unsigned filesize = 0;
int res = DW_DLV_ERROR;
int errcode = 0;
int fd = -1;
Dwarf_Debug dbg = 0;
char *file_path = 0;
unsigned char lpath_source = DW_PATHSOURCE_basic;
if (!ret_dbg) {
DWARF_DBG_ERROR(NULL,DW_DLE_DWARF_INIT_DBG_NULL,
DW_DLV_ERROR);
}
/* Non-null *ret_dbg will cause problems dealing with
DW_DLV_ERROR */
*ret_dbg = 0;
if (!path) {
/* Oops. Null path */
_dwarf_error_string(NULL,
error,DW_DLE_STRING_PTR_NULL,
"DW_DLE_STRING_PTR_NULL: Passing a"
" null path argument to "
"dwarf_init_path or dwarf_init_path_dl"
" cannot work. Error.");
return DW_DLV_ERROR;
}
/* a special dsym call so we only check once. */
if (true_path_out_buffer) {
res = dwarf_object_detector_path_dSYM(path,
true_path_out_buffer,
true_path_bufferlen,
dl_path_array,dl_path_count,
&ftype,&endian,&offsetsize,&filesize,
&lpath_source,
&errcode);
if (res != DW_DLV_OK) {
if (res == DW_DLV_ERROR) {
/* ignore error. Look further. */
errcode = 0;
}
}
}
if (res != DW_DLV_OK) {
res = dwarf_object_detector_path_b(path,
true_path_out_buffer,
true_path_bufferlen,
dl_path_array,dl_path_count,
&ftype,&endian,&offsetsize,&filesize,
&lpath_source,
&errcode);
if (res != DW_DLV_OK ) {
if (res == DW_DLV_ERROR) {
errcode = 0;
}
}
}
if (res != DW_DLV_OK) {
/* So as a last resort in case
of data corruption in the object.
Lets try without
investigating debuglink or dSYM. */
res = dwarf_object_detector_path_b(path,
0,
0,
dl_path_array,dl_path_count,
&ftype,&endian,&offsetsize,&filesize,
&lpath_source,
&errcode);
}
if (res != DW_DLV_OK) {
/* impossible. The last above *had* to work */
if (res == DW_DLV_ERROR) {
_dwarf_error(NULL, error, errcode);
}
return res;
}
/* ASSERT: lpath_source != DW_PATHSOURCE_unspecified */
if (lpath_source != DW_PATHSOURCE_basic &&
true_path_out_buffer && *true_path_out_buffer) {
/* MacOS dSYM or GNU debuglink */
file_path = true_path_out_buffer;
fd = open_a_file(true_path_out_buffer);
} else {
/* ASSERT: lpath_source = DW_PATHSOURCE_basic */
file_path = (char *)path;
fd = open_a_file(path);
}
if (fd == -1) {
DWARF_DBG_ERROR(NULL, DW_DLE_FILE_UNAVAILABLE,
DW_DLV_ERROR);
}
switch(ftype) {
case DW_FTYPE_ELF: {
res = _dwarf_elf_nlsetup(fd,
file_path,
ftype,endian,offsetsize,filesize,
groupnumber,errhand,errarg,&dbg,error);
if (res != DW_DLV_OK) {
close(fd);
return res;
}
final_common_settings(dbg,file_path,fd,
lpath_source,path_source,error);
*ret_dbg = dbg;
return res;
}
case DW_FTYPE_APPLEUNIVERSAL:
case DW_FTYPE_MACH_O: {
res = _dwarf_macho_setup(fd,
file_path,
universalnumber,
ftype,endian,offsetsize,filesize,
groupnumber,errhand,errarg,&dbg,error);
if (res != DW_DLV_OK) {
close(fd);
return res;
}
final_common_settings(dbg,file_path,fd,
lpath_source,path_source,error);
*ret_dbg = dbg;
return res;
}
case DW_FTYPE_PE: {
res = _dwarf_pe_setup(fd,
file_path,
ftype,endian,offsetsize,filesize,
groupnumber,errhand,errarg,&dbg,error);
if (res != DW_DLV_OK) {
close(fd);
return res;
}
final_common_settings(dbg,file_path,fd,
lpath_source,path_source,error);
*ret_dbg = dbg;
return res;
}
default:
close(fd);
DWARF_DBG_ERROR(NULL, DW_DLE_FILE_WRONG_TYPE,
DW_DLV_ERROR);
/* Macro returns, cannot reach this line. */
}
/* Cannot reach this line */
}
/* New March 2017, this provides for reading
object files with multiple elf section groups.
If you are unsure about group_number, use
DW_GROUPNUMBER_ANY as groupnumber.
*/
int
dwarf_init_b(int fd,
unsigned group_number,
Dwarf_Handler errhand,
Dwarf_Ptr errarg,
Dwarf_Debug * ret_dbg,
Dwarf_Error * error)
{
unsigned ftype = 0;
unsigned endian = 0;
unsigned offsetsize = 0;
unsigned universalnumber = 0;
Dwarf_Unsigned filesize = 0;
int res = 0;
int errcode = 0;
if (!ret_dbg) {
DWARF_DBG_ERROR(NULL,DW_DLE_DWARF_INIT_DBG_NULL,DW_DLV_ERROR);
}
/* Non-null *ret_dbg will cause problems dealing with
DW_DLV_ERROR */
*ret_dbg = 0;
res = dwarf_object_detector_fd(fd, &ftype,
&endian,&offsetsize,&filesize,&errcode);
if (res == DW_DLV_NO_ENTRY) {
return res;
}
if (res == DW_DLV_ERROR) {
/* This macro does a return. */
DWARF_DBG_ERROR(NULL, DW_DLE_FILE_WRONG_TYPE, DW_DLV_ERROR);
}
switch(ftype) {
case DW_FTYPE_ELF: {
int res2 = 0;
res2 = _dwarf_elf_nlsetup(fd,"",
ftype,endian,offsetsize,filesize,
group_number,errhand,errarg,ret_dbg,error);
if (res2 != DW_DLV_OK) {
return res2;
}
set_global_paths_init(*ret_dbg,error);
return res2;
}
case DW_FTYPE_APPLEUNIVERSAL:
case DW_FTYPE_MACH_O: {
int resm = 0;
resm = _dwarf_macho_setup(fd,"",
universalnumber,
ftype,endian,offsetsize,filesize,
group_number,errhand,errarg,ret_dbg,error);
if (resm != DW_DLV_OK) {
return resm;
}
set_global_paths_init(*ret_dbg,error);
return resm;
}
case DW_FTYPE_PE: {
int resp = 0;
resp = _dwarf_pe_setup(fd,
"",
ftype,endian,offsetsize,filesize,
group_number,errhand,errarg,ret_dbg,error);
if (resp != DW_DLV_OK) {
return resp;
}
set_global_paths_init(*ret_dbg,error);
return resp;
}
default: break;
}
DWARF_DBG_ERROR(NULL, DW_DLE_FILE_WRONG_TYPE, DW_DLV_ERROR);
/* Macro above returns. cannot reach here. */
}
/*
Frees all memory that was not previously freed
by dwarf_dealloc.
Aside from certain categories.
Applicable when dwarf_init() or dwarf_elf_init()
or the -b() form was used to init 'dbg'.
*/
int
dwarf_finish(Dwarf_Debug dbg)
{
if (!dbg) {
_dwarf_free_static_errlist();
return DW_DLV_OK;
}
if (dbg->de_obj_file) {
/* The initial character of a valid
dbg->de_obj_file->object struct is a letter:
E, F, M, or P */
char otype = *(char *)(dbg->de_obj_file->ai_object);
switch(otype) {
case 'E':
break;
case 'F':
/* Non-libelf elf access */
_dwarf_destruct_elf_nlaccess(dbg->de_obj_file);
break;
case 'M':
_dwarf_destruct_macho_access(dbg->de_obj_file);
break;
case 'P':
_dwarf_destruct_pe_access(dbg->de_obj_file);
break;
default:
/* Do nothing. A serious internal error */
break;
}
}
if (dbg->de_owns_fd) {
close(dbg->de_fd);
dbg->de_owns_fd = FALSE;
}
free((void *)dbg->de_path);
dbg->de_path = 0;
/* dwarf_object_finish() also frees de_path,
but that is safe because we set it to zero
here so no duplicate free will occur.
It never returns DW_DLV_ERROR.
Not all code uses libdwarf exactly as we do
hence the free() there. */
return dwarf_object_finish(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.
Allows setting to NULL (NULL is the default
of de_tied_data.td_tied_object).
New September 2015.
*/
int
dwarf_set_tied_dbg(Dwarf_Debug dbg,
Dwarf_Debug tieddbg,
Dwarf_Error*error)
{
if (!dbg) {
DWARF_DBG_ERROR(NULL, DW_DLE_DBG_NULL, DW_DLV_ERROR);
}
dbg->de_tied_data.td_tied_object = tieddbg;
if (tieddbg) {
tieddbg->de_tied_data.td_is_tied_object = TRUE;
}
return DW_DLV_OK;
}
/* New September 2015. */
int
dwarf_get_tied_dbg(Dwarf_Debug dbg, Dwarf_Debug *tieddbg_out,
Dwarf_Error*error)
{
(void)error;
*tieddbg_out = dbg->de_tied_data.td_tied_object;
return DW_DLV_OK;
}

1674
src/lib/libdwarf/dwarf_global.c vendored Normal file

File diff suppressed because it is too large Load Diff

135
src/lib/libdwarf/dwarf_global.h vendored Normal file
View File

@ -0,0 +1,135 @@
/*
Copyright (C) 2000,2004,2005 Silicon Graphics, Inc. All Rights Reserved.
Portions Copyright (C) 2011-2023 David Anderson. All Rights Reserved.
This program is free software; you can redistribute it
and/or modify it under the terms of version 2.1 of the
GNU Lesser General Public License as published by the Free
Software Foundation.
This program is distributed in the hope that it would be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
Further, this software is distributed without any warranty
that it is free of the rightful claim of any third person
regarding infringement or the like. Any license provided
herein, whether implied or otherwise, applies only to this
software file. Patent licenses, if any, provided herein
do not apply to combinations of this program with other
software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write the
Free Software Foundation, Inc., 51 Franklin Street - Fifth
Floor, Boston MA 02110-1301, USA.
*/
typedef struct Dwarf_Global_Context_s *Dwarf_Global_Context;
/*
This struct contains header information for a set of pubnames.
Essentially, they contain the context for a set of pubnames
belonging to a compilation-unit.
Also used for the sgi-specific
weaknames, typenames, varnames, funcnames data:
the structs for those are incomplete and
instances of this are used instead.
Also used for DWARF3,4 .debug_pubtypes and DWARF5 .debug_names.
These never refer to .debug_types, only to .debug_info.
*/
struct Dwarf_Global_Context_s {
unsigned pu_is_dnames; /* 0 if not .debug_names. */
unsigned pu_alloc_type; /* DW_DLA something */
Dwarf_Debug pu_dbg;
/* One of DW_GL_GLOBAL,DW_GL_PUBTYPES,etc */
int pu_global_category;
/* The following set with the DW_TAG of the DIE
involved. Left 0 with .debug_pubnames. */
Dwarf_Bool pu_is_debug_names;
/* For DWARF5 .debug_names the following
are irellevant, left 0. */
/* For this context, size of a length (offset). 4 or 8 */
unsigned char pu_length_size;
/* Size of the data section for the CU */
unsigned char pu_length;
/* For this CU, size of the extension. 0 except
for dwarf2 extension (IRIX) 64bit, in which case is 4. */
unsigned char pu_extension_size;
Dwarf_Half pu_version; /* 2,3,4 or 5 */
/* offset in pubnames or debug_names of the pu header. */
Dwarf_Off pu_pub_offset;
/* One past end of the section entries for this CU. */
Dwarf_Byte_Ptr pu_pub_entries_end_ptr;
/* Offset into .debug_info of the compilation-unit header
(not DIE) for this set of pubnames. */
Dwarf_Off pu_offset_of_cu_header;
/* Size of compilation-unit that these pubnames are in. */
Dwarf_Unsigned pu_info_length;
};
/* This struct contains information for a single pubname. */
struct Dwarf_Global_s {
/* Offset from the start of the corresponding compilation-unit of
the DIE for the given pubname CU. */
Dwarf_Off gl_named_die_offset_within_cu;
/* Points to the given pubname. */
Dwarf_Small *gl_name;
/* Context for this pubname. */
Dwarf_Global_Context gl_context;
Dwarf_Half gl_alloc_type; /* DW_DLA something */
Dwarf_Half gl_tag; /* .debug_names only. Else 0. */
};
/* In all but pubnames, head_chain and globals
should be passed in as NULL.
So that .debug_names entries can be added to the chain
before making an array.
*/
int _dwarf_internal_get_pubnames_like_data(Dwarf_Debug dbg,
const char *secname,
Dwarf_Small *section_data_ptr,
Dwarf_Unsigned section_length,
Dwarf_Global ** globals,
Dwarf_Chain * head_chain,
Dwarf_Chain ** plast_chain,
Dwarf_Signed * return_count,
Dwarf_Error * error,
int context_code,
int global_code,
int length_err_num,
int version_err_num);
void _dwarf_internal_globals_dealloc( Dwarf_Debug dbg,
Dwarf_Global *dwgl, Dwarf_Signed count);
#ifdef __sgi /* __sgi should only be defined for IRIX/MIPS. */
void _dwarf_fix_up_offset_irix(Dwarf_Debug dbg,
Dwarf_Unsigned *varp,
char *caller_site_name);
#define FIX_UP_OFFSET_IRIX_BUG(ldbg,var,name) \
_dwarf_fix_up_offset_irix((ldbg),&(var),(name))
#else /* ! __sgi */
#define FIX_UP_OFFSET_IRIX_BUG(ldbg,var,name)
#endif /* __sgi */

791
src/lib/libdwarf/dwarf_gnu_index.c vendored Normal file
View File

@ -0,0 +1,791 @@
/*
Copyright (C) 2020 David Anderson. All Rights Reserved.
Redistribution and use in source and binary forms, with
or without modification, are permitted provided that the
following conditions are met:
Redistributions of source code must retain the above
copyright notice, this list of conditions and the following
disclaimer.
Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* This is for accessing .debug_gnu_pubnames
and .debug_gnu_pubtypes.
These sections are designed to be compiler-generated
to be used by the linker to create the .gdb_index
section for DWARF3 and DWARF4 as part of
Split Dwarf (aka Debug Fission).
They are not expected to be in an executable. */
#include <config.h>
#include <stdlib.h> /* calloc() free() */
#include <stdio.h> /* debugging */
#if defined(_WIN32) && defined(HAVE_STDAFX_H)
#include "stdafx.h"
#endif /* HAVE_STDAFX_H */
#include "dwarf.h"
#include "libdwarf.h"
#include "libdwarf_private.h"
#include "dwarf_base_types.h"
#include "dwarf_opaque.h"
#include "dwarf_alloc.h"
#include "dwarf_error.h"
#include "dwarf_util.h"
#include "dwarf_gnu_index.h"
#include "dwarf_string.h"
#if 0
static void
dump_head(const char *msg,int lno,
struct Dwarf_Gnu_Index_Head_s *h)
{
printf("HEAD block line %d\n",__LINE__);
printf("data : %p\n",
(void *)h->gi_section_data);
printf("sec len : %llu 0x%llx\n",
h->gi_section_length,
h->gi_section_length);
printf("data end : %p\n",
(void *)(h->gi_section_end));
printf("blockarray : %p\n",
(void *)h->gi_blockarray);
printf("block count : %llu 0x%llx\n",
h->gi_blockcount,
h->gi_blockcount);
printf("gnu_pubnames: %u\n",h->gi_is_pubnames);
}
static void
dump_block(const char *msg,int bn, int lno,
struct Dwarf_Gnu_IBlock_s *b)
{
printf("BLOCK dump block %d %s line %d\n",
bn,msg,lno);
printf("head : 0x%lx\n",
(unsigned long)b->ib_head);
printf("index : %lu\n",
(unsigned long)b->ib_index);
printf("blk len offset : %lu 0x%lx\n",
(unsigned long)b->ib_block_length_offset,
(unsigned long)b->ib_block_length_offset);
printf("block length : %lu 0x%lx\n",
(unsigned long)b->ib_block_length,
(unsigned long)b->ib_block_length);
printf("offset size : %u\n",
b->ib_offset_size);
printf("extension size : %u\n",
b->ib_extension_size);
printf("version : %u\n",
b->ib_version);
printf("built entries? : %s\n",
b->ib_counted_entries?"yes":"no");
printf("debug_info offset: %lu 0x%lx\n",
(unsigned long)b->ib_offset_in_debug_info,
(unsigned long)b->ib_offset_in_debug_info);
printf("debug_info size : %lu 0x%lx\n",
(unsigned long)b->ib_size_in_debug_info,
(unsigned long)b->ib_size_in_debug_info);
printf("data offset : %lu 0x%lx\n",
(unsigned long)b->ib_b_data_offset,
(unsigned long)b->ib_b_data_offset);
printf("entries offset : %lu 0x%lx\n",
(unsigned long)b->ib_b_offset,
(unsigned long)b->ib_b_offset);
printf("entries ptr : 0x%lx\n",
(unsigned long)b->ib_b_data);
printf("entries length : %lu 0x%lx\n",
(unsigned long)b->ib_b_entrylength,
(unsigned long)b->ib_b_entrylength);
printf("entry count : %lu 0x%lx\n",
(unsigned long)b->ib_entry_count,
(unsigned long)b->ib_entry_count);
printf("entries array : 0x%lx\n",
(unsigned long)b->ib_entryarray);
fflush(stdout);
}
#endif /*0*/
/* We could use dwarf_get_real_section_name()
to determine the real name (perhaps ending in .dwo)
but for now we just use the standard name here. */
static void
get_pubxx_fields(Dwarf_Debug dbg,
Dwarf_Bool for_gnu_pubnames,
struct Dwarf_Section_s **sec_out,
const char **sec_name_out,
int *errnum_out,
const char **errstr_out)
{
if (!dbg) {
return;
}
if (for_gnu_pubnames) {
if (sec_name_out) {
*sec_name_out = ".debug_gnu_pubnames";
}
if (sec_out) {
*sec_out = &dbg->de_debug_gnu_pubnames;
}
if (errnum_out) {
*errnum_out = DW_DLE_GNU_PUBNAMES_ERROR;
}
if (errstr_out) {
*errstr_out = "DW_DLE_GNU_PUBNAMES_ERROR";
}
} else {
if (sec_name_out) {
*sec_name_out = ".debug_gnu_pubtypes";
}
if (sec_out) {
*sec_out = &dbg->de_debug_gnu_pubtypes;
}
if (errnum_out) {
*errnum_out = DW_DLE_GNU_PUBTYPES_ERROR;
}
if (errstr_out) {
*errstr_out = "DW_DLE_GNU_PUBTYPES_ERROR";
}
}
}
static void
build_errm_no_v(Dwarf_Debug dbg,
Dwarf_Bool is_for_pubnames,
const char * str1,
Dwarf_Error *error)
{
const char *errstr = 0;
int errnum = 0;
const char *secname = 0;
dwarfstring m;
get_pubxx_fields(dbg,is_for_pubnames,
0,&secname,&errnum, &errstr);
dwarfstring_constructor(&m);
dwarfstring_append(&m,(char *)errstr);
dwarfstring_append(&m," ");
dwarfstring_append(&m,(char *)str1);
dwarfstring_append_printf_s(&m," for section %s",
(char*)secname);
_dwarf_error_string(dbg,error,errnum,
dwarfstring_string(&m));
dwarfstring_destructor(&m);
return;
}
static void
build_errm_one_num(Dwarf_Debug dbg,
Dwarf_Bool is_for_pubnames,
const char * str1,
Dwarf_Unsigned val1,
Dwarf_Error *error)
{
const char *errstr = 0;
int errnum = 0;
const char *secname = 0;
dwarfstring m;
/* Something is very wrong */
get_pubxx_fields(dbg,is_for_pubnames,
0,&secname,&errnum, &errstr);
dwarfstring_constructor(&m);
dwarfstring_append(&m,(char *)errstr);
dwarfstring_append(&m," ");
dwarfstring_append_printf_u(&m,(char *)str1,val1);
dwarfstring_append_printf_s(&m," for section %s",
(char*)secname);
_dwarf_error_string(dbg,error,errnum,
dwarfstring_string(&m));
dwarfstring_destructor(&m);
return;
}
static int
load_pub_section(Dwarf_Debug dbg,
Dwarf_Bool for_gnu_pubnames,
Dwarf_Error *error)
{
struct Dwarf_Section_s * sec = 0;
int res;
get_pubxx_fields(dbg,for_gnu_pubnames,&sec,0,0,0);
if (sec) {
res = _dwarf_load_section(dbg,sec,error);
return res;
}
return DW_DLV_NO_ENTRY;
}
static int
scan_block_entries(Dwarf_Debug dbg,
Dwarf_Bool for_gnu_pubnames,
Dwarf_Unsigned *count_out,
Dwarf_Error *error)
{
struct Dwarf_Section_s *sec = 0;
Dwarf_Small *startptr = 0;
Dwarf_Small *curptr = 0;
Dwarf_Small *endptr = 0;
Dwarf_Unsigned seclen = 0;
Dwarf_Unsigned count = 0;
Dwarf_Unsigned filesize = 0;
int errnum = 0;
Dwarf_Unsigned totalframessize = 0;
const char * errstr = 0;
const char * secname = 0;
get_pubxx_fields(dbg,for_gnu_pubnames,&sec,&secname,
&errnum,&errstr);
filesize = dbg->de_filesize;
startptr = sec->dss_data;
curptr = startptr;
seclen = sec->dss_size;
endptr = startptr + seclen;
if (filesize) {
if (seclen >= filesize) {
build_errm_one_num(dbg,for_gnu_pubnames,
": section length %u"
" is larger than the file size in",
seclen,error);
return DW_DLV_ERROR;
}
}
for (;;) {
Dwarf_Unsigned length = 0;
unsigned int offsetsize = 0;
unsigned int extensize = 0;
if (curptr == endptr) {
*count_out = count;
return DW_DLV_OK;
}
/* Not sure how the coders think about
the initial value. But the last
4 bytes are zero, ignore those.
Unclear 64bit is not allowed. */
READ_AREA_LENGTH_CK(dbg,length,Dwarf_Unsigned,
curptr,offsetsize,extensize,error,seclen,endptr);
totalframessize += length +offsetsize+extensize;
if (length > seclen || totalframessize > seclen) {
build_errm_one_num(dbg,for_gnu_pubnames,
"Sum of frame fde/cies sizes 0x%" DW_PR_DUx
" exceeds section size",totalframessize,error);
return DW_DLV_ERROR;
}
++count;
curptr += length -offsetsize - extensize;
curptr += 4;
}
/* NOTREACHED */
*count_out = count;
return DW_DLV_OK;
}
static int
_dwarf_count_entries_in_block(struct Dwarf_Gnu_IBlock_s * gib,
struct DGI_Entry_s* entries,
Dwarf_Bool for_gnu_pubnames,
Dwarf_Error* error)
{
Dwarf_Small *curptr = gib->ib_b_data;
Dwarf_Small *endptr = curptr + gib->ib_b_entrylength;
Dwarf_Unsigned entrycount = 0;
Dwarf_Half offsetsize = gib->ib_offset_size;
struct DGI_Entry_s *curentry = 0;
Dwarf_Debug dbg = 0;
Dwarf_Gnu_Index_Head head = 0;
Dwarf_Bool for_pubnames = 0;
char *strptr = 0;
head = gib->ib_head;
for_pubnames = head->gi_is_pubnames;
dbg = head->gi_dbg;
for ( ; curptr < endptr; ++entrycount) {
Dwarf_Unsigned infooffset = 0;
Dwarf_Unsigned offset = 0;
char flagbyte = 0;
if ((curptr+offsetsize) == endptr) {
break;
}
if ((curptr+offsetsize) > endptr) {
build_errm_one_num(dbg,for_gnu_pubnames,
" Reading an address runs off the end of "
"this entry at entry %" DW_PR_DUu,
entrycount,error);
return DW_DLV_ERROR;
}
READ_UNALIGNED_CK(dbg,offset,
Dwarf_Unsigned,curptr,
offsetsize,error,endptr);
infooffset = offset;
curptr += offsetsize;
if (entries) {
curentry = entries +entrycount;
curentry->ge_debug_info_offset = infooffset;
}
/* Ensure flag and start-of-string possible. */
if ((curptr+2) >= endptr) {
build_errm_one_num(dbg,for_gnu_pubnames,
"Past end of current block reading strings"
" Reading an address runs off the end of "
"this entry at entry %" DW_PR_DUu,
entrycount,error);
return DW_DLV_ERROR;
}
flagbyte = *curptr;
curptr += 1;
strptr = (char *)curptr;
if (curentry) {
curentry->ge_flag_byte = flagbyte;
curentry->ge_string = (char *)strptr;
}
for ( ; curptr && curptr < endptr ;++curptr,++offset ) {
if (! *curptr ) {
/* end of string */
break;
}
if (curptr > endptr) {
build_errm_no_v(dbg,for_gnu_pubnames,
"Past end of current block reading strings",
error);
return DW_DLV_ERROR;
}
}
/* string-terminating null byte */
curptr += 1;
}
if (!entries) {
gib->ib_entry_count = entrycount;
} else if (gib->ib_entry_count != entrycount) {
int err = 0;
const char *errstr = 0;
const char *secname = 0;
char buf[120];
dwarfstring m;
buf[0] = 0;
get_pubxx_fields(dbg,for_pubnames,0,&secname,
&err,&errstr);
dwarfstring_constructor_static(&m,buf,sizeof(buf));
dwarfstring_append(&m,(char *)errstr);
dwarfstring_append_printf_s(&m,":mismatch counts "
"creating %s"
"block_entries.",
(char *)secname);
dwarfstring_append_printf_u(&m," Origcount %u",
gib->ib_entry_count);
dwarfstring_append_printf_u(&m," new count %u",
entrycount);
_dwarf_error_string(dbg,error,err,
dwarfstring_string(&m));
dwarfstring_destructor(&m);
return DW_DLV_ERROR;
}
return DW_DLV_OK;
}
static int
fill_in_blocks(Dwarf_Gnu_Index_Head head,
Dwarf_Error *error)
{
Dwarf_Unsigned i = 0;
Dwarf_Unsigned dataoffset = 0;
Dwarf_Small * endptr = 0;
Dwarf_Small * curptr = 0;
Dwarf_Small * baseptr = 0;
Dwarf_Bool is_for_pubnames = head->gi_is_pubnames;
Dwarf_Debug dbg = head->gi_dbg;
Dwarf_Unsigned seclen = head->gi_section_length;
baseptr = head->gi_section_data;
endptr = baseptr + head->gi_section_length;
for ( ;i < head->gi_blockcount; ++i) {
Dwarf_Unsigned length = 0;
unsigned int offsetsize = 0;
unsigned int extensize = 0;
Dwarf_Half version = 0;
Dwarf_Unsigned offset_into_debug_info = 0;
Dwarf_Unsigned length_of_CU_in_debug_info = 0;
struct Dwarf_Gnu_IBlock_s *gib = 0;
int res = 0;
gib = head->gi_blockarray+i;
/* gib is a blank slate ready to be filled */
curptr = baseptr+ dataoffset;
READ_AREA_LENGTH_CK(dbg,length,Dwarf_Unsigned,
curptr,offsetsize,extensize,error,seclen,endptr);
if (!length) {
/* Must be end of the section */
if (curptr != endptr) {
build_errm_no_v(dbg,is_for_pubnames,
": encountered zero area length "
"before the section end.",
error);
return DW_DLV_ERROR;
}
return DW_DLV_OK;
}
if (length > head->gi_section_length ||
(length+offsetsize+extensize) >
head->gi_section_length) {
build_errm_one_num(dbg,is_for_pubnames,
": block"
" length %" DW_PR_DUu " is too big",
length,error);
return DW_DLV_ERROR;
}
/* offsetsize will be set to a constant
of either 4 or 8 by READ_AREA_LENGTH_CK.
So any check for a usable offsetsize
here is dead code.
see dwarf_util.h */
gib->ib_index = i;
gib->ib_head = head;
gib->ib_offset_size = offsetsize;
gib->ib_block_length = length;
gib->ib_block_length_offset = dataoffset;
dataoffset += offsetsize + extensize;
/* Now past length field. */
gib->ib_b_data_offset = dataoffset;
if ((dataoffset + length) > head->gi_section_length){
build_errm_one_num(dbg,is_for_pubnames,
" header length is %u which runs past the "
"end of section suggesting corrupt data",
length,error);
return DW_DLV_ERROR;
}
READ_UNALIGNED_CK(dbg,version,Dwarf_Half,curptr,
DWARF_HALF_SIZE,error,endptr);
if (version != 2) {
build_errm_one_num(dbg,is_for_pubnames,
" version is %u, not 2,"
" which suggests corrupt data",version,error);
return DW_DLV_ERROR;
}
curptr += DWARF_HALF_SIZE;
dataoffset += DWARF_HALF_SIZE;
gib->ib_version = version;
READ_UNALIGNED_CK(dbg,offset_into_debug_info,
Dwarf_Unsigned,curptr,
offsetsize,error,endptr);
curptr += offsetsize;
dataoffset += offsetsize;
gib->ib_offset_in_debug_info = offset_into_debug_info;
READ_UNALIGNED_CK(dbg,length_of_CU_in_debug_info,
Dwarf_Unsigned,curptr,
offsetsize,error,endptr);
gib->ib_size_in_debug_info = length_of_CU_in_debug_info;
dataoffset += offsetsize;
curptr += offsetsize;
gib->ib_b_data = curptr;
gib->ib_b_offset = dataoffset;
gib->ib_b_entrylength = length - (2 +
(2*offsetsize)) -4;
if ((gib->ib_b_data +gib->ib_b_entrylength)
> endptr) {
build_errm_one_num(dbg,is_for_pubnames,
" length is %u which runs past the "
"end of section suggesting corrupt data",
length,error);
return DW_DLV_ERROR;
}
res = _dwarf_count_entries_in_block(gib,0,is_for_pubnames,
error);
if (res != DW_DLV_OK) {
return res;
}
/* Set for next block., add in 4 for ending zeros */
dataoffset = gib->ib_block_length_offset + length + 4;
}
return DW_DLV_OK;
}
static int
fill_in_entries(Dwarf_Gnu_Index_Head head,
struct Dwarf_Gnu_IBlock_s *gib,
Dwarf_Error *error)
{
Dwarf_Unsigned count = gib->ib_entry_count;
struct DGI_Entry_s * entryarray = 0;
Dwarf_Bool for_gnu_pubnames = head->gi_is_pubnames;
int res = 0;
Dwarf_Debug dbg = 0;
dbg = head->gi_dbg;
entryarray = (struct DGI_Entry_s*)calloc(count,
sizeof(struct DGI_Entry_s));
if (!entryarray) {
build_errm_no_v(dbg,for_gnu_pubnames,
": Unable to allocate "
"block_entries. Out of memory creating record.",
error);
return DW_DLV_ERROR;
}
res = _dwarf_count_entries_in_block(gib,
entryarray,for_gnu_pubnames,error);
if (res != DW_DLV_OK) {
free(entryarray);
return res;
}
gib->ib_entryarray = entryarray;
entryarray = 0;
return DW_DLV_OK;
}
int
dwarf_get_gnu_index_head(Dwarf_Debug dbg,
/* The following arg false to select gnu_pubtypes */
Dwarf_Bool for_gnu_pubnames ,
Dwarf_Gnu_Index_Head * index_head_out,
Dwarf_Unsigned * index_block_count_out,
Dwarf_Error * error)
{
Dwarf_Unsigned count = 0;
Dwarf_Gnu_Index_Head head = 0;
struct Dwarf_Gnu_IBlock_s *iblock_array = 0;
int res = 0;
if (!dbg) {
_dwarf_error_string(dbg,error,DW_DLE_DBG_NULL,
"DW_DLE_DBG_NULL: in "
"dwarf_get_gnu_index_head");
return DW_DLV_ERROR;
}
res = load_pub_section(dbg,for_gnu_pubnames,error);
if (res != DW_DLV_OK) {
return res;
}
/* We want this loaded for error checking by callers
in case they had no reason to load already. */
res = _dwarf_load_debug_info(dbg,error);
if (res == DW_DLV_ERROR) {
return res;
}
/* if count zero, returns DW_DLV_NO_ENTRY */
res = scan_block_entries(dbg,for_gnu_pubnames,&count,error);
if (res != DW_DLV_OK) {
return res;
}
head = (Dwarf_Gnu_Index_Head)
_dwarf_get_alloc(dbg,DW_DLA_GNU_INDEX_HEAD,1);
if (!head) {
build_errm_no_v(dbg,for_gnu_pubnames,
" Unable to allocate "
"a header record. Out of memory creating record.",
error);
return DW_DLV_ERROR;
}
head->gi_dbg = dbg;
head->gi_section_data = for_gnu_pubnames?
dbg->de_debug_gnu_pubnames.dss_data:
dbg->de_debug_gnu_pubtypes.dss_data;
head->gi_section_length = for_gnu_pubnames?
dbg->de_debug_gnu_pubnames.dss_size:
dbg->de_debug_gnu_pubtypes.dss_size;
head->gi_section_end = head->gi_section_data +
head->gi_section_length;
head->gi_is_pubnames = for_gnu_pubnames;
iblock_array = calloc(count,
sizeof(struct Dwarf_Gnu_IBlock_s));
if (!iblock_array) {
build_errm_one_num(dbg,for_gnu_pubnames,
"Unable to allocate "
" %u block records. Out of memory.",
count,error);
dwarf_gnu_index_dealloc(head);
head = 0;
return DW_DLV_ERROR;
}
head->gi_blockarray = iblock_array;
head->gi_blockcount = count;
res = fill_in_blocks(head,error);
if (res != DW_DLV_OK) {
dwarf_gnu_index_dealloc(head);
head = 0;
return res;
}
*index_head_out = head;
*index_block_count_out = count;
return DW_DLV_OK;
}
/* Frees all resources used for the indexes. */
void
_dwarf_free_gnu_index_head_content(Dwarf_Gnu_Index_Head head)
{
if (!head) {
return;
}
if (head->gi_blockarray) {
Dwarf_Unsigned i = 0;
struct Dwarf_Gnu_IBlock_s *block =
head->gi_blockarray;
for ( ; i < head->gi_blockcount; ++i,block++) {
if (block->ib_entryarray) {
free(block->ib_entryarray);
block->ib_entryarray = 0;
}
block->ib_entry_count = 0;
}
free(head->gi_blockarray);
head->gi_blockarray = 0;
head->gi_blockcount = 0;
}
}
void
dwarf_gnu_index_dealloc(Dwarf_Gnu_Index_Head head)
{
Dwarf_Debug dbg;
if (!head) {
return;
}
dbg = head->gi_dbg;
if (!dbg) {
return;
}
_dwarf_free_gnu_index_head_content(head);
dwarf_dealloc(dbg,head,DW_DLA_GNU_INDEX_HEAD);
}
void
_dwarf_gnu_index_head_destructor(void *incoming)
{
Dwarf_Gnu_Index_Head head = 0;
head = (Dwarf_Gnu_Index_Head)incoming;
if (!head) {
return;
}
_dwarf_free_gnu_index_head_content(head);
return;
}
int
dwarf_get_gnu_index_block(Dwarf_Gnu_Index_Head head,
Dwarf_Unsigned number,
Dwarf_Unsigned * block_length,
Dwarf_Half * version,
Dwarf_Unsigned * offset_into_debug_info,
Dwarf_Unsigned * size_of_debug_info_area,
Dwarf_Unsigned * count_of_entries,
Dwarf_Error * error)
{
struct Dwarf_Gnu_IBlock_s *gib = 0;
if (!head) {
_dwarf_error_string(0,error,DW_DLE_DBG_NULL,
"DW_DLE_DBG_NULL: in "
"dwarf_get_gnu_index_block");
return DW_DLV_ERROR;
}
if (number >= head->gi_blockcount) {
return DW_DLV_NO_ENTRY;
}
gib = head->gi_blockarray + number;
if (block_length) {
*block_length = gib->ib_block_length;
}
if (version) {
*version = gib->ib_version;
}
if (offset_into_debug_info) {
*offset_into_debug_info = gib->ib_offset_in_debug_info;
}
if (size_of_debug_info_area) {
*size_of_debug_info_area = gib->ib_size_in_debug_info;
}
if (count_of_entries) {
*count_of_entries = gib->ib_entry_count;
}
return DW_DLV_OK;
}
int
dwarf_get_gnu_index_block_entry(Dwarf_Gnu_Index_Head head,
Dwarf_Unsigned blocknumber,
Dwarf_Unsigned entrynumber,
Dwarf_Unsigned * offset_in_debug_info,
const char ** name_string,
unsigned char * flagbyte,
unsigned char * staticorglobal,
unsigned char * typeofentry,
Dwarf_Error * error)
{
struct Dwarf_Gnu_IBlock_s *gib = 0;
struct DGI_Entry_s *be = 0;
if (!head) {
_dwarf_error_string(0,error,DW_DLE_DBG_NULL,
"DW_DLE_DBG_NULL: in "
"dwarf_get_gnu_index_block_entry");
return DW_DLV_ERROR;
}
if (blocknumber >= head->gi_blockcount) {
return DW_DLV_NO_ENTRY;
}
gib = head->gi_blockarray + blocknumber;
if (!gib->ib_counted_entries) {
int res = 0;
gib->ib_counted_entries = TRUE;
res = fill_in_entries(head,gib,error);
if (res != DW_DLV_OK) {
return res;
}
}
if (entrynumber >= gib->ib_entry_count) {
return DW_DLV_NO_ENTRY;
}
be = gib->ib_entryarray + entrynumber;
if (offset_in_debug_info) {
*offset_in_debug_info = be->ge_debug_info_offset;
}
if (name_string) {
*name_string = be->ge_string;
}
if (flagbyte) {
*flagbyte = be->ge_flag_byte;
}
if (staticorglobal) {
if (be->ge_flag_byte &0x80) {
/* value 1, of course... */
*staticorglobal = DW_GNUIVIS_global;
} else {
*staticorglobal = DW_GNUIVIS_static;
}
}
if (typeofentry) {
/* DW_GNUIKIND_ */
unsigned v = be->ge_flag_byte & 0x70;
v = v>>4;
*typeofentry = v;
}
return DW_DLV_OK;
}

95
src/lib/libdwarf/dwarf_gnu_index.h vendored Normal file
View File

@ -0,0 +1,95 @@
/*
Copyright (C) 2020-2023 David Anderson. All Rights Reserved.
Redistribution and use in source and binary forms, with
or without modification, are permitted provided that the
following conditions are met:
Redistributions of source code must retain the above
copyright notice, this list of conditions and the following
disclaimer.
Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* This is for accessing .debug_gnu_pubnames
and .debug_gnu_pubtypes.
It has nothing to do with .gdb_index. */
struct DGI_Entry_s {
char * ge_string;
Dwarf_Unsigned ge_debug_info_offset;
char ge_flag_byte;
#if 0
/* Following is DW_GNUIVIS bit 7 of flag byte
shifted right 7. */
char ge_flag_global_static;
/* Following is DW_GNUIKIND bits 4,5,6 of flag byte
shifted right 4.
Bits 0-3 are reserved and should de zero. */
char ge_flag_type;
#endif
};
/*
each block data on disk looks like:
LENGTH (which determines offset size)
version
offset into .debug_info (offsetsize)
size of area in .debug_info (offsetsize)
For each entry
offset in debug_info of DIE (offsetsize)
1 byte flag
strlen+1 string
Trailing LENGTH 4 bytes zero.
*/
struct Dwarf_Gnu_IBlock_s {
Dwarf_Gnu_Index_Head ib_head;
Dwarf_Unsigned ib_index; /*of this ib */
Dwarf_Unsigned ib_block_length_offset;
Dwarf_Unsigned ib_block_length;
Dwarf_Half ib_offset_size; /* 4 or 8 */
Dwarf_Half ib_extension_size; /* 0 or 4 */
Dwarf_Half ib_version;
Dwarf_Bool ib_counted_entries; /* see ib_entry_count*/
Dwarf_Unsigned ib_offset_in_debug_info;
Dwarf_Unsigned ib_size_in_debug_info;
/* following the length field*/
Dwarf_Unsigned ib_b_data_offset;
Dwarf_Unsigned ib_b_offset; /* offset of entry area */
Dwarf_Small * ib_b_data; /* the entry area */
/* entrylength = LENGTH - 2 - 2*offsetsize */
Dwarf_Unsigned ib_b_entrylength;
Dwarf_Unsigned ib_entry_count;
struct DGI_Entry_s *ib_entryarray;
};
struct Dwarf_Gnu_Index_Head_s {
Dwarf_Debug gi_dbg;
Dwarf_Small * gi_section_data;
Dwarf_Unsigned gi_section_length;
Dwarf_Small * gi_section_end;
struct Dwarf_Gnu_IBlock_s *gi_blockarray;
Dwarf_Unsigned gi_blockcount;
Dwarf_Bool gi_is_pubnames; /* if false is pubtypes */
};
void _dwarf_gnu_index_head_destructor(void *incoming);
void _dwarf_free_gnu_index_head_content(Dwarf_Gnu_Index_Head);

396
src/lib/libdwarf/dwarf_groups.c vendored Normal file
View File

@ -0,0 +1,396 @@
/*
Copyright (C) 2017-2018 David Anderson. All Rights Reserved.
This program is free software; you can redistribute it
and/or modify it under the terms of version 2.1 of the
GNU Lesser General Public License as published by the Free
Software Foundation.
This program is distributed in the hope that it would be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
Further, this software is distributed without any warranty
that it is free of the rightful claim of any third person
regarding infringement or the like. Any license provided
herein, whether implied or otherwise, applies only to this
software file. Patent licenses, if any, provided herein
do not apply to combinations of this program with other
software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write the
Free Software Foundation, Inc., 51 Franklin Street - Fifth
Floor, Boston MA 02110-1301, USA.
*/
#include <config.h>
#include <stdlib.h> /* calloc() free() */
#include <string.h> /* strcmp() */
#if defined(_WIN32) && defined(HAVE_STDAFX_H)
#include "stdafx.h"
#endif /* HAVE_STDAFX_H */
#ifdef HAVE_STDINT_H
#include <stdint.h> /* uintptr_t */
#endif /* HAVE_STDINT_H */
#include "dwarf.h"
#include "libdwarf.h"
#include "libdwarf_private.h"
#include "dwarf_base_types.h"
#include "dwarf_opaque.h"
#include "dwarf_error.h"
#include "dwarf_tsearch.h"
#define HASHSEARCH
/* It has not escaped our attention that the section-group
tsearch hash table could
be replaced by a simple array with space for each possible
section number, each element being the group number.
This would be much simpler than what follows here. */
/* Each section number can appear in at most one record in the hash
because each section belongs in only one group.
Each group number appears as often as appropriate. */
struct Dwarf_Group_Map_Entry_s {
unsigned gm_key; /* section number */
unsigned gm_group_number; /* What group number is. */
/* The name is from static storage or from elf,
so there is nothing to free on record delete. */
const char * gm_section_name;
};
static void *
grp_make_entry(unsigned section, unsigned group,const char *name)
{
struct Dwarf_Group_Map_Entry_s *e = 0;
e = calloc(1,sizeof(struct Dwarf_Group_Map_Entry_s));
if (e) {
e->gm_key = section;
e->gm_group_number = group;
e->gm_section_name = name;
}
return e;
}
static DW_TSHASHTYPE
grp_data_hashfunc(const void *keyp)
{
const struct Dwarf_Group_Map_Entry_s * enp = keyp;
DW_TSHASHTYPE hashv = 0;
hashv = enp->gm_key;
return hashv;
}
static int
grp_compare_function(const void *l, const void *r)
{
const struct Dwarf_Group_Map_Entry_s * lp = l;
const struct Dwarf_Group_Map_Entry_s * rp = r;
if (lp->gm_key < rp->gm_key) {
return -1;
}
if (lp->gm_key > rp->gm_key) {
return 1;
}
/* match. */
return 0;
}
int
_dwarf_insert_in_group_map(Dwarf_Debug dbg,
unsigned groupnum,
unsigned section_index,
const char *name,
Dwarf_Error * error)
{
struct Dwarf_Group_Data_s *grp = &dbg->de_groupnumbers;
void *entry2 = 0;
struct Dwarf_Group_Map_Entry_s * entry3 = 0;
if (!grp->gd_map) {
/* Number of sections is a kind of decent guess
as to how much space would be useful. */
dwarf_initialize_search_hash(&grp->gd_map,
grp_data_hashfunc,grp->gd_number_of_sections);
if (!grp->gd_map) {
/* It's really an error I suppose. */
return DW_DLV_NO_ENTRY;
}
}
entry3 = grp_make_entry(section_index,groupnum,name);
if (!entry3) {
_dwarf_error(dbg, error, DW_DLE_GROUP_MAP_ALLOC);
return DW_DLV_ERROR;
}
entry2 = dwarf_tsearch(entry3,&grp->gd_map,grp_compare_function);
if (!entry2) {
free(entry3);
_dwarf_error(dbg, error, DW_DLE_GROUP_MAP_ALLOC);
return DW_DLV_ERROR;
} else {
struct Dwarf_Group_Map_Entry_s *re = 0;
re = *(struct Dwarf_Group_Map_Entry_s **)entry2;
if (re != entry3) {
free(entry3);
_dwarf_error(dbg, error, DW_DLE_GROUP_MAP_DUPLICATE);
return DW_DLV_ERROR;
} else {
++grp->gd_map_entry_count;
/* OK. Added. Fall thru */
}
}
return DW_DLV_OK;
}
int
_dwarf_section_get_target_group_from_map(Dwarf_Debug dbg,
unsigned obj_section_index,
unsigned * groupnumber_out,
Dwarf_Error * error)
{
struct Dwarf_Group_Map_Entry_s entry;
struct Dwarf_Group_Map_Entry_s *entry2;
struct Dwarf_Group_Data_s *grp = &dbg->de_groupnumbers;
(void)error;
if (!grp->gd_map) {
return DW_DLV_NO_ENTRY;
}
entry.gm_key = obj_section_index;
entry.gm_group_number = 0; /* FAKE */
entry.gm_section_name = ""; /* FAKE */
entry2 = dwarf_tfind(&entry, &grp->gd_map,grp_compare_function);
if (entry2) {
struct Dwarf_Group_Map_Entry_s *e2 =
*(struct Dwarf_Group_Map_Entry_s **)entry2;;
*groupnumber_out = e2->gm_group_number;
return DW_DLV_OK;
}
return DW_DLV_NO_ENTRY;
}
/* New May 2017. So users can find out what groups (dwo or COMDAT)
are in the object and how much to allocate so one can get the
group-section map data. */
int dwarf_sec_group_sizes(Dwarf_Debug dbg,
Dwarf_Unsigned * section_count_out,
Dwarf_Unsigned * group_count_out,
Dwarf_Unsigned * selected_group_out,
Dwarf_Unsigned * map_entry_count_out,
Dwarf_Error * error)
{
struct Dwarf_Group_Data_s *grp = &dbg->de_groupnumbers;
(void)error;
*section_count_out = grp->gd_number_of_sections;
*group_count_out = grp->gd_number_of_groups;
*selected_group_out = dbg->de_groupnumber;
*map_entry_count_out = grp->gd_map_entry_count;
return DW_DLV_OK;
}
static Dwarf_Unsigned map_reccount = 0;
static struct temp_map_struc_s {
Dwarf_Unsigned section;
Dwarf_Unsigned group;
const char *name;
} *temp_map_data;
static void
grp_walk_map(const void *nodep,
const DW_VISIT which,
const int depth)
{
struct Dwarf_Group_Map_Entry_s *re = 0;
(void)depth;
re = *(struct Dwarf_Group_Map_Entry_s **)nodep;
if (which == dwarf_postorder || which == dwarf_endorder) {
return;
}
temp_map_data[map_reccount].group = re->gm_group_number;
temp_map_data[map_reccount].section = re->gm_key;
temp_map_data[map_reccount].name = re->gm_section_name;
map_reccount += 1;
}
/* Looks better sorted by group then sec num. */
static int
map_sort_compar(const void*l, const void*r)
{
struct temp_map_struc_s *lv = (struct temp_map_struc_s *)l;
struct temp_map_struc_s *rv = (struct temp_map_struc_s *)r;
if (lv->group < rv->group) {
return -1;
}
if (lv->group > rv->group) {
return 1;
}
if (lv->section < rv->section) {
return -1;
}
if (lv->section > rv->section) {
return 1;
}
/* Should never get here! */
return 0;
}
/* New May 2017. Reveals the map between group numbers
and section numbers.
Caller must allocate the arrays with space for 'map_entry_count'
values and this function fills in the array entries.
Output ordered by group number and section number.
*/
int dwarf_sec_group_map(Dwarf_Debug dbg,
Dwarf_Unsigned map_entry_count,
Dwarf_Unsigned * group_numbers_array,
Dwarf_Unsigned * sec_numbers_array,
const char ** sec_names_array,
Dwarf_Error * error)
{
Dwarf_Unsigned i = 0;
struct Dwarf_Group_Data_s *grp = 0;
if (temp_map_data) {
_dwarf_error(dbg,error,DW_DLE_GROUP_INTERNAL_ERROR);
return DW_DLV_ERROR;
}
map_reccount = 0;
grp = &dbg->de_groupnumbers;
if (map_entry_count < grp->gd_map_entry_count) {
_dwarf_error(dbg,error,DW_DLE_GROUP_COUNT_ERROR);
return DW_DLV_ERROR;
}
temp_map_data = calloc(map_entry_count,
sizeof(struct temp_map_struc_s));
if (!temp_map_data) {
_dwarf_error(dbg,error,DW_DLE_GROUP_MAP_ALLOC);
return DW_DLV_ERROR;
}
dwarf_twalk(grp->gd_map,grp_walk_map);
if (map_reccount != grp->gd_map_entry_count) {
/* Impossible. */
_dwarf_error(dbg,error,DW_DLE_GROUP_INTERNAL_ERROR);
return DW_DLV_ERROR;
}
qsort(temp_map_data,map_reccount,sizeof(struct temp_map_struc_s),
map_sort_compar);
for (i =0 ; i < map_reccount; ++i) {
sec_numbers_array[i] = temp_map_data[i].section;
group_numbers_array[i] = temp_map_data[i].group;
sec_names_array[i] = temp_map_data[i].name;
}
free(temp_map_data);
map_reccount = 0;
temp_map_data = 0;
return DW_DLV_OK;
}
static const char *dwo_secnames[] = {
".debug_info.dwo",
".debug_types.dwo",
".debug_abbrev.dwo",
".debug_line.dwo",
".debug_loc.dwo",
".debug_str.dwo",
".debug_loclists.dwo",
".debug_rnglists.dwo",
".debug_str_offsets.dwo",
".debug_macro.dwo",
".debug_cu_index",
".debug_tu_index",
0 };
/* Assumption: dwo sections are never in a COMDAT group
(groupnumber >2)
and by definition here are never group 1.
Assumption: the map of COMDAT groups (not necessarily all
sections, but at least all COMDAT) is complete. */
int
_dwarf_dwo_groupnumber_given_name(
const char *name,
unsigned *grpnum_out)
{
const char **s = 0;
for (s = dwo_secnames; *s; s++) {
if (!strcmp(name,*s)) {
*grpnum_out = DW_GROUPNUMBER_DWO;
return DW_DLV_OK;
}
}
return DW_DLV_NO_ENTRY;
}
static unsigned target_group = 0;
static int found_name_in_group = 0;
const char *lookfor_name = 0;
static void
grp_walk_for_name(const void *nodep,
const DW_VISIT which,
const int depth)
{
struct Dwarf_Group_Map_Entry_s *re = 0;
(void)depth;
re = *(struct Dwarf_Group_Map_Entry_s **)nodep;
if (which == dwarf_postorder || which == dwarf_endorder) {
return;
}
if (re->gm_group_number == target_group) {
if (!strcmp(lookfor_name,re->gm_section_name)) {
found_name_in_group = TRUE;
}
}
}
/* returns TRUE or FALSE */
int
_dwarf_section_in_group_by_name(Dwarf_Debug dbg,
const char * scn_name,
unsigned groupnum)
{
struct Dwarf_Group_Data_s *grp = 0;
grp = &dbg->de_groupnumbers;
found_name_in_group = FALSE;
target_group = groupnum;
lookfor_name = scn_name;
dwarf_twalk(grp->gd_map,grp_walk_for_name);
return found_name_in_group;
}
static void
_dwarf_grp_destroy_free_node(void*nodep)
{
struct Dwarf_Group_Map_Entry_s * enp = nodep;
free(enp);
return;
}
void
_dwarf_destroy_group_map(Dwarf_Debug dbg)
{
dwarf_tdestroy(dbg->de_groupnumbers.gd_map,
_dwarf_grp_destroy_free_node);
dbg->de_groupnumbers.gd_map = 0;
}

240
src/lib/libdwarf/dwarf_harmless.c vendored Normal file
View File

@ -0,0 +1,240 @@
/*
Copyright (C) 2010-2022 David Anderson. All Rights Reserved.
Portions Copyright 2012 SN Systems Ltd. All rights reserved.
This program is free software; you can redistribute it
and/or modify it under the terms of version 2.1 of the
GNU Lesser General Public License as published by the Free
Software Foundation.
This program is distributed in the hope that it would be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
Further, this software is distributed without any warranty
that it is free of the rightful claim of any third person
regarding infringement or the like. Any license provided
herein, whether implied or otherwise, applies only to this
software file. Patent licenses, if any, provided herein
do not apply to combinations of this program with other
software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write the
Free Software Foundation, Inc., 51 Franklin Street - Fifth
Floor, Boston MA 02110-1301, USA.
*/
/* This implements _dwarf_insert_harmless_error
and related helper functions for recording
compiler errors that need not make the input
unusable.
Applications can use dwarf_get_harmless_error_list to
find (and possibly print) a warning about such errors.
The initial error reported here is
DW_DLE_DEBUG_FRAME_LENGTH_NOT_MULTIPLE which was a
bug in a specific compiler.
It is a fixed length circular list to constrain
the space used for errors.
The assumption is that these errors are exceedingly
rare, and indicate a broken compiler (the one that
produced the object getting the error(s)).
dh_maxcount is recorded internally as 1 greater than
requested. Hiding the fact we always leave one
slot unused (at least). So a user request for
N slots really gives the user N usable slots. */
#include <config.h>
#include <stddef.h> /* size_t */
#include <stdlib.h> /* free() malloc() */
#include <string.h> /* memcpy() strcpy() strlen() */
#if defined(_WIN32) && defined(HAVE_STDAFX_H)
#include "stdafx.h"
#endif /* HAVE_STDAFX_H */
#include "dwarf.h"
#include "libdwarf.h"
#include "libdwarf_private.h"
#include "dwarf_base_types.h"
#include "dwarf_safe_strcpy.h"
#include "dwarf_opaque.h"
#include "dwarf_frame.h"
#include "dwarf_harmless.h"
/* Not user configurable. */
#define DW_HARMLESS_ERROR_MSG_STRING_SIZE 300
/* The pointers returned here through errmsg_ptrs_array
become invalidated by any call to libdwarf. Any call.
*/
int dwarf_get_harmless_error_list(Dwarf_Debug dbg,
unsigned count,
const char ** errmsg_ptrs_array,
unsigned * errs_count)
{
struct Dwarf_Harmless_s *dhp = &dbg->de_harmless_errors;
if (!dhp->dh_errors) {
dhp->dh_errs_count = 0;
return DW_DLV_NO_ENTRY;
}
if (dhp->dh_errs_count == 0) {
return DW_DLV_NO_ENTRY;
}
if (errs_count) {
*errs_count = dhp->dh_errs_count;
}
if (count) {
/* NULL terminate the array of pointers */
--count;
errmsg_ptrs_array[count] = 0;
if (dhp->dh_next_to_use != dhp->dh_first) {
unsigned i = 0;
unsigned cur = dhp->dh_first;
for (i = 0; cur != dhp->dh_next_to_use;
++i, cur = (cur +1) % dhp->dh_maxcount) {
if (i >= count ) {
/* All output spaces are used. */
break;
}
errmsg_ptrs_array[i] = dhp->dh_errors[cur];
}
errmsg_ptrs_array[i] = 0;
}
}
dhp->dh_next_to_use = 0;
dhp->dh_first = 0;
dhp->dh_errs_count = 0;
return DW_DLV_OK;
}
/* Insertion made public is only for testing the harmless error code,
it is not necessarily useful for libdwarf client code aside
from code testing libdwarf. */
void dwarf_insert_harmless_error(Dwarf_Debug dbg,
char *newerror)
{
struct Dwarf_Harmless_s *dhp = &dbg->de_harmless_errors;
unsigned next = 0;
unsigned cur = dhp->dh_next_to_use;
char *msgspace;
if (!dhp->dh_errors) {
dhp->dh_errs_count++;
return;
}
msgspace = dhp->dh_errors[cur];
_dwarf_safe_strcpy(msgspace,
DW_HARMLESS_ERROR_MSG_STRING_SIZE,
newerror,
strlen(newerror));
next = (cur+1) % dhp->dh_maxcount;
dhp->dh_errs_count++;
dhp->dh_next_to_use = next;
if (dhp->dh_next_to_use == dhp->dh_first) {
/* Array is full set full invariant. */
dhp->dh_first = (dhp->dh_first+1) % dhp->dh_maxcount;
}
}
/* The size of the circular list of strings may be set
and reset as desired. Returns the previous size of
the list. If the list is shortened excess error entries
are simply dropped.
If the reallocation fails the list size is left unchanged.
Do not make this a long list!
Remember the maxcount we record is 1 > the user count,
so we adjust it so it looks like the user count.
*/
unsigned dwarf_set_harmless_error_list_size(Dwarf_Debug dbg,
unsigned maxcount )
{
struct Dwarf_Harmless_s *dhp = &dbg->de_harmless_errors;
unsigned prevcount = dhp->dh_maxcount;
if (maxcount != 0) {
++maxcount;
if (maxcount != dhp->dh_maxcount) {
/* Assign transfers 'ownership' of the malloc areas
to oldarray. */
struct Dwarf_Harmless_s oldarray = *dhp;
/* Do not double increment the max, the init() func
increments it too. */
_dwarf_harmless_init(dhp,maxcount-1);
if (oldarray.dh_next_to_use != oldarray.dh_first) {
unsigned i = 0;
for (i = oldarray.dh_first;
i != oldarray.dh_next_to_use;
i = (i+1)%oldarray.dh_maxcount) {
dwarf_insert_harmless_error(dbg,
oldarray.dh_errors[i]);
}
if (oldarray.dh_errs_count > dhp->dh_errs_count) {
dhp->dh_errs_count = oldarray.dh_errs_count;
}
}
_dwarf_harmless_cleanout(&oldarray);
}
}
return prevcount-1;
}
/* Only callable from within libdwarf (as a practical matter)
*/
void
_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(sizeof(char *),
dhp->dh_maxcount);
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);
dhp->dh_errors[i] = newstr;
#if 0
/* BAD IDEA. just use the NULL pointer,
so we avoid problems later with
freeing. */
if (!newstr) {
dhp->dh_maxcount = 0;
/* Let it leak, the leak is a constrained amount. */
free(dhp->dh_errors);
dhp->dh_errors = 0;
return;
}
#endif /* 0 */
dhp->dh_errors[i] = newstr;
}
}
void
_dwarf_harmless_cleanout(struct Dwarf_Harmless_s *dhp)
{
unsigned i = 0;
if (!dhp->dh_errors) {
return;
}
for (i = 0; i < dhp->dh_maxcount; ++i) {
free(dhp->dh_errors[i]);
dhp->dh_errors[i] = 0;
}
free(dhp->dh_errors);
dhp->dh_errors = 0;
dhp->dh_maxcount = 0;
}

31
src/lib/libdwarf/dwarf_harmless.h vendored Normal file
View File

@ -0,0 +1,31 @@
/*
Copyright (C) 2012-2023 David Anderson. All Rights Reserved.
This program is free software; you can redistribute it
and/or modify it under the terms of version 2.1 of the
GNU Lesser General Public License as published by the Free
Software Foundation.
This program is distributed in the hope that it would be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
Further, this software is distributed without any warranty
that it is free of the rightful claim of any third person
regarding infringement or the like. Any license provided
herein, whether implied or otherwise, applies only to this
software file. Patent licenses, if any, provided herein
do not apply to combinations of this program with other
software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write the
Free Software Foundation, Inc., 51 Franklin Street - Fifth
Floor, Boston MA 02110-1301, USA.
*/
void _dwarf_harmless_init(struct Dwarf_Harmless_s *dhp,unsigned size);
void _dwarf_harmless_cleanout(struct Dwarf_Harmless_s *dhp);

1745
src/lib/libdwarf/dwarf_init_finish.c vendored Normal file

File diff suppressed because it is too large Load Diff

430
src/lib/libdwarf/dwarf_leb.c vendored Normal file
View File

@ -0,0 +1,430 @@
/*
Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
Portions Copyright 2011-2020 David Anderson. All Rights Reserved.
This program is free software; you can redistribute it
and/or modify it under the terms of version 2.1 of the
GNU Lesser General Public License as published by the Free
Software Foundation.
This program is distributed in the hope that it would be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
Further, this software is distributed without any warranty
that it is free of the rightful claim of any third person
regarding infringement or the like. Any license provided
herein, whether implied or otherwise, applies only to this
software file. Patent licenses, if any, provided herein
do not apply to combinations of this program with other
software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write the
Free Software Foundation, Inc., 51 Franklin Street - Fifth
Floor, Boston MA 02110-1301, USA.
*/
#include <config.h>
#include <stddef.h> /* size_t */
#if defined(_WIN32) && defined(HAVE_STDAFX_H)
#include "stdafx.h"
#endif /* HAVE_STDAFX_H */
#include "dwarf.h"
#include "libdwarf.h"
#include "libdwarf_private.h"
#include "dwarf_base_types.h"
#include "dwarf_opaque.h"
#include "dwarf_error.h"
#include "dwarf_util.h"
#define MORE_BYTES 0x80
#define DATA_MASK 0x7f
#define DIGIT_WIDTH 7
#define SIGN_BIT 0x40
/* Note that with 'make check')
many of the test items
only make sense if Dwarf_Unsigned (and Dwarf_Signed)
are 64 bits. The encode/decode logic should
be fine whether those types are 64 or 32 bits.
See runtests.sh */
/* The encode/decode functions here are public */
/* 10 bytes of leb, 7 bits each part of the number, gives
room for a 64bit number.
While any number of leading zeroes would be legal, so
no max is really truly required here, why would a
compiler generate leading zeros (for unsigned leb)?
That would seem strange except in rare circumstances
a compiler may want, for overall alignment, to
add extra bytes..
So we allow more than 10 as it is legal for a compiler to
generate an leb with correct but useless trailing
zero bytes (note the interaction with sign in the signed case).
The value of BYTESLEBMAX is arbitrary but allows catching
corrupt data before dark.
Before April 2021 BYTESLEBMAX was 10.
*/
#define BYTESLEBMAX 24
#define BITSPERBYTE 8
/* When an leb value needs to reveal its length,
but the value is not needed */
int
_dwarf_skip_leb128(char * leb128,
Dwarf_Unsigned * leb128_length,
char * endptr)
{
unsigned byte = 0;
/* The byte_length value will be a small non-negative integer. */
unsigned byte_length = 1;
if (leb128 >=endptr) {
return DW_DLV_ERROR;
}
byte = *leb128;
if ((byte & 0x80) == 0) {
*leb128_length = 1;
return DW_DLV_OK;
} else {
unsigned byte2 = 0;
if ((leb128+1) >=endptr) {
return DW_DLV_ERROR;
}
byte2 = *(leb128 + 1);
if ((byte2 & 0x80) == 0) {
*leb128_length = 2;
return DW_DLV_OK;
}
/* Gets messy to hand-inline more byte checking.
One or two byte leb is very frequent. */
}
++byte_length;
++leb128;
/* Validity of leb128+1 checked above */
for (;;byte_length++,leb128++) {
if (leb128 >= endptr) {
/* Off end of available space. */
return DW_DLV_ERROR;
}
byte = *leb128;
if (byte & 0x80) {
if (byte_length >= BYTESLEBMAX) {
/* Too long. Not sane length. */
return DW_DLV_ERROR;
}
continue;
}
break;
}
*leb128_length = byte_length;
return DW_DLV_OK;
}
/* Decode ULEB with checking. */
int
dwarf_decode_leb128(char * leb128,
Dwarf_Unsigned * leb128_length,
Dwarf_Unsigned *outval,
char * endptr)
{
unsigned byte = 0;
Dwarf_Unsigned word_number = 0;
Dwarf_Unsigned number = 0;
size_t shift = 0;
/* The byte_length value will be a small non-negative integer. */
unsigned byte_length = 0;
if (leb128 >=endptr) {
return DW_DLV_ERROR;
}
/* The following unrolls-the-loop for the first two bytes and
unpacks into 32 bits to make this as fast as possible.
word_number is assumed big enough that the shift has a defined
result. */
byte = *leb128;
if ((byte & 0x80) == 0) {
if (leb128_length) {
*leb128_length = 1;
}
if (outval) {
*outval = byte;
}
return DW_DLV_OK;
} else {
unsigned byte2 = 0;
if ((leb128+1) >=endptr) {
return DW_DLV_ERROR;
}
byte2 = *(leb128 + 1);
if ((byte2 & 0x80) == 0) {
if (leb128_length) {
*leb128_length = 2;
}
word_number = byte & 0x7f;
word_number |= (byte2 & 0x7f) << 7;
if (outval) {
*outval = word_number;
}
return DW_DLV_OK;
}
/* Gets messy to hand-inline more byte checking. */
}
/* The rest handles long numbers. Because the 'number'
may be larger than the default int/unsigned,
we must cast the 'byte' before
the shift for the shift to have a defined result. */
number = 0;
shift = 0;
byte_length = 1;
for (;;) {
unsigned b = byte & 0x7f;
if (shift >= (sizeof(number)*BITSPERBYTE)) {
/* Shift is large. Maybe corrupt value,
maybe some padding high-end byte zeroes
that we can ignore. */
if (!b) {
if (byte_length >= BYTESLEBMAX) {
/* Erroneous input. */
if (leb128_length) {
*leb128_length = BYTESLEBMAX;
}
return DW_DLV_ERROR;
}
++leb128;
/* shift cannot overflow as
BYTESLEBMAX is not a large value */
shift += 7;
if (leb128 >=endptr ) {
if (leb128 == endptr && !byte) {
/* Meaning zero bits a padding byte */
if (leb128_length) {
*leb128_length = byte_length;
}
if (outval) {
*outval = number;
}
return DW_DLV_OK;
}
return DW_DLV_ERROR;
}
++byte_length;
byte = *leb128;
continue;
}
/* Too big, corrupt data given the non-zero
byte content */
return DW_DLV_ERROR;
}
number |= ((Dwarf_Unsigned)b << shift);
if ((byte & 0x80) == 0) {
if (leb128_length) {
*leb128_length = byte_length;
}
if (outval) {
*outval = number;
}
return DW_DLV_OK;
}
shift += 7;
byte_length++;
if (byte_length > BYTESLEBMAX) {
/* Erroneous input. */
if (leb128_length) {
*leb128_length = BYTESLEBMAX;
}
break;
}
++leb128;
if (leb128 >= endptr) {
return DW_DLV_ERROR;
}
byte = *leb128;
}
return DW_DLV_ERROR;
}
/* Decode SLEB with checking */
int
dwarf_decode_signed_leb128(char * leb128,
Dwarf_Unsigned * leb128_length,
Dwarf_Signed *outval,char * endptr)
{
Dwarf_Unsigned byte = 0;
unsigned int b = 0;
Dwarf_Signed number = 0;
size_t shift = 0;
int sign = FALSE;
/* The byte_length value will be a small non-negative integer. */
unsigned byte_length = 1;
/* byte_length being the number of bytes
of data absorbed so far in
turning the leb into a Dwarf_Signed. */
if (!outval) {
return DW_DLV_ERROR;
}
if (leb128 >= endptr) {
return DW_DLV_ERROR;
}
byte = *leb128;
for (;;) {
b = byte & 0x7f;
if (shift >= (sizeof(number)*BITSPERBYTE)) {
/* Shift is large. Maybe corrupt value,
maybe some padding high-end byte zeroes
that we can ignore (but notice sign bit
from the last usable byte). */
sign = b & 0x40;
if (!byte || byte == 0x40) {
/* The value is complete. */
break;
}
if (b == 0) {
++byte_length;
if (byte_length > BYTESLEBMAX) {
/* Erroneous input. */
if (leb128_length) {
*leb128_length = BYTESLEBMAX;
}
return DW_DLV_ERROR;
}
++leb128;
/* shift cannot overflow as
BYTESLEBMAX is not a large value */
shift += 7;
if (leb128 >= endptr) {
return DW_DLV_ERROR;
}
byte = *leb128;
continue;
}
/* Too big, corrupt data given the non-zero
byte content */
return DW_DLV_ERROR;
}
/* This bit of the last byte indicates sign */
sign = b & 0x40;
number |= ((Dwarf_Unsigned)b) << shift;
shift += 7;
if ((byte & 0x80) == 0) {
break;
}
++leb128;
if (leb128 >= endptr) {
return DW_DLV_ERROR;
}
byte = *leb128;
byte_length++;
if (byte_length > BYTESLEBMAX) {
/* Erroneous input. */
if (leb128_length) {
*leb128_length = BYTESLEBMAX;
}
return DW_DLV_ERROR;
}
}
if (sign) {
/* The following avoids undefined behavior. */
unsigned shiftlim = sizeof(Dwarf_Signed) * BITSPERBYTE -1;
if (shift < shiftlim) {
Dwarf_Signed y = (Dwarf_Signed)
(((Dwarf_Unsigned)1) << shift);
Dwarf_Signed x = -y;
number |= x;
} else if (shift == shiftlim) {
Dwarf_Signed x= (((Dwarf_Unsigned)1) << shift);
number |= x;
} else {
/* trailing zeroes case */
Dwarf_Signed x= (((Dwarf_Unsigned)1) << shiftlim);
number |= x;
}
}
if (leb128_length) {
*leb128_length = byte_length;
}
*outval = number;
return DW_DLV_OK;
}
/* Encode val as a uleb128. This encodes it as an unsigned
number.
Return DW_DLV_ERROR or DW_DLV_OK.
space to write leb number is provided by caller, with caller
passing length.
number of bytes used returned thru nbytes arg.
This never emits padding, it emits the minimum
number of bytes that can hold the value. */
int dwarf_encode_leb128(Dwarf_Unsigned val, int *nbytes,
char *space, int splen)
{
char *a;
char *end = space + splen;
a = space;
do {
unsigned char uc;
if (a >= end) {
return DW_DLV_ERROR;
}
uc = val & DATA_MASK;
val >>= DIGIT_WIDTH;
if (val != 0) {
uc |= MORE_BYTES;
}
*a = uc;
a++;
} while (val);
*nbytes = (int)(a - space);
return DW_DLV_OK;
}
/* This never emits padding at the end, so it
says nothing about what such would look like
for a negative value. */
int dwarf_encode_signed_leb128(Dwarf_Signed value, int *nbytes,
char *space, int splen)
{
char *str;
Dwarf_Signed sign = -(value < 0);
int more = 1;
char *end = space + splen;
str = space;
do {
unsigned char byte = value & DATA_MASK;
value >>= DIGIT_WIDTH;
if (str >= end) {
return DW_DLV_ERROR;
}
/* Remaining chunks would just contain the sign
bit, and this chunk
has already captured at least one sign bit. */
if (value == sign &&
((byte & SIGN_BIT) == (sign & SIGN_BIT))) {
more = 0;
} else {
byte |= MORE_BYTES;
}
*str = byte;
str++;
} while (more);
*nbytes = (int)(str - space);
return DW_DLV_OK;
}

2649
src/lib/libdwarf/dwarf_line.c vendored Normal file

File diff suppressed because it is too large Load Diff

491
src/lib/libdwarf/dwarf_line.h vendored Normal file
View File

@ -0,0 +1,491 @@
/*
Copyright (C) 2000, 2004, 2006 Silicon Graphics, Inc. All Rights Reserved.
Portions Copyright (C) 2009-2023 David Anderson. All Rights Reserved.
Portions Copyright (C) 2010-2012 SN Systems Ltd. All Rights Reserved.
This program is free software; you can redistribute it
and/or modify it under the terms of version 2.1 of the
GNU Lesser General Public License as published by the Free
Software Foundation.
This program is distributed in the hope that it would be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
Further, this software is distributed without any warranty
that it is free of the rightful claim of any third person
regarding infringement or the like. Any license provided
herein, whether implied or otherwise, applies only to this
software file. Patent licenses, if any, provided herein
do not apply to combinations of this program with other
software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write the
Free Software Foundation, Inc., 51 Franklin Street - Fifth
Floor, Boston MA 02110-1301, USA.
*/
#define DW_EXTENDED_OPCODE 0
/*
This is used as the starting value for an algorithm
to get the minimum difference between 2 values.
UINT_MAX is used as our approximation to infinity.
*/
#define MAX_LINE_DIFF UINT_MAX
/* This is for a sanity check on line
table extended opcodes.
It is entirely arbitrary, and 100 is surely too small if
someone was inserting strings in the opcode. */
#define DW_LNE_LEN_MAX 100
/*
This structure is used to build a list of all the
files that are used in the current compilation unit.
All of the fields execpt fi_next have meanings that
are obvious from section 6.2.4 of the Libdwarf Doc.
Because of DW_LNE_define_file we
make this a list, not an array.
*/
struct Dwarf_File_Entry_s {
struct Dwarf_File_Entry_s *fi_next;
/* Points to string naming the file: DW_LNCT_path. */
Dwarf_Small *fi_file_name;
/* Points to string naming the source, with \n endings
and null terminated (UTF-8). Embedded source. */
Dwarf_Small *fi_llvm_source;
/* Index into the list of directories of the directory in which
this file exits.
For DWARF5, values are 0 to N-1
For DWARF4 etc values are 1 to N
so the test for overrun differs. */
Dwarf_Unsigned fi_dir_index;
/* Time of last modification of the file. */
Dwarf_Unsigned fi_time_last_mod;
/* Length in bytes of the file. */
Dwarf_Unsigned fi_file_length;
Dwarf_Small * fi_gnu_subprogram_name;
Dwarf_Unsigned fi_gnu_decl_file;
Dwarf_Unsigned fi_gnu_decl_line;
Dwarf_Form_Data16 fi_md5_value;
char fi_dir_index_present;
char fi_time_last_mod_present;
char fi_file_length_present;
char fi_md5_present;
char fi_gnu_decl_file_present;
char fi_gnu_decl_line_present;
};
/* Part of two-level line tables support. */
struct Dwarf_Subprog_Entry_s {
Dwarf_Small *ds_subprog_name;
Dwarf_Unsigned ds_decl_file;
Dwarf_Unsigned ds_decl_line;
};
typedef struct Dwarf_Subprog_Entry_s *Dwarf_Subprog_Entry;
struct Dwarf_Unsigned_Pair_s {
Dwarf_Unsigned up_first;
Dwarf_Unsigned up_second;
};
/*
This structure provides the context in which the fields of
a Dwarf_Line structure are interpreted. They come from the
statement program prologue. **Updated by dwarf_srclines in
dwarf_line.c.
lc_magic will be DW_CONTEXT_MAGIC unless there is a serious
programming error somewhere.
It's set zero when a Line_Context is deallocated.
Any other value indicates there is bug somewhere.
*/
#define DW_CONTEXT_MAGIC 0xd00d1111
struct Dwarf_Line_Context_s {
unsigned lc_magic;
/* lc_new_style_access is non-zero if this was allocated
via a dwarf_srclines_b() call or equivalent.
Otherwise this is 0. */
unsigned char lc_new_style_access;
Dwarf_Unsigned lc_unit_length; /* all versions */
/* The section offset (in .debug_line
or .debug_line.dwo of the line table */
Dwarf_Unsigned lc_section_offset;
/* 2 for DWARF2, 3 for DWARF3, 4 for DWARF4, 5 for DWARF5.
0xf006 for experimental two-level line tables. */
Dwarf_Half lc_version_number; /* all versions */
/* Total length of the line data for this CU */
Dwarf_Unsigned lc_total_length; /* all versions */
/* Length of the initial length field itself. */
Dwarf_Half lc_length_field_length; /* all versions */
/* address size and segment sizefields new in DWARF5 header. */
Dwarf_Small lc_address_size; /* DWARF5 */
Dwarf_Small lc_segment_selector_size; /* DWARF5 */
Dwarf_Unsigned lc_header_length; /* all versions */
Dwarf_Unsigned lc_prologue_length;
Dwarf_Unsigned lc_actuals_table_offset;
Dwarf_Unsigned lc_logicals_table_offset;
Dwarf_Small lc_minimum_instruction_length; /* all versions */
Dwarf_Ubyte lc_maximum_ops_per_instruction; /*DWARF5*/
/* Start and end of this CU line area. pf_line_ptr_start +
pf_total_length + pf_length_field_length == pf_line_ptr_end.
Meaning lc_line_ptr_start is before the length info. */
Dwarf_Small *lc_line_ptr_start;
Dwarf_Small *lc_line_ptr_end;
/* Start of the lines themselves. */
Dwarf_Small *lc_line_ptr_lines;
/* Used to check that decoding of the line prologue
is done right. */
Dwarf_Small *lc_line_prologue_start;
Dwarf_Small lc_default_is_stmt; /* all versions */
Dwarf_Sbyte lc_line_base; /* all versions */
Dwarf_Small lc_line_range; /* all versions */
/* Highest std opcode (+1). */
Dwarf_Small lc_opcode_base; /* all versions */
/* pf_opcode_base -1 entries (each a count,
normally the value of
each entry is 0 or 1). */
Dwarf_Small *lc_opcode_length_table; /* all versions */
/* The number to treat as standard ops. This is a special
accommodation of gcc using the new standard opcodes but not
updating the version number.
It's legal dwarf2, but much better
for the user to understand as dwarf3 when 'it looks ok'. */
Dwarf_Small lc_std_op_count;
/* ======== includes =========*/
/* Points to the portion of .debug_line section that
contains a list of strings naming the included
directories. Do not free().
No free even DWARF5?
An array of pointers to strings. */
/* DWARF 2,3,4: does not name the current dir of the compilation.
DWARF5: Initial entry is the dir of the compilation. */
Dwarf_Small **lc_include_directories;
/* Count of the number of included directories. */
Dwarf_Unsigned lc_include_directories_count;
/* count of uleb pairs */
Dwarf_Unsigned lc_directory_entry_format_count; /* DWARF5 */
Dwarf_Unsigned lc_directory_entry_values_count; /* DWARF5 */
/* This must be freed,malloc space, an array of the
values of each entry. DWARF5 */
struct Dwarf_Unsigned_Pair_s * lc_directory_format_values;
/* ======== end includes =========*/
/* ======== file names =========*/
Dwarf_Unsigned lc_file_name_format_count; /* DWARF5 */
Dwarf_Unsigned * lc_file_name_format; /* DWARF5 */
Dwarf_Unsigned lc_file_entry_values_count; /* DWARF5 */
/* This must be freed,malloc space, an array of the
values of each entry. */
struct Dwarf_Unsigned_Pair_s * lc_file_format_values; /* DWARF5 */
/* Points to a singly-linked list of entries providing info
about source files
for the current set of Dwarf_Line structures.
The initial entry on the list is 'file 1'
per DWARF2,3,4 rules.
And so on. lc_last_entry points at the last entry
in the list (so we can easily expand the list).
It's a list (not a table) since we may encounter
DW_LNE_define_file entries.
For Dwarf5 the initial entry is 'file 0'
and must match the CU-DIE DW_AT_name string. */
Dwarf_File_Entry lc_file_entries;
Dwarf_File_Entry lc_last_entry;
/* Count of number of source files for this set of Dwarf_Line
structures. */
Dwarf_Unsigned lc_file_entry_count; /* all versions */
/* Values Easing the process of indexing
through lc_file_entries. */
Dwarf_Unsigned lc_file_entry_baseindex;
Dwarf_Unsigned lc_file_entry_endindex;
/* ======== end file names =========*/
/* Points to an array of subprogram entries.
With Two level line tables this may be non-zero.
An array of Dwarf_Subprogram_Entry_s structs. */
Dwarf_Subprog_Entry lc_subprogs;
/* Count of the number of subprogram entries
With Two level line tables this may be non-zero. */
Dwarf_Unsigned lc_subprogs_count;
/* Count of the number of lines for this cu. */
Dwarf_Unsigned lc_line_count;
/* Points to name of compilation directory.
That string is in a .debug section (DWARF 2,3,4)
so do not free this. For DWARF5 must be the same
as lc_include_directories[0] */
Dwarf_Small *lc_compilation_directory;
Dwarf_Debug lc_dbg;
/* zero table count is skeleton, or just missing names.
1 is standard table.
2 means two-level table (experimental)
Other is a bug somewhere. */
Dwarf_Small lc_table_count;
Dwarf_Bool lc_is_single_table;
/* For standard line tables the logicals are
the only tables and linecount_actuals is 0. */
Dwarf_Line *lc_linebuf_logicals;
Dwarf_Unsigned lc_linecount_logicals;
/* Non-zero only if two-level table with actuals */
Dwarf_Line *lc_linebuf_actuals;
Dwarf_Unsigned lc_linecount_actuals;
};
/* The line table set of registers.
The state machine state variables.
Using names from the DWARF documentation
but preceded by lr_. */
struct Dwarf_Line_Registers_s {
Dwarf_Addr lr_address; /* DWARF2 */
Dwarf_Unsigned lr_file ; /* DWARF2 */
Dwarf_Unsigned lr_line ; /* DWARF2 */
Dwarf_Unsigned lr_column ; /* DWARF2 */
Dwarf_Bool lr_is_stmt; /* DWARF2 */
Dwarf_Bool lr_basic_block; /* DWARF2 */
Dwarf_Bool lr_end_sequence; /* DWARF2 */
Dwarf_Bool lr_prologue_end; /* DWARF3 */
Dwarf_Bool lr_epilogue_begin; /* DWARF3 */
Dwarf_Small lr_isa; /* DWARF3 */
Dwarf_Unsigned lr_op_index; /* DWARF4, operation
within VLIW instruction. */
Dwarf_Unsigned lr_discriminator; /* DWARF4 */
Dwarf_Unsigned lr_call_context; /* EXPERIMENTAL */
Dwarf_Unsigned lr_subprogram; /* EXPERIMENTAL */
};
typedef struct Dwarf_Line_Registers_s *Dwarf_Line_Registers;
void _dwarf_set_line_table_regs_default_values(
Dwarf_Line_Registers regs,
unsigned lineversion,
Dwarf_Bool is_stmt);
/*
This structure defines a row of the line table.
All of the fields
same meaning that is defined in Section 6.2.2
of the Libdwarf Document.
*/
struct Dwarf_Line_s {
Dwarf_Addr li_address; /* pc value of machine instr */
#if 1
struct li_inner_s {
/* New as of DWARF4 */
Dwarf_Unsigned li_discriminator;
/* int identifying src file
li_file is a number 1-N, indexing into a conceptual
source file table as described in dwarf2/3 spec line
table doc. (see Dwarf_File_Entry lc_file_entries; and
Dwarf_Unsigned lc_file_entry_count;) */
Dwarf_Unsigned li_file;
/* In single-level table is line number in
source file. 1-N
In logicals table is not used.
In actuals table is index into logicals table. 1-N*/
Dwarf_Unsigned li_line;
Dwarf_Half li_column; /*source file column number 1-N */
Dwarf_Small li_isa; /*New as of DWARF4. */
/* Two-level line tables.
Is index from logicals table
into logicals table. 1-N */
Dwarf_Unsigned li_call_context;
/* Two-level line tables.
is index into subprograms table. 1-N */
Dwarf_Unsigned li_subprogram;
/* To save space, use bit flags. */
/* indicate start of stmt */
unsigned li_is_stmt:1;
/* indicate start basic block */
unsigned li_basic_block:1;
/* first post sequence instr */
unsigned li_end_sequence:1;
unsigned li_prologue_end:1;
unsigned li_epilogue_begin:1;
/* Mark a line record as being DW_LNS_set_address. */
unsigned li_is_addr_set:1;
} li_l_data;
#endif /* 1 */
Dwarf_Line_Context li_context; /* assoc Dwarf_Line_Context_s */
/* Set only on the actuals table of a two-level line table.
Assists in the dealloc code.
*/
Dwarf_Bool li_is_actuals_table;
};
int _dwarf_line_address_offsets(Dwarf_Debug dbg,
Dwarf_Die die,
Dwarf_Addr ** addrs,
Dwarf_Off ** offs,
Dwarf_Unsigned * returncount,
Dwarf_Error * err);
int _dwarf_internal_srclines(Dwarf_Die die,
Dwarf_Bool old_interface,
Dwarf_Unsigned * version,
Dwarf_Small * table_count,
Dwarf_Line_Context *line_context,
Dwarf_Line ** linebuf,
Dwarf_Signed * count,
Dwarf_Line ** linebuf_actuals,
Dwarf_Signed * count_actuals,
Dwarf_Bool doaddrs,
Dwarf_Bool dolines,
Dwarf_Error * error);
/* The LOP, WHAT_IS_OPCODE stuff is here so it can
be reused in 3 places. Seemed hard to keep
the 3 places the same without an inline func or
a macro.
Handling the line section where the header and the
file being processed do not match (unusual, but
planned for in the design of .debug_line)
is too tricky to recode this several times and keep
it right.
*/
#define LOP_EXTENDED 1
#define LOP_DISCARD 2
#define LOP_STANDARD 3
#define LOP_SPECIAL 4
/* ASSERT: sets type to one of the above 4. Never anything else. */
#define WHAT_IS_OPCODE(type,opcode,base,opcode_length,\
line_ptr,highest_std) \
if ((opcode) < (base)) { \
/* we know we must treat as a standard op \
or a special case. */ \
if ((opcode) == DW_EXTENDED_OPCODE) { \
(type) = LOP_EXTENDED; \
} else if (((highest_std)+1) >= (base)) { \
/* == Standard case: compile of \
dwarf_line.c and object \
have same standard op codes set. \
== Special case: compile of dwarf_line.c \
has things in standard op codes list \
in dwarf.h header not \
in the object: handle this as a standard \
op code in switch below. \
The header special ops overlap the \
object standard ops. \
The new standard op codes will not \
appear in the object. */ \
(type) = LOP_STANDARD; \
} else { \
/* These are standard opcodes in the object \
** that were not defined in the header \
** at the time dwarf_line.c \
** was compiled. Provides the ability of \
** out-of-date dwarf reader to read newer \
** line table data transparently. \
*/ \
(type) = LOP_DISCARD; \
} \
} else { \
/* Is a special op code. */ \
(type) = LOP_SPECIAL; \
}
/* The following is from the dwarf definition of 'ubyte'
and is specifically mentioned in section 6.2.5.1, page 54
of the Rev 2.0.0 dwarf specification.
*/
#define MAX_LINE_OP_CODE 255
/* Operand counts per standard operand.
The initial zero is for DW_LNS_copy.
This is an economical way to verify we understand the table
of standard-opcode-lengths in the line table prologue. */
#define STANDARD_OPERAND_COUNT_DWARF2 9
#define STANDARD_OPERAND_COUNT_DWARF3 12
/* For two-level line tables, we have three additional
standard opcodes. */
#define STANDARD_OPERAND_COUNT_TWO_LEVEL 15
void _dwarf_print_header_issue(Dwarf_Debug dbg,
const char *specific_msg,
Dwarf_Small *data_start,
Dwarf_Signed value,
unsigned index,
unsigned tabv,
unsigned linetabv,
int *err_count_out);
int _dwarf_decode_line_string_form(Dwarf_Debug dbg,
Dwarf_Unsigned attrnum,
Dwarf_Unsigned form,
Dwarf_Unsigned offset_size,
Dwarf_Small **line_ptr,
Dwarf_Small *line_ptr_end,
char **return_str,
Dwarf_Error * error);
int _dwarf_decode_line_udata_form(Dwarf_Debug dbg,
Dwarf_Unsigned attrnum,
Dwarf_Unsigned form,
Dwarf_Small **line_ptr,
Dwarf_Unsigned *return_val,
Dwarf_Small *line_end_ptr,
Dwarf_Error * error);
void _dwarf_report_bad_lnct( Dwarf_Debug dbg,
Dwarf_Unsigned ltype,
int dlecode,
const char * dlename,
Dwarf_Error *err);
void _dwarf_update_chain_list( Dwarf_Chain chain_line,
Dwarf_Chain *head_chain, Dwarf_Chain *curr_chain);
void _dwarf_free_chain_entries(Dwarf_Debug dbg,Dwarf_Chain head,
int count);
int _dwarf_line_context_constructor(Dwarf_Debug dbg, void *m);
void _dwarf_line_context_destructor(void *m);
void _dwarf_print_line_context_record(Dwarf_Debug dbg,
Dwarf_Line_Context line_context);
void _dwarf_context_src_files_destroy(Dwarf_Line_Context context);
int _dwarf_add_to_files_list(Dwarf_Line_Context context,
Dwarf_File_Entry fe);

File diff suppressed because it is too large Load Diff

1929
src/lib/libdwarf/dwarf_loc.c vendored Normal file

File diff suppressed because it is too large Load Diff

339
src/lib/libdwarf/dwarf_loc.h vendored Normal file
View File

@ -0,0 +1,339 @@
/*
Copyright (C) 2000, 2004 Silicon Graphics, Inc. All Rights Reserved.
Portions Copyright (C) 2015-2023 David Anderson. All Rights Reserved.
This program is free software; you can redistribute it
and/or modify it under the terms of version 2.1 of the
GNU Lesser General Public License as published by the Free
Software Foundation.
This program is distributed in the hope that it would be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
Further, this software is distributed without any warranty
that it is free of the rightful claim of any third person
regarding infringement or the like. Any license provided
herein, whether implied or otherwise, applies only to this
software file. Patent licenses, if any, provided herein
do not apply to combinations of this program with other
software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write the
Free Software Foundation, Inc., 51 Franklin Street - Fifth
Floor, Boston MA 02110-1301, USA.
*/
#ifndef DWARF_LOC_H
#define DWARF_LOC_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define LOCLISTS_MAGIC 0xadab4
typedef struct Dwarf_Loc_Chain_s *Dwarf_Loc_Chain;
struct Dwarf_Loc_Chain_s {
Dwarf_Small lc_atom;
Dwarf_Unsigned lc_number;
Dwarf_Unsigned lc_number2;
Dwarf_Unsigned lc_number3;
Dwarf_Unsigned lc_offset;
Dwarf_Unsigned lc_opnumber;
Dwarf_Loc_Chain lc_next;
};
/* Dwarf_Loclists_Context_s contains the data from
the .debug_loclists
section headers (if that section exists). Dwarf 2,3,4 .debug_loc
has no such data. The array (one of these per header in
.debug_loclists) is recorded in Dwarf_Debug. These
are filled in at startup at the same time .debug_info
is opened. Nothing of this struct is exposed to
libdwarf callers */
struct Dwarf_Loclists_Context_s {
Dwarf_Debug lc_dbg;
Dwarf_Unsigned lc_index; /* An index assigned by
libdwarf to each loclists context. Starting
with zero at the zero offset in .debug_loclists. */
/* Offset of the .debug_loclists header involved. */
Dwarf_Unsigned lc_header_offset;
Dwarf_Unsigned lc_length;
unsigned long lc_magic;
/* Many places in in libdwarf this is called length_size. */
Dwarf_Small lc_offset_size;
/* rc_extension_size is zero unless this is standard
DWARF3 and later 64bit dwarf using the extension mechanism.
64bit DWARF3 and later: rc_extension_size is 4.
64bit DWARF2 MIPS/IRIX: rc_extension_size is zero.
32bit DWARF: rc_extension_size is zero. */
Dwarf_Small lc_extension_size;
unsigned lc_version; /* 5 */
Dwarf_Small lc_address_size;
Dwarf_Small lc_segment_selector_size;
Dwarf_Unsigned lc_offset_entry_count;
/* offset in the section of the offset entries */
Dwarf_Unsigned lc_offsets_off_in_sect;
/* Do not free. Points into section memory */
Dwarf_Small * lc_offsets_array;
/* Offset in the .debug_loclists section of the
first loclist in the set of loclists for the
CU. */
Dwarf_Unsigned lc_first_loclist_offset;
Dwarf_Unsigned lc_past_last_loclist_offset;
/* pointer to 1st byte of loclist header*/
Dwarf_Small * lc_loclists_header;
/* pointer to first byte of the loclist data
for loclist involved. Do not free. */
Dwarf_Small *lc_startaddr;
/* pointer one past end of the loclist data. */
Dwarf_Small *lc_endaddr;
};
/* Contains info on an uninterpreted block of data,
the data is DWARF location expression operators. */
struct Dwarf_Block_c_s {
/* length of block bl_data points at */
Dwarf_Unsigned bl_len;
/* Uninterpreted data, location expressions,
DW_OP_reg31 etc */
Dwarf_Byte_Ptr bl_data;
/* DW_LKIND, see libdwarf.h.in */
Dwarf_Small bl_kind;
/* Section (not CU) offset which 'data' comes from. */
Dwarf_Unsigned bl_section_offset;
/* Section offset where the location description
itself starts. So a few bytes lower than
bl_section_offset */
Dwarf_Unsigned bl_locdesc_offset;
};
typedef struct Dwarf_Block_c_s Dwarf_Block_c;
/* Location record. Records up to 3 operand values.
For DWARF5 ops with a 1 byte size and then a block
of data of that size we the size in an operand
and follow that with the next operand as a
pointer to the block. The pointer is inserted
via cast, so an ugly hack.
This struct is opaque. Not visible to callers.
*/
typedef struct Dwarf_Loc_Expr_Op_s *Dwarf_Loc_Expr_Op;
struct Dwarf_Loc_Expr_Op_s {
Dwarf_Small lr_atom; /* Location operation */
Dwarf_Unsigned lr_raw1;
Dwarf_Unsigned lr_raw2;
Dwarf_Unsigned lr_raw3;
Dwarf_Unsigned lr_number; /* First operand */
/* Second operand.
For OP_bregx, OP_bit_piece, OP_[GNU_]const_type,
OP_[GNU_]deref_type, OP_[GNU_]entry_value,
OP_implicit_value,
OP_[GNU_]implicit_pointer, OP_[GNU_]regval_type,
OP_xderef_type, */
Dwarf_Unsigned lr_number2;
/* Third Operand.
For OP_[GNU_]const type, pointer to
block of length 'lr_number2'
FIXME: retrieve the value at the pointer,
store the value here instead*/
Dwarf_Unsigned lr_number3;
/* The number assigned. 0 to the number-of-ops-1 in
the expression we are expanding. */
Dwarf_Unsigned lr_opnumber;
Dwarf_Unsigned lr_offset; /* offset for OP_BRA etc */
Dwarf_Loc_Expr_Op lr_next; /* When a list is useful.*/
};
/* Used at construction to enable verifying we set
sensibly before returning to callers. */
#define DW_LLE_VALUE_BOGUS 254
/* Location description DWARF 2,3,4,5
Adds the DW_LLE value (new in DWARF5).
This struct is opaque. Not visible to callers. */
struct Dwarf_Locdesc_c_s {
Dwarf_Small ld_kind; /* DW_LKIND */
/* A DW_LLEX or DW_LLE value, real or synthesized */
Dwarf_Small ld_lle_value;
/* Failed means .debug_addr section needed but missing.
(possibly tied file needed) */
Dwarf_Bool ld_index_failed;
unsigned long ld_magic;
/* Beginning of active range. This is actually an offset
of an applicable base address, not a pc value. */
Dwarf_Addr ld_rawlow;
/* Translated to address */
Dwarf_Addr ld_lopc;
/* End of active range. This is actually an offset
of an applicable base address,
or a length, never a pc value. */
Dwarf_Addr ld_rawhigh;
/* Translated to address */
Dwarf_Addr ld_highpc;
/* Byte length of the entire record for this entry,
including any DW_OP entries */
Dwarf_Unsigned ld_entrylen;
/* For .debug_loclists, eases building record. */
Dwarf_Block_c ld_opsblock;
/* count of struct Dwarf_Loc_Expr_Op_s (expression operators)
in array. */
Dwarf_Half ld_cents;
/* pointer to array of expression operator structs */
Dwarf_Loc_Expr_Op ld_s;
/* Section (not CU) offset where loc-expr begins*/
Dwarf_Unsigned ld_section_offset;
/* Section (not CU) offset where location descr begins*/
Dwarf_Unsigned ld_locdesc_offset;
/* Pointer to our header (in which we are located). */
Dwarf_Loc_Head_c ld_loclist_head;
Dwarf_Locdesc_c ld_next; /*helps building the locdescs*/
};
int _dwarf_locdesc_c_constructor(Dwarf_Debug dbg, void *locd);
/* A 'header' to the loclist and the
location description(s) attached to an attribute.
This struct is opaque. The contents not visible to
callers. */
struct Dwarf_Loc_Head_c_s {
/* The array (1 or more entries) of
struct Loc_Desc_c_s
If 1 it may really be a locexpr */
Dwarf_Locdesc_c ll_locdesc;
/* Entry count of the ll_locdesc array. */
Dwarf_Unsigned ll_locdesc_count;
unsigned ll_attrnum;
unsigned ll_attrform;
unsigned ll_cuversion;
unsigned ll_address_size;
unsigned ll_offset_size;
/* The CU Context of this loclist or locexpr. */
Dwarf_CU_Context ll_context;
/* DW_LKIND* */
Dwarf_Small ll_kind;
Dwarf_Debug ll_dbg;
unsigned long ll_magic;
/* If ll_kind == DW_LKIND_loclists the following
pointer is non-null and index is the index
of the localcontext */
Dwarf_Unsigned ll_index;
Dwarf_Loclists_Context ll_localcontext;
/* rh_last and rh_first used during build-up.
Zero when array rh_loclists built. */
Dwarf_Locdesc_c ll_first;
Dwarf_Locdesc_c ll_last;
Dwarf_Unsigned ll_bytes_total;
unsigned ll_segment_selector_size;
/* DW_AT_loclists_base */
Dwarf_Bool ll_at_loclists_base_present;
Dwarf_Unsigned ll_at_loclists_base;
/* DW_AT_low_pc of CU or zero if none. */
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_Small * ll_llepointer;
Dwarf_Unsigned ll_llearea_offset;
Dwarf_Small * ll_end_data_area;
};
int _dwarf_fill_in_locdesc_op_c(Dwarf_Debug dbg,
Dwarf_Unsigned locdesc_index,
Dwarf_Loc_Head_c loc_head,
Dwarf_Block_c * loc_block,
Dwarf_Half address_size,
Dwarf_Half offset_size,
Dwarf_Small version_stamp,
Dwarf_Addr lowpc,
Dwarf_Addr highpc,
Dwarf_Half lle_op,
Dwarf_Error * error);
int _dwarf_loc_block_sanity_check(Dwarf_Debug dbg,
Dwarf_Block_c *loc_block,Dwarf_Error*error);
int _dwarf_internal_read_loclists_header(Dwarf_Debug dbg,
Dwarf_Unsigned contextnum,
Dwarf_Unsigned sectionlength,
Dwarf_Small *data,
Dwarf_Small *end_data,
Dwarf_Unsigned offset,
Dwarf_Loclists_Context buildhere,
Dwarf_Unsigned *next_offset,
Dwarf_Error *error);
void _dwarf_loclists_head_destructor(void *l);
int _dwarf_loclists_fill_in_lle_head(Dwarf_Debug dbg,
Dwarf_Attribute attr,
Dwarf_Loc_Head_c llhead,
Dwarf_Error *error);
int _dwarf_loclists_expression_build(Dwarf_Debug dbg,
Dwarf_Attribute attr,
Dwarf_Loc_Head_c* llhead,
Dwarf_Error *error);
int _dwarf_read_loc_expr_op(Dwarf_Debug dbg,
Dwarf_Block_c * loc_block,
/* Caller: Start numbering at 0. */
Dwarf_Signed opnumber,
/* 2 for DWARF 2 etc. */
Dwarf_Half version_stamp,
Dwarf_Half offset_size, /* 4 or 8 */
Dwarf_Half address_size, /* 2,4, 8 */
Dwarf_Signed startoffset_in, /* offset in block,
not section offset */
Dwarf_Small *section_end,
/* nextoffset_out so caller knows next entry startoffset */
Dwarf_Unsigned *nextoffset_out,
/* The values picked up. */
Dwarf_Loc_Expr_Op curr_loc,
Dwarf_Error * error);
void _dwarf_free_loclists_head_content(Dwarf_Loc_Head_c head);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* DWARF_LOC_H */

895
src/lib/libdwarf/dwarf_locationop_read.c vendored Normal file
View File

@ -0,0 +1,895 @@
/*
Copyright (C) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
Portions Copyright (C) 2007-2018 David Anderson. All Rights Reserved.
Portions Copyright (C) 2010-2012 SN Systems Ltd. All Rights Reserved.
This program is free software; you can redistribute it
and/or modify it under the terms of version 2.1 of the
GNU Lesser General Public License as published by the Free
Software Foundation.
This program is distributed in the hope that it would be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
Further, this software is distributed without any warranty
that it is free of the rightful claim of any third person
regarding infringement or the like. Any license provided
herein, whether implied or otherwise, applies only to this
software file. Patent licenses, if any, provided herein
do not apply to combinations of this program with other
software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write the
Free Software Foundation, Inc., 51 Franklin Street - Fifth
Floor, Boston MA 02110-1301, USA.
*/
#include <config.h>
#include <string.h> /* memcpy() memset() */
#if defined(_WIN32) && defined(HAVE_STDAFX_H)
#include "stdafx.h"
#endif /* HAVE_STDAFX_H */
#ifdef HAVE_STDINT_H
#include <stdint.h> /* uintptr_t */
#endif /* HAVE_STDINT_H */
#include "dwarf.h"
#include "libdwarf.h"
#include "libdwarf_private.h"
#include "dwarf_base_types.h"
#include "dwarf_opaque.h"
#include "dwarf_alloc.h"
#include "dwarf_error.h"
#include "dwarf_util.h"
#include "dwarf_loc.h"
#include "dwarf_string.h"
/* Richard Henderson, on DW_OP_GNU_encoded_addr:
The operand is an absolute address.
The first byte of the value is an encoding length:
0 2 4 or 8.
If zero it means the following is address-size.
The address then follows immediately for
that number of bytes. */
static int
read_encoded_addr(Dwarf_Small *loc_ptr,
Dwarf_Debug dbg,
Dwarf_Small *section_end_ptr,
Dwarf_Half address_size,
Dwarf_Unsigned * val_out,
int * len_out,
Dwarf_Error *error)
{
int len = 0;
Dwarf_Small op = *loc_ptr;
Dwarf_Unsigned operand = 0;
len++;
if (!op) {
op = address_size;
}
switch (op) {
case 1:
*val_out = *loc_ptr;
len++;
break;
case 2:
READ_UNALIGNED_CK(dbg, operand, Dwarf_Unsigned, loc_ptr, 2,
error,section_end_ptr);
*val_out = operand;
len +=2;
break;
case 4:
READ_UNALIGNED_CK(dbg, operand, Dwarf_Unsigned, loc_ptr, 4,
error,section_end_ptr);
*val_out = operand;
len +=4;
break;
case 8:
READ_UNALIGNED_CK(dbg, operand, Dwarf_Unsigned, loc_ptr, 8,
error,section_end_ptr);
*val_out = operand;
len +=8;
break;
default:
/* We do not know how much to read. */
_dwarf_error(dbg, error, DW_DLE_GNU_OPCODE_ERROR);
return DW_DLV_ERROR;
};
*len_out = len;
return DW_DLV_OK;
}
/* Return DW_DLV_NO_ENTRY when at the end of
the ops for this block (a single Dwarf_Loccesc
and multiple Dwarf_Locs will eventually result
from calling this till DW_DLV_NO_ENTRY).
All op reader code should call this to
extract operator fields. For any
DWARF version.
*/
int
_dwarf_read_loc_expr_op(Dwarf_Debug dbg,
Dwarf_Block_c * loc_block,
/* Caller: Start numbering at 0. */
Dwarf_Signed opnumber,
/* 2 for DWARF 2 etc. */
Dwarf_Half version_stamp,
Dwarf_Half offset_size, /* 4 or 8 */
Dwarf_Half address_size, /* 2,4, 8 */
Dwarf_Signed startoffset_in, /* offset in block,
not section offset */
Dwarf_Small *section_end,
/* nextoffset_out so caller knows next entry startoffset */
Dwarf_Unsigned *nextoffset_out,
/* The values picked up. */
Dwarf_Loc_Expr_Op curr_loc,
Dwarf_Error * error)
{
Dwarf_Small *loc_ptr = 0;
Dwarf_Unsigned loc_len = 0;
Dwarf_Unsigned offset = startoffset_in;
Dwarf_Unsigned operand1 = 0;
Dwarf_Unsigned operand2 = 0;
Dwarf_Unsigned operand3 = 0;
Dwarf_Small atom = 0;
Dwarf_Unsigned leb128_length = 0;
if (offset > loc_block->bl_len) {
_dwarf_error(dbg,error,DW_DLE_LOCEXPR_OFF_SECTION_END);
return DW_DLV_ERROR;
}
loc_len = loc_block->bl_len;
if (offset == loc_len) {
return DW_DLV_NO_ENTRY;
}
loc_ptr = (Dwarf_Small*)loc_block->bl_data + offset;
if ((loc_ptr+1) > section_end) {
_dwarf_error(dbg,error,DW_DLE_LOCEXPR_OFF_SECTION_END);
return DW_DLV_ERROR;
}
memset(curr_loc,0,sizeof(*curr_loc));
curr_loc->lr_opnumber = opnumber;
curr_loc->lr_offset = offset;
/* loc_ptr is ok to deref, see loc_ptr+1 test just above. */
atom = *(Dwarf_Small *) loc_ptr;
loc_ptr++;
offset++;
curr_loc->lr_atom = atom;
switch (atom) {
case DW_OP_reg0:
case DW_OP_reg1:
case DW_OP_reg2:
case DW_OP_reg3:
case DW_OP_reg4:
case DW_OP_reg5:
case DW_OP_reg6:
case DW_OP_reg7:
case DW_OP_reg8:
case DW_OP_reg9:
case DW_OP_reg10:
case DW_OP_reg11:
case DW_OP_reg12:
case DW_OP_reg13:
case DW_OP_reg14:
case DW_OP_reg15:
case DW_OP_reg16:
case DW_OP_reg17:
case DW_OP_reg18:
case DW_OP_reg19:
case DW_OP_reg20:
case DW_OP_reg21:
case DW_OP_reg22:
case DW_OP_reg23:
case DW_OP_reg24:
case DW_OP_reg25:
case DW_OP_reg26:
case DW_OP_reg27:
case DW_OP_reg28:
case DW_OP_reg29:
case DW_OP_reg30:
case DW_OP_reg31:
break;
case DW_OP_regx:
DECODE_LEB128_UWORD_LEN_CK(loc_ptr, operand1,leb128_length,
dbg,error,section_end);
offset = offset + leb128_length;
break;
case DW_OP_lit0:
case DW_OP_lit1:
case DW_OP_lit2:
case DW_OP_lit3:
case DW_OP_lit4:
case DW_OP_lit5:
case DW_OP_lit6:
case DW_OP_lit7:
case DW_OP_lit8:
case DW_OP_lit9:
case DW_OP_lit10:
case DW_OP_lit11:
case DW_OP_lit12:
case DW_OP_lit13:
case DW_OP_lit14:
case DW_OP_lit15:
case DW_OP_lit16:
case DW_OP_lit17:
case DW_OP_lit18:
case DW_OP_lit19:
case DW_OP_lit20:
case DW_OP_lit21:
case DW_OP_lit22:
case DW_OP_lit23:
case DW_OP_lit24:
case DW_OP_lit25:
case DW_OP_lit26:
case DW_OP_lit27:
case DW_OP_lit28:
case DW_OP_lit29:
case DW_OP_lit30:
case DW_OP_lit31:
operand1 = atom - DW_OP_lit0;
break;
case DW_OP_addr:
READ_UNALIGNED_CK(dbg, operand1, Dwarf_Unsigned,
loc_ptr, address_size,
error,section_end);
loc_ptr += address_size;
offset += address_size;
break;
case DW_OP_const1u:
if (loc_ptr >= section_end) {
_dwarf_error(dbg,error,DW_DLE_LOCEXPR_OFF_SECTION_END);
return DW_DLV_ERROR;
}
operand1 = *(Dwarf_Small *) loc_ptr;
loc_ptr = loc_ptr + 1;
if (loc_ptr > section_end) {
_dwarf_error(dbg,error,DW_DLE_LOCEXPR_OFF_SECTION_END);
return DW_DLV_ERROR;
}
offset = offset + 1;
break;
case DW_OP_const1s:
if (loc_ptr >= section_end) {
_dwarf_error(dbg,error,DW_DLE_LOCEXPR_OFF_SECTION_END);
return DW_DLV_ERROR;
}
operand1 = *(Dwarf_Sbyte *) loc_ptr;
SIGN_EXTEND(operand1,1);
loc_ptr = loc_ptr + 1;
if (loc_ptr > section_end) {
_dwarf_error(dbg,error,DW_DLE_LOCEXPR_OFF_SECTION_END);
return DW_DLV_ERROR;
}
offset = offset + 1;
break;
case DW_OP_const2u:
READ_UNALIGNED_CK(dbg, operand1, Dwarf_Unsigned, loc_ptr, 2,
error,section_end);
loc_ptr = loc_ptr + 2;
offset = offset + 2;
break;
case DW_OP_const2s:
READ_UNALIGNED_CK(dbg, operand1, Dwarf_Unsigned, loc_ptr, 2,
error, section_end);
SIGN_EXTEND(operand1,2);
loc_ptr = loc_ptr + 2;
offset = offset + 2;
break;
case DW_OP_const4u:
READ_UNALIGNED_CK(dbg, operand1, Dwarf_Unsigned, loc_ptr, 4,
error, section_end);
loc_ptr = loc_ptr + 4;
offset = offset + 4;
break;
case DW_OP_const4s:
READ_UNALIGNED_CK(dbg, operand1, Dwarf_Unsigned, loc_ptr, 4,
error, section_end);
SIGN_EXTEND(operand1,4);
loc_ptr = loc_ptr + 4;
offset = offset + 4;
break;
case DW_OP_const8u:
READ_UNALIGNED_CK(dbg, operand1, Dwarf_Unsigned, loc_ptr, 8,
error, section_end);
loc_ptr = loc_ptr + 8;
offset = offset + 8;
break;
case DW_OP_const8s:
READ_UNALIGNED_CK(dbg, operand1, Dwarf_Unsigned, loc_ptr, 8,
error, section_end);
loc_ptr = loc_ptr + 8;
offset = offset + 8;
break;
case DW_OP_constu:
DECODE_LEB128_UWORD_LEN_CK(loc_ptr, operand1,leb128_length,
dbg,error,section_end);
offset = offset + leb128_length;
break;
case DW_OP_consts:
DECODE_LEB128_SWORD_LEN_CK(loc_ptr, operand1,leb128_length,
dbg,error,section_end);
offset = offset + leb128_length;
break;
case DW_OP_fbreg:
DECODE_LEB128_SWORD_LEN_CK(loc_ptr, operand1,leb128_length,
dbg,error,section_end);
offset = offset + leb128_length;
break;
case DW_OP_breg0:
case DW_OP_breg1:
case DW_OP_breg2:
case DW_OP_breg3:
case DW_OP_breg4:
case DW_OP_breg5:
case DW_OP_breg6:
case DW_OP_breg7:
case DW_OP_breg8:
case DW_OP_breg9:
case DW_OP_breg10:
case DW_OP_breg11:
case DW_OP_breg12:
case DW_OP_breg13:
case DW_OP_breg14:
case DW_OP_breg15:
case DW_OP_breg16:
case DW_OP_breg17:
case DW_OP_breg18:
case DW_OP_breg19:
case DW_OP_breg20:
case DW_OP_breg21:
case DW_OP_breg22:
case DW_OP_breg23:
case DW_OP_breg24:
case DW_OP_breg25:
case DW_OP_breg26:
case DW_OP_breg27:
case DW_OP_breg28:
case DW_OP_breg29:
case DW_OP_breg30:
case DW_OP_breg31:
DECODE_LEB128_SWORD_LEN_CK(loc_ptr, operand1,leb128_length,
dbg,error,section_end);
offset = offset + leb128_length;
break;
case DW_OP_bregx:
/* uleb reg num followed by sleb offset */
DECODE_LEB128_UWORD_LEN_CK(loc_ptr, operand1,leb128_length,
dbg,error,section_end);
offset = offset + leb128_length;
DECODE_LEB128_SWORD_LEN_CK(loc_ptr, operand2,leb128_length,
dbg,error,section_end);
offset = offset + leb128_length;
break;
case DW_OP_dup:
case DW_OP_drop:
break;
case DW_OP_pick:
if (loc_ptr >= section_end) {
_dwarf_error(dbg,error,DW_DLE_LOCEXPR_OFF_SECTION_END);
return DW_DLV_ERROR;
}
operand1 = *(Dwarf_Small *) loc_ptr;
loc_ptr = loc_ptr + 1;
if (loc_ptr > section_end) {
_dwarf_error(dbg,error,DW_DLE_LOCEXPR_OFF_SECTION_END);
return DW_DLV_ERROR;
}
offset = offset + 1;
break;
case DW_OP_over:
case DW_OP_swap:
case DW_OP_rot:
case DW_OP_deref:
break;
case DW_OP_deref_size:
if (loc_ptr >= section_end) {
_dwarf_error(dbg,error,DW_DLE_LOCEXPR_OFF_SECTION_END);
return DW_DLV_ERROR;
}
operand1 = *(Dwarf_Small *) loc_ptr;
loc_ptr = loc_ptr + 1;
if (loc_ptr > section_end) {
_dwarf_error(dbg,error,DW_DLE_LOCEXPR_OFF_SECTION_END);
return DW_DLV_ERROR;
}
offset = offset + 1;
break;
case DW_OP_xderef:
break;
case DW_OP_xderef_type: /* DWARF5 */
if (loc_ptr >= section_end) {
_dwarf_error(dbg,error,DW_DLE_LOCEXPR_OFF_SECTION_END);
return DW_DLV_ERROR;
}
operand1 = *(Dwarf_Small *) loc_ptr;
loc_ptr = loc_ptr + 1;
if (loc_ptr > section_end) {
_dwarf_error(dbg,error,DW_DLE_LOCEXPR_OFF_SECTION_END);
return DW_DLV_ERROR;
}
offset = offset + 1;
DECODE_LEB128_UWORD_LEN_CK(loc_ptr, operand2,leb128_length,
dbg,error,section_end);
offset = offset + leb128_length;
break;
case DW_OP_xderef_size:
if (loc_ptr >= section_end) {
_dwarf_error(dbg,error,DW_DLE_LOCEXPR_OFF_SECTION_END);
return DW_DLV_ERROR;
}
operand1 = *(Dwarf_Small *) loc_ptr;
loc_ptr = loc_ptr + 1;
if (loc_ptr > section_end) {
_dwarf_error(dbg,error,DW_DLE_LOCEXPR_OFF_SECTION_END);
return DW_DLV_ERROR;
}
offset = offset + 1;
break;
case DW_OP_abs:
case DW_OP_and:
case DW_OP_div:
case DW_OP_minus:
case DW_OP_mod:
case DW_OP_mul:
case DW_OP_neg:
case DW_OP_not:
case DW_OP_or:
case DW_OP_plus:
break;
case DW_OP_plus_uconst:
DECODE_LEB128_UWORD_LEN_CK(loc_ptr, operand1,leb128_length,
dbg,error,section_end);
offset = offset + leb128_length;
break;
case DW_OP_shl:
case DW_OP_shr:
case DW_OP_shra:
case DW_OP_xor:
break;
case DW_OP_le:
case DW_OP_ge:
case DW_OP_eq:
case DW_OP_lt:
case DW_OP_gt:
case DW_OP_ne:
break;
case DW_OP_skip:
case DW_OP_bra:
READ_UNALIGNED_CK(dbg, operand1, Dwarf_Unsigned, loc_ptr, 2,
error,section_end);
SIGN_EXTEND(operand1,2);
loc_ptr = loc_ptr + 2;
offset = offset + 2;
break;
case DW_OP_piece:
DECODE_LEB128_UWORD_LEN_CK(loc_ptr, operand1,leb128_length,
dbg,error,section_end);
offset = offset + leb128_length;
break;
case DW_OP_nop:
break;
case DW_OP_push_object_address: /* DWARF3 */
break;
case DW_OP_call2: /* DWARF3 */
READ_UNALIGNED_CK(dbg, operand1, Dwarf_Unsigned, loc_ptr, 2,
error,section_end);
loc_ptr = loc_ptr + 2;
offset = offset + 2;
break;
case DW_OP_call4: /* DWARF3 */
READ_UNALIGNED_CK(dbg, operand1, Dwarf_Unsigned, loc_ptr, 4,
error,section_end);
loc_ptr = loc_ptr + 4;
offset = offset + 4;
break;
case DW_OP_call_ref: /* DWARF3 */
READ_UNALIGNED_CK(dbg, operand1, Dwarf_Unsigned, loc_ptr,
offset_size,
error,section_end);
loc_ptr = loc_ptr + offset_size;
offset = offset + offset_size;
break;
case DW_OP_form_tls_address: /* DWARF3f */
break;
case DW_OP_call_frame_cfa: /* DWARF3f */
break;
case DW_OP_bit_piece: /* DWARF3f */
/* uleb size in bits followed by uleb offset in bits */
DECODE_LEB128_UWORD_LEN_CK(loc_ptr, operand1,leb128_length,
dbg,error,section_end);
offset = offset + leb128_length;
DECODE_LEB128_UWORD_LEN_CK(loc_ptr, operand2,leb128_length,
dbg,error,section_end);
offset = offset + leb128_length;
break;
/* The operator means: push the currently computed
(by the operations encountered so far in this
expression) onto the expression stack as the offset
in thread-local-storage of the variable. */
case DW_OP_GNU_push_tls_address: /* 0xe0 */
/* Believed to have no operands. */
/* Unimplemented in gdb 7.5.1 ? */
break;
case DW_OP_deref_type: /* DWARF5 */
case DW_OP_GNU_deref_type: /* 0xf6 */
if (loc_ptr >= section_end) {
_dwarf_error(dbg,error,DW_DLE_LOCEXPR_OFF_SECTION_END);
return DW_DLV_ERROR;
}
operand1 = *(Dwarf_Small *) loc_ptr;
loc_ptr = loc_ptr + 1;
if (loc_ptr > section_end) {
_dwarf_error(dbg,error,DW_DLE_LOCEXPR_OFF_SECTION_END);
return DW_DLV_ERROR;
}
offset = offset + 1;
/* die offset (uleb128). */
DECODE_LEB128_UWORD_LEN_CK(loc_ptr, operand2,leb128_length,
dbg,error,section_end);
offset = offset + leb128_length;
break;
case DW_OP_implicit_value: /* DWARF4 0xa0 */
/* uleb length of value bytes followed by that
number of bytes of the value. */
DECODE_LEB128_UWORD_LEN_CK(loc_ptr, operand1,leb128_length,
dbg,error,section_end);
offset = offset + leb128_length;
/* Second operand is block of 'operand1' bytes of stuff. */
/* This using the second operand as a pointer
is quite ugly. */
/* This gets an ugly compiler warning. Sorry. */
operand2 = (Dwarf_Unsigned)(uintptr_t)loc_ptr;
offset = offset + operand1;
loc_ptr = loc_ptr + operand1;
if (loc_ptr > section_end) {
_dwarf_error(dbg,error,DW_DLE_LOCEXPR_OFF_SECTION_END);
return DW_DLV_ERROR;
}
break;
case DW_OP_stack_value: /* DWARF4 */
break;
case DW_OP_GNU_uninit: /* 0xf0 */
/* Unimplemented in gdb 7.5.1 */
/* Carolyn Tice: Follows a DW_OP_reg or DW_OP_regx
and marks the reg as being uninitialized. */
break;
case DW_OP_GNU_encoded_addr: { /* 0xf1 */
/* Richard Henderson: The operand is an absolute
address. The first byte of the value
is an encoding length: 0 2 4 or 8. If zero
it means the following is address-size.
The address then follows immediately for
that number of bytes. */
int length = 0;
int reares = 0;
if (loc_ptr >= section_end) {
_dwarf_error_string(dbg,error,
DW_DLE_LOCEXPR_OFF_SECTION_END,
"DW_DLE_LOCEXPR_OFF_SECTION_END "
"at DW_OP_GNU_encoded_addr. "
"Corrupt DWARF");
return DW_DLV_ERROR;
}
reares = read_encoded_addr(loc_ptr,dbg,
section_end,
address_size,
&operand1, &length,error);
if (reares != DW_DLV_OK) {
return reares;
}
loc_ptr += length;
if (loc_ptr > section_end) {
_dwarf_error(dbg,error,
DW_DLE_LOCEXPR_OFF_SECTION_END);
return DW_DLV_ERROR;
}
offset += length;
}
break;
case DW_OP_implicit_pointer: /* DWARF5 */
case DW_OP_GNU_implicit_pointer:{ /* 0xf2 */
/* Jakub Jelinek: The value is an optimized-out
pointer value. Represented as
an offset_size DIE offset
(a simple unsigned integer) in DWARF3,4
followed by a signed leb128 offset.
For DWARF2, it is actually pointer size
(address size).
The offset is global a section offset, not cu-relative.
Relocation to a different object file is up to
the user, per DWARF5 Page 41.
http://www.dwarfstd.org/ShowIssue.php?issue=100831.1 */
Dwarf_Small iplen = offset_size;
if (version_stamp == DW_CU_VERSION2 /* 2 */ ) {
iplen = address_size;
}
READ_UNALIGNED_CK(dbg, operand1, Dwarf_Unsigned, loc_ptr,
iplen,error,section_end);
loc_ptr = loc_ptr + iplen;
if (loc_ptr > section_end) {
_dwarf_error(dbg,error,DW_DLE_LOCEXPR_OFF_SECTION_END);
return DW_DLV_ERROR;
}
offset = offset + iplen;
DECODE_LEB128_SWORD_LEN_CK(loc_ptr, operand2,leb128_length,
dbg,error,section_end);
offset = offset + leb128_length;
}
break;
case DW_OP_entry_value: /* DWARF5 */
case DW_OP_GNU_entry_value: /* 0xf3 */
/* Jakub Jelinek: A register reused really soon,
but the value is unchanged. So to represent
that value we have a uleb128 size followed
by a DWARF expression block that size.
http://www.dwarfstd.org/ShowIssue.php?issue=100909.1 */
/* uleb length of value bytes followed by that
number of bytes of the value. */
DECODE_LEB128_UWORD_LEN_CK(loc_ptr, operand1,leb128_length,
dbg,error,section_end);
offset = offset + leb128_length;
/* Second operand is block of 'operand1' bytes of stuff. */
/* This using the second operand as a pointer
is quite ugly. */
/* This gets an ugly compiler warning. Sorry. */
operand2 = (Dwarf_Unsigned)(uintptr_t)loc_ptr;
offset = offset + operand1;
loc_ptr = loc_ptr + operand1;
if (loc_ptr > section_end) {
_dwarf_error(dbg,error,DW_DLE_LOCEXPR_OFF_SECTION_END);
return DW_DLV_ERROR;
}
break;
case DW_OP_const_type: /* DWARF5 */
case DW_OP_GNU_const_type: /* 0xf4 */
{
/* die offset as uleb. cu-relative */
DECODE_LEB128_UWORD_LEN_CK(loc_ptr, operand1,leb128_length,
dbg,error,section_end);
offset = offset + leb128_length;
if (loc_ptr >= section_end) {
_dwarf_error_string(dbg,error,
DW_DLE_LOCEXPR_OFF_SECTION_END,
"DW_DLE_LOCEXPR_OFF_SECTION_END: Error reading "
"DW_OP_const_type/DW_OP_GNU_const_type content");
return DW_DLV_ERROR;
}
/* Next byte is size of following data block. */
operand2 = *loc_ptr;
loc_ptr = loc_ptr + 1;
offset = offset + 1;
/* Operand 3 points to a value in the block of size
just gotten as operand2.
It must fit in a Dwarf_Unsigned.
Get the type from the die at operand1
(a CU relative offset). */
/* FIXME: We should do something very different than
what we do here! */
operand3 = (Dwarf_Unsigned)(uintptr_t)loc_ptr;
loc_ptr = loc_ptr + operand2;
if (loc_ptr > section_end) {
_dwarf_error(dbg,error,DW_DLE_LOCEXPR_OFF_SECTION_END);
return DW_DLV_ERROR;
}
offset = offset + operand2;
}
break;
case DW_OP_regval_type: /* DWARF5 */
case DW_OP_GNU_regval_type: /* 0xf5 */
/* reg num uleb*/
DECODE_LEB128_UWORD_LEN_CK(loc_ptr, operand1,leb128_length,
dbg,error,section_end);
offset = offset + leb128_length;
/* cu die off uleb*/
DECODE_LEB128_UWORD_LEN_CK(loc_ptr, operand2,leb128_length,
dbg,error,section_end);
offset = offset + leb128_length;
break;
case DW_OP_convert: /* DWARF5 */
case DW_OP_GNU_convert: /* 0xf7 */
case DW_OP_reinterpret: /* DWARF5 */
case DW_OP_GNU_reinterpret: /* 0xf9 */
/* die offset or zero */
DECODE_LEB128_UWORD_LEN_CK(loc_ptr, operand1,leb128_length,
dbg,error,section_end);
offset = offset + leb128_length;
break;
case DW_OP_GNU_parameter_ref : /* 0xfa */
/* 4 byte unsigned int */
READ_UNALIGNED_CK(dbg, operand1, Dwarf_Unsigned, loc_ptr, 4,
error,section_end);;
loc_ptr = loc_ptr + 4;
if (loc_ptr > section_end) {
_dwarf_error_string(dbg,error,
DW_DLE_LOCEXPR_OFF_SECTION_END,
"DW_DLE_LOCEXPR_OFF_SECTION_END: Error reading "
"DW_OP_GNU_parameter_ref.");
return DW_DLV_ERROR;
}
offset = offset + 4;
break;
case DW_OP_addrx : /* DWARF5 */
case DW_OP_GNU_addr_index : /* 0xfb DebugFission */
/* Index into .debug_addr. The value in .debug_addr
is an address. */
DECODE_LEB128_UWORD_LEN_CK(loc_ptr, operand1,leb128_length,
dbg,error,section_end);
offset = offset + leb128_length;
break;
case DW_OP_constx : /* DWARF5 */
case DW_OP_GNU_const_index : /* 0xfc DebugFission */
/* Index into .debug_addr. The value in .debug_addr
is a constant that fits in an address. */
DECODE_LEB128_UWORD_LEN_CK(loc_ptr, operand1,leb128_length,
dbg,error,section_end);
offset = offset + leb128_length;
break;
case DW_OP_GNU_variable_value: { /* 0xfd, 2017 By J Jelinek */
/* https://gcc.gnu.org/legacy-ml/gcc-patches/2017-02/
msg01499.html */
READ_UNALIGNED_CK(dbg, operand1, Dwarf_Unsigned, loc_ptr,
offset_size,error,section_end);
loc_ptr = loc_ptr + offset_size;
if (loc_ptr > section_end) {
_dwarf_error_string(dbg,error,
DW_DLE_LOCEXPR_OFF_SECTION_END,
"DW_DLE_LOCEXPR_OFF_SECTION_END: Error reading "
"DW_OP_GNU_variable_value.");
return DW_DLV_ERROR;
}
break;
}
/* See https://www.llvm.org/docs/
AMDGPUDwarfExtensionsForHeterogeneousDebugging.html */
case DW_OP_LLVM_form_aspace_address:
case DW_OP_LLVM_push_lane:
case DW_OP_LLVM_offset:
case DW_OP_LLVM_bit_offset:
case DW_OP_LLVM_undefined:
case DW_OP_LLVM_piece_end:
/* no operands on these */
break;
case DW_OP_LLVM_offset_uconst: /*uleb operand*/
case DW_OP_LLVM_call_frame_entry_reg: /*uleb operand*/
DECODE_LEB128_UWORD_LEN_CK(loc_ptr, operand1,leb128_length,
dbg,error,section_end);
offset = offset + leb128_length;
break;
case DW_OP_LLVM_aspace_implicit_pointer:
READ_UNALIGNED_CK(dbg, operand1, Dwarf_Unsigned, loc_ptr,
offset_size,error,section_end);
loc_ptr = loc_ptr + offset_size;
if (loc_ptr > section_end) {
_dwarf_error_string(dbg,error,
DW_DLE_LOCEXPR_OFF_SECTION_END,
"DW_DLE_LOCEXPR_OFF_SECTION_END: Error reading "
"DW_OP_LLVM_aspace_implicit_pointer.");
return DW_DLV_ERROR;
}
DECODE_LEB128_SWORD_LEN_CK(loc_ptr, operand2,leb128_length,
dbg,error,section_end);
offset = offset + leb128_length;
break;
case DW_OP_LLVM_aspace_bregx:
case DW_OP_LLVM_extend:
case DW_OP_LLVM_select_bit_piece:
DECODE_LEB128_UWORD_LEN_CK(loc_ptr, operand1,leb128_length,
dbg,error,section_end);
offset = offset + leb128_length;
DECODE_LEB128_UWORD_LEN_CK(loc_ptr, operand2,leb128_length,
dbg,error,section_end);
offset = offset + leb128_length;
break;
default: {
dwarfstring m;
const char *atomname = 0;
/* This can happen if the offset_size or address_size
in the OP stream was incorrect for the object file.*/
dwarfstring_constructor(&m);
dwarfstring_append_printf_u(&m,
"ERROR: DW_DLE_LOC_EXPR_BAD as DW_OP atom "
"0x%x ",atom);
dwarfstring_append(&m, "(");
dwarf_get_OP_name(atom,&atomname);
dwarfstring_append(&m,(char *)(atomname?
atomname:"<no name>"));
dwarfstring_append(&m, ")");
dwarfstring_append(&m,"is unknown.");
_dwarf_error_string(dbg, error, DW_DLE_LOC_EXPR_BAD,
dwarfstring_string(&m));
dwarfstring_destructor(&m);
return DW_DLV_ERROR;
}
}
if (loc_ptr > section_end) {
_dwarf_error(dbg,error,DW_DLE_LOCEXPR_OFF_SECTION_END);
return DW_DLV_ERROR;
}
/* If offset == loc_len this would be normal end-of-expression. */
if (offset > loc_len) {
/* We stepped past the end of the expression.
This has to be a compiler bug.
Operators missing their values cannot be detected
as such except at the end of an expression (like this).
The results would be wrong if returned.
*/
_dwarf_error(dbg, error, DW_DLE_LOC_BAD_TERMINATION);
return DW_DLV_ERROR;
}
curr_loc->lr_atom = atom;
curr_loc->lr_number = operand1;
curr_loc->lr_number2 = operand2;
/* lr_number 3 is a pointer to a value iff DW_OP_const or
DW_OP_GNU_const_type */
curr_loc->lr_number3 = operand3;
*nextoffset_out = offset;
return DW_DLV_OK;
}

1360
src/lib/libdwarf/dwarf_loclists.c vendored Normal file

File diff suppressed because it is too large Load Diff

1959
src/lib/libdwarf/dwarf_macho_loader.h vendored Normal file

File diff suppressed because it is too large Load Diff

1427
src/lib/libdwarf/dwarf_machoread.c vendored Normal file

File diff suppressed because it is too large Load Diff

158
src/lib/libdwarf/dwarf_machoread.h vendored Normal file
View File

@ -0,0 +1,158 @@
/*
Copyright (c) 2018-2023, David Anderson
All rights reserved.
Redistribution and use in source and binary forms, with
or without modification, are permitted provided that the
following conditions are met:
Redistributions of source code must retain the above
copyright notice, this list of conditions and the following
disclaimer.
Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef DWARF_MACHOREAD_H
#define DWARF_MACHOREAD_H
struct Dwarf_Universal_Arch_s;
struct Dwarf_Universal_Head_s {
Dwarf_Unsigned au_magic;
Dwarf_Unsigned au_count;
Dwarf_Unsigned au_filesize; /* physical file size */
struct Dwarf_Universal_Arch_s * au_arches;
};
struct Dwarf_Universal_Arch_s {
Dwarf_Unsigned au_cputype;
Dwarf_Unsigned au_cpusubtype;
Dwarf_Unsigned au_offset;
Dwarf_Unsigned au_size;
Dwarf_Unsigned au_align;
Dwarf_Unsigned au_reserved;
};
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
struct generic_macho_header {
Dwarf_Unsigned magic;
Dwarf_Unsigned cputype;
Dwarf_Unsigned cpusubtype;
Dwarf_Unsigned filetype;
Dwarf_Unsigned ncmds; /* number of load commands */
/* the size of all the load commands */
Dwarf_Unsigned sizeofcmds;
Dwarf_Unsigned flags;
Dwarf_Unsigned reserved;
};
struct generic_macho_command {
Dwarf_Unsigned cmd;
Dwarf_Unsigned cmdsize;
Dwarf_Unsigned offset_this_command;
};
struct generic_macho_segment_command {
Dwarf_Unsigned cmd;
Dwarf_Unsigned cmdsize;
char segname[24];
Dwarf_Unsigned vmaddr;
Dwarf_Unsigned vmsize;
Dwarf_Unsigned fileoff;
Dwarf_Unsigned filesize;
Dwarf_Unsigned maxprot;
Dwarf_Unsigned initprot;
Dwarf_Unsigned nsects;
Dwarf_Unsigned flags;
/* our index into mo_commands */
Dwarf_Unsigned macho_command_index;
Dwarf_Unsigned sectionsoffset;
};
struct generic_macho_section {
/* Larger than in file, room for NUL guaranteed */
char sectname[24];
char segname[24];
const char * dwarfsectname;
Dwarf_Unsigned addr;
Dwarf_Unsigned size;
Dwarf_Unsigned offset;
Dwarf_Unsigned align;
Dwarf_Unsigned reloff;
Dwarf_Unsigned nreloc;
Dwarf_Unsigned flags;
Dwarf_Unsigned reserved1;
Dwarf_Unsigned reserved2;
Dwarf_Unsigned reserved3;
Dwarf_Unsigned generic_segment_num;
Dwarf_Unsigned offset_of_sec_rec;
Dwarf_Small* loaded_data;
};
/* ident[0] == 'M' means this is a macho header.
ident[1] will be 1 indicating version 1.
Other bytes in ident not defined, should be zero. */
typedef struct dwarf_macho_filedata_s {
char mo_ident[8];
const char * mo_path; /* libdwarf must free.*/
int mo_fd;
int mo_destruct_close_fd; /*aka: lib owns fd */
Dwarf_Unsigned mo_filesize;
Dwarf_Unsigned mo_inner_offset; /* for universal inner */
Dwarf_Small mo_offsetsize; /* 32 or 64 section data */
Dwarf_Small mo_pointersize;
int mo_ftype;
Dwarf_Small mo_endian;
unsigned mo_uninumber; /* for universal binary */
unsigned mo_universal_count; /* for universal binary*/
/*Dwarf_Small mo_machine; */
void (*mo_copy_word) (void *, const void *, unsigned long);
/* Used to hold 32 and 64 header data */
struct generic_macho_header mo_header;
unsigned mo_command_count;
Dwarf_Unsigned mo_command_start_offset;
struct generic_macho_command *mo_commands;
Dwarf_Unsigned mo_offset_after_commands;
Dwarf_Unsigned mo_segment_count;
struct generic_macho_segment_command *mo_segment_commands;
Dwarf_Unsigned mo_dwarf_sectioncount;
struct generic_macho_section *mo_dwarf_sections;
} dwarf_macho_object_access_internals_t;
int _dwarf_load_macho_header(
dwarf_macho_object_access_internals_t * mfp,
int *errcode);
int _dwarf_load_macho_commands(
dwarf_macho_object_access_internals_t * mfp,
int *errcode);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* DWARF_MACHOREAD_H */

517
src/lib/libdwarf/dwarf_macro.c vendored Normal file
View File

@ -0,0 +1,517 @@
/*
Copyright (C) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
Portions Copyright (C) 2007-2020 David Anderson. All Rights Reserved.
Portions Copyright 2012 SN Systems Ltd. All rights reserved.
This program is free software; you can redistribute it
and/or modify it under the terms of version 2.1 of the
GNU Lesser General Public License as published by the Free
Software Foundation.
This program is distributed in the hope that it would be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
Further, this software is distributed without any warranty
that it is free of the rightful claim of any third person
regarding infringement or the like. Any license provided
herein, whether implied or otherwise, applies only to this
software file. Patent licenses, if any, provided herein
do not apply to combinations of this program with other
software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write the
Free Software Foundation, Inc., 51 Franklin Street - Fifth
Floor, Boston MA 02110-1301, USA.
*/
#include <config.h>
#include <limits.h> /* ULONG_MAX */
#include <string.h> /* memcpy() strlen() */
#if defined(_WIN32) && defined(HAVE_STDAFX_H)
#include "stdafx.h"
#endif /* HAVE_STDAFX_H */
#include "dwarf.h"
#include "libdwarf.h"
#include "libdwarf_private.h"
#include "dwarf_base_types.h"
#include "dwarf_safe_strcpy.h"
#include "dwarf_opaque.h"
#include "dwarf_alloc.h"
#include "dwarf_error.h"
#include "dwarf_util.h"
#include "dwarf_macro.h"
#define LEFTPAREN '('
#define RIGHTPAREN ')'
#define SPACE ' '
/* Given the dwarf macro string, return a pointer to
the value. Returns pointer to 0 byte at end of string
if no value found (meaning the value is the empty string).
Only understands well-formed .debug_macinfo
and .debug_macro strings.
*/
char *
dwarf_find_macro_value_start(char *str)
{
char *lcp;
int funclike = 0;
for (lcp = str; *lcp; ++lcp) {
switch (*lcp) {
case LEFTPAREN:
++funclike;
break;
case RIGHTPAREN:
--funclike;
break;
case SPACE:
/* We allow extraneous spaces inside macro parameter **
list, just in case... This is not really needed. */
if (!funclike) {
return lcp + 1;
}
break;
default:
break;
}
}
/* Never found value: returns pointer to the 0 byte at end of
string.
Or maybe the parentheses are unbalanced! Compiler error?
*/
return lcp;
}
/*
Try to keep fileindex correct in every Macro_Details
record by tracking file starts and ends.
Uses high water mark: space reused, not freed.
Presumption is that this makes sense for most uses.
STARTERMAX is set so that the array need not be expanded for
most files: it is the initial include file depth.
*/
struct macro_stack_s {
Dwarf_Signed *st_base;
long st_max;
long st_next_to_use;
int st_was_fault;
};
static void _dwarf_reset_index_macro_stack(struct macro_stack_s *ms);
static void
free_macro_stack(Dwarf_Debug dbg, struct macro_stack_s *ms)
{
dwarf_dealloc(dbg,ms->st_base,DW_DLA_STRING);
_dwarf_reset_index_macro_stack(ms);
}
#define STARTERMAX 10
static void
_dwarf_reset_index_macro_stack(struct macro_stack_s *ms)
{
ms->st_base = 0;
ms->st_max = 0;
ms->st_next_to_use = 0;
ms->st_was_fault = 0;
}
static int
_dwarf_macro_stack_push_index(Dwarf_Debug dbg, Dwarf_Signed indx,
struct macro_stack_s *ms)
{
if (!ms->st_max || ms->st_next_to_use >= ms->st_max) {
long new_size = ms->st_max;
Dwarf_Signed *newbase = 0;
if (!new_size) {
new_size = STARTERMAX;
}
new_size = new_size * 2;
newbase =
(Dwarf_Signed *)_dwarf_get_alloc(dbg, DW_DLA_STRING,
new_size * sizeof(Dwarf_Signed));
if (!newbase) {
/* just leave the old array in place */
ms->st_was_fault = 1;
return DW_DLV_ERROR;
}
if (ms->st_base) {
memcpy(newbase, ms->st_base,
ms->st_next_to_use * sizeof(*newbase));
dwarf_dealloc(dbg, ms->st_base, DW_DLA_STRING);
}
ms->st_base = newbase;
ms->st_max = new_size;
}
ms->st_base[ms->st_next_to_use] = indx;
++ms->st_next_to_use;
return DW_DLV_OK;
}
static Dwarf_Signed
_dwarf_macro_stack_pop_index(struct macro_stack_s *ms)
{
if (ms->st_was_fault) {
return -1;
}
if (ms->st_next_to_use > 0) {
ms->st_next_to_use--;
return (ms->st_base[ms->st_next_to_use]);
} else {
ms->st_was_fault = 1;
}
return -1;
}
/* Starting at macro_offset in .debug_macinfo,
if maximum_count is 0, treat as if it is infinite.
get macro data up thru
maximum_count entries or the end of a compilation
unit's entries (whichever comes first).
.debug_macinfo never appears in a .dwp Package File.
So offset adjustment for such is not needed.
*/
int
dwarf_get_macro_details(Dwarf_Debug dbg,
Dwarf_Off macro_offset,
Dwarf_Unsigned maximum_count,
Dwarf_Signed * entry_count,
Dwarf_Macro_Details ** details,
Dwarf_Error * error)
{
Dwarf_Small *macro_base = 0;
Dwarf_Small *macro_end = 0;
Dwarf_Small *pnext = 0;
Dwarf_Unsigned endloc = 0;
unsigned char uc = 0;
unsigned long depth = 0;
/* By section 6.3.2 Dwarf3 draft 8/9,
the base file should appear as
DW_MACINFO_start_file. See
http://gcc.gnu.org/ml/gcc-bugs/2005-02/msg03442.html
on "[Bug debug/20253] New: [3.4/4.0 regression]:
Macro debug info broken due to lexer change" for how
gcc is broken in some versions. We no longer use
depth as a stopping point, it's not needed as a
stopping point anyway. */
int res = 0;
/* count space used by strings */
unsigned long str_space = 0;
int done = 0;
unsigned long space_needed = 0;
unsigned long space_used = 0;
unsigned long string_offset = 0;
Dwarf_Small *return_data = 0;
Dwarf_Small *pdata = 0;
unsigned long final_count = 0;
Dwarf_Signed fileindex = -1;
Dwarf_Small *latest_str_loc = 0;
struct macro_stack_s msdata;
unsigned long count = 0;
unsigned long max_count = (unsigned long) maximum_count;
_dwarf_reset_index_macro_stack(&msdata);
if (!dbg || dbg->de_magic != DBG_IS_VALID) {
_dwarf_error_string(NULL, error, DW_DLE_DBG_NULL,
"DW_DLE_DBG_NULL: Either null or it contains"
"a stale Dwarf_Debug pointer");
free_macro_stack(dbg,&msdata);
return DW_DLV_ERROR;
}
res = _dwarf_load_section(dbg, &dbg->de_debug_macinfo,error);
if (res != DW_DLV_OK) {
free_macro_stack(dbg,&msdata);
return res;
}
if (!dbg->de_debug_abbrev.dss_size) {
free_macro_stack(dbg,&msdata);
return DW_DLV_NO_ENTRY;
}
macro_base = dbg->de_debug_macinfo.dss_data;
if (macro_base == NULL) {
free_macro_stack(dbg,&msdata);
return DW_DLV_NO_ENTRY;
}
if (macro_offset >= dbg->de_debug_macinfo.dss_size) {
free_macro_stack(dbg,&msdata);
return DW_DLV_NO_ENTRY;
}
macro_end = macro_base + dbg->de_debug_macinfo.dss_size;
/* FIXME debugfission is NOT handled here. */
pnext = macro_base + macro_offset;
if (maximum_count == 0) {
max_count = ULONG_MAX;
}
/* how many entries and how much space will they take? */
endloc = (pnext - macro_base);
if (endloc >= dbg->de_debug_macinfo.dss_size) {
if (endloc == dbg->de_debug_macinfo.dss_size) {
/* normal: found last entry */
free_macro_stack(dbg,&msdata);
return DW_DLV_NO_ENTRY;
}
_dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_LENGTH_BAD);
free_macro_stack(dbg,&msdata);
return DW_DLV_ERROR;
}
for (count = 0; !done && count < max_count; ++count) {
unsigned long slen = 0;
uc = *pnext;
++pnext; /* get past the type code */
switch (uc) {
case DW_MACINFO_define:
case DW_MACINFO_undef:
/* line, string */
case DW_MACINFO_vendor_ext:
/* number, string */
SKIP_LEB128_CK(pnext,dbg,error,
macro_end);
if (((Dwarf_Unsigned)(pnext - macro_base)) >=
dbg->de_debug_macinfo.dss_size) {
free_macro_stack(dbg,&msdata);
_dwarf_error(dbg, error,
DW_DLE_DEBUG_MACRO_INCONSISTENT);
return DW_DLV_ERROR;
}
res = _dwarf_check_string_valid(dbg,
macro_base,pnext,macro_end,
DW_DLE_MACINFO_STRING_BAD,error);
if (res != DW_DLV_OK) {
return res;
}
slen = strlen((char *) pnext) + 1;
pnext += slen;
if (((Dwarf_Unsigned)(pnext - macro_base)) >=
dbg->de_debug_macinfo.dss_size) {
free_macro_stack(dbg,&msdata);
_dwarf_error(dbg, error,
DW_DLE_DEBUG_MACRO_INCONSISTENT);
return DW_DLV_ERROR;
}
str_space += slen;
break;
case DW_MACINFO_start_file:
/* line, file index */
SKIP_LEB128_CK(pnext,dbg,error,
macro_end);
if (((Dwarf_Unsigned)(pnext - macro_base)) >=
dbg->de_debug_macinfo.dss_size) {
free_macro_stack(dbg,&msdata);
_dwarf_error(dbg, error,
DW_DLE_DEBUG_MACRO_INCONSISTENT);
return DW_DLV_ERROR;
}
SKIP_LEB128_CK(pnext,dbg,error,
macro_end);
if (((Dwarf_Unsigned)(pnext - macro_base)) >=
dbg->de_debug_macinfo.dss_size) {
free_macro_stack(dbg,&msdata);
_dwarf_error(dbg, error,
DW_DLE_DEBUG_MACRO_INCONSISTENT);
return DW_DLV_ERROR;
}
++depth;
break;
case DW_MACINFO_end_file:
if (--depth == 0) {
/* done = 1; no, do not stop here,
at least one gcc had
the wrong depth settings in the
gcc 3.4 timeframe. */
}
/* no string or number here */
break;
case 0:
/* end of cu's entries */
done = 1;
break;
default:
free_macro_stack(dbg,&msdata);
_dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INCONSISTENT);
return DW_DLV_ERROR;
/* bogus macinfo! */
}
endloc = (pnext - macro_base);
if (endloc == dbg->de_debug_macinfo.dss_size) {
done = 1;
} else if (endloc > dbg->de_debug_macinfo.dss_size) {
_dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_LENGTH_BAD);
free_macro_stack(dbg,&msdata);
return DW_DLV_ERROR;
}
}
/* ASSERT: The above loop will never let us get here
with count < 1. No need to test for a zero count.
We have 'count' array entries to allocate and
str_space bytes of string space to provide for. */
string_offset = count * sizeof(Dwarf_Macro_Details);
/* extra 2 not really needed */
space_needed = string_offset + str_space + 2;
space_used = 0;
return_data = pdata = (Dwarf_Small *)_dwarf_get_alloc(
dbg, DW_DLA_STRING, space_needed);
latest_str_loc = pdata + string_offset;
if (pdata == 0) {
free_macro_stack(dbg,&msdata);
_dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_MALLOC_SPACE);
return DW_DLV_ERROR;
}
pnext = macro_base + macro_offset;
done = 0;
/* A series ends with a type code of 0. */
for (final_count = 0; !done && final_count < count;
++final_count) {
unsigned long slen = 0;
Dwarf_Unsigned v1 = 0;
Dwarf_Macro_Details *pdmd = (Dwarf_Macro_Details *) (pdata +
(final_count * sizeof (Dwarf_Macro_Details)));
endloc = (pnext - macro_base);
if (endloc > dbg->de_debug_macinfo.dss_size) {
dwarf_dealloc(dbg,return_data,DW_DLA_STRING);
free_macro_stack(dbg,&msdata);
_dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_LENGTH_BAD);
return DW_DLV_ERROR;
}
uc = *pnext;
pdmd->dmd_offset = (pnext - macro_base);
pdmd->dmd_type = uc;
pdmd->dmd_fileindex = fileindex;
pdmd->dmd_lineno = 0;
pdmd->dmd_macro = 0;
++pnext; /* get past the type code */
switch (uc) {
case DW_MACINFO_define:
case DW_MACINFO_undef:
/* line, string */
case DW_MACINFO_vendor_ext:
/* number, string */
res = _dwarf_leb128_uword_wrapper(dbg,&pnext,
macro_end,&v1,error);
if (res != DW_DLV_OK) {
free_macro_stack(dbg,&msdata);
dwarf_dealloc(dbg, return_data, DW_DLA_STRING);
return res;
}
pdmd->dmd_lineno = v1;
if (((Dwarf_Unsigned)(pnext - macro_base)) >=
dbg->de_debug_macinfo.dss_size) {
free_macro_stack(dbg,&msdata);
dwarf_dealloc(dbg, return_data, DW_DLA_STRING);
_dwarf_error(dbg, error,
DW_DLE_DEBUG_MACRO_INCONSISTENT);
return DW_DLV_ERROR;
}
res = _dwarf_check_string_valid(dbg,
macro_base,pnext,macro_end,
DW_DLE_MACINFO_STRING_BAD,error);
if (res != DW_DLV_OK) {
dwarf_dealloc(dbg,return_data,DW_DLA_STRING);
return res;
}
slen = strlen((char *) pnext) + 1;
_dwarf_safe_strcpy((char *)latest_str_loc,
space_needed - space_used,
(const char *)pnext,slen-1);
pdmd->dmd_macro = (char *) latest_str_loc;
latest_str_loc += slen;
space_used +=slen;
pnext += slen;
if (((Dwarf_Unsigned)(pnext - macro_base)) >=
dbg->de_debug_macinfo.dss_size) {
free_macro_stack(dbg,&msdata);
dwarf_dealloc(dbg, return_data, DW_DLA_STRING);
_dwarf_error(dbg, error,
DW_DLE_DEBUG_MACRO_INCONSISTENT);
return DW_DLV_ERROR;
}
break;
case DW_MACINFO_start_file:
/* Line, file index */
res = _dwarf_leb128_uword_wrapper(dbg,&pnext,
macro_end,&v1,error);
if (res != DW_DLV_OK) {
free_macro_stack(dbg,&msdata);
dwarf_dealloc(dbg, return_data, DW_DLA_STRING);
return res;
}
pdmd->dmd_lineno = v1;
if (((Dwarf_Unsigned)(pnext - macro_base)) >=
dbg->de_debug_macinfo.dss_size) {
free_macro_stack(dbg,&msdata);
dwarf_dealloc(dbg, return_data, DW_DLA_STRING);
_dwarf_error(dbg, error,
DW_DLE_DEBUG_MACRO_INCONSISTENT);
return DW_DLV_ERROR;
}
res = _dwarf_leb128_uword_wrapper(dbg,&pnext,
macro_end,&v1,error);
if (res != DW_DLV_OK) {
free_macro_stack(dbg,&msdata);
dwarf_dealloc(dbg, return_data, DW_DLA_STRING);
return res;
}
pdmd->dmd_fileindex = v1;
(void) _dwarf_macro_stack_push_index(dbg, fileindex,
&msdata);
/* We ignore the error, we just let
fileindex ** be -1 when
we pop this one. */
fileindex = v1;
if (((Dwarf_Unsigned)(pnext - macro_base)) >=
dbg->de_debug_macinfo.dss_size) {
free_macro_stack(dbg,&msdata);
dwarf_dealloc(dbg, return_data, DW_DLA_STRING);
_dwarf_error(dbg, error,
DW_DLE_DEBUG_MACRO_INCONSISTENT);
return DW_DLV_ERROR;
}
break;
case DW_MACINFO_end_file:
fileindex = _dwarf_macro_stack_pop_index(&msdata);
break; /* no string or number here */
case 0:
/* Type code of 0 means the end of cu's entries. */
done = 1;
break;
default:
/* Bogus macinfo! */
dwarf_dealloc(dbg, return_data, DW_DLA_STRING);
free_macro_stack(dbg,&msdata);
_dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INCONSISTENT);
return DW_DLV_ERROR;
}
}
*entry_count = count;
*details = (Dwarf_Macro_Details *) return_data;
free_macro_stack(dbg,&msdata);
return DW_DLV_OK;
}

36
src/lib/libdwarf/dwarf_macro.h vendored Normal file
View File

@ -0,0 +1,36 @@
/*
Copyright (C) 2000, 2004 Silicon Graphics, Inc. All Rights Reserved.
This program is free software; you can redistribute it
and/or modify it under the terms of version 2.1 of the
GNU Lesser General Public License as published by the Free
Software Foundation.
This program is distributed in the hope that it would be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
Further, this software is distributed without any warranty
that it is free of the rightful claim of any third person
regarding infringement or the like. Any license provided
herein, whether implied or otherwise, applies only to this
software file. Patent licenses, if any, provided herein
do not apply to combinations of this program with other
software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write the
Free Software Foundation, Inc., 51 Franklin Street - Fifth
Floor, Boston MA 02110-1301, USA.
*/
/*
dwarf_macro.h
$Revision: 1.4 $ $Date: 2004/10/28 22:19:14 $
*/

1666
src/lib/libdwarf/dwarf_macro5.c vendored Normal file

File diff suppressed because it is too large Load Diff

151
src/lib/libdwarf/dwarf_macro5.h vendored Normal file
View File

@ -0,0 +1,151 @@
/*
Copyright (C) 2015-2023 David Anderson. All Rights Reserved.
This program is free software; you can redistribute it
and/or modify it under the terms of version 2.1 of the
GNU Lesser General Public License as published by the Free
Software Foundation.
This program is distributed in the hope that it would be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
Further, this software is distributed without any warranty
that it is free of the rightful claim of any third person
regarding infringement or the like. Any license provided
herein, whether implied or otherwise, applies only to this
software file. Patent licenses, if any, provided herein
do not apply to combinations of this program with other
software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write the
Free Software Foundation, Inc., 51 Franklin Street - Fifth
Floor, Boston MA 02110-1301, USA.
*/
/*
dwarf_macro5.h
For the DWARF5 .debug_macro section
(also appears as an extension to DWARF4)
*/
struct Dwarf_Macro_Forms_s {
/* Code means DW_MACRO_define etc. */
Dwarf_Small mf_code;
/* How many entries in mf_formbytes array. */
Dwarf_Small mf_formcount;
/* Never free these, these are in the object file memory */
const Dwarf_Small * mf_formbytes;
};
struct Dwarf_Macro_OperationsList_s {
unsigned mol_count;
struct Dwarf_Macro_Forms_s * mol_data;
};
struct Dwarf_Macro_Operator_s {
/* mo_opcode == mo_form->mf_code unless it is
the final 0 byte in which case all 3 values
are zero */
Dwarf_Small mo_opcode;
struct Dwarf_Macro_Forms_s * mo_form;
/* Points at the first byte of the data, meaning
it points one-past the macro operation code byte. */
Dwarf_Small * mo_data;
};
#define MACRO_OFFSET_SIZE_FLAG 1
#define MACRO_LINE_OFFSET_FLAG 2
#define MACRO_OP_TABLE_FLAG 4
#define DW_MACRO_VERSION4 4 /* GNU Extension for DWARF 4 */
#define DW_MACRO_VERSION5 5 /* DWARF 5 */
/* Could be reordered to be most space efficient.
That might be a little harder to read. Hmm. */
struct Dwarf_Macro_Context_s {
Dwarf_Unsigned mc_sentinel;
Dwarf_Half mc_version_number;
/* Section_offset in .debug_macro of macro header */
Dwarf_Unsigned mc_section_offset;
Dwarf_Unsigned mc_section_size;
/* Total length of the macro data for this
macro unit.
Calculated, not part of header. */
Dwarf_Unsigned mc_total_length;
Dwarf_Half mc_macro_header_length;
Dwarf_Small mc_flags;
/* If DW_MACRO_start_file is in the operators of this
table then the mc_debug_line_offset must be present from
the header. */
Dwarf_Unsigned mc_debug_line_offset;
/* the following three set from the bits in mc_flags */
/* If 1, offsets 64 bits */
Dwarf_Bool mc_offset_size_flag;
/* if 1, debug_line offset is present. */
Dwarf_Bool mc_debug_line_offset_flag;
/* 4 or 8, depending on mc_offset_size_flag */
Dwarf_Small mc_offset_size;
/* If one the operands/opcodes (mc_opcode_forms) table is present
in the header. If not we use a default table.
Even when there are operands in the header
the standardops may or may not be
defined in the header. */
Dwarf_Bool mc_operands_table_flag;
/* Count of the Dwarf_Macro_Forms_s structs pointed to by
mc_opcode_forms. These from the header. */
Dwarf_Small mc_opcode_count;
struct Dwarf_Macro_Forms_s *mc_opcode_forms;
/* mc_ops must be free()d, but pointers inside
mc_ops are to static or section data so must not
be freed. */
Dwarf_Unsigned mc_macro_ops_count;
Dwarf_Unsigned mc_ops_data_length;
struct Dwarf_Macro_Operator_s *mc_ops;
Dwarf_Small * mc_macro_header;
Dwarf_Small * mc_macro_ops;
/* These are malloc space, not _dwarf_get_alloc()
so the DW_DLA_MACRO_CONTEXT dealloc will
free them. */
char ** mc_srcfiles;
Dwarf_Signed mc_srcfiles_count;
/* These are from CU DIE attribute names.
They may be NULL or point at data in
a dwarf section. Do not free().
This attempts to make up for the lack of a
base file name
in DWARF2,3,4 line tables.
*/
const char * mc_at_comp_dir;
const char * mc_at_name;
/* The following is malloc,so macro_context_s destructor
needs to free it. */
const char * mc_file_path;
Dwarf_Debug mc_dbg;
Dwarf_CU_Context mc_cu_context;
};
int _dwarf_macro_constructor(Dwarf_Debug dbg, void *m);
void _dwarf_macro_destructor(void *m);

74
src/lib/libdwarf/dwarf_memcpy_swap.c vendored Normal file
View File

@ -0,0 +1,74 @@
/*
Copyright (C) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
Portions Copyright (C) 2007-2020 David Anderson. All Rights Reserved.
Portions Copyright 2012 SN Systems Ltd. All rights reserved.
Portions Copyright 2020 Google All rights reserved.
This program is free software; you can redistribute it
and/or modify it under the terms of version 2.1 of the
GNU Lesser General Public License as published by the Free
Software Foundation.
This program is distributed in the hope that it would be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
Further, this software is distributed without any warranty
that it is free of the rightful claim of any third person
regarding infringement or the like. Any license provided
herein, whether implied or otherwise, applies only to this
software file. Patent licenses, if any, provided herein
do not apply to combinations of this program with other
software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write the
Free Software Foundation, Inc., 51 Franklin Street - Fifth
Floor, Boston MA 02110-1301, USA.
*/
#include <config.h>
#include <stddef.h> /* size_t */
#include <string.h> /* memcpy() */
#include "dwarf_memcpy_swap.h"
/*
A byte-swapping version of memcpy
for cross-endian use.
Only 2,4,8 should be lengths passed in.
*/
void
_dwarf_memcpy_noswap_bytes(void *s1,
const void *s2,
unsigned long len)
{
memcpy(s1,s2,(size_t)len);
return;
}
void
_dwarf_memcpy_swap_bytes(void *s1,
const void *s2,
unsigned long len)
{
unsigned char *targ = (unsigned char *) s1;
const unsigned char *src = (const unsigned char *) s2;
unsigned long i = 0;
unsigned long n = (long)(len-1);
if (len > 8) {
/* Really we should not be here!
Not writing an integer, we think, so
best to not swap bytes! */
memcpy(s1,s2,(size_t)len);
return;
}
for ( ; i < len; ++i,--n) {
targ[n] = src[i];
}
return;
}

46
src/lib/libdwarf/dwarf_memcpy_swap.h vendored Normal file
View File

@ -0,0 +1,46 @@
/*
Copyright (C) 2018-2023 David Anderson. All Rights Reserved.
This program is free software; you can redistribute it
and/or modify it under the terms of version 2.1 of the
GNU Lesser General Public License as published by the
Free Software Foundation.
This program is distributed in the hope that it would
be useful, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Further, this software is distributed without any warranty
that it is free of the rightful claim of any third person
regarding infringement or the like. Any license provided
herein, whether implied or otherwise, applies only to
this software file. Patent licenses, if any, provided
herein do not apply to combinations of this program with
other software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write
the Free Software Foundation, Inc., 51 Franklin Street -
Fifth Floor, Boston MA 02110-1301, USA.
*/
#ifndef MEMCPY_SWAP_H
#define MEMCPY_SWAP_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void _dwarf_memcpy_swap_bytes(void *s1, const void *s2,
unsigned long len);
/* It was once inconvenient to use memcpy directly as it
uses size_t and that requires <stddef.h>,
although stddef.h is a part of C90, so..ok. */
void _dwarf_memcpy_noswap_bytes(void *s1,
const void *s2, unsigned long len);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* MEMCPY_SWAP_H */

3834
src/lib/libdwarf/dwarf_names.c vendored Normal file

File diff suppressed because it is too large Load Diff

1019
src/lib/libdwarf/dwarf_object_detector.c vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,91 @@
/* Copyright (c) 2018-2023, David Anderson
All rights reserved.
Redistribution and use in source and binary forms, with
or without modification, are permitted provided that the
following conditions are met:
Redistributions of source code must retain the above
copyright notice, this list of conditions and the following
disclaimer.
Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef DWARF_OBJECT_DETECTOR_H
#define DWARF_OBJECT_DETECTOR_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* Declares the interface function.
outpath is a place you provide, of a length outpath_len
you consider reasonable,
where the final path used is recorded.
outpath_len must be larger than strlen(path);
This matters as for mach-o if the path is a directory
name the function will look in the standard macho-place
for the object file (useful for dSYM) and return the
constructed path in oupath.
returns DW_DLV_OK, DW_DLV_ERROR, or DW_DLV_NO_ENTRY */
#ifndef DW_FTYPE_UNKNOWN
#define DW_FTYPE_UNKNOWN 0
#define DW_FTYPE_ELF 1
#define DW_FTYPE_MACH_O 2
#define DW_FTYPE_PE 3
#define DW_FTYPE_ARCHIVE 4 /* unix archive */
#endif /* DW_FTYPE_UNKNOWN */
/* offsetsize refers to the object-file-format.
Elf 32 or macho-32 or PE 32, for example.
Not to DWARF offset sizes. */
/* Path means look(first) for an dynsym object
of the same name per MacOS standards,
making the outpath space needed is more than
that in path.
Copies the actual path into outpath, (an error
if the length in outpath_len is less than needed
for the object found).
If DW_DLV_NO_ENTRY or DW_DLV_ERROR returned
the argument values other than path
must be considered to be in an unknown state. */
/* The errcode is a small integer distinct from libdwarf
and simply printing the integer (returned through
*errcode when the function returns DW_DLV_ERROR)
will hopefully suffice for most purposes. */
/* Added September 2023 for Mach-O universal binaries */
int _dwarf_object_detector_fd_a(int dw_fd,
unsigned int *dw_ftype,
unsigned int *dw_endian,
unsigned int *dw_offsetsize,
Dwarf_Unsigned dw_offset_base,
Dwarf_Unsigned *dw_filesize,
int *dw_errcode);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* DWARF_OBJECT_DETECTOR_H */

View File

@ -0,0 +1,96 @@
/*
Copyright (c) 2018, David Anderson
All rights reserved.
Redistribution and use in source and binary forms, with
or without modification, are permitted provided that the
following conditions are met:
Redistributions of source code must retain the above
copyright notice, this list of conditions and the following
disclaimer.
Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef _WIN32
#define _CRT_SECURE_NO_WARNINGS
#endif /* _WIN32 */
#include <config.h>
#include <stddef.h> /* size_t */
#include <stdio.h> /* SEEK_END SEEK_SET */
#ifdef _WIN32
#ifdef HAVE_STDAFX_H
#include "stdafx.h"
#endif /* HAVE_STDAFX_H */
#include <io.h> /* off_t */
#elif defined HAVE_UNISTD_H
#include <unistd.h> /* off_t */
#endif /* _WIN32*/
#include "dwarf.h"
#include "libdwarf.h"
#include "libdwarf_private.h"
#include "dwarf_base_types.h"
#include "dwarf_opaque.h"
#include "dwarf_safe_strcpy.h"
#include "dwarf_object_read_common.h"
/* Neither off_t nor ssize_t is in C90.
However, both are in Posix:
IEEE Std 1003.1-1990, aka
ISO/IEC 9954-1:1990. */
int
_dwarf_object_read_random(int fd, char *buf, off_t loc,
size_t size, off_t filesize, int *errc)
{
off_t scode = 0;
ssize_t rcode = 0;
off_t endpoint = 0;
if (loc >= filesize) {
/* Seek can seek off the end. Lets not allow that.
The object is corrupt. */
*errc = DW_DLE_SEEK_OFF_END;
return DW_DLV_ERROR;
}
endpoint = loc+size;
if (endpoint > filesize) {
/* Let us -not- try to read past end of object.
The object is corrupt. */
*errc = DW_DLE_READ_OFF_END;
return DW_DLV_ERROR;
}
scode = lseek(fd,loc,SEEK_SET);
if (scode == (off_t)-1) {
*errc = DW_DLE_SEEK_ERROR;
return DW_DLV_ERROR;
}
rcode = read(fd,buf,size);
if (rcode == -1 ||
(size_t)rcode != size) {
*errc = DW_DLE_READ_ERROR;
return DW_DLV_ERROR;
}
return DW_DLV_OK;
}

View File

@ -0,0 +1,47 @@
/*
Copyright (c) 2018-2023, David Anderson
All rights reserved.
Redistribution and use in source and binary forms, with
or without modification, are permitted provided that the
following conditions are met:
Redistributions of source code must retain the above
copyright notice, this list of conditions and the following
disclaimer.
Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef DWARF_OBJECT_READ_COMMON_H
#define DWARF_OBJECT_READ_COMMON_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
int _dwarf_object_read_random(int fd,char *buf,off_t loc,
size_t size,off_t filesize,int *errc);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* DWARF_OBJECT_READ_COMMON_H */

1108
src/lib/libdwarf/dwarf_opaque.h vendored Normal file

File diff suppressed because it is too large Load Diff

257
src/lib/libdwarf/dwarf_pe_descr.h vendored Normal file
View File

@ -0,0 +1,257 @@
#ifndef DWARF_PE_DESCR_H
#define DWARF_PE_DESCR_H
/*
Copyright (c) 2018-2023, David Anderson All rights reserved.
Redistribution and use in source and binary forms, with
or without modification, are permitted provided that the
following conditions are met:
Redistributions of source code must retain the above
copyright notice, this list of conditions and the following
disclaimer.
Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define IMAGE_DOS_SIGNATURE_dw 0x5a4d /* le on disk 'M' 'Z' */
#define IMAGE_DOS_REVSIGNATURE_dw 0x4d5a /* be on disk */
#define IMAGE_NT_SIGNATURE_dw 0x00004550
#ifndef TYP
#define TYP(n,l) char (n)[(l)]
#endif /* TYPE */
/* Data types
see https://msdn.microsoft.com/en-us/library/\
windows/desktop/aa383751(v=vs.85).aspx */
/*#define FIELD_OFFSET(type,field) \
((LONG)(LONG_PTR)&(((type *)0)->field))*/
#define IMAGE_SIZEOF_SYMBOL 18
struct dos_header_dw {
TYP(dh_mz,2);
TYP(dh_dos_data,58);
TYP(dh_image_offset,4);
};
/* IMAGE_FILE_HEADER_dw
see https://msdn.microsoft.com/fr-fr/library/\
windows/desktop/ms680313(v=vs.85).aspx */
typedef struct
{
TYP(Machine,2);
TYP(NumberOfSections,2);
TYP(TimeDateStamp,4);
TYP(PointerToSymbolTable,4);
TYP(NumberOfSymbols,4);
TYP(SizeOfOptionalHeader,2);
TYP(Characteristics,2);
} IMAGE_FILE_HEADER_dw;
/* IMAGE_DATA_DIRECTORY_dw
see https://msdn.microsoft.com/fr-fr/library/\
windows/desktop/ms680305(v=vs.85).aspx */
typedef struct
{
TYP(VirtualAddress,4);
TYP(Size,4);
} IMAGE_DATA_DIRECTORY_dw;
/* IMAGE_OPTIONAL_HEADER
see https://msdn.microsoft.com/en-us/library/\
windows/desktop/ms680339(v=vs.85).aspx */
#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
typedef struct
{
TYP(Magic,2);
unsigned char MajorLinkerVersion;
unsigned char MinorLinkerVersion;
TYP(SizeOfCode,4);
TYP(SizeOfInitializedData,4);
TYP(SizeOfUninitializedData,4);
TYP(AddressOfEntryPoint,4);
TYP(BaseOfCode,4);
TYP(BaseOfData,4);
TYP(ImageBase,4);
TYP(SectionAlignment,4);
TYP(FileAlignment,4);
TYP(MajorOperatingSystemVersion,2);
TYP(MinorOperatingSystemVersion,2);
TYP(MajorImageVersion,2);
TYP(MinorImageVersion,2);
TYP(MajorSubsystemVersion,2);
TYP(MinorSubsystemVersion,2);
TYP(Win32VersionValue,4);
TYP(SizeOfImage,4);
TYP(SizeOfHeaders,4);
TYP(CheckSum,4);
TYP(Subsystem,2);
TYP(DllCharacteristics,2);
TYP(SizeOfStackReserve,4);
TYP(SizeOfStackCommit,4);
TYP(SizeOfHeapReserve,4);
TYP(SizeOfHeapCommit,4);
TYP(LoaderFlags,4);
TYP(NumberOfRvaAndSizes,4);
IMAGE_DATA_DIRECTORY_dw
DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32_dw;
typedef struct
{
TYP(Magic,2);
unsigned char MajorLinkerVersion;
unsigned char MinorLinkerVersion;
TYP(SizeOfCode,4);
TYP(SizeOfInitializedData,4);
TYP(SizeOfUninitializedData,4);
TYP(AddressOfEntryPoint,4);
TYP(BaseOfCode,4);
TYP(ImageBase,8);
TYP(SectionAlignment,4);
TYP(FileAlignment,4);
TYP(MajorOperatingSystemVersion,2);
TYP(MinorOperatingSystemVersion,2);
TYP(MajorImageVersion,2);
TYP(MinorImageVersion,2);
TYP(MajorSubsystemVersion,2);
TYP(MinorSubsystemVersion,2);
TYP(Win32VersionValue,4);
TYP(SizeOfImage,4);
TYP(SizeOfHeaders,4);
TYP(CheckSum,4);
TYP(Subsystem,2);
TYP(DllCharacteristics,2);
TYP(SizeOfStackReserve,8);
TYP(SizeOfStackCommit,8);
TYP(SizeOfHeapReserve,8);
TYP(SizeOfHeapCommit,8);
TYP(LoaderFlags,4);
TYP(NumberOfRvaAndSizes,4);
IMAGE_DATA_DIRECTORY_dw
DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER64_dw;
/* IMAGE_NT_HEADERS
see https://msdn.microsoft.com/fr-fr/library/\
windows/desktop/ms680336(v=vs.85).aspx */
#define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b
#define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
#define IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x107
typedef struct
{
TYP(Signature,4);
IMAGE_FILE_HEADER_dw FileHeader;
IMAGE_OPTIONAL_HEADER64_dw OptionalHeader;
} IMAGE_NT_HEADERS64_dw, *PIMAGE_NT_HEADERS64_dw;
typedef struct
{
TYP(Signature,4);
IMAGE_FILE_HEADER_dw FileHeader;
IMAGE_OPTIONAL_HEADER32_dw OptionalHeader;
} IMAGE_NT_HEADERS32_dw, *PIMAGE_NT_HEADERS32_dw;
/* IMAGE_SECTION_HEADER_dw
see:
https://msdn.microsoft.com/en-us/library/windows/\
desktop/ms680341(v=vs.85).aspx
and, for details on VirtualSize and SizeOfRawData:
https://docs.microsoft.com/en-us/windows/desktop/\
api/winnt/ns-winnt-_image_section_header */
#define IMAGE_SIZEOF_SHORT_NAME 8
typedef struct
{
char Name[IMAGE_SIZEOF_SHORT_NAME];
union {
TYP(PhysicalAddress,4);
TYP(VirtualSize,4);
} Misc;
TYP(VirtualAddress,4);
TYP(SizeOfRawData,4);
TYP(PointerToRawData,4);
TYP(PointerToRelocations,4);
TYP(PointerToLinenumbers,4);
TYP(NumberOfRelocations,2);
TYP(NumberOfLinenumbers,2);
TYP(Characteristics,4);
} IMAGE_SECTION_HEADER_dw, *PIMAGE_SECTION_HEADER_dw;
#define IMAGE_SCN_SCALE_INDEX 0x00000001
#define IMAGE_SCN_TYPE_NO_PAD 0x00000008
#define IMAGE_SCN_CNT_CODE 0x00000020
#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040
#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080
#define IMAGE_SCN_LNK_OTHER 0x00000100
#define IMAGE_SCN_LNK_INFO 0x00000200
#define IMAGE_SCN_LNK_REMOVE 0x00000800
#define IMAGE_SCN_LNK_COMDAT 0x00001000
#define IMAGE_SCN_NO_DEFER_SPEC_EXC 0x00004000
#define IMAGE_SCN_MEM_FARDATA 0x00008000
#define IMAGE_SCN_MEM_PURGEABLE 0x00020000
#define IMAGE_SCN_MEM_LOCKED 0x00040000
#define IMAGE_SCN_MEM_PRELOAD 0x00080000
#define IMAGE_SCN_ALIGN_1BYTES 0x00100000
#define IMAGE_SCN_ALIGN_2BYTES 0x00200000
#define IMAGE_SCN_ALIGN_4BYTES 0x00300000
#define IMAGE_SCN_ALIGN_8BYTES 0x00400000
#define IMAGE_SCN_ALIGN_16BYTES 0x00500000
#define IMAGE_SCN_ALIGN_32BYTES 0x00600000
#define IMAGE_SCN_ALIGN_64BYTES 0x00700000
#define IMAGE_SCN_ALIGN_128BYTES 0x00800000
#define IMAGE_SCN_ALIGN_256BYTES 0x00900000
#define IMAGE_SCN_ALIGN_512BYTES 0x00A00000
#define IMAGE_SCN_ALIGN_1024BYTES 0x00B00000
#define IMAGE_SCN_ALIGN_2048BYTES 0x00C00000
#define IMAGE_SCN_ALIGN_4096BYTES 0x00D00000
#define IMAGE_SCN_ALIGN_8192BYTES 0x00E00000
#define IMAGE_SCN_ALIGN_MASK 0x00F00000
#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000
#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000
#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000
#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000
#define IMAGE_SCN_MEM_SHARED 0x10000000
#define IMAGE_SCN_MEM_EXECUTE 0x20000000
#define IMAGE_SCN_MEM_READ 0x40000000
#define IMAGE_SCN_MEM_WRITE 0x80000000
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* DWARF_PE_DESCR_H */

1005
src/lib/libdwarf/dwarf_peread.c vendored Normal file

File diff suppressed because it is too large Load Diff

155
src/lib/libdwarf/dwarf_peread.h vendored Normal file
View File

@ -0,0 +1,155 @@
#ifndef PE_GENERIC_H
#define PE_GENERIC_H
/*
Copyright (c) 2018-2023, David Anderson All rights reserved.
Redistribution and use in source and binary forms, with
or without modification, are permitted provided that the
following conditions are met:
Redistributions of source code must retain the above
copyright notice, this list of conditions and the following
disclaimer.
Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
struct dwarf_pe_generic_file_header
{
Dwarf_Unsigned Machine;
Dwarf_Unsigned NumberOfSections;
Dwarf_Unsigned TimeDateStamp;
Dwarf_Unsigned PointerToSymbolTable;
Dwarf_Unsigned NumberOfSymbols;
Dwarf_Unsigned SizeOfOptionalHeader; /* in object file */
Dwarf_Unsigned Characteristics;
};
struct dwarf_pe_generic_data_directory
{
Dwarf_Unsigned VirtualAddress;
Dwarf_Unsigned Size;
};
#define DWARF_PE_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES 16
struct dwarf_pe_generic_optional_header
{
Dwarf_Unsigned Magic;
unsigned char MajorLinkerVersion;
unsigned char MinorLinkerVersion;
Dwarf_Unsigned SizeOfCode;
Dwarf_Unsigned SizeOfInitializedData;
Dwarf_Unsigned SizeOfUninitializedData;
Dwarf_Unsigned AddressOfEntryPoint;
Dwarf_Unsigned BaseOfCode;
Dwarf_Unsigned BaseOfData;
Dwarf_Unsigned ImageBase;
Dwarf_Unsigned SectionAlignment;
Dwarf_Unsigned FileAlignment;
Dwarf_Unsigned MajorOperatingSystemVersion;
Dwarf_Unsigned MinorOperatingSystemVersion;
Dwarf_Unsigned MajorImageVersion;
Dwarf_Unsigned MinorImageVersion;
Dwarf_Unsigned MajorSubsystemVersion;
Dwarf_Unsigned MinorSubsystemVersion;
Dwarf_Unsigned Win32VersionValue;
Dwarf_Unsigned SizeOfImage; /* size in object file */
Dwarf_Unsigned SizeOfHeaders; /* size in object file */
Dwarf_Unsigned CheckSum;
Dwarf_Unsigned Subsystem;
Dwarf_Unsigned DllCharacteristics;
Dwarf_Unsigned SizeOfStackReserve;
Dwarf_Unsigned SizeOfStackCommit;
Dwarf_Unsigned SizeOfHeapReserve;
Dwarf_Unsigned SizeOfHeapCommit;
Dwarf_Unsigned LoaderFlags;
Dwarf_Unsigned NumberOfRvaAndSizes;
Dwarf_Unsigned SizeOfDataDirEntry; /* size in object file */
struct dwarf_pe_generic_data_directory
DataDirectory[DWARF_PE_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES];
};
struct dwarf_pe_generic_image_section_header
{
char *name; /* Name must be freed */
char *dwarfsectname; /* Name must be freed */
Dwarf_Unsigned SecHeaderOffset; /* offset in object file */
/* union { */
/* Dwarf_Unsigned PhysicalAddress; */
Dwarf_Unsigned VirtualSize;
/* } Misc; */
Dwarf_Unsigned VirtualAddress;
Dwarf_Unsigned SizeOfRawData; /* size we need */
Dwarf_Unsigned PointerToRawData;
Dwarf_Unsigned PointerToRelocations;
Dwarf_Unsigned PointerToLinenumbers;
Dwarf_Unsigned NumberOfRelocations;
Dwarf_Unsigned NumberOfLinenumbers;
Dwarf_Unsigned Characteristics;
Dwarf_Small * loaded_data; /* must be freed. */
};
#define DWARF_PE_IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b
#define DWARF_PE_IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
#define DWARF_PE_IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x107
/* ident[0] == 'P' means this is a PE header.
ident[1] will be 1 indicating version 1.
Other bytes in ident not defined, should be zero. */
typedef struct pe_filedata_s {
char pe_ident[8];
const char * pe_path; /* must free.*/
int pe_fd;
int pe_destruct_close_fd; /*aka: lib owns fd */
int pe_is_64bit;
Dwarf_Unsigned pe_filesize;
Dwarf_Small pe_offsetsize; /* 32 or 64 section data */
Dwarf_Small pe_pointersize;
int pe_ftype;
unsigned pe_endian;
/*Dwarf_Small pe_machine; */
void (*pe_copy_word) (void *, const void *, unsigned long);
Dwarf_Unsigned pe_nt_header_offset;
Dwarf_Unsigned pe_optional_header_offset;
Dwarf_Unsigned pe_optional_header_size;
Dwarf_Unsigned pe_symbol_table_offset;
Dwarf_Unsigned pe_string_table_offset;
Dwarf_Unsigned pe_section_table_offset;
Dwarf_Unsigned pe_signature;
struct dwarf_pe_generic_file_header pe_FileHeader;
struct dwarf_pe_generic_optional_header pe_OptionalHeader;
Dwarf_Unsigned pe_section_count;
struct dwarf_pe_generic_image_section_header *pe_sectionptr;
Dwarf_Unsigned pe_string_table_size;
char *pe_string_table;
} dwarf_pe_object_access_internals_t;
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* PE_GENERIC_H */

1030
src/lib/libdwarf/dwarf_print_lines.c vendored Normal file

File diff suppressed because it is too large Load Diff

2129
src/lib/libdwarf/dwarf_query.c vendored Normal file

File diff suppressed because it is too large Load Diff

356
src/lib/libdwarf/dwarf_ranges.c vendored Normal file
View File

@ -0,0 +1,356 @@
/*
Copyright (C) 2008-2020 David Anderson. All Rights Reserved.
Portions Copyright 2012 SN Systems Ltd. All rights reserved.
This program is free software; you can redistribute it
and/or modify it under the terms of version 2.1 of the
GNU Lesser General Public License as published by the Free
Software Foundation.
This program is distributed in the hope that it would be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
Further, this software is distributed without any warranty
that it is free of the rightful claim of any third person
regarding infringement or the like. Any license provided
herein, whether implied or otherwise, applies only to this
software file. Patent licenses, if any, provided herein
do not apply to combinations of this program with other
software, or any other product whatsoever.
You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write the
Free Software Foundation, Inc., 51 Franklin Street - Fifth
Floor, Boston MA 02110-1301, USA.
*/
#include <config.h>
#include <stdlib.h> /* calloc() free() */
#if defined(_WIN32) && defined(HAVE_STDAFX_H)
#include "stdafx.h"
#endif /* HAVE_STDAFX_H */
#include "dwarf.h"
#include "libdwarf.h"
#include "libdwarf_private.h"
#include "dwarf_base_types.h"
#include "dwarf_opaque.h"
#include "dwarf_alloc.h"
#include "dwarf_error.h"
#include "dwarf_util.h"
#include "dwarf_string.h"
struct ranges_entry {
struct ranges_entry *next;
Dwarf_Ranges cur;
};
static void
free_allocated_ranges( struct ranges_entry *base)
{
struct ranges_entry *cur = 0;
struct ranges_entry *next = 0;
for ( cur = base ; cur ; cur = next ) {
next = cur->next;
free(cur);
}
}
/* We encapsulate the macro use so we can
free local malloc resources that would otherwise
leak. See the call points below. */
static int
read_unaligned_addr_check(Dwarf_Debug dbg,
Dwarf_Addr *addr_out,
Dwarf_Small *rangeptr,
unsigned address_size,
Dwarf_Error *error,
Dwarf_Small *section_end)
{
Dwarf_Addr a = 0;
READ_UNALIGNED_CK(dbg,a,
Dwarf_Addr, rangeptr,
address_size,
error,section_end);
*addr_out = a;
return DW_DLV_OK;
}
/* As of DWARF5 the ranges section each range list set has
a range-list-table header. See "7.28 Range List Table"
in the DWARF5 standard.
For DWARF5 the offset should be the offset of
the range-list-table-header for that range list.
For DWARF3 and DWARF4 the offset has to be that
of a range list.
*/
/* Ranges and pc values can be in a split dwarf object.
In that case the appropriate values need to be
incremented by data from the executable in
the compilation unit with the same dwo_id.
We return an error which is on the incoming dbg, not
the possibly-tied-dbg localdbg.
If incoming die is NULL there is no context, so do not look
for a tied file, and address_size is the size
of the overall object, not the address_size of the context. */
#define MAX_ADDR ((address_size == 8)? \
0xffffffffffffffffULL:0xffffffff)
/* New 10 September 2020 to accommodate the
GNU extension of DWARF4 split-dwarf.
The actual_offset field is set by the function
to the actual final offset of the ranges
in the separate tied (a.out) file. */
int dwarf_get_ranges_b(Dwarf_Debug dbg,
Dwarf_Off rangesoffset,
Dwarf_Die die,
Dwarf_Off *actual_offset,
Dwarf_Ranges ** rangesbuf,
Dwarf_Signed * listlen,
Dwarf_Unsigned * bytecount,
Dwarf_Error * error)
{
Dwarf_Small *rangeptr = 0;
Dwarf_Small *beginrangeptr = 0;
Dwarf_Small *section_end = 0;
unsigned entry_count = 0;
struct ranges_entry *base = 0;
struct ranges_entry *last = 0;
struct ranges_entry *curre = 0;
Dwarf_Ranges * ranges_data_out = 0;
unsigned copyindex = 0;
Dwarf_Half address_size = 0;
int res = DW_DLV_ERROR;
Dwarf_Unsigned ranges_base = 0;
Dwarf_Debug localdbg = dbg;
Dwarf_Error localerror = 0;
Dwarf_Half die_version = 3; /* default for dwarf_get_ranges() */
Dwarf_Half offset_size= 4;
Dwarf_CU_Context cucontext = 0;
Dwarf_Bool rangeslocal = TRUE;
(void)offset_size;
if (!dbg) {
_dwarf_error(NULL, error, DW_DLE_DBG_NULL);
return DW_DLV_ERROR;
}
address_size = localdbg->de_pointer_size; /* default */
if (die) {
/* 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.
Add err code if error. Version comes from the
cu context, not the DIE itself. */
res = dwarf_get_version_of_die(die,&die_version,
&offset_size);
if (res == DW_DLV_ERROR) {
_dwarf_error(dbg, error, DW_DLE_DIE_NO_CU_CONTEXT);
return DW_DLV_ERROR;
}
if (!die->di_cu_context) {
_dwarf_error(dbg, error, DW_DLE_DIE_NO_CU_CONTEXT);
return DW_DLV_ERROR;
}
cucontext = die->di_cu_context;
/* The DW4 ranges base was never used in GNU
but did get emitted, the note says, but
the note is probably obsolete (so, now wrong).
http://llvm.1065342.n5.nabble.com/DebugInfo\
-DW-AT-GNU-ranges-base-in-non-fission-\
td64194.html
*/
/* ranges_base was merged from tied context. */
ranges_base = cucontext->cc_ranges_base;
address_size = cucontext->cc_address_size;
}
localdbg = dbg;
res = _dwarf_load_section(localdbg, &localdbg->de_debug_ranges,
error);
if (res == DW_DLV_ERROR) {
return res;
}
if (res == DW_DLV_NO_ENTRY) {
/* data is in a.out, not dwp */
localdbg = dbg->de_tied_data.td_tied_object;
if (!localdbg) {
return DW_DLV_NO_ENTRY;
}
res = _dwarf_load_section(localdbg,
&localdbg->de_debug_ranges, &localerror);
if (res == DW_DLV_ERROR) {
_dwarf_error_mv_s_to_t(localdbg,&localerror,dbg,error);
return res;
}
if (res == DW_DLV_NO_ENTRY) {
return res;
}
rangeslocal = FALSE;
}
/* Be safe in case adding rangesoffset and rangebase
overflows. */
if (rangesoffset >= localdbg->de_debug_ranges.dss_size) {
/* Documented behavior in libdwarf2.1.mm */
return DW_DLV_NO_ENTRY;
}
if (ranges_base >= localdbg->de_debug_ranges.dss_size) {
dwarfstring m;
dwarfstring_constructor(&m);
dwarfstring_append_printf_u(&m,
"DW_DLE_DEBUG_RANGES_OFFSET_BAD: "
" ranges base is 0x%lx ",ranges_base);
dwarfstring_append_printf_u(&m,
" and section size is 0x%lx.",
localdbg->de_debug_ranges.dss_size);
_dwarf_error_string(dbg, error,
DW_DLE_DEBUG_RANGES_OFFSET_BAD,
dwarfstring_string(&m));
dwarfstring_destructor(&m);
return DW_DLV_ERROR;
}
if (!rangeslocal && ((rangesoffset +ranges_base) >=
localdbg->de_debug_ranges.dss_size)) {
dwarfstring m;
dwarfstring_constructor(&m);
dwarfstring_append_printf_u(&m,
"DW_DLE_DEBUG_RANGES_OFFSET_BAD: "
" ranges base+offset is 0x%lx ",
ranges_base+rangesoffset);
dwarfstring_append_printf_u(&m,
" and section size is 0x%lx.",
localdbg->de_debug_ranges.dss_size);
_dwarf_error_string(dbg, error,
DW_DLE_DEBUG_RANGES_OFFSET_BAD,
dwarfstring_string(&m));
dwarfstring_destructor(&m);
return DW_DLV_ERROR;
}
/* tied address_size must match the dwo address_size */
section_end = localdbg->de_debug_ranges.dss_data +
localdbg->de_debug_ranges.dss_size;
rangeptr = localdbg->de_debug_ranges.dss_data;
if (!rangeslocal) {
/* printing ranges where range source is dwp,
here we just assume present. */
rangesoffset += ranges_base;
}
rangeptr += rangesoffset;
beginrangeptr = rangeptr;
for (;;) {
struct ranges_entry * re = 0;
if (rangeptr == section_end) {
break;
}
if (rangeptr > section_end) {
dwarfstring m;
free_allocated_ranges(base);
dwarfstring_constructor(&m);
dwarfstring_append(&m,
"DW_DLE_DEBUG_RANGES_OFFSET_BAD: "
" ranges pointer ran off the end "
"of the section");
_dwarf_error_string(dbg, error,
DW_DLE_DEBUG_RANGES_OFFSET_BAD,
dwarfstring_string(&m));
dwarfstring_destructor(&m);
return DW_DLV_ERROR;
}
re = calloc(sizeof(struct ranges_entry),1);
if (!re) {
free_allocated_ranges(base);
_dwarf_error(dbg, error, DW_DLE_DEBUG_RANGES_OUT_OF_MEM);
return DW_DLV_ERROR;
}
if ((rangeptr + (2*address_size)) > section_end) {
free(re);
free_allocated_ranges(base);
_dwarf_error_string(dbg, error,
DW_DLE_DEBUG_RANGES_OFFSET_BAD,
"DW_DLE_DEBUG_RANGES_OFFSET_BAD: "
" Not at the end of the ranges section "
" but there is not enough room in the section "
" for the next ranges entry");
return DW_DLV_ERROR;
}
entry_count++;
res = read_unaligned_addr_check(localdbg,&re->cur.dwr_addr1,
rangeptr, address_size,error,section_end);
if (res != DW_DLV_OK) {
free(re);
free_allocated_ranges(base);
return res;
}
rangeptr += address_size;
res = read_unaligned_addr_check(localdbg,&re->cur.dwr_addr2,
rangeptr, address_size,error,section_end);
if (res != DW_DLV_OK) {
free(re);
free_allocated_ranges(base);
return res;
}
rangeptr += address_size;
if (!base) {
base = re;
last = re;
} else {
last->next = re;
last = re;
}
if (re->cur.dwr_addr1 == 0 && re->cur.dwr_addr2 == 0) {
re->cur.dwr_type = DW_RANGES_END;
break;
} else if (re->cur.dwr_addr1 == MAX_ADDR) {
re->cur.dwr_type = DW_RANGES_ADDRESS_SELECTION;
} else {
re->cur.dwr_type = DW_RANGES_ENTRY;
}
}
/* We return ranges on dbg, so use that to allocate. */
ranges_data_out = (Dwarf_Ranges *)
_dwarf_get_alloc(dbg,DW_DLA_RANGES,entry_count);
if (!ranges_data_out) {
/* Error, apply to original, not local dbg. */
free_allocated_ranges(base);
_dwarf_error(dbg, error, DW_DLE_DEBUG_RANGES_OUT_OF_MEM);
return DW_DLV_ERROR;
}
curre = base;
*rangesbuf = ranges_data_out;
*listlen = entry_count;
for (copyindex = 0; curre && (copyindex < entry_count);
++copyindex,++ranges_data_out,curre=curre->next) {
*ranges_data_out = curre->cur;
}
/* ASSERT: curre == NULL */
free_allocated_ranges(base);
base = 0;
/* Callers will often not care about the bytes used. */
if (actual_offset) {
*actual_offset = rangesoffset;
}
if (bytecount) {
*bytecount = rangeptr - beginrangeptr;
}
return DW_DLV_OK;
}
void
dwarf_dealloc_ranges(Dwarf_Debug dbg, Dwarf_Ranges * rangesbuf,
Dwarf_Signed rangecount)
{
(void)rangecount;
dwarf_dealloc(dbg,rangesbuf, DW_DLA_RANGES);
}

72
src/lib/libdwarf/dwarf_reading.h vendored Normal file
View File

@ -0,0 +1,72 @@
/*
Copyright (c) 2018-2023, David Anderson
All rights reserved.
Redistribution and use in source and binary forms, with
or without modification, are permitted provided that the
following conditions are met:
Redistributions of source code must retain the above
copyright notice, this list of conditions and the following
disclaimer.
Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef DWARF_READING_H
#define DWARF_READING_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#ifndef DW_DLV_OK
/* DW_DLV_OK must match libdwarf.h */
/* DW_DLV_NO_ENTRY must match libdwarf.h */
#define DW_DLV_OK 0
#define DW_DLV_NO_ENTRY -1
#define DW_DLV_ERROR 1
#endif /* DW_DLV_OK */
#define ALIGN4 4
#define ALIGN8 8
#define PREFIX "\t"
#define LUFMT "%lu"
#define UFMT "%u"
#define DFMT "%d"
#define XFMT "0x%x"
/* even if already seen, values must match, so no #ifdef needed. */
#define DW_DLV_NO_ENTRY -1
#define DW_DLV_OK 0
#define DW_DLV_ERROR 1
#define P printf
#define F fflush(stdout)
#define RRMOA(f,buf,loc,siz,fsiz,errc) _dwarf_object_read_random(\
(f),(char *)(buf),(loc),(siz),(fsiz),(errc));
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* DWARF_READING_H */

1541
src/lib/libdwarf/dwarf_rnglists.c vendored Normal file

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More