mirror of
https://github.com/jeremy-rifkin/libdwarf-lite.git
synced 2024-12-25 23:20:48 +08:00
Create mirror of 6216e185863f41d6f19ab850caabfff7326020d7
This commit is contained in:
commit
c78e984f3a
3
.gitattributes
vendored
Normal file
3
.gitattributes
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
src/** linguist-vendored
|
||||
cmake/** linguist-vendored
|
||||
CMakeLists.txt linguist-vendored
|
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
build
|
||||
libdwarf-code
|
366
CMakeLists.txt
vendored
Normal file
366
CMakeLists.txt
vendored
Normal 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
25
COPYING
Normal 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
2
README.md
Normal 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
63
cmake/FindZSTD.cmake
vendored
Normal 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
120
cmake/config.h.cmake
vendored
Normal 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
5
notes.txt
Normal 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
239
patches/CMakeLists.patch
Normal 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
24
pull.sh
Normal 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
167
src/lib/libdwarf/CMakeLists.txt
vendored
Normal 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
32
src/lib/libdwarf/COPYING
vendored
Normal 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
504
src/lib/libdwarf/LGPL.txt
vendored
Normal 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
42
src/lib/libdwarf/LIBDWARFCOPYRIGHT
vendored
Normal 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
162
src/lib/libdwarf/Makefile.am
vendored
Normal 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
238
src/lib/libdwarf/README
vendored
Normal 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
|
3
src/lib/libdwarf/cmake/libdwarf-config.cmake
vendored
Normal file
3
src/lib/libdwarf/cmake/libdwarf-config.cmake
vendored
Normal 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
44
src/lib/libdwarf/dw-linetableheader.txt
vendored
Normal 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
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
451
src/lib/libdwarf/dwarf_abbrev.c
vendored
Normal 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
82
src/lib/libdwarf/dwarf_abbrev.h
vendored
Normal 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
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
58
src/lib/libdwarf/dwarf_alloc.h
vendored
Normal 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
738
src/lib/libdwarf/dwarf_arange.c
vendored
Normal 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
60
src/lib/libdwarf/dwarf_arange.h
vendored
Normal 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
137
src/lib/libdwarf/dwarf_base_types.h
vendored
Normal 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
137
src/lib/libdwarf/dwarf_crc.c
vendored
Normal 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
153
src/lib/libdwarf/dwarf_crc32.c
vendored
Normal 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
206
src/lib/libdwarf/dwarf_debug_sup.c
vendored
Normal 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
342
src/lib/libdwarf/dwarf_debugaddr.c
vendored
Normal 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
75
src/lib/libdwarf/dwarf_debugaddr.h
vendored
Normal 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
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
60
src/lib/libdwarf/dwarf_debuglink.h
vendored
Normal 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
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
121
src/lib/libdwarf/dwarf_debugnames.h
vendored
Normal 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
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
78
src/lib/libdwarf/dwarf_die_deliv.h
vendored
Normal 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
331
src/lib/libdwarf/dwarf_dsc.c
vendored
Normal 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
59
src/lib/libdwarf/dwarf_dsc.h
vendored
Normal 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
47
src/lib/libdwarf/dwarf_elf_access.h
vendored
Normal 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
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
2230
src/lib/libdwarf/dwarf_elf_load_headers.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
368
src/lib/libdwarf/dwarf_elf_rel_detector.c
vendored
Normal file
368
src/lib/libdwarf/dwarf_elf_rel_detector.c
vendored
Normal 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;
|
||||
}
|
48
src/lib/libdwarf/dwarf_elf_rel_detector.h
vendored
Normal file
48
src/lib/libdwarf/dwarf_elf_rel_detector.h
vendored
Normal 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
809
src/lib/libdwarf/dwarf_elfread.c
vendored
Normal 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
288
src/lib/libdwarf/dwarf_elfread.h
vendored
Normal 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
213
src/lib/libdwarf/dwarf_elfstructs.h
vendored
Normal 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
691
src/lib/libdwarf/dwarf_errmsg_list.h
vendored
Normal 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
230
src/lib/libdwarf/dwarf_error.c
vendored
Normal 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
71
src/lib/libdwarf/dwarf_error.h
vendored
Normal 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 */
|
195
src/lib/libdwarf/dwarf_fill_in_attr_form.c
vendored
Normal file
195
src/lib/libdwarf/dwarf_fill_in_attr_form.c
vendored
Normal 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
222
src/lib/libdwarf/dwarf_find_sigref.c
vendored
Normal 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
367
src/lib/libdwarf/dwarf_fission_to_cu.c
vendored
Normal 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
2263
src/lib/libdwarf/dwarf_form.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
110
src/lib/libdwarf/dwarf_form_class_names.c
vendored
Normal file
110
src/lib/libdwarf/dwarf_form_class_names.c
vendored
Normal 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
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
509
src/lib/libdwarf/dwarf_frame.h
vendored
Normal 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
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
850
src/lib/libdwarf/dwarf_gdbindex.c
vendored
Normal 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
84
src/lib/libdwarf/dwarf_gdbindex.h
vendored
Normal 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
557
src/lib/libdwarf/dwarf_generic_init.c
vendored
Normal 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
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
135
src/lib/libdwarf/dwarf_global.h
vendored
Normal 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
791
src/lib/libdwarf/dwarf_gnu_index.c
vendored
Normal 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
95
src/lib/libdwarf/dwarf_gnu_index.h
vendored
Normal 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
396
src/lib/libdwarf/dwarf_groups.c
vendored
Normal 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
240
src/lib/libdwarf/dwarf_harmless.c
vendored
Normal 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
31
src/lib/libdwarf/dwarf_harmless.h
vendored
Normal 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
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
430
src/lib/libdwarf/dwarf_leb.c
vendored
Normal 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
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
491
src/lib/libdwarf/dwarf_line.h
vendored
Normal 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);
|
2857
src/lib/libdwarf/dwarf_line_table_reader_common.h
vendored
Normal file
2857
src/lib/libdwarf/dwarf_line_table_reader_common.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1929
src/lib/libdwarf/dwarf_loc.c
vendored
Normal file
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
339
src/lib/libdwarf/dwarf_loc.h
vendored
Normal 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
895
src/lib/libdwarf/dwarf_locationop_read.c
vendored
Normal 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
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
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
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
158
src/lib/libdwarf/dwarf_machoread.h
vendored
Normal 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
517
src/lib/libdwarf/dwarf_macro.c
vendored
Normal 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
36
src/lib/libdwarf/dwarf_macro.h
vendored
Normal 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
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
151
src/lib/libdwarf/dwarf_macro5.h
vendored
Normal 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
74
src/lib/libdwarf/dwarf_memcpy_swap.c
vendored
Normal 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
46
src/lib/libdwarf/dwarf_memcpy_swap.h
vendored
Normal 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
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
1019
src/lib/libdwarf/dwarf_object_detector.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
91
src/lib/libdwarf/dwarf_object_detector.h
vendored
Normal file
91
src/lib/libdwarf/dwarf_object_detector.h
vendored
Normal 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 */
|
96
src/lib/libdwarf/dwarf_object_read_common.c
vendored
Normal file
96
src/lib/libdwarf/dwarf_object_read_common.c
vendored
Normal 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;
|
||||
}
|
47
src/lib/libdwarf/dwarf_object_read_common.h
vendored
Normal file
47
src/lib/libdwarf/dwarf_object_read_common.h
vendored
Normal 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
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
257
src/lib/libdwarf/dwarf_pe_descr.h
vendored
Normal 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
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
155
src/lib/libdwarf/dwarf_peread.h
vendored
Normal 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
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
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
356
src/lib/libdwarf/dwarf_ranges.c
vendored
Normal 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
72
src/lib/libdwarf/dwarf_reading.h
vendored
Normal 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
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
Loading…
x
Reference in New Issue
Block a user