Switch to fetch-content for udmp-parser
This commit is contained in:
parent
0b00197a4a
commit
54ddde3de0
|
|
@ -1,5 +1,5 @@
|
|||
function(init_submodule folder)
|
||||
set(full_path "${CMAKE_CURRENT_SOURCE_DIR}/${folder}")
|
||||
set(full_path "${CMAKE_CURRENT_LIST_DIR}/../${folder}")
|
||||
if(NOT EXISTS ${full_path})
|
||||
message(FATAL_ERROR "Submodule folder does not exist: ${full_path}")
|
||||
endif()
|
||||
|
|
@ -9,7 +9,7 @@ function(init_submodule folder)
|
|||
message(STATUS "Submodule '${folder}' not initialized, running git...")
|
||||
execute_process(
|
||||
COMMAND "${GIT_EXECUTABLE}" rev-parse --show-toplevel
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/.."
|
||||
OUTPUT_VARIABLE git_root
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
COMMAND_ERROR_IS_FATAL ANY
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
# cmkr
|
||||
/**/CMakeLists.txt linguist-generated
|
||||
/**/cmkr.cmake linguist-vendored
|
||||
|
|
@ -12,7 +12,7 @@ if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
|
|||
set(CMKR_ROOT_PROJECT ON)
|
||||
|
||||
# Bootstrap cmkr and automatically regenerate CMakeLists.txt
|
||||
include(cmkr.cmake OPTIONAL RESULT_VARIABLE CMKR_INCLUDE_RESULT)
|
||||
include("../../cmake/cmkr.cmake" OPTIONAL RESULT_VARIABLE CMKR_INCLUDE_RESULT)
|
||||
if(CMKR_INCLUDE_RESULT)
|
||||
cmkr()
|
||||
endif()
|
||||
|
|
@ -74,7 +74,6 @@ set(minidump_SOURCES
|
|||
"minidump/REToolSync.cpp"
|
||||
"minidump/REToolSync.h"
|
||||
"minidump/main.cpp"
|
||||
"minidump/udmp-parser.h"
|
||||
"minidump/udmp-utils.h"
|
||||
)
|
||||
|
||||
|
|
@ -85,10 +84,19 @@ target_compile_features(minidump PRIVATE
|
|||
cxx_std_20
|
||||
)
|
||||
|
||||
if(NOT TARGET linux-pe)
|
||||
message(FATAL_ERROR "Target \"linux-pe\" referenced by \"minidump\" does not exist!")
|
||||
endif()
|
||||
|
||||
if(NOT TARGET udmp-parser)
|
||||
message(FATAL_ERROR "Target \"udmp-parser\" referenced by \"minidump\" does not exist!")
|
||||
endif()
|
||||
|
||||
target_link_libraries(minidump PRIVATE
|
||||
x64dbg::widgets
|
||||
cpp-httplib
|
||||
httplib::httplib
|
||||
linux-pe
|
||||
udmp-parser
|
||||
)
|
||||
|
||||
get_directory_property(CMKR_VS_STARTUP_PROJECT DIRECTORY ${PROJECT_SOURCE_DIR} DEFINITION VS_STARTUP_PROJECT)
|
||||
|
|
@ -112,7 +120,6 @@ set(remote_table_SOURCES
|
|||
"remote_table/TableRpcData.h"
|
||||
"remote_table/TableServer.cpp"
|
||||
"remote_table/TableServer.h"
|
||||
"remote_table/json.hpp"
|
||||
"remote_table/main.cpp"
|
||||
)
|
||||
|
||||
|
|
@ -125,6 +132,7 @@ target_compile_features(remote_table PRIVATE
|
|||
|
||||
target_link_libraries(remote_table PRIVATE
|
||||
x64dbg::widgets
|
||||
nlohmann_json::nlohmann_json
|
||||
)
|
||||
|
||||
get_directory_property(CMKR_VS_STARTUP_PROJECT DIRECTORY ${PROJECT_SOURCE_DIR} DEFINITION VS_STARTUP_PROJECT)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
# Reference: https://build-cpp.github.io/cmkr/cmake-toml
|
||||
[cmake]
|
||||
version = "3.19"
|
||||
cmkr-include = "../../cmake/cmkr.cmake"
|
||||
|
||||
[project]
|
||||
name = "cross"
|
||||
|
|
@ -31,8 +32,9 @@ sources = [
|
|||
]
|
||||
link-libraries = [
|
||||
"x64dbg::widgets",
|
||||
"cpp-httplib",
|
||||
"linux-pe",
|
||||
"httplib::httplib",
|
||||
"::linux-pe",
|
||||
"::udmp-parser",
|
||||
]
|
||||
|
||||
[target.remote_table]
|
||||
|
|
@ -42,10 +44,10 @@ sources = [
|
|||
"remote_table/*.h",
|
||||
"remote_table/*.ui",
|
||||
"remote_table/*.qrc",
|
||||
"remote_table/json.hpp",
|
||||
]
|
||||
link-libraries = [
|
||||
"x64dbg::widgets",
|
||||
"nlohmann_json::nlohmann_json",
|
||||
]
|
||||
|
||||
[target.release_notes]
|
||||
|
|
|
|||
|
|
@ -1,253 +0,0 @@
|
|||
include_guard()
|
||||
|
||||
# Change these defaults to point to your infrastructure if desired
|
||||
set(CMKR_REPO "https://github.com/build-cpp/cmkr" CACHE STRING "cmkr git repository" FORCE)
|
||||
set(CMKR_TAG "v0.2.44" CACHE STRING "cmkr git tag (this needs to be available forever)" FORCE)
|
||||
set(CMKR_COMMIT_HASH "" CACHE STRING "cmkr git commit hash (optional)" FORCE)
|
||||
|
||||
# To bootstrap/generate a cmkr project: cmake -P cmkr.cmake
|
||||
if(CMAKE_SCRIPT_MODE_FILE)
|
||||
set(CMAKE_BINARY_DIR "${CMAKE_BINARY_DIR}/build")
|
||||
set(CMAKE_CURRENT_BINARY_DIR "${CMAKE_BINARY_DIR}")
|
||||
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}")
|
||||
endif()
|
||||
|
||||
# Set these from the command line to customize for development/debugging purposes
|
||||
set(CMKR_EXECUTABLE "" CACHE FILEPATH "cmkr executable")
|
||||
set(CMKR_SKIP_GENERATION OFF CACHE BOOL "skip automatic cmkr generation")
|
||||
set(CMKR_BUILD_TYPE "Debug" CACHE STRING "cmkr build configuration")
|
||||
mark_as_advanced(CMKR_REPO CMKR_TAG CMKR_COMMIT_HASH CMKR_EXECUTABLE CMKR_SKIP_GENERATION CMKR_BUILD_TYPE)
|
||||
|
||||
# Disable cmkr if generation is disabled
|
||||
if(DEFINED ENV{CI} OR CMKR_SKIP_GENERATION OR CMKR_BUILD_SKIP_GENERATION)
|
||||
message(STATUS "[cmkr] Skipping automatic cmkr generation")
|
||||
unset(CMKR_BUILD_SKIP_GENERATION CACHE)
|
||||
macro(cmkr)
|
||||
endmacro()
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Disable cmkr if no cmake.toml file is found
|
||||
if(NOT CMAKE_SCRIPT_MODE_FILE AND NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake.toml")
|
||||
message(AUTHOR_WARNING "[cmkr] Not found: ${CMAKE_CURRENT_SOURCE_DIR}/cmake.toml")
|
||||
macro(cmkr)
|
||||
endmacro()
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Convert a Windows native path to CMake path
|
||||
if(CMKR_EXECUTABLE MATCHES "\\\\")
|
||||
string(REPLACE "\\" "/" CMKR_EXECUTABLE_CMAKE "${CMKR_EXECUTABLE}")
|
||||
set(CMKR_EXECUTABLE "${CMKR_EXECUTABLE_CMAKE}" CACHE FILEPATH "" FORCE)
|
||||
unset(CMKR_EXECUTABLE_CMAKE)
|
||||
endif()
|
||||
|
||||
# Helper macro to execute a process (COMMAND_ERROR_IS_FATAL ANY is 3.19 and higher)
|
||||
function(cmkr_exec)
|
||||
execute_process(COMMAND ${ARGV} RESULT_VARIABLE CMKR_EXEC_RESULT)
|
||||
if(NOT CMKR_EXEC_RESULT EQUAL 0)
|
||||
message(FATAL_ERROR "cmkr_exec(${ARGV}) failed (exit code ${CMKR_EXEC_RESULT})")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Windows-specific hack (CMAKE_EXECUTABLE_PREFIX is not set at the moment)
|
||||
if(WIN32)
|
||||
set(CMKR_EXECUTABLE_NAME "cmkr.exe")
|
||||
else()
|
||||
set(CMKR_EXECUTABLE_NAME "cmkr")
|
||||
endif()
|
||||
|
||||
# Use cached cmkr if found
|
||||
if(DEFINED ENV{CMKR_CACHE})
|
||||
set(CMKR_DIRECTORY_PREFIX "$ENV{CMKR_CACHE}")
|
||||
string(REPLACE "\\" "/" CMKR_DIRECTORY_PREFIX "${CMKR_DIRECTORY_PREFIX}")
|
||||
if(NOT CMKR_DIRECTORY_PREFIX MATCHES "\\/$")
|
||||
set(CMKR_DIRECTORY_PREFIX "${CMKR_DIRECTORY_PREFIX}/")
|
||||
endif()
|
||||
# Build in release mode for the cache
|
||||
set(CMKR_BUILD_TYPE "Release")
|
||||
else()
|
||||
set(CMKR_DIRECTORY_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/_cmkr_")
|
||||
endif()
|
||||
set(CMKR_DIRECTORY "${CMKR_DIRECTORY_PREFIX}${CMKR_TAG}")
|
||||
set(CMKR_CACHED_EXECUTABLE "${CMKR_DIRECTORY}/bin/${CMKR_EXECUTABLE_NAME}")
|
||||
|
||||
# Helper function to check if a string starts with a prefix
|
||||
# Cannot use MATCHES, see: https://github.com/build-cpp/cmkr/issues/61
|
||||
function(cmkr_startswith str prefix result)
|
||||
string(LENGTH "${prefix}" prefix_length)
|
||||
string(LENGTH "${str}" str_length)
|
||||
if(prefix_length LESS_EQUAL str_length)
|
||||
string(SUBSTRING "${str}" 0 ${prefix_length} str_prefix)
|
||||
if(prefix STREQUAL str_prefix)
|
||||
set("${result}" ON PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
endif()
|
||||
set("${result}" OFF PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Handle upgrading logic
|
||||
if(CMKR_EXECUTABLE AND NOT CMKR_CACHED_EXECUTABLE STREQUAL CMKR_EXECUTABLE)
|
||||
cmkr_startswith("${CMKR_EXECUTABLE}" "${CMAKE_CURRENT_BINARY_DIR}/_cmkr" CMKR_STARTSWITH_BUILD)
|
||||
cmkr_startswith("${CMKR_EXECUTABLE}" "${CMKR_DIRECTORY_PREFIX}" CMKR_STARTSWITH_CACHE)
|
||||
if(CMKR_STARTSWITH_BUILD)
|
||||
if(DEFINED ENV{CMKR_CACHE})
|
||||
message(AUTHOR_WARNING "[cmkr] Switching to cached cmkr: '${CMKR_CACHED_EXECUTABLE}'")
|
||||
if(EXISTS "${CMKR_CACHED_EXECUTABLE}")
|
||||
set(CMKR_EXECUTABLE "${CMKR_CACHED_EXECUTABLE}" CACHE FILEPATH "Full path to cmkr executable" FORCE)
|
||||
else()
|
||||
unset(CMKR_EXECUTABLE CACHE)
|
||||
endif()
|
||||
else()
|
||||
message(AUTHOR_WARNING "[cmkr] Upgrading '${CMKR_EXECUTABLE}' to '${CMKR_CACHED_EXECUTABLE}'")
|
||||
unset(CMKR_EXECUTABLE CACHE)
|
||||
endif()
|
||||
elseif(DEFINED ENV{CMKR_CACHE} AND CMKR_STARTSWITH_CACHE)
|
||||
message(AUTHOR_WARNING "[cmkr] Upgrading cached '${CMKR_EXECUTABLE}' to '${CMKR_CACHED_EXECUTABLE}'")
|
||||
unset(CMKR_EXECUTABLE CACHE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CMKR_EXECUTABLE AND EXISTS "${CMKR_EXECUTABLE}")
|
||||
message(VERBOSE "[cmkr] Found cmkr: '${CMKR_EXECUTABLE}'")
|
||||
elseif(CMKR_EXECUTABLE AND NOT CMKR_EXECUTABLE STREQUAL CMKR_CACHED_EXECUTABLE)
|
||||
message(FATAL_ERROR "[cmkr] '${CMKR_EXECUTABLE}' not found")
|
||||
elseif(NOT CMKR_EXECUTABLE AND EXISTS "${CMKR_CACHED_EXECUTABLE}")
|
||||
set(CMKR_EXECUTABLE "${CMKR_CACHED_EXECUTABLE}" CACHE FILEPATH "Full path to cmkr executable" FORCE)
|
||||
message(STATUS "[cmkr] Found cached cmkr: '${CMKR_EXECUTABLE}'")
|
||||
else()
|
||||
set(CMKR_EXECUTABLE "${CMKR_CACHED_EXECUTABLE}" CACHE FILEPATH "Full path to cmkr executable" FORCE)
|
||||
message(VERBOSE "[cmkr] Bootstrapping '${CMKR_EXECUTABLE}'")
|
||||
|
||||
message(STATUS "[cmkr] Fetching cmkr...")
|
||||
if(EXISTS "${CMKR_DIRECTORY}")
|
||||
cmkr_exec("${CMAKE_COMMAND}" -E rm -rf "${CMKR_DIRECTORY}")
|
||||
endif()
|
||||
find_package(Git QUIET REQUIRED)
|
||||
cmkr_exec("${GIT_EXECUTABLE}"
|
||||
clone
|
||||
--config advice.detachedHead=false
|
||||
--branch ${CMKR_TAG}
|
||||
--depth 1
|
||||
${CMKR_REPO}
|
||||
"${CMKR_DIRECTORY}"
|
||||
)
|
||||
if(CMKR_COMMIT_HASH)
|
||||
execute_process(
|
||||
COMMAND "${GIT_EXECUTABLE}" checkout -q "${CMKR_COMMIT_HASH}"
|
||||
RESULT_VARIABLE CMKR_EXEC_RESULT
|
||||
WORKING_DIRECTORY "${CMKR_DIRECTORY}"
|
||||
)
|
||||
if(NOT CMKR_EXEC_RESULT EQUAL 0)
|
||||
message(FATAL_ERROR "Tag '${CMKR_TAG}' hash is not '${CMKR_COMMIT_HASH}'")
|
||||
endif()
|
||||
endif()
|
||||
message(STATUS "[cmkr] Building cmkr (using system compiler)...")
|
||||
cmkr_exec("${CMAKE_COMMAND}"
|
||||
--no-warn-unused-cli
|
||||
"${CMKR_DIRECTORY}"
|
||||
"-B${CMKR_DIRECTORY}/build"
|
||||
"-DCMAKE_BUILD_TYPE=${CMKR_BUILD_TYPE}"
|
||||
"-DCMAKE_UNITY_BUILD=ON"
|
||||
"-DCMAKE_INSTALL_PREFIX=${CMKR_DIRECTORY}"
|
||||
"-DCMKR_GENERATE_DOCUMENTATION=OFF"
|
||||
)
|
||||
cmkr_exec("${CMAKE_COMMAND}"
|
||||
--build "${CMKR_DIRECTORY}/build"
|
||||
--config "${CMKR_BUILD_TYPE}"
|
||||
--parallel
|
||||
)
|
||||
cmkr_exec("${CMAKE_COMMAND}"
|
||||
--install "${CMKR_DIRECTORY}/build"
|
||||
--config "${CMKR_BUILD_TYPE}"
|
||||
--prefix "${CMKR_DIRECTORY}"
|
||||
--component cmkr
|
||||
)
|
||||
if(NOT EXISTS ${CMKR_EXECUTABLE})
|
||||
message(FATAL_ERROR "[cmkr] Failed to bootstrap '${CMKR_EXECUTABLE}'")
|
||||
endif()
|
||||
cmkr_exec("${CMKR_EXECUTABLE}" version)
|
||||
message(STATUS "[cmkr] Bootstrapped ${CMKR_EXECUTABLE}")
|
||||
endif()
|
||||
execute_process(COMMAND "${CMKR_EXECUTABLE}" version
|
||||
RESULT_VARIABLE CMKR_EXEC_RESULT
|
||||
)
|
||||
if(NOT CMKR_EXEC_RESULT EQUAL 0)
|
||||
message(FATAL_ERROR "[cmkr] Failed to get version, try clearing the cache and rebuilding")
|
||||
endif()
|
||||
|
||||
# Use cmkr.cmake as a script
|
||||
if(CMAKE_SCRIPT_MODE_FILE)
|
||||
if(NOT EXISTS "${CMAKE_SOURCE_DIR}/cmake.toml")
|
||||
execute_process(COMMAND "${CMKR_EXECUTABLE}" init
|
||||
RESULT_VARIABLE CMKR_EXEC_RESULT
|
||||
)
|
||||
if(NOT CMKR_EXEC_RESULT EQUAL 0)
|
||||
message(FATAL_ERROR "[cmkr] Failed to bootstrap cmkr project. Please report an issue: https://github.com/build-cpp/cmkr/issues/new")
|
||||
else()
|
||||
message(STATUS "[cmkr] Modify cmake.toml and then configure using: cmake -B build")
|
||||
endif()
|
||||
else()
|
||||
execute_process(COMMAND "${CMKR_EXECUTABLE}" gen
|
||||
RESULT_VARIABLE CMKR_EXEC_RESULT
|
||||
)
|
||||
if(NOT CMKR_EXEC_RESULT EQUAL 0)
|
||||
message(FATAL_ERROR "[cmkr] Failed to generate project.")
|
||||
else()
|
||||
message(STATUS "[cmkr] Configure using: cmake -B build")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# This is the macro that contains black magic
|
||||
macro(cmkr)
|
||||
# When this macro is called from the generated file, fake some internal CMake variables
|
||||
get_source_file_property(CMKR_CURRENT_LIST_FILE "${CMAKE_CURRENT_LIST_FILE}" CMKR_CURRENT_LIST_FILE)
|
||||
if(CMKR_CURRENT_LIST_FILE)
|
||||
set(CMAKE_CURRENT_LIST_FILE "${CMKR_CURRENT_LIST_FILE}")
|
||||
get_filename_component(CMAKE_CURRENT_LIST_DIR "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY)
|
||||
endif()
|
||||
|
||||
# File-based include guard (include_guard is not documented to work)
|
||||
get_source_file_property(CMKR_INCLUDE_GUARD "${CMAKE_CURRENT_LIST_FILE}" CMKR_INCLUDE_GUARD)
|
||||
if(NOT CMKR_INCLUDE_GUARD)
|
||||
set_source_files_properties("${CMAKE_CURRENT_LIST_FILE}" PROPERTIES CMKR_INCLUDE_GUARD TRUE)
|
||||
|
||||
file(SHA256 "${CMAKE_CURRENT_LIST_FILE}" CMKR_LIST_FILE_SHA256_PRE)
|
||||
|
||||
# Generate CMakeLists.txt
|
||||
cmkr_exec("${CMKR_EXECUTABLE}" gen
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
)
|
||||
|
||||
file(SHA256 "${CMAKE_CURRENT_LIST_FILE}" CMKR_LIST_FILE_SHA256_POST)
|
||||
|
||||
# Delete the temporary file if it was left for some reason
|
||||
set(CMKR_TEMP_FILE "${CMAKE_CURRENT_SOURCE_DIR}/CMakerLists.txt")
|
||||
if(EXISTS "${CMKR_TEMP_FILE}")
|
||||
file(REMOVE "${CMKR_TEMP_FILE}")
|
||||
endif()
|
||||
|
||||
if(NOT CMKR_LIST_FILE_SHA256_PRE STREQUAL CMKR_LIST_FILE_SHA256_POST)
|
||||
# Copy the now-generated CMakeLists.txt to CMakerLists.txt
|
||||
# This is done because you cannot include() a file you are currently in
|
||||
configure_file(CMakeLists.txt "${CMKR_TEMP_FILE}" COPYONLY)
|
||||
|
||||
# Add the macro required for the hack at the start of the cmkr macro
|
||||
set_source_files_properties("${CMKR_TEMP_FILE}" PROPERTIES
|
||||
CMKR_CURRENT_LIST_FILE "${CMAKE_CURRENT_LIST_FILE}"
|
||||
)
|
||||
|
||||
# 'Execute' the newly-generated CMakeLists.txt
|
||||
include("${CMKR_TEMP_FILE}")
|
||||
|
||||
# Delete the generated file
|
||||
file(REMOVE "${CMKR_TEMP_FILE}")
|
||||
|
||||
# Do not execute the rest of the original CMakeLists.txt
|
||||
return()
|
||||
endif()
|
||||
# Resume executing the unmodified CMakeLists.txt
|
||||
endif()
|
||||
endmacro()
|
||||
|
|
@ -439,7 +439,8 @@ std::unique_ptr<FileParser> FileParser::Create(const uint8_t* begin, const uint8
|
|||
if(memcmp(magic, mdmpMagic, sizeof(mdmpMagic)) == 0)
|
||||
{
|
||||
auto parser = std::make_unique<DmpFileParser>();
|
||||
if(!parser->mDmp.Parse(begin, end))
|
||||
udmpparser::MemoryView_t memoryView(begin, end);
|
||||
if(!parser->mDmp.Parse(memoryView))
|
||||
{
|
||||
error = "Minidump parsing failed!";
|
||||
return nullptr;
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
int main(int argc, char* argv[])
|
||||
{
|
||||
QApplication a(argc, argv);
|
||||
Configuration config(ConfigurationPalette());
|
||||
Configuration config({});
|
||||
MainWindow w;
|
||||
w.show();
|
||||
return a.exec();
|
||||
|
|
|
|||
|
|
@ -1,555 +0,0 @@
|
|||
// Axel '0vercl0k' Souchet - January 22 2022
|
||||
#include "udmp-parser.h"
|
||||
#include <algorithm>
|
||||
#include <cinttypes>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <optional>
|
||||
|
||||
//
|
||||
// Bunch of utils.
|
||||
//
|
||||
|
||||
namespace utils {
|
||||
|
||||
//
|
||||
// Get a string representation of the memory state.
|
||||
//
|
||||
|
||||
const char *StateToString(const uint32_t State) {
|
||||
switch (State) {
|
||||
case 0x10'00: {
|
||||
return "MEM_COMMIT";
|
||||
}
|
||||
|
||||
case 0x20'00: {
|
||||
return "MEM_RESERVE";
|
||||
}
|
||||
|
||||
case 0x1'00'00: {
|
||||
return "MEM_FREE";
|
||||
}
|
||||
|
||||
default: {
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char *TypeToString(const uint32_t Type) {
|
||||
switch (Type) {
|
||||
case 0x2'00'00: {
|
||||
return "MEM_PRIVATE";
|
||||
}
|
||||
case 0x4'00'00: {
|
||||
return "MEM_MAPPED";
|
||||
}
|
||||
case 0x1'00'00'00: {
|
||||
return "MEM_IMAGE";
|
||||
}
|
||||
default: {
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Print an Intel X86 context like windbg.
|
||||
//
|
||||
|
||||
void PrintX86Context(const udmpparser::Context32_t &C, const int Prefix = 0) {
|
||||
printf("%*ceax=%08" PRIx32 " ebx=%08" PRIx32 " ecx=%08" PRIx32
|
||||
" edx=%08" PRIx32 " esi=%08" PRIx32 " edi=%08" PRIx32 "\n",
|
||||
Prefix, ' ', C.Eax, C.Ebx, C.Ecx, C.Edx, C.Esi, C.Edi);
|
||||
printf("%*ceip=%08" PRIx32 " esp=%08" PRIx32 " ebp=%08" PRIx32 "\n", Prefix,
|
||||
' ', C.Eip, C.Esp, C.Ebp);
|
||||
printf("%*ccs=%04x ss=%04x ds=%04x es=%04x fs=%04x gs=%04x "
|
||||
"efl=%08x\n",
|
||||
Prefix, ' ', C.SegCs, C.SegSs, C.SegDs, C.SegEs, C.SegFs, C.SegGs,
|
||||
C.EFlags);
|
||||
}
|
||||
|
||||
//
|
||||
// Print an Intel X64 context like windbg.
|
||||
//
|
||||
|
||||
void PrintX64Context(const udmpparser::Context64_t &C, const int Prefix = 0) {
|
||||
printf("%*crax=%016" PRIx64 " rbx=%016" PRIx64 " rcx=%016" PRIx64 "\n",
|
||||
Prefix, ' ', C.Rax, C.Rbx, C.Rcx);
|
||||
printf("%*crdx=%016" PRIx64 " rsi=%016" PRIx64 " rdi=%016" PRIx64 "\n",
|
||||
Prefix, ' ', C.Rdx, C.Rsi, C.Rdi);
|
||||
printf("%*crip=%016" PRIx64 " rsp=%016" PRIx64 " rbp=%016" PRIx64 "\n",
|
||||
Prefix, ' ', C.Rip, C.Rsp, C.Rbp);
|
||||
printf("%*c r8=%016" PRIx64 " r9=%016" PRIx64 " r10=%016" PRIx64 "\n",
|
||||
Prefix, ' ', C.R8, C.R9, C.R10);
|
||||
printf("%*cr11=%016" PRIx64 " r12=%016" PRIx64 " r13=%016" PRIx64 "\n",
|
||||
Prefix, ' ', C.R11, C.R12, C.R13);
|
||||
printf("%*cr14=%016" PRIx64 " r15=%016" PRIx64 "\n", Prefix, ' ', C.R14,
|
||||
C.R15);
|
||||
printf("%*ccs=%04x ss=%04x ds=%04x es=%04x fs=%04x gs=%04x "
|
||||
"efl=%08x\n",
|
||||
Prefix, ' ', C.SegCs, C.SegSs, C.SegDs, C.SegEs, C.SegFs, C.SegGs,
|
||||
C.EFlags);
|
||||
printf("%*cfpcw=%04x fpsw=%04x fptw=%04x\n", Prefix, ' ', C.ControlWord,
|
||||
C.StatusWord, C.TagWord);
|
||||
printf("%*c st0=%016" PRIx64 "%016" PRIx64 " st1=%016" PRIx64
|
||||
"%016" PRIx64 "\n",
|
||||
Prefix, ' ', C.FloatRegisters[0].High, C.FloatRegisters[0].Low,
|
||||
C.FloatRegisters[1].High, C.FloatRegisters[1].Low);
|
||||
printf("%*c st2=%016" PRIx64 "%016" PRIx64 " st3=%016" PRIx64
|
||||
"%016" PRIx64 "\n",
|
||||
Prefix, ' ', C.FloatRegisters[2].High, C.FloatRegisters[2].Low,
|
||||
C.FloatRegisters[3].High, C.FloatRegisters[3].Low);
|
||||
printf("%*c st4=%016" PRIx64 "%016" PRIx64 " st5=%016" PRIx64
|
||||
"%016" PRIx64 "\n",
|
||||
Prefix, ' ', C.FloatRegisters[4].High, C.FloatRegisters[4].Low,
|
||||
C.FloatRegisters[5].High, C.FloatRegisters[5].Low);
|
||||
printf("%*c st6=%016" PRIx64 "%016" PRIx64 " st7=%016" PRIx64
|
||||
"%016" PRIx64 "\n",
|
||||
Prefix, ' ', C.FloatRegisters[6].High, C.FloatRegisters[6].Low,
|
||||
C.FloatRegisters[7].High, C.FloatRegisters[7].Low);
|
||||
printf("%*c xmm0=%016" PRIx64 "%016" PRIx64 " xmm1=%016" PRIx64
|
||||
"%016" PRIx64 "\n",
|
||||
Prefix, ' ', C.Xmm0.High, C.Xmm0.Low, C.Xmm1.High, C.Xmm1.Low);
|
||||
printf("%*c xmm2=%016" PRIx64 "%016" PRIx64 " xmm3=%016" PRIx64
|
||||
"%016" PRIx64 "\n",
|
||||
Prefix, ' ', C.Xmm2.High, C.Xmm2.Low, C.Xmm3.High, C.Xmm3.Low);
|
||||
printf("%*c xmm4=%016" PRIx64 "%016" PRIx64 " xmm5=%016" PRIx64
|
||||
"%016" PRIx64 "\n",
|
||||
Prefix, ' ', C.Xmm4.High, C.Xmm4.Low, C.Xmm5.High, C.Xmm5.Low);
|
||||
printf("%*c xmm6=%016" PRIx64 "%016" PRIx64 " xmm7=%016" PRIx64
|
||||
"%016" PRIx64 "\n",
|
||||
Prefix, ' ', C.Xmm6.High, C.Xmm6.Low, C.Xmm7.High, C.Xmm7.Low);
|
||||
printf("%*c xmm8=%016" PRIx64 "%016" PRIx64 " xmm9=%016" PRIx64
|
||||
"%016" PRIx64 "\n",
|
||||
Prefix, ' ', C.Xmm8.High, C.Xmm8.Low, C.Xmm9.High, C.Xmm9.Low);
|
||||
printf("%*cxmm10=%016" PRIx64 "%016" PRIx64 " xmm11=%016" PRIx64
|
||||
"%016" PRIx64 "\n",
|
||||
Prefix, ' ', C.Xmm10.High, C.Xmm10.Low, C.Xmm11.High, C.Xmm11.Low);
|
||||
printf("%*cxmm12=%016" PRIx64 "%016" PRIx64 " xmm13=%016" PRIx64
|
||||
"%016" PRIx64 "\n",
|
||||
Prefix, ' ', C.Xmm12.High, C.Xmm12.Low, C.Xmm13.High, C.Xmm13.Low);
|
||||
printf("%*cxmm14=%016" PRIx64 "%016" PRIx64 " xmm15=%016" PRIx64
|
||||
"%016" PRIx64 "\n",
|
||||
Prefix, ' ', C.Xmm14.High, C.Xmm14.Low, C.Xmm15.High, C.Xmm15.Low);
|
||||
}
|
||||
|
||||
//
|
||||
// Print a CPU context like windbg does.
|
||||
//
|
||||
|
||||
void PrintContext(const udmpparser::Thread_t &T, const int Prefix = 0) {
|
||||
printf("%*cTID %" PRIx32 ", TEB %" PRIx64 "\n", Prefix, ' ', T.ThreadId,
|
||||
T.Teb);
|
||||
printf("%*cContext:\n", Prefix, ' ');
|
||||
const auto &C = T.Context;
|
||||
if (std::holds_alternative<udmpparser::Context32_t>(C)) {
|
||||
const auto &C32 = std::get<udmpparser::Context32_t>(C);
|
||||
return PrintX86Context(C32, Prefix + 2);
|
||||
}
|
||||
|
||||
if (std::holds_alternative<udmpparser::Context64_t>(C)) {
|
||||
const auto &C64 = std::get<udmpparser::Context64_t>(C);
|
||||
return PrintX64Context(C64, Prefix + 2);
|
||||
}
|
||||
|
||||
printf("%*cUnknown type of context!\n", Prefix, ' ');
|
||||
}
|
||||
|
||||
void Hexdump(const uint64_t Address, const void *Buffer, size_t Len,
|
||||
const int Prefix = 0) {
|
||||
const uint8_t *Ptr = (uint8_t *)Buffer;
|
||||
|
||||
for (size_t i = 0; i < Len; i += 16) {
|
||||
printf("%*c%" PRIx64 ": ", Prefix, ' ', Address + i);
|
||||
for (size_t j = 0; j < 16; j++) {
|
||||
if (i + j < Len) {
|
||||
printf("%02" PRIx8, Ptr[i + j]);
|
||||
} else {
|
||||
printf(" ");
|
||||
}
|
||||
}
|
||||
printf(" |");
|
||||
for (size_t j = 0; j < 16; j++) {
|
||||
if (i + j < Len) {
|
||||
printf("%c", isprint(Ptr[i + j]) ? char(Ptr[i + j]) : '.');
|
||||
} else {
|
||||
printf(" ");
|
||||
}
|
||||
}
|
||||
printf("|\n");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace utils
|
||||
|
||||
//
|
||||
// Delimiter.
|
||||
//
|
||||
|
||||
#define DELIMITER \
|
||||
"----------------------------------------------------------------------" \
|
||||
"----------"
|
||||
|
||||
//
|
||||
// The options available for the parser.
|
||||
//
|
||||
|
||||
struct Options_t {
|
||||
|
||||
//
|
||||
// This is enabled if -h is used.
|
||||
//
|
||||
|
||||
bool ShowHelp = false;
|
||||
|
||||
//
|
||||
// This is enabled if -a is used.
|
||||
//
|
||||
|
||||
bool ShowAll = false;
|
||||
|
||||
//
|
||||
// This is enabled if -mods is used.
|
||||
//
|
||||
|
||||
bool ShowLoadedModules = false;
|
||||
|
||||
//
|
||||
// This is enabled if -mem is used.
|
||||
//
|
||||
|
||||
bool ShowMemoryMap = false;
|
||||
|
||||
//
|
||||
// This is enabled if -t is used.
|
||||
//
|
||||
|
||||
bool ShowThreads = false;
|
||||
|
||||
//
|
||||
// This holds a TID if -t is followed by an integer.
|
||||
//
|
||||
|
||||
std::optional<uint32_t> Tid;
|
||||
|
||||
//
|
||||
// This is enabled if -t main is used.
|
||||
//
|
||||
|
||||
bool ShowForegroundThread = false;
|
||||
|
||||
//
|
||||
// This is set if -dump <addr> is used.
|
||||
//
|
||||
|
||||
std::optional<uint64_t> DumpAddress;
|
||||
|
||||
//
|
||||
// The path to the dump file.
|
||||
//
|
||||
|
||||
std::string_view DumpPath;
|
||||
};
|
||||
|
||||
//
|
||||
// Help menu.
|
||||
//
|
||||
|
||||
void Help() {
|
||||
printf("parser.exe [-a] [-mods] [-mem] [-t [<TID|main>] [-h] [-dump <addr>] "
|
||||
"<dump path>\n");
|
||||
printf("\n");
|
||||
printf("Examples:\n");
|
||||
printf(" Show all:\n");
|
||||
printf(" parser.exe -a user.dmp\n");
|
||||
printf(" Show loaded modules:\n");
|
||||
printf(" parser.exe -mods user.dmp\n");
|
||||
printf(" Show memory map:\n");
|
||||
printf(" parser.exe -mem user.dmp\n");
|
||||
printf(" Show all threads:\n");
|
||||
printf(" parser.exe -t user.dmp\n");
|
||||
printf(" Show thread w/ specific TID:\n");
|
||||
printf(" parser.exe -t 1337 user.dmp\n");
|
||||
printf(" Show foreground thread:\n");
|
||||
printf(" parser.exe -t main user.dmp\n");
|
||||
printf(" Dump a memory page at a specific address:\n");
|
||||
printf(" parser.exe -dump 0x7ff00 user.dmp\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
//
|
||||
// Parse the options.
|
||||
//
|
||||
|
||||
Options_t Opts;
|
||||
for (int ArgIdx = 1; ArgIdx < argc; ArgIdx++) {
|
||||
const std::string_view Arg(argv[ArgIdx]);
|
||||
const bool IsLastArg = (ArgIdx + 1) >= argc;
|
||||
if (Arg == "-a") {
|
||||
Opts.ShowAll = true;
|
||||
} else if (Arg == "-h") {
|
||||
Opts.ShowHelp = true;
|
||||
} else if (Arg == "-mods") {
|
||||
Opts.ShowLoadedModules = true;
|
||||
} else if (Arg == "-mem") {
|
||||
Opts.ShowMemoryMap = true;
|
||||
} else if (Arg == "-t") {
|
||||
Opts.ShowThreads = true;
|
||||
|
||||
//
|
||||
// Verify that there's enough argument for an integer and the last
|
||||
// argument which is the dump.
|
||||
//
|
||||
const std::string_view NextArg(IsLastArg ? "" : argv[ArgIdx + 1]);
|
||||
if (NextArg == "main") {
|
||||
Opts.ShowForegroundThread = true;
|
||||
} else {
|
||||
char *End = nullptr;
|
||||
const uint32_t Tid = std::strtoul(NextArg.data(), &End, 0);
|
||||
const bool Valid = errno == 0 && End != NextArg.data();
|
||||
if (Valid) {
|
||||
Opts.Tid = Tid;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// If we grabbed a TID or set the foreground thread, skip an argument.
|
||||
//
|
||||
|
||||
if (Opts.Tid.has_value() || Opts.ShowForegroundThread) {
|
||||
ArgIdx++;
|
||||
}
|
||||
} else if (Arg == "-dump") {
|
||||
const std::string_view NextArg(IsLastArg ? "" : argv[ArgIdx + 1]);
|
||||
char *End = nullptr;
|
||||
const uint64_t Address = std::strtoull(NextArg.data(), &End, 0);
|
||||
const bool Valid = errno == 0 && End != NextArg.data();
|
||||
if (Valid) {
|
||||
Opts.DumpAddress = Address;
|
||||
ArgIdx++;
|
||||
}
|
||||
} else if (IsLastArg) {
|
||||
|
||||
//
|
||||
// If this is the last argument, then this is the dump path.
|
||||
//
|
||||
|
||||
Opts.DumpPath = Arg;
|
||||
} else {
|
||||
|
||||
//
|
||||
// Otherwise it seems that the user passed something wrong?
|
||||
//
|
||||
|
||||
printf("The argument %s is not recognized.\n\n", Arg.data());
|
||||
Help();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Display help if wanted or no argument were specified.
|
||||
//
|
||||
|
||||
if (argc == 1 || Opts.ShowHelp) {
|
||||
Help();
|
||||
return argc == 1 ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize the parser.
|
||||
//
|
||||
|
||||
udmpparser::UserDumpParser UserDump;
|
||||
if (!UserDump.Parse(Opts.DumpPath.data())) {
|
||||
printf("Loading '%s' failed.\n", Opts.DumpPath.data());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
//
|
||||
// Show the loaded modules.
|
||||
//
|
||||
|
||||
if (Opts.ShowLoadedModules || Opts.ShowAll) {
|
||||
printf(DELIMITER "\nLoaded modules:\n");
|
||||
const auto &Modules = UserDump.GetModules();
|
||||
for (const auto &[Base, ModuleInfo] : Modules) {
|
||||
printf(" %016" PRIx64 ": %s\n", Base, ModuleInfo.ModuleName.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Show the memory map.
|
||||
//
|
||||
|
||||
if (Opts.ShowMemoryMap || Opts.ShowAll) {
|
||||
printf(DELIMITER "\nMemory map:\n");
|
||||
for (const auto &[_, Descriptor] : UserDump.GetMem()) {
|
||||
|
||||
//
|
||||
// Get a string representation for the state of the region.
|
||||
//
|
||||
|
||||
const char *State = utils::StateToString(Descriptor.State);
|
||||
|
||||
//
|
||||
// Get a string representation for the memory type of the region.
|
||||
//
|
||||
|
||||
const char *Type = "";
|
||||
if (strcmp(State, "MEM_FREE")) {
|
||||
Type = utils::TypeToString(Descriptor.Type);
|
||||
}
|
||||
|
||||
//
|
||||
// Display start / end / size / state / type of the region.
|
||||
//
|
||||
|
||||
const uint64_t BaseAddress = Descriptor.BaseAddress;
|
||||
const uint64_t RegionSize = Descriptor.RegionSize;
|
||||
const uint64_t EndAddress = BaseAddress + RegionSize;
|
||||
printf(" %16" PRIx64 " %16" PRIx64 " %16" PRIx64 " %11s %11s",
|
||||
BaseAddress, EndAddress, RegionSize, State, Type);
|
||||
|
||||
//
|
||||
// Is the region actually part of a module?
|
||||
//
|
||||
|
||||
const auto &Module = UserDump.GetModule(BaseAddress);
|
||||
|
||||
//
|
||||
// If we found a module that overlaps with this region, let's dump it as
|
||||
// well.
|
||||
//
|
||||
|
||||
if (Module != nullptr) {
|
||||
|
||||
//
|
||||
// Find the last '\' to get the module name off its path.
|
||||
//
|
||||
|
||||
const auto &ModulePathName = Module->ModuleName;
|
||||
auto ModuleNameOffset = ModulePathName.find_last_of('\\');
|
||||
if (ModuleNameOffset == ModulePathName.npos) {
|
||||
ModuleNameOffset = 0;
|
||||
} else {
|
||||
ModuleNameOffset++;
|
||||
}
|
||||
|
||||
//
|
||||
// Show the module path & module name.
|
||||
//
|
||||
|
||||
printf(" [%s; \"%s\"]", &ModulePathName[ModuleNameOffset],
|
||||
ModulePathName.c_str());
|
||||
}
|
||||
|
||||
//
|
||||
// Dump the first 4 bytes of the region if its available in the dump.
|
||||
//
|
||||
|
||||
if (Descriptor.DataSize >= 4) {
|
||||
printf(" %02" PRIx8 " %02" PRIx8 " %02" PRIx8 " %02" PRIx8 "...",
|
||||
Descriptor.Data[0], Descriptor.Data[1], Descriptor.Data[2],
|
||||
Descriptor.Data[3]);
|
||||
}
|
||||
|
||||
//
|
||||
// Phew! We are done for this region :)
|
||||
//
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Show the threads.
|
||||
//
|
||||
|
||||
if (Opts.ShowThreads || Opts.ShowAll) {
|
||||
printf(DELIMITER "\nThreads:\n");
|
||||
const auto &ForegroundTid = UserDump.GetForegroundThreadId();
|
||||
for (const auto &[Tid, Thread] : UserDump.GetThreads()) {
|
||||
|
||||
//
|
||||
// If we are looking for a specific TID, skip unless we have a match.
|
||||
//
|
||||
|
||||
if (Opts.Tid && Tid != *Opts.Tid) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// If we are looking for the foreground thread, skip unless we have a
|
||||
// match.
|
||||
//
|
||||
|
||||
if (Opts.ShowForegroundThread && Tid != *ForegroundTid) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// If we have a match or no filters, dump the context.
|
||||
//
|
||||
|
||||
utils::PrintContext(Thread, 2);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Dump virtual memory.
|
||||
//
|
||||
|
||||
if (Opts.DumpAddress.has_value()) {
|
||||
printf(DELIMITER "\nMemory:\n");
|
||||
|
||||
//
|
||||
// Find a block of virtual memory that overlaps with the address we want to
|
||||
// dump.
|
||||
//
|
||||
|
||||
const uint64_t DumpAddress = *Opts.DumpAddress;
|
||||
const auto &Block = UserDump.GetMemBlock(DumpAddress);
|
||||
|
||||
//
|
||||
// If we found a match, let's go.
|
||||
//
|
||||
|
||||
if (Block != nullptr) {
|
||||
|
||||
//
|
||||
// Display basic information about the matching memory region.
|
||||
//
|
||||
|
||||
const uint64_t BlockStart = Block->BaseAddress;
|
||||
const uint64_t BlockSize = Block->DataSize;
|
||||
const uint64_t BlockEnd = BlockStart + BlockSize;
|
||||
printf("%016" PRIx64 " -> %016" PRIx64 "\n", BlockStart, BlockEnd);
|
||||
if (BlockSize > 0) {
|
||||
|
||||
//
|
||||
// Calculate where from we need to start dumping, and the appropriate
|
||||
// amount of bytes to dump.
|
||||
//
|
||||
|
||||
const uint64_t OffsetFromStart = DumpAddress - BlockStart;
|
||||
const uint64_t Remaining = BlockSize - OffsetFromStart;
|
||||
const uint64_t MaxSize = 0x100;
|
||||
const uint64_t DumpSize = std::min(MaxSize, Remaining);
|
||||
utils::Hexdump(BlockStart + OffsetFromStart,
|
||||
Block->Data + OffsetFromStart, size_t(DumpSize), 2);
|
||||
} else {
|
||||
printf("The dump does not have the content of the memory at %" PRIx64
|
||||
"\n",
|
||||
DumpAddress);
|
||||
}
|
||||
} else {
|
||||
printf("No memory block were found for %" PRIx64 ".\n", DumpAddress);
|
||||
}
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -6,7 +6,7 @@
|
|||
#include <unordered_map>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include "json.hpp"
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
// https://www.jsonrpc.org/specification
|
||||
class JsonRpcClient : public QObject
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "Types.h"
|
||||
#include "json.hpp"
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -12,7 +12,7 @@
|
|||
int main(int argc, char* argv[])
|
||||
{
|
||||
QApplication a(argc, argv);
|
||||
Configuration config(ConfigurationPalette());
|
||||
Configuration config({});
|
||||
TableServer server;
|
||||
MainWindow w;
|
||||
w.show();
|
||||
|
|
|
|||
|
|
@ -8,6 +8,11 @@ endif()
|
|||
|
||||
# Variables
|
||||
set(LIBWOLV_ENABLE_TESTS OFF)
|
||||
set(HTTPLIB_INSTALL OFF)
|
||||
set(HTTPLIB_USE_ZSTD_IF_AVAILABLE OFF)
|
||||
set(HTTPLIB_USE_BROTLI_IF_AVAILABLE OFF)
|
||||
set(HTTPLIB_USE_ZLIB_IF_AVAILABLE OFF)
|
||||
set(HTTPLIB_USE_OPENSSL_IF_AVAILABLE OFF)
|
||||
|
||||
include(FetchContent)
|
||||
|
||||
|
|
@ -15,6 +20,33 @@ include(FetchContent)
|
|||
if(POLICY CMP0135)
|
||||
cmake_policy(SET CMP0135 NEW)
|
||||
endif()
|
||||
message(STATUS "Fetching json...")
|
||||
FetchContent_Declare(json
|
||||
URL
|
||||
"https://github.com/nlohmann/json/releases/download/v3.12.0/json.tar.xz"
|
||||
URL_HASH
|
||||
SHA256=42f6e95cad6ec532fd372391373363b62a14af6d771056dbfc86160e6dfff7aa
|
||||
)
|
||||
FetchContent_MakeAvailable(json)
|
||||
|
||||
message(STATUS "Fetching cpp-httplib (v0.25.0)...")
|
||||
FetchContent_Declare(cpp-httplib
|
||||
GIT_REPOSITORY
|
||||
"https://github.com/yhirose/cpp-httplib"
|
||||
GIT_TAG
|
||||
v0.25.0
|
||||
)
|
||||
FetchContent_MakeAvailable(cpp-httplib)
|
||||
|
||||
message(STATUS "Fetching linux-pe (1fcb057963da3d25048bf1a331cd84aab9e09c99)...")
|
||||
FetchContent_Declare(linux-pe
|
||||
GIT_REPOSITORY
|
||||
"https://github.com/can1357/linux-pe"
|
||||
GIT_TAG
|
||||
1fcb057963da3d25048bf1a331cd84aab9e09c99
|
||||
)
|
||||
FetchContent_MakeAvailable(linux-pe)
|
||||
|
||||
message(STATUS "Fetching PatternLanguage (3e98b047c52c07bb1816bd0936f561ce7797469d)...")
|
||||
FetchContent_Declare(PatternLanguage
|
||||
GIT_REPOSITORY
|
||||
|
|
@ -24,19 +56,16 @@ FetchContent_Declare(PatternLanguage
|
|||
)
|
||||
FetchContent_MakeAvailable(PatternLanguage)
|
||||
|
||||
# Target: cpp-httplib
|
||||
add_library(cpp-httplib INTERFACE)
|
||||
|
||||
target_include_directories(cpp-httplib INTERFACE
|
||||
cpp-httplib
|
||||
)
|
||||
|
||||
# Target: linux-pe
|
||||
add_library(linux-pe INTERFACE)
|
||||
|
||||
target_include_directories(linux-pe INTERFACE
|
||||
linux-pe
|
||||
message(STATUS "Fetching udmp-parser (bc5952eda39ba0b1a07fc57f57d166292f1e9563)...")
|
||||
FetchContent_Declare(udmp-parser
|
||||
GIT_REPOSITORY
|
||||
"https://github.com/mrexodia/udmp-parser"
|
||||
GIT_TAG
|
||||
bc5952eda39ba0b1a07fc57f57d166292f1e9563
|
||||
SOURCE_SUBDIR
|
||||
src
|
||||
)
|
||||
FetchContent_MakeAvailable(udmp-parser)
|
||||
|
||||
# Target: md4c-html
|
||||
set(md4c-html_SOURCES
|
||||
|
|
|
|||
|
|
@ -1,18 +1,32 @@
|
|||
[target.cpp-httplib]
|
||||
type = "interface"
|
||||
include-directories = ["cpp-httplib"]
|
||||
|
||||
[target.linux-pe]
|
||||
type = "interface"
|
||||
include-directories = ["linux-pe"]
|
||||
|
||||
[variables]
|
||||
LIBWOLV_ENABLE_TESTS = false
|
||||
HTTPLIB_INSTALL = false
|
||||
HTTPLIB_USE_ZSTD_IF_AVAILABLE = false
|
||||
HTTPLIB_USE_BROTLI_IF_AVAILABLE = false
|
||||
HTTPLIB_USE_ZLIB_IF_AVAILABLE = false
|
||||
HTTPLIB_USE_OPENSSL_IF_AVAILABLE = false
|
||||
|
||||
[fetch-content.json]
|
||||
url = "https://github.com/nlohmann/json/releases/download/v3.12.0/json.tar.xz"
|
||||
sha256 = "42f6e95cad6ec532fd372391373363b62a14af6d771056dbfc86160e6dfff7aa"
|
||||
|
||||
[fetch-content.cpp-httplib]
|
||||
git = "https://github.com/yhirose/cpp-httplib"
|
||||
tag = "v0.25.0"
|
||||
|
||||
[fetch-content.linux-pe]
|
||||
git = "https://github.com/can1357/linux-pe"
|
||||
tag = "1fcb057963da3d25048bf1a331cd84aab9e09c99"
|
||||
|
||||
[fetch-content.PatternLanguage]
|
||||
git = "https://github.com/WerWolv/PatternLanguage"
|
||||
tag = "3e98b047c52c07bb1816bd0936f561ce7797469d"
|
||||
|
||||
[fetch-content.udmp-parser]
|
||||
git = "https://github.com/mrexodia/udmp-parser"
|
||||
tag = "bc5952eda39ba0b1a07fc57f57d166292f1e9563"
|
||||
subdir = "src"
|
||||
|
||||
# https://github.com/mity/md4c/commit/481fbfbdf72daab2912380d62bb5f2187d438408
|
||||
[target.md4c-html]
|
||||
type = "static"
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,348 +0,0 @@
|
|||
// Copyright (c) 2020 Can Boluk
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// 2. 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.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// 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 OWNER 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.
|
||||
//
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <iterator>
|
||||
#include <string_view>
|
||||
#include <cstring>
|
||||
#include <stdlib.h>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include "../img_common.hpp"
|
||||
|
||||
COFF_STRUCT_PACKING
|
||||
namespace ar
|
||||
{
|
||||
// Magic constants.
|
||||
//
|
||||
constexpr uint64_t format_magic = 0x0A3E686372613C21; // "!<arch>\n"
|
||||
constexpr uint16_t entry_terminator = 0x0A60; // "`\n"
|
||||
|
||||
// Stupid string integers.
|
||||
//
|
||||
template<size_t B, size_t N>
|
||||
struct string_integer
|
||||
{
|
||||
char string[ N ];
|
||||
|
||||
// Integer to string.
|
||||
//
|
||||
string_integer( uint64_t integer )
|
||||
{
|
||||
// Handle zero:
|
||||
//
|
||||
if ( !integer )
|
||||
{
|
||||
string[ 0 ] = '0';
|
||||
memset( string + 1, ' ', N - 1 );
|
||||
return;
|
||||
}
|
||||
|
||||
// Until all characters are written:
|
||||
//
|
||||
static constexpr char dictionary[] = "0123456789ABCDEF";
|
||||
char* it = std::end( string );
|
||||
while ( integer )
|
||||
{
|
||||
*--it = dictionary[ integer % B ];
|
||||
integer /= B;
|
||||
|
||||
// Overflow, malformed.
|
||||
//
|
||||
if ( it == std::begin( string ) )
|
||||
{
|
||||
it = std::end( string );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Move to leftmost and right pad with spaces.
|
||||
//
|
||||
size_t len = ( size_t ) ( std::end( string ) - it );
|
||||
memmove( string, it, len );
|
||||
memset( string + len, ' ', N - len );
|
||||
}
|
||||
string_integer( const string_integer& ) = default;
|
||||
string_integer& operator=( const string_integer& ) = default;
|
||||
|
||||
// String to integer.
|
||||
//
|
||||
uint64_t get() const
|
||||
{
|
||||
char* it = ( char* ) string;
|
||||
while ( it != std::end( string ) && *it && *it != ' ' )
|
||||
++it;
|
||||
return strtoull( string, &it, B );
|
||||
}
|
||||
operator uint64_t() const { return get(); }
|
||||
};
|
||||
|
||||
// Big endian integers.
|
||||
//
|
||||
template<typename T>
|
||||
struct big_endian_t
|
||||
{
|
||||
uint8_t bytes[ sizeof( T ) ];
|
||||
|
||||
big_endian_t( T val )
|
||||
{
|
||||
for( size_t i = 0; i != sizeof( T ); i++ )
|
||||
bytes[ sizeof( T ) - ( i + 1 ) ] = ( val >> ( 8 * i ) ) & 0xFF;
|
||||
}
|
||||
|
||||
T get() const
|
||||
{
|
||||
T value = 0;
|
||||
for ( size_t i = 0; i != sizeof( T ); i++ )
|
||||
value |= bytes[ sizeof( T ) - ( i + 1 ) ] << ( 8 * i );
|
||||
return value;
|
||||
}
|
||||
operator T() const { return get(); }
|
||||
};
|
||||
|
||||
// File entry.
|
||||
//
|
||||
struct entry_t
|
||||
{
|
||||
union
|
||||
{
|
||||
char identifier[ 16 ];
|
||||
struct
|
||||
{
|
||||
char _pad;
|
||||
string_integer<10, 15> long_string_offset;
|
||||
};
|
||||
};
|
||||
string_integer<10, 12> modify_timestamp;
|
||||
string_integer<10, 6> owner_id;
|
||||
string_integer<10, 6> group_id;
|
||||
string_integer<8, 8> mode;
|
||||
string_integer<10, 10> length;
|
||||
uint16_t terminator;
|
||||
|
||||
// Data getter.
|
||||
//
|
||||
uint8_t* data() { return ( uint8_t* ) ( this + 1 ); };
|
||||
const uint8_t* data() const { return ( const uint8_t* ) ( this + 1 ); };
|
||||
uint8_t* begin() { return data(); };
|
||||
const uint8_t* begin() const { return data(); };
|
||||
uint8_t* end() { return data() + length; };
|
||||
const uint8_t* end() const { return data() + length; };
|
||||
|
||||
// Forward to next.
|
||||
//
|
||||
entry_t* next() { return ( entry_t* ) ( data() + ( ( length + 1 ) & ~1 ) ); }
|
||||
const entry_t* next() const { return ( const entry_t* ) ( data() + ( ( length + 1 ) & ~1 ) ); }
|
||||
|
||||
// System-V extension properties.
|
||||
//
|
||||
bool is_symbol_table() const { return identifier[ 0 ] == '/' && identifier[ 1 ] == ' '; }
|
||||
bool is_string_table() const { return identifier[ 0 ] == '/' && identifier[ 1 ] == '/' && identifier[ 2 ] == ' '; }
|
||||
bool has_long_name() const { return identifier[ 0 ] == '/' && '0' <= identifier[ 1 ] && identifier[ 1 ] <= '9'; }
|
||||
|
||||
// Convert identifier to string view.
|
||||
//
|
||||
std::string_view to_string( const entry_t* string_table = nullptr ) const
|
||||
{
|
||||
const char* begin = std::begin( identifier );
|
||||
const char* end = std::end( identifier );
|
||||
char terminator = '/';
|
||||
|
||||
if ( has_long_name() )
|
||||
{
|
||||
begin = ( const char* ) string_table->begin() + long_string_offset;
|
||||
end = ( const char* ) string_table->end();
|
||||
terminator = '\n';
|
||||
if ( begin >= end ) return {};
|
||||
}
|
||||
|
||||
auto it = begin;
|
||||
while ( it != end && *it != terminator && *it ) it++;
|
||||
if ( it != begin && it[ -1 ] == '/' ) --it;
|
||||
return { begin, ( size_t ) ( it - begin ) };
|
||||
}
|
||||
};
|
||||
|
||||
// Archive header.
|
||||
//
|
||||
struct header_t
|
||||
{
|
||||
uint64_t magic;
|
||||
entry_t first_entry;
|
||||
};
|
||||
|
||||
// Archive view wrapping the AR format.
|
||||
//
|
||||
template<bool constant = true>
|
||||
struct view
|
||||
{
|
||||
// Typedefs.
|
||||
//
|
||||
using archive_type = std::conditional_t<constant, const header_t, header_t>;
|
||||
using entry_type = std::conditional_t<constant, const entry_t, entry_t>;
|
||||
|
||||
// Declare iterator.
|
||||
//
|
||||
struct iterator
|
||||
{
|
||||
// Declare iterator traits
|
||||
//
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using difference_type = int64_t;
|
||||
using reference = std::pair<std::string_view, entry_type&>;
|
||||
using pointer = const void*;
|
||||
|
||||
// Stores current location, the limit and the string table.
|
||||
//
|
||||
entry_type* str_table;
|
||||
entry_type* at;
|
||||
const void* limit;
|
||||
|
||||
// Implement forward iteration and basic comparison.
|
||||
//
|
||||
iterator& operator++() { at = at->next(); return *this; }
|
||||
iterator operator++( int ) { auto s = *this; operator++(); return s; }
|
||||
bool operator==( const iterator& other ) const
|
||||
{
|
||||
if ( !at ) return !other.at || other.at >= other.limit || other.at->terminator != entry_terminator;
|
||||
if ( !other.at ) return !at || at >= limit || at->terminator != entry_terminator;
|
||||
else return at == other.at;
|
||||
}
|
||||
bool operator<( const iterator& other ) const
|
||||
{
|
||||
if ( !at ) return false;
|
||||
if ( !other.at ) return !operator==( other );
|
||||
else return at < other.at;
|
||||
}
|
||||
bool operator!=( const iterator& other ) const { return !operator==( other ); }
|
||||
|
||||
// Implement iterator interface and the name helper.
|
||||
//
|
||||
std::string_view to_string() const { return at->to_string( str_table ); }
|
||||
reference operator*() const { return reference{ to_string(), *at }; }
|
||||
entry_type* operator->() const { return at; }
|
||||
};
|
||||
using const_iterator = iterator;
|
||||
|
||||
// Holds the archive header and the region limit.
|
||||
//
|
||||
archive_type* archive;
|
||||
const void* limit;
|
||||
|
||||
// Holds special tables discovered during construction.
|
||||
//
|
||||
entry_type* string_table = nullptr;
|
||||
std::vector<entry_type*> symbol_tables = {};
|
||||
entry_type* first_entry = nullptr;
|
||||
|
||||
// Constructed by pointer and the region size.
|
||||
//
|
||||
view( const void* _archive, size_t size ) : archive( ( archive_type* ) _archive ), limit( ( uint8_t* ) _archive + size )
|
||||
{
|
||||
// Validate magic.
|
||||
//
|
||||
if ( archive->magic != format_magic )
|
||||
limit = &archive->first_entry;
|
||||
|
||||
// Resolve special entries and assign the first non-special entry.
|
||||
//
|
||||
for ( entry_type* it = &archive->first_entry; it < limit; it = it->next() )
|
||||
{
|
||||
if ( it->is_string_table() && !string_table )
|
||||
{
|
||||
string_table = it;
|
||||
}
|
||||
else if ( it->is_symbol_table() )
|
||||
{
|
||||
symbol_tables.emplace_back( it );
|
||||
}
|
||||
else
|
||||
{
|
||||
first_entry = it;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
view( view&& ) noexcept = default;
|
||||
view( const view& ) = default;
|
||||
view& operator=( view&& ) noexcept = default;
|
||||
view& operator=( const view& ) = default;
|
||||
|
||||
// Make iterable.
|
||||
//
|
||||
iterator begin() const { return { string_table, first_entry, limit }; }
|
||||
iterator end() const { return { nullptr, nullptr, nullptr }; }
|
||||
|
||||
// Parser for the System V symbol table.
|
||||
//
|
||||
std::unordered_multimap<std::string_view, iterator> read_symbols() const
|
||||
{
|
||||
// Get the table descriptor.
|
||||
//
|
||||
if ( symbol_tables.empty() ) return {};
|
||||
auto* table = symbol_tables.front();
|
||||
const uint8_t* it = table->begin();
|
||||
const uint8_t* end = table->end();
|
||||
|
||||
// Read entry count.
|
||||
//
|
||||
if ( ( it + 4 ) > end ) return {};
|
||||
uint32_t entry_count = *( const big_endian_t<uint32_t>* ) it;
|
||||
it += 4;
|
||||
|
||||
// Reference the offset table.
|
||||
//
|
||||
if ( ( it + 4 * entry_count ) > end ) return {};
|
||||
const big_endian_t<uint32_t>* offsets = ( const big_endian_t<uint32_t>* ) it;
|
||||
it += 4 * entry_count;
|
||||
|
||||
// Read the entries one by one.
|
||||
//
|
||||
std::unordered_multimap<std::string_view, iterator> entries;
|
||||
for ( size_t n = 0; n != entry_count; n++ )
|
||||
{
|
||||
// Read a zero-terminated string.
|
||||
//
|
||||
const uint8_t* str_begin = it;
|
||||
while ( it != end && *it ) it++;
|
||||
if ( it == end ) return {}; // Malformed entry.
|
||||
std::string_view string{ ( const char* ) str_begin, ( size_t ) ( it++ - str_begin ) };
|
||||
|
||||
// Read the entry.
|
||||
//
|
||||
entry_type* entry = ( entry_type* ) ( ( uint8_t* ) archive + offsets[ n ].get() );
|
||||
if ( entry >= limit || entry->terminator != entry_terminator ) return {}; // Malformed entry.
|
||||
iterator entry_iterator = { string_table, entry, limit };
|
||||
entries.emplace( std::move( string ), std::move( entry_iterator ) );
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
};
|
||||
template<typename T> view( T*, size_t ) -> view<std::is_const_v<T>>;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
// Copyright (c) 2020 Can Boluk
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// 2. 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.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// 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 OWNER 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.
|
||||
//
|
||||
#pragma once
|
||||
#include <string_view>
|
||||
#include "../../img_common.hpp"
|
||||
#include "../symbol.hpp"
|
||||
|
||||
COFF_STRUCT_PACKING
|
||||
namespace coff
|
||||
{
|
||||
// Declare the data type.
|
||||
//
|
||||
struct aux_file_name_t
|
||||
{
|
||||
// Name of the file, zero terminated, multiple entries will be used if longer than 18 chars.
|
||||
//
|
||||
char file_name[ 18 ];
|
||||
std::string_view to_string() const { return file_name; }
|
||||
};
|
||||
static_assert( sizeof( aux_file_name_t ) == sizeof( symbol_t ), "Invalid auxiliary symbol." );
|
||||
|
||||
// Declare the matching logic.
|
||||
//
|
||||
template<>
|
||||
inline bool symbol_t::valid_aux<aux_file_name_t>() const
|
||||
{
|
||||
return name.equals_s( ".file" ) &&
|
||||
storage_class == storage_class_id::file_name;
|
||||
}
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
// Copyright (c) 2020 Can Boluk
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// 2. 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.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// 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 OWNER 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.
|
||||
//
|
||||
#pragma once
|
||||
#include "../../img_common.hpp"
|
||||
#include "../symbol.hpp"
|
||||
|
||||
COFF_STRUCT_PACKING
|
||||
namespace coff
|
||||
{
|
||||
// Declare the data type.
|
||||
//
|
||||
struct aux_function_t
|
||||
{
|
||||
uint32_t sym_begin_idx; // Symbol table index for the beginning of the function.
|
||||
uint32_t length; // Length of the code.
|
||||
uint32_t ptr_line_numbers; // Raw offset to the first COFF line number entry.
|
||||
uint32_t sym_next_function_idx; // Symbol table index for the next function index, if zero last entry.
|
||||
uint16_t _pad;
|
||||
};
|
||||
static_assert( sizeof( aux_function_t ) == sizeof( symbol_t ), "Invalid auxiliary symbol." );
|
||||
|
||||
// Declare the matching logic.
|
||||
//
|
||||
template<>
|
||||
inline bool symbol_t::valid_aux<aux_function_t>() const
|
||||
{
|
||||
return storage_class == storage_class_id::public_symbol &&
|
||||
derived_type == derived_type_id::function &&
|
||||
has_section();
|
||||
}
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
// Copyright (c) 2020 Can Boluk
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// 2. 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.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// 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 OWNER 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.
|
||||
//
|
||||
#pragma once
|
||||
#include "../../img_common.hpp"
|
||||
#include "../symbol.hpp"
|
||||
|
||||
COFF_STRUCT_PACKING
|
||||
namespace coff
|
||||
{
|
||||
// Declare the data type.
|
||||
//
|
||||
struct aux_function_delimiter_t
|
||||
{
|
||||
uint32_t _pad0;
|
||||
uint16_t line_number; // Line number
|
||||
uint16_t _pad1;
|
||||
uint32_t _pad2;
|
||||
uint32_t sym_next_bf_idx; // Symbol table index for the next .bf index, if zero last entry.
|
||||
uint16_t _pad;
|
||||
};
|
||||
static_assert( sizeof( aux_function_delimiter_t ) == sizeof( symbol_t ), "Invalid auxiliary symbol." );
|
||||
|
||||
// Declare the matching logic.
|
||||
//
|
||||
template<>
|
||||
inline bool symbol_t::valid_aux<aux_function_delimiter_t>() const
|
||||
{
|
||||
return ( name.equals_s( ".bf" ) || name.equals_s( ".ef" ) ) &&
|
||||
storage_class == storage_class_id::function_delimiter;
|
||||
}
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
// Copyright (c) 2020 Can Boluk
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// 2. 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.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// 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 OWNER 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.
|
||||
//
|
||||
#pragma once
|
||||
#include <string_view>
|
||||
#include "../../img_common.hpp"
|
||||
#include "../symbol.hpp"
|
||||
|
||||
COFF_STRUCT_PACKING
|
||||
namespace coff
|
||||
{
|
||||
enum class comdat_select_id : uint8_t
|
||||
{
|
||||
invalid = 0,
|
||||
select_no_duplicates = 1, // Throw multiply defined symbol if matching entry found.
|
||||
select_any = 2, // Pick any, discard rest.
|
||||
select_same_size = 3, // If all options have equivalent sizes pick any, else throw multiply defined symbol.
|
||||
select_exact_match = 4, // If all options have equivalent size and checksums pick any, else throw multiply defined symbol.
|
||||
select_associative = 5, // Inherits COMDAT state of another section associated, useful for discaring multiple data and code with the same logic.
|
||||
select_largest = 6 // Picks the largest entry, if matching size arbitrarily chosen.
|
||||
};
|
||||
|
||||
// Declare the data type.
|
||||
//
|
||||
struct aux_section_t
|
||||
{
|
||||
// Generic information.
|
||||
//
|
||||
uint32_t length; // Length of the data, same as size of raw data.
|
||||
uint16_t num_relocs; // Number of relocation entries.
|
||||
uint16_t num_line_numbers; // Number of line number entries.
|
||||
|
||||
// COMDAT information, applicable if characteristics.lnk_comdat == true.
|
||||
//
|
||||
uint32_t checksum; // Checksum of the data for COMDAT matching.
|
||||
uint16_t associative_section; // One-based index into section table, only used if selection type is ::select_associative.
|
||||
comdat_select_id comdat_select; // COMDAT selection type.
|
||||
|
||||
uint8_t _pad[ 3 ];
|
||||
};
|
||||
static_assert( sizeof( aux_section_t ) == sizeof( symbol_t ), "Invalid auxiliary symbol." );
|
||||
|
||||
// Declare the matching logic.
|
||||
//
|
||||
template<>
|
||||
inline bool symbol_t::valid_aux<aux_section_t>() const
|
||||
{
|
||||
// Must also have matching names, but cannot be checked here.
|
||||
//
|
||||
return value == 0 &&
|
||||
storage_class == storage_class_id::private_symbol &&
|
||||
base_type == base_type_id::none &&
|
||||
derived_type == derived_type_id::none;
|
||||
}
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
// Copyright (c) 2020 Can Boluk
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// 2. 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.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// 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 OWNER 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.
|
||||
//
|
||||
#pragma once
|
||||
#include "../../img_common.hpp"
|
||||
#include "../symbol.hpp"
|
||||
|
||||
COFF_STRUCT_PACKING
|
||||
namespace coff
|
||||
{
|
||||
enum class weak_external_type : uint32_t
|
||||
{
|
||||
invalid = 0,
|
||||
no_library = 1, // No library search for sym1 should be performed.
|
||||
library = 2, // Library search for sym1 should be performed.
|
||||
alias = 3, // Sym1 is just an alias to Sym2.
|
||||
};
|
||||
|
||||
// Declare the data type.
|
||||
//
|
||||
struct aux_weak_external_t
|
||||
{
|
||||
uint32_t sym_alias_idx; // Index of sym2 that should be linked if sym1 does not exist.
|
||||
weak_external_type type; // Type of the weak external.
|
||||
uint8_t _pad[ 10 ];
|
||||
};
|
||||
static_assert( sizeof( aux_weak_external_t ) == sizeof( symbol_t ), "Invalid auxiliary symbol." );
|
||||
|
||||
// Declare the matching logic.
|
||||
//
|
||||
template<>
|
||||
inline bool symbol_t::valid_aux<aux_weak_external_t>() const
|
||||
{
|
||||
return storage_class == storage_class_id::weak_external &&
|
||||
section_index == special_section_id::symbol_undefined &&
|
||||
value == 0;
|
||||
}
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
|
@ -1,117 +0,0 @@
|
|||
// Copyright (c) 2020 Can Boluk
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// 2. 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.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// 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 OWNER 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.
|
||||
//
|
||||
#pragma once
|
||||
#include "../img_common.hpp"
|
||||
|
||||
WIN_STRUCT_PACKING
|
||||
namespace win
|
||||
{
|
||||
// File target machine
|
||||
//
|
||||
enum class machine_id : uint16_t
|
||||
{
|
||||
unknown = 0x0000,
|
||||
target_host = 0x0001, // Useful for indicating we want to interact with the host and not a WoW guest.
|
||||
i386 = 0x014C, // Intel 386.
|
||||
r3000 = 0x0162, // MIPS little-endian, 0x160 big-endian
|
||||
r4000 = 0x0166, // MIPS little-endian
|
||||
r10000 = 0x0168, // MIPS little-endian
|
||||
wcemipsv2 = 0x0169, // MIPS little-endian WCE v2
|
||||
alpha = 0x0184, // Alpha_AXP
|
||||
sh3 = 0x01A2, // SH3 little-endian
|
||||
sh3dsp = 0x01A3,
|
||||
sh3e = 0x01A4, // SH3E little-endian
|
||||
sh4 = 0x01A6, // SH4 little-endian
|
||||
sh5 = 0x01A8, // SH5
|
||||
arm = 0x01C0, // ARM Little-Endian
|
||||
thumb = 0x01C2, // ARM Thumb/Thumb-2 Little-Endian
|
||||
armnt = 0x01C4, // ARM Thumb-2 Little-Endian
|
||||
am33 = 0x01D3,
|
||||
powerpc = 0x01F0, // IBM PowerPC Little-Endian
|
||||
powerpcfp = 0x01F1,
|
||||
ia64 = 0x0200, // Intel 64
|
||||
mips16 = 0x0266, // MIPS
|
||||
alpha64 = 0x0284, // ALPHA64
|
||||
mipsfpu = 0x0366, // MIPS
|
||||
mipsfpu16 = 0x0466, // MIPS
|
||||
axp64 = 0x0284,
|
||||
tricore = 0x0520, // Infineon
|
||||
cef = 0x0CEF,
|
||||
ebc = 0x0EBC, // EFI Byte Code
|
||||
amd64 = 0x8664, // AMD64 (K8)
|
||||
m32r = 0x9041, // M32R little-endian
|
||||
arm64 = 0xAA64, // ARM64 Little-Endian
|
||||
cee = 0xC0EE,
|
||||
};
|
||||
|
||||
// File characteristics
|
||||
//
|
||||
union file_characteristics_t
|
||||
{
|
||||
uint16_t flags;
|
||||
struct
|
||||
{
|
||||
uint16_t relocs_stripped : 1; // Relocation info stripped from file.
|
||||
uint16_t executable : 1; // File is executable (i.e. no unresolved external references).
|
||||
uint16_t lines_stripped : 1; // Line nunbers stripped from file.
|
||||
uint16_t local_symbols_stripped : 1; // Local symbols stripped from file.
|
||||
uint16_t aggressive_ws_trim : 1; // Aggressively trim working set
|
||||
uint16_t large_address_aware : 1; // App can handle >2gb addresses
|
||||
uint16_t _pad0 : 1;
|
||||
uint16_t bytes_reversed_lo : 1; // Bytes of machine word are reversed.
|
||||
uint16_t machine_32 : 1; // 32 bit word machine.
|
||||
uint16_t debug_stripped : 1; // Debugging info stripped from file in .DBG file
|
||||
uint16_t runnable_from_swap : 1; // If Image is on removable media, copy and run from the swap file.
|
||||
uint16_t net_run_from_swap : 1; // If Image is on Net, copy and run from the swap file.
|
||||
uint16_t system_file : 1; // System File.
|
||||
uint16_t dll_file : 1; // File is a DLL.
|
||||
uint16_t up_system_only : 1; // File should only be run on a UP machine
|
||||
uint16_t bytes_reversed_hi : 1; // Bytes of machine word are reversed.
|
||||
};
|
||||
};
|
||||
|
||||
// File header
|
||||
//
|
||||
struct file_header_t
|
||||
{
|
||||
machine_id machine;
|
||||
uint16_t num_sections;
|
||||
uint32_t timedate_stamp;
|
||||
uint32_t ptr_symbols;
|
||||
uint32_t num_symbols;
|
||||
uint16_t size_optional_header;
|
||||
file_characteristics_t characteristics;
|
||||
};
|
||||
};
|
||||
namespace coff
|
||||
{
|
||||
using machine_id = win::machine_id;
|
||||
using file_header_t = win::file_header_t;
|
||||
using file_characteristics_t = win::file_characteristics_t;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
// Copyright (c) 2020 Can Boluk
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// 2. 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.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// 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 OWNER 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.
|
||||
//
|
||||
#pragma once
|
||||
#include "../img_common.hpp"
|
||||
#include "line_number.hpp"
|
||||
#include "reloc.hpp"
|
||||
#include "string.hpp"
|
||||
#include "symbol.hpp"
|
||||
#include "file_header.hpp"
|
||||
#include "import_library.hpp"
|
||||
#include "section_header.hpp"
|
||||
#include "auxiliaries/aux_file_name.hpp"
|
||||
#include "auxiliaries/aux_function.hpp"
|
||||
#include "auxiliaries/aux_function_delimiter.hpp"
|
||||
#include "auxiliaries/aux_section.hpp"
|
||||
#include "auxiliaries/aux_weak_external.hpp"
|
||||
|
||||
COFF_STRUCT_PACKING
|
||||
namespace coff
|
||||
{
|
||||
// Optional header and the header collection.
|
||||
//
|
||||
struct optional_header_t
|
||||
{
|
||||
// Only standard fields as described in the common object file format.
|
||||
//
|
||||
uint16_t magic;
|
||||
version_t linker_version;
|
||||
|
||||
uint32_t size_code;
|
||||
uint32_t size_init_data;
|
||||
uint32_t size_uninit_data;
|
||||
|
||||
uint32_t entry_point;
|
||||
uint32_t base_of_code;
|
||||
uint32_t base_of_data;
|
||||
};
|
||||
struct image_t
|
||||
{
|
||||
file_header_t file_header;
|
||||
optional_header_t optional_header;
|
||||
|
||||
// Section getter
|
||||
//
|
||||
inline section_header_t* get_sections() { return ( section_header_t* ) ( ( uint8_t* ) &optional_header + file_header.size_optional_header ); }
|
||||
inline const section_header_t* get_sections() const { return const_cast< image_t*>( this )->get_sections(); }
|
||||
inline section_header_t* get_section( size_t n ) { return get_sections() + n; }
|
||||
inline const section_header_t* get_section( size_t n ) const { return get_sections() + n; }
|
||||
|
||||
// Symbol table getter
|
||||
//
|
||||
inline symbol_t* get_symbols() { return ( symbol_t* ) ( ( uint8_t* ) this + file_header.ptr_symbols ); }
|
||||
inline const symbol_t* get_symbols() const { return const_cast< image_t* >( this )->get_symbols(); }
|
||||
inline symbol_t* get_symbol( size_t n ) { return get_symbols() + n; }
|
||||
inline const symbol_t* get_symbol( size_t n ) const { return get_symbols() + n; }
|
||||
|
||||
// String table getter.
|
||||
//
|
||||
inline string_table_t* get_strings() { return ( string_table_t* ) ( get_symbols() + file_header.num_symbols ); }
|
||||
inline const string_table_t* get_strings() const { return const_cast< image_t* >( this )->get_strings(); }
|
||||
};
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
// Copyright (c) 2020 Can Boluk
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// 2. 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.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// 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 OWNER 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.
|
||||
//
|
||||
#pragma once
|
||||
#include "../img_common.hpp"
|
||||
#include "file_header.hpp"
|
||||
#include <string_view>
|
||||
|
||||
COFF_STRUCT_PACKING
|
||||
namespace coff
|
||||
{
|
||||
static constexpr uint32_t import_lib_magic = 0xFFFF0000;
|
||||
|
||||
|
||||
enum class import_type : uint16_t // :2
|
||||
{
|
||||
code = 0, // Executable code.
|
||||
data = 1, // Data.
|
||||
rdata = 2, // Specified as CONST in the .def file.
|
||||
};
|
||||
enum class import_name_type : uint16_t // :3
|
||||
{
|
||||
ordinal = 0, // The import is by ordinal. This indicates that the value in the Ordinal/Hint field of the import header
|
||||
// is the import's ordinal. If this constant is not specified, then the Ordinal/Hint field should always be
|
||||
// interpreted as the import's hint.
|
||||
name = 1, // The import name is identical to the public symbol name.
|
||||
name_no_prefix = 2, // The import name is the public symbol name, but skipping the leading ?, @, or optionally _.
|
||||
name_no_undecorate = 3, // The import name is the public symbol name, but skipping the leading ?, @, or optionally _, and truncating at the first @.
|
||||
};
|
||||
|
||||
// Import library header.
|
||||
//
|
||||
struct import_header_t
|
||||
{
|
||||
uint32_t magic;
|
||||
version_t version;
|
||||
machine_id machine;
|
||||
uint32_t timedate_stamp;
|
||||
uint32_t data_size;
|
||||
union
|
||||
{
|
||||
uint16_t hint;
|
||||
uint16_t ordinal;
|
||||
};
|
||||
import_type type : 2;
|
||||
import_name_type name_type : 3;
|
||||
uint16_t reserved : 11;
|
||||
|
||||
const char* get_symbol_name() const { return ( const char* ) ( this + 1 ); }
|
||||
const char* get_library_name() const { return get_symbol_name() + strlen( get_symbol_name() ) + 1; }
|
||||
};
|
||||
static_assert( sizeof( import_header_t ) == 20, "Invalid enum bitfield." );
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
// Copyright (c) 2020 Can Boluk
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// 2. 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.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// 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 OWNER 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.
|
||||
//
|
||||
#pragma once
|
||||
#include "../img_common.hpp"
|
||||
|
||||
COFF_STRUCT_PACKING
|
||||
namespace coff
|
||||
{
|
||||
// Line number entry.
|
||||
//
|
||||
struct line_number_t
|
||||
{
|
||||
union
|
||||
{
|
||||
uint32_t symbol_index; // If first entry at line #0, symbol index to the function.
|
||||
uint32_t ptr_raw_data; // Else, raw offset from the beginning of the directory that this data relates to.
|
||||
};
|
||||
uint16_t line_number; // Line number.
|
||||
};
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
// Copyright (c) 2020 Can Boluk
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// 2. 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.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// 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 OWNER 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.
|
||||
//
|
||||
#pragma once
|
||||
#include "../img_common.hpp"
|
||||
|
||||
COFF_STRUCT_PACKING
|
||||
namespace coff
|
||||
{
|
||||
enum reloc_type : uint16_t
|
||||
{
|
||||
// AMD64:
|
||||
//
|
||||
rel_amd64_absolute = 0x0000, // The relocation is ignored.
|
||||
rel_amd64_addr64 = 0x0001, // The 64-bit VA of the relocation target.
|
||||
rel_amd64_addr32 = 0x0002, // The 32-bit VA of the relocation target.
|
||||
rel_amd64_addr32nb = 0x0003, // The 32-bit address without an image base (RVA).
|
||||
rel_amd64_rel32 = 0x0004, // The 32-bit relative address from the byte following the relocation.
|
||||
rel_amd64_rel32_1 = 0x0005, // The 32-bit address relative to byte distance 1 from the relocation.
|
||||
rel_amd64_rel32_2 = 0x0006, // The 32-bit address relative to byte distance 2 from the relocation.
|
||||
rel_amd64_rel32_3 = 0x0007, // The 32-bit address relative to byte distance 3 from the relocation.
|
||||
rel_amd64_rel32_4 = 0x0008, // The 32-bit address relative to byte distance 4 from the relocation.
|
||||
rel_amd64_rel32_5 = 0x0009, // The 32-bit address relative to byte distance 5 from the relocation.
|
||||
rel_amd64_section = 0x000A, // The 16-bit section index of the section that contains the target. This is used to support debugging information.
|
||||
rel_amd64_secrel = 0x000B, // The 32-bit offset of the target from the beginning of its section. This is used to support debugging information and static thread local storage.
|
||||
rel_amd64_secrel7 = 0x000C, // A 7-bit unsigned offset from the base of the section that contains the target.
|
||||
rel_amd64_token = 0x000D, // CLR tokens.
|
||||
rel_amd64_srel32 = 0x000E, // A 32-bit signed span-dependent value emitted into the object.
|
||||
rel_amd64_pair = 0x000F, // A pair that must immediately follow every span-dependent value.
|
||||
rel_amd64_sspan32 = 0x0010, // A 32-bit signed span-dependent value that is applied at link time.
|
||||
|
||||
// I386:
|
||||
//
|
||||
rel_i386_absolute = 0x0000, // The relocation is ignored.
|
||||
rel_i386_dir16 = 0x0001, // Not supported.
|
||||
rel_i386_rel16 = 0x0002, // Not supported.
|
||||
rel_i386_dir32 = 0x0006, // The target's 32-bit VA.
|
||||
rel_i386_dir32nb = 0x0007, // The target's 32-bit RVA.
|
||||
rel_i386_seg12 = 0x0009, // Not supported.
|
||||
rel_i386_section = 0x000A, // The 16-bit section index of the section that contains the target. This is used to support debugging information.
|
||||
rel_i386_secrel = 0x000B, // The 32-bit offset of the target from the beginning of its section. This is used to support debugging information and static thread local storage.
|
||||
rel_i386_token = 0x000C, // The CLR token.
|
||||
rel_i386_secrel7 = 0x000D, // A 7-bit offset from the base of the section that contains the target.
|
||||
rel_i386_rel32 = 0x0014, // The 32-bit relative displacement to the target. This supports the x86 relative branch and call instructions.
|
||||
};
|
||||
|
||||
// Relocation entry.
|
||||
//
|
||||
struct reloc_t
|
||||
{
|
||||
uint32_t virtual_address; // Virtual address of the relocated data.
|
||||
uint32_t symbol_index; // Symbol index.
|
||||
reloc_type type; // Type of the relocation applied.
|
||||
};
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
|
@ -1,112 +0,0 @@
|
|||
// Copyright (c) 2020 Can Boluk
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// 2. 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.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// 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 OWNER 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.
|
||||
//
|
||||
#pragma once
|
||||
#include "../img_common.hpp"
|
||||
#include "string.hpp"
|
||||
|
||||
WIN_STRUCT_PACKING
|
||||
namespace coff
|
||||
{
|
||||
// Section characteristics
|
||||
//
|
||||
union section_characteristics_t
|
||||
{
|
||||
uint32_t flags;
|
||||
struct
|
||||
{
|
||||
uint32_t _pad0 : 5;
|
||||
uint32_t cnt_code : 1; // Section contains code.
|
||||
uint32_t cnt_init_data : 1; // Section contains initialized data.
|
||||
uint32_t cnt_uninit_data : 1; // Section contains uninitialized data.
|
||||
uint32_t _pad1 : 1;
|
||||
uint32_t lnk_info : 1; // Section contains comments or some other type of information.
|
||||
uint32_t _pad2 : 1;
|
||||
uint32_t lnk_remove : 1; // Section contents will not become part of image.
|
||||
uint32_t lnk_comdat : 1; // Section contents comdat.
|
||||
uint32_t _pad3 : 1;
|
||||
uint32_t no_defer_spec_exc : 1; // Reset speculative exceptions handling bits in the TLB entries for this section.
|
||||
uint32_t mem_far : 1;
|
||||
uint32_t _pad4 : 1;
|
||||
uint32_t mem_purgeable : 1;
|
||||
uint32_t mem_locked : 1;
|
||||
uint32_t mem_preload : 1;
|
||||
uint32_t alignment : 4; // Alignment calculated as: n ? 1 << ( n - 1 ) : 16
|
||||
uint32_t lnk_nreloc_ovfl : 1; // Section contains extended relocations.
|
||||
uint32_t mem_discardable : 1; // Section can be discarded.
|
||||
uint32_t mem_not_cached : 1; // Section is not cachable.
|
||||
uint32_t mem_not_paged : 1; // Section is not pageable.
|
||||
uint32_t mem_shared : 1; // Section is shareable.
|
||||
uint32_t mem_execute : 1; // Section is executable.
|
||||
uint32_t mem_read : 1; // Section is readable.
|
||||
uint32_t mem_write : 1; // Section is writeable.
|
||||
};
|
||||
|
||||
inline size_t get_alignment() const { return win::convert_alignment( alignment ); }
|
||||
inline bool set_alignment( size_t align ) { return alignment = win::reflect_alignment( align ); }
|
||||
};
|
||||
|
||||
// Section header
|
||||
//
|
||||
struct section_header_t
|
||||
{
|
||||
scn_string_t name;
|
||||
union
|
||||
{
|
||||
uint32_t physical_address;
|
||||
uint32_t virtual_size;
|
||||
};
|
||||
uint32_t virtual_address;
|
||||
|
||||
uint32_t size_raw_data;
|
||||
uint32_t ptr_raw_data;
|
||||
|
||||
uint32_t ptr_relocs;
|
||||
uint32_t ptr_line_numbers;
|
||||
uint16_t num_relocs;
|
||||
uint16_t num_line_numbers;
|
||||
|
||||
section_characteristics_t characteristics;
|
||||
|
||||
// Characteristics NT checks based on the name as well as the real flag
|
||||
//
|
||||
bool is_paged() const
|
||||
{
|
||||
return !characteristics.mem_not_paged && ( *( uint32_t* ) &name.short_name == 'ade.' || *( uint32_t* ) &name.short_name == 'EGAP' );
|
||||
}
|
||||
bool is_discardable() const
|
||||
{
|
||||
return characteristics.mem_discardable || *( uint32_t* ) &name.short_name == 'TINI';
|
||||
}
|
||||
};
|
||||
};
|
||||
namespace win
|
||||
{
|
||||
using section_header_t = coff::section_header_t;
|
||||
using section_characteristics_t = coff::section_characteristics_t;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
|
@ -1,170 +0,0 @@
|
|||
// Copyright (c) 2020 Can Boluk
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// 2. 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.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// 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 OWNER 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.
|
||||
//
|
||||
#pragma once
|
||||
#include <string_view>
|
||||
#include <stdlib.h>
|
||||
#include <cstring>
|
||||
#include "../img_common.hpp"
|
||||
|
||||
COFF_STRUCT_PACKING
|
||||
namespace coff
|
||||
{
|
||||
// String table.
|
||||
//
|
||||
union string_table_t
|
||||
{
|
||||
uint32_t size;
|
||||
char raw_data[ VAR_LEN ];
|
||||
|
||||
// Resolves a string given the offset.
|
||||
//
|
||||
const char* begin() const { return size > 4 ? &raw_data[ 0 ] : nullptr; }
|
||||
const char* end() const { return size > 4 ? &raw_data[ size ] : nullptr; }
|
||||
std::string_view resolve( size_t offset ) const
|
||||
{
|
||||
// Fail if invalid offset.
|
||||
//
|
||||
if ( offset < 4 ) return {};
|
||||
|
||||
// Search for the null terminator, return if found.
|
||||
//
|
||||
const char* start = begin() + offset;
|
||||
const char* lim = end();
|
||||
for ( const char* it = start; it < lim; it++ )
|
||||
if ( !*it )
|
||||
return { start, ( size_t ) ( it - start ) };
|
||||
|
||||
// Invalid string.
|
||||
//
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
// External reference to string table.
|
||||
//
|
||||
struct string_t
|
||||
{
|
||||
union
|
||||
{
|
||||
char short_name[ LEN_SHORT_STR ]; // Name as inlined string.
|
||||
struct
|
||||
{
|
||||
uint32_t is_short; // If non-zero, name is inline'd into short_name, else has a long name.
|
||||
uint32_t long_name_offset; // Offset into string table.
|
||||
};
|
||||
};
|
||||
|
||||
// Convert to string view given an optional string table.
|
||||
//
|
||||
std::string_view to_string( const string_table_t* tbl = nullptr ) const
|
||||
{
|
||||
if ( tbl && !is_short )
|
||||
return tbl->resolve( long_name_offset );
|
||||
size_t len = 0;
|
||||
while ( len != LEN_SHORT_STR && short_name[ len ] ) len++;
|
||||
return { short_name, len };
|
||||
}
|
||||
|
||||
// Array lookup, only available for short strings.
|
||||
//
|
||||
char& operator[]( size_t n ) { return const_cast<char&>( to_string()[ n ] ); }
|
||||
const char& operator[]( size_t n ) const { return to_string()[ n ]; }
|
||||
|
||||
// Basic comparison primitive.
|
||||
//
|
||||
bool equals( const char* str, const string_table_t* tbl = nullptr ) const { return to_string( tbl ) == str; }
|
||||
|
||||
// Short string comparison primitive.
|
||||
//
|
||||
template<size_t N> requires( N <= ( LEN_SHORT_STR + 1 ) )
|
||||
bool equals_s( const char( &str )[ N ] ) const
|
||||
{
|
||||
// Compare with against empty string.
|
||||
//
|
||||
if constexpr ( N == 1 )
|
||||
return ( !is_short && !long_name_offset ) || ( is_short && !short_name[ 0 ] );
|
||||
|
||||
// Can skip is short check since if string is not null, is short will be overwritten.
|
||||
//
|
||||
if constexpr ( N == ( LEN_SHORT_STR + 1 ) )
|
||||
return !memcmp( short_name, str, LEN_SHORT_STR );
|
||||
else
|
||||
return !memcmp( short_name, str, N );
|
||||
}
|
||||
};
|
||||
|
||||
// Same as above but archive convention, used for section names.
|
||||
//
|
||||
struct scn_string_t
|
||||
{
|
||||
char short_name[ LEN_SHORT_STR ];
|
||||
|
||||
// Convert to string view given an optional string table.
|
||||
//
|
||||
std::string_view to_string( const string_table_t* tbl = nullptr ) const
|
||||
{
|
||||
if ( tbl && short_name[ 0 ] == '/' )
|
||||
{
|
||||
char* end = ( char* ) std::end( short_name );
|
||||
return tbl->resolve( strtoll( short_name + 1, &end, 10 ) );
|
||||
}
|
||||
|
||||
size_t len = 0;
|
||||
while ( len != LEN_SHORT_STR && short_name[ len ] ) len++;
|
||||
return { short_name, len };
|
||||
}
|
||||
|
||||
// Array lookup, only available for short strings.
|
||||
//
|
||||
char& operator[]( size_t n ) { return const_cast<char&>( to_string()[ n ] ); }
|
||||
const char& operator[]( size_t n ) const { return to_string()[ n ]; }
|
||||
|
||||
// Basic comparison primitive.
|
||||
//
|
||||
bool equals( const char* str, const string_table_t* tbl = nullptr ) const { return to_string( tbl ) == str; }
|
||||
|
||||
// Short string comparison primitive.
|
||||
//
|
||||
template<size_t N> requires( N <= ( LEN_SHORT_STR + 1 ) )
|
||||
bool equals_s( const char( &str )[ N ] ) const
|
||||
{
|
||||
// Compare with against empty string.
|
||||
//
|
||||
if constexpr ( N == 1 )
|
||||
return !short_name[ 0 ];
|
||||
|
||||
// Can skip is short check since if string is not null, is short will be overwritten.
|
||||
//
|
||||
if constexpr ( N == ( LEN_SHORT_STR + 1 ) )
|
||||
return !memcmp( short_name, str, LEN_SHORT_STR );
|
||||
else
|
||||
return !memcmp( short_name, str, N );
|
||||
}
|
||||
};
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
|
@ -1,140 +0,0 @@
|
|||
// Copyright (c) 2020 Can Boluk
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// 2. 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.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// 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 OWNER 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.
|
||||
//
|
||||
#pragma once
|
||||
#include "../img_common.hpp"
|
||||
#include "string.hpp"
|
||||
|
||||
COFF_STRUCT_PACKING
|
||||
namespace coff
|
||||
{
|
||||
// Special section indices.
|
||||
//
|
||||
enum special_section_id : uint16_t
|
||||
{
|
||||
symbol_undefined = 0, // External symbol
|
||||
symbol_absolute = 0xFFFF, // Absolute symbol, non-relocatable value.
|
||||
symbol_debug = 0xFFFE, // Misc. debugging info, not within a section.
|
||||
};
|
||||
|
||||
// Storage class.
|
||||
//
|
||||
enum class storage_class_id : uint8_t
|
||||
{
|
||||
none = 0, // None.
|
||||
auto_variable = 1, // Automatic variable.
|
||||
public_symbol = 2, // Public symbol, global.
|
||||
private_symbol = 3, // Private symbol, static.
|
||||
register_variable = 4, // Register variable.
|
||||
external_definition = 5, // External definition.
|
||||
label = 6, // Label.
|
||||
undefined_label = 7, // Undefined label.
|
||||
struct_member = 8, // Struct field.
|
||||
function_argument = 9, // Function argument.
|
||||
struct_tag = 10, // Struct tag.
|
||||
union_member = 11, // Union field.
|
||||
union_tag = 12, // Union tag.
|
||||
type_definition = 13, // Type definition.
|
||||
undefined_static = 14, // Undefined static.
|
||||
enum_tag = 15, // Enumerator tag.
|
||||
enum_member = 16, // Enumerator entry.
|
||||
register_parameter = 17, // Register parameter.
|
||||
bitfield = 18, // Marks a bitfield.
|
||||
auto_argument = 19, // Automatic argument.
|
||||
end_of_block = 20, // Marks the end of a block.
|
||||
block_delimiter = 100, // Marks the beginning or the end of a block.
|
||||
function_delimiter = 101, // Marks the beginning or the end of a function
|
||||
struct_end = 102, // Marks the end of a structure definition.
|
||||
file_name = 103, // File name as symbol.
|
||||
line_number = 104, // a) Line number as symbol.
|
||||
section = 104, // b) Section entry.
|
||||
alias_entry = 105, // a) Alias to another entry.
|
||||
weak_external = 105, // b) Weak external.
|
||||
hidden_ext_symbol = 106, // Hidden external symbol.
|
||||
clr_token = 107, // CLR token.
|
||||
phys_end_of_function = 255, // Marks physical end of a function.
|
||||
};
|
||||
|
||||
// Type identifiers.
|
||||
//
|
||||
enum class base_type_id : uint16_t
|
||||
{
|
||||
none = 0,
|
||||
t_void = 1,
|
||||
t_char = 2,
|
||||
t_short = 3,
|
||||
t_int = 4,
|
||||
t_long = 5,
|
||||
t_float = 6,
|
||||
t_double = 7,
|
||||
t_struct = 8,
|
||||
t_union = 9,
|
||||
t_enum = 10,
|
||||
t_enum_mem = 11,
|
||||
t_uchar = 12,
|
||||
t_ushort = 13,
|
||||
t_uint = 14,
|
||||
t_ulong = 15,
|
||||
};
|
||||
enum class derived_type_id : uint16_t
|
||||
{
|
||||
none = 0, // Not derived.
|
||||
pointer = 1, // Pointer to base type.
|
||||
function = 2, // Function returning base type.
|
||||
c_array = 3, // Array of base type.
|
||||
};
|
||||
|
||||
// Symbol table entry.
|
||||
//
|
||||
struct symbol_t
|
||||
{
|
||||
string_t name; // Name of the symbol.
|
||||
int32_t value; // Value associated with the symbol, interp. depends on the type, usually address of the entry.
|
||||
uint16_t section_index; // Special index or scn#+1.
|
||||
|
||||
base_type_id base_type : 4; // Base and derived type describing the symbol.
|
||||
derived_type_id derived_type : 12; //
|
||||
|
||||
storage_class_id storage_class; // Storage class as described above.
|
||||
uint8_t num_auxiliary; // Auxiliary data following this symbol.
|
||||
|
||||
// Dynamic logic for auxiliary entries.
|
||||
//
|
||||
template<typename T> bool valid_aux() const;
|
||||
|
||||
// Checks whether or not this symbol has a section.
|
||||
//
|
||||
bool has_section() const
|
||||
{
|
||||
return section_index != symbol_debug &&
|
||||
section_index != symbol_absolute &&
|
||||
section_index != symbol_undefined;
|
||||
}
|
||||
};
|
||||
static_assert( sizeof( symbol_t ) == 18, "Invalid enum bitfield." );
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
|
@ -1,119 +0,0 @@
|
|||
// Copyright (c) 2020 Can Boluk
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// 2. 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.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// 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 OWNER 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.
|
||||
//
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <tuple>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace coff
|
||||
{
|
||||
// Utility to encode/decode a ULEB128 value commonly seen in address signifiance tables.
|
||||
//
|
||||
inline void encode_uleb128( uint64_t value, std::vector<uint8_t>& out )
|
||||
{
|
||||
while( 1 )
|
||||
{
|
||||
// Push the value of the segment and shift the integer.
|
||||
//
|
||||
auto& segment = out.emplace_back( ( uint8_t ) ( value & 0x7F ) );
|
||||
value >>= 7;
|
||||
|
||||
// If we reached zero, break.
|
||||
//
|
||||
if ( !value ) break;
|
||||
segment |= 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename It1, typename It2>
|
||||
inline std::pair<uint64_t, bool> decode_uleb128( It1& it, It2&& end )
|
||||
{
|
||||
uint64_t value = 0;
|
||||
for ( size_t bitcnt = 0; it < end; ++it, bitcnt += 7 )
|
||||
{
|
||||
// Read one segment and write it into value.
|
||||
//
|
||||
uint8_t segment = *it;
|
||||
value |= uint64_t( segment & 0x7F ) << bitcnt;
|
||||
|
||||
// Make sure we did not overflow out of u64 range.
|
||||
//
|
||||
if ( ( value >> bitcnt ) != ( segment & 0x7F ) )
|
||||
return { value, false };
|
||||
|
||||
// If stream is terminated, return the value.
|
||||
//
|
||||
if ( !( segment & 0x80 ) )
|
||||
{
|
||||
++it;
|
||||
return { value, true };
|
||||
}
|
||||
}
|
||||
|
||||
// Invalid stream.
|
||||
//
|
||||
return { value, false };
|
||||
}
|
||||
|
||||
inline std::vector<uint8_t> encode_uleb128s( const std::vector<uint64_t>& values )
|
||||
{
|
||||
// Allocate a vector for the result and reserve the maximum size.
|
||||
//
|
||||
constexpr size_t max_size = ( 64 + 6 ) / 7;
|
||||
std::vector<uint8_t> result;
|
||||
result.reserve( values.size() * max_size );
|
||||
|
||||
// Encode every value and return.
|
||||
//
|
||||
for ( uint64_t value : values )
|
||||
encode_uleb128( value, result );
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename It1, typename It2>
|
||||
inline std::vector<uint64_t> decode_uleb128s( It1&& begin, It2&& end )
|
||||
{
|
||||
// Allocate a vector for the result and reserve an average result size assuming average integer is 22 bits.
|
||||
//
|
||||
constexpr size_t avg_size = ( 22 + 6 ) / 7;
|
||||
std::vector<uint64_t> result;
|
||||
result.reserve( ( end - begin ) * avg_size );
|
||||
|
||||
// Read until we reach the end, indicate failure by returning null.
|
||||
//
|
||||
auto it = begin;
|
||||
while ( it != end )
|
||||
{
|
||||
auto [val, success] = decode_uleb128( it, end );
|
||||
if ( !success ) return {};
|
||||
result.emplace_back( val );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -1,107 +0,0 @@
|
|||
// Copyright (c) 2020 Can Boluk
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// 2. 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.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// 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 OWNER 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.
|
||||
//
|
||||
#pragma once
|
||||
#include <type_traits>
|
||||
#include <stdint.h>
|
||||
#include <cstddef>
|
||||
|
||||
#define WIN_STRUCT_PACKING _Pragma("pack(push, 4)") // Structure packings of the variants.
|
||||
#define COFF_STRUCT_PACKING _Pragma("pack(push, 1)") //
|
||||
#define LEN_SHORT_STR 8 // Common short string length used in COFF and it's variants.
|
||||
|
||||
// If your compiler does not support zero-len arrays, define VAR_LEN as 1 before including linuxpe.
|
||||
//
|
||||
#ifndef VAR_LEN
|
||||
#ifndef _MSC_VER
|
||||
#define VAR_LEN 1
|
||||
#else
|
||||
#pragma warning(disable:4200)
|
||||
#define VAR_LEN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
COFF_STRUCT_PACKING
|
||||
namespace win
|
||||
{
|
||||
// Default image architecture
|
||||
//
|
||||
static constexpr bool default_architecture = sizeof( void* ) == 8;
|
||||
|
||||
// NT versioning
|
||||
//
|
||||
union version_t
|
||||
{
|
||||
uint16_t identifier;
|
||||
struct
|
||||
{
|
||||
uint8_t major;
|
||||
uint8_t minor;
|
||||
};
|
||||
};
|
||||
union ex_version_t
|
||||
{
|
||||
uint32_t identifier;
|
||||
struct
|
||||
{
|
||||
uint16_t major;
|
||||
uint16_t minor;
|
||||
};
|
||||
};
|
||||
|
||||
struct guid_t
|
||||
{
|
||||
uint32_t dword;
|
||||
uint16_t word[ 2 ];
|
||||
uint8_t byte[ 8 ];
|
||||
};
|
||||
|
||||
// Common alignment helpers
|
||||
// - Both return 0 on failure.
|
||||
//
|
||||
static constexpr size_t convert_alignment( uint8_t align_flag /*: 4*/ )
|
||||
{
|
||||
if ( align_flag == 0 )
|
||||
return 16;
|
||||
if ( align_flag >= 0xF )
|
||||
return 0;
|
||||
return 1ull << ( align_flag - 1 );
|
||||
}
|
||||
static constexpr uint8_t reflect_alignment( size_t alignment )
|
||||
{
|
||||
for ( uint8_t align_flag = 1; align_flag != 0xF; align_flag++ )
|
||||
if ( ( 1ull << ( align_flag - 1 ) ) >= alignment )
|
||||
return align_flag;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
namespace coff
|
||||
{
|
||||
using version_t = win::version_t;
|
||||
using ex_version_t = win::ex_version_t;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
#pragma once
|
||||
#include "coff/image.hpp"
|
||||
#include "nt/image.hpp"
|
||||
|
|
@ -1,138 +0,0 @@
|
|||
// Copyright (c) 2020 Can Boluk
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// 2. 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.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// 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 OWNER 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.
|
||||
//
|
||||
#pragma once
|
||||
#include "../img_common.hpp"
|
||||
|
||||
WIN_STRUCT_PACKING
|
||||
namespace win
|
||||
{
|
||||
static constexpr uint32_t NUM_DATA_DIRECTORIES = 16;
|
||||
|
||||
// Directory indices
|
||||
//
|
||||
enum directory_id : uint8_t
|
||||
{
|
||||
directory_entry_export = 0, // Export Directory
|
||||
directory_entry_import = 1, // Import Directory
|
||||
directory_entry_resource = 2, // Resource Directory
|
||||
directory_entry_exception = 3, // Exception Directory
|
||||
directory_entry_security = 4, // Security Directory
|
||||
directory_entry_basereloc = 5, // Base Relocation Table
|
||||
directory_entry_debug = 6, // Debug Directory
|
||||
directory_entry_copyright = 7, // (X86 usage)
|
||||
directory_entry_architecture = 7, // Architecture Specific Data
|
||||
directory_entry_globalptr = 8, // RVA of GP
|
||||
directory_entry_tls = 9, // TLS Directory
|
||||
directory_entry_load_config = 10, // Load Configuration Directory
|
||||
directory_entry_bound_import = 11, // Bound Import Directory in headers
|
||||
directory_entry_iat = 12, // Import Address Table
|
||||
directory_entry_delay_import = 13, // Delay Load Import Descriptors
|
||||
directory_entry_com_descriptor = 14, // COM Runtime descriptor
|
||||
directory_reserved0 = 15, // -
|
||||
};
|
||||
|
||||
// Declare generic mapping for indices
|
||||
//
|
||||
template<directory_id id, bool x64, typename = void>
|
||||
struct directory_type { using type = char; };
|
||||
template<directory_id id, bool x64>
|
||||
using directory_type_t = typename directory_type<id, x64>::type;
|
||||
|
||||
// Generic directory descriptors
|
||||
//
|
||||
struct data_directory_t
|
||||
{
|
||||
uint32_t rva;
|
||||
uint32_t size;
|
||||
inline bool present() const { return size; }
|
||||
};
|
||||
struct raw_data_directory_t
|
||||
{
|
||||
uint32_t ptr_raw_data;
|
||||
uint32_t size;
|
||||
inline bool present() const { return size; }
|
||||
};
|
||||
|
||||
// Data directories
|
||||
//
|
||||
struct data_directories_x86_t
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
data_directory_t export_directory;
|
||||
data_directory_t import_directory;
|
||||
data_directory_t resource_directory;
|
||||
data_directory_t exception_directory;
|
||||
raw_data_directory_t security_directory; // File offset instead of RVA!
|
||||
data_directory_t basereloc_directory;
|
||||
data_directory_t debug_directory;
|
||||
data_directory_t copyright_directory;
|
||||
data_directory_t globalptr_directory;
|
||||
data_directory_t tls_directory;
|
||||
data_directory_t load_config_directory;
|
||||
data_directory_t bound_import_directory;
|
||||
data_directory_t iat_directory;
|
||||
data_directory_t delay_import_directory;
|
||||
data_directory_t com_descriptor_directory;
|
||||
data_directory_t _reserved0;
|
||||
};
|
||||
data_directory_t entries[ NUM_DATA_DIRECTORIES ];
|
||||
};
|
||||
};
|
||||
struct data_directories_x64_t
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
data_directory_t export_directory;
|
||||
data_directory_t import_directory;
|
||||
data_directory_t resource_directory;
|
||||
data_directory_t exception_directory;
|
||||
raw_data_directory_t security_directory; // File offset instead of RVA!
|
||||
data_directory_t basereloc_directory;
|
||||
data_directory_t debug_directory;
|
||||
data_directory_t architecture_directory;
|
||||
data_directory_t globalptr_directory;
|
||||
data_directory_t tls_directory;
|
||||
data_directory_t load_config_directory;
|
||||
data_directory_t bound_import_directory;
|
||||
data_directory_t iat_directory;
|
||||
data_directory_t delay_import_directory;
|
||||
data_directory_t com_descriptor_directory;
|
||||
data_directory_t _reserved0;
|
||||
};
|
||||
data_directory_t entries[ NUM_DATA_DIRECTORIES ];
|
||||
};
|
||||
};
|
||||
template<bool x64 = default_architecture>
|
||||
using data_directories_t = std::conditional_t<x64, data_directories_x64_t, data_directories_x86_t>;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
|
@ -1,185 +0,0 @@
|
|||
// Copyright (c) 2020 Can Boluk
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// 2. 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.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// 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 OWNER 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.
|
||||
//
|
||||
#pragma once
|
||||
#include <utility>
|
||||
#include <string>
|
||||
|
||||
#include "../../img_common.hpp"
|
||||
#include "../data_directories.hpp"
|
||||
|
||||
WIN_STRUCT_PACKING
|
||||
namespace win
|
||||
{
|
||||
namespace impl
|
||||
{
|
||||
inline constexpr char hexdigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
||||
|
||||
inline constexpr void fmt_u8_0pad( char*& out, uint8_t value )
|
||||
{
|
||||
*out++ = hexdigits[ value >> 4 ];
|
||||
*out++ = hexdigits[ value & 0xF ];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline constexpr void fmt_uhex_0pad( char*& out, T value )
|
||||
{
|
||||
if constexpr ( sizeof( T ) == 1 )
|
||||
return fmt_u8_0pad( out, value );
|
||||
for ( size_t n = 0; n != sizeof( T ); n++ )
|
||||
fmt_u8_0pad( out, uint8_t( value >> ( ( sizeof( T ) - n - 1 ) * 8 ) ) );
|
||||
}
|
||||
|
||||
inline constexpr void fmt_udec( char*& out, uint32_t value )
|
||||
{
|
||||
size_t idx = 0;
|
||||
do
|
||||
{
|
||||
out[ idx++ ] = ( value % 10 ) + '0';
|
||||
value /= 10;
|
||||
}
|
||||
while ( value );
|
||||
|
||||
size_t swap_count = idx / 2;
|
||||
for ( size_t i = 0; i != swap_count; i++ )
|
||||
std::swap( out[ i ], out[ idx - i - 1 ] );
|
||||
|
||||
out += idx;
|
||||
}
|
||||
};
|
||||
|
||||
enum class debug_directory_type_id : uint32_t
|
||||
{
|
||||
unknown = 0x00000000,
|
||||
coff = 0x00000001,
|
||||
codeview = 0x00000002,
|
||||
fpo = 0x00000003,
|
||||
misc = 0x00000004,
|
||||
exception = 0x00000005,
|
||||
fixup = 0x00000006,
|
||||
omap_to_src = 0x00000007,
|
||||
omap_from_src = 0x00000008,
|
||||
borland = 0x00000009,
|
||||
reserved10 = 0x0000000A,
|
||||
clsid = 0x0000000B,
|
||||
vc_feature = 0x0000000C,
|
||||
pogo = 0x0000000D,
|
||||
iltcg = 0x0000000E,
|
||||
mpx = 0x0000000F,
|
||||
repro = 0x00000010,
|
||||
};
|
||||
|
||||
// Codeview headers
|
||||
//
|
||||
enum class cv_signature : uint32_t
|
||||
{
|
||||
cv41 = 0x3930424E, // 'NB09'
|
||||
pdb20 = 0x3031424E, // 'NB10'
|
||||
cv50 = 0x3131424E, // 'NB11'
|
||||
pdb70 = 0x53445352, // 'RSDS'
|
||||
};
|
||||
|
||||
struct cv_header_t
|
||||
{
|
||||
cv_signature signature;
|
||||
};
|
||||
|
||||
struct cv_pdb20_t : cv_header_t
|
||||
{
|
||||
uint32_t offset; // If not zero, stored within the image.
|
||||
uint32_t timedate_stamp;
|
||||
uint32_t age;
|
||||
|
||||
};
|
||||
|
||||
struct cv_pdb70_t : cv_header_t
|
||||
{
|
||||
guid_t guid;
|
||||
uint32_t age;
|
||||
char pdb_name[ VAR_LEN ];
|
||||
|
||||
// Formats into the MSDL format.
|
||||
//
|
||||
inline std::string format() const
|
||||
{
|
||||
std::string result;
|
||||
result.resize( 8 + 8 + 16 + 10 );
|
||||
|
||||
char* it = result.data();
|
||||
// u32 * 1 = 8 digits
|
||||
impl::fmt_uhex_0pad( it, guid.dword );
|
||||
// u16 * 2 = 8 digits
|
||||
for ( uint16_t v : guid.word )
|
||||
impl::fmt_uhex_0pad( it, v );
|
||||
// u8 * 8 = 16 digits
|
||||
for ( uint8_t v : guid.byte )
|
||||
impl::fmt_uhex_0pad( it, v );
|
||||
// u32 dec = max 10 digits
|
||||
impl::fmt_udec( it, age );
|
||||
|
||||
result.resize( it - result.data() );
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
// Misc headers
|
||||
//
|
||||
enum class misc_debug_data_id : uint32_t
|
||||
{
|
||||
exe_name = 1,
|
||||
};
|
||||
|
||||
struct misc_debug_data_t
|
||||
{
|
||||
misc_debug_data_id data_type;
|
||||
uint32_t record_length;
|
||||
uint8_t is_unicode;
|
||||
uint8_t _pad[ 3 ];
|
||||
uint8_t data[ VAR_LEN ];
|
||||
};
|
||||
|
||||
// Directory type.
|
||||
//
|
||||
struct debug_directory_entry_t
|
||||
{
|
||||
uint32_t characteristics;
|
||||
uint32_t timedate_stamp;
|
||||
ex_version_t version;
|
||||
debug_directory_type_id type;
|
||||
uint32_t size_raw_data;
|
||||
uint32_t rva_raw_data;
|
||||
uint32_t ptr_raw_data;
|
||||
};
|
||||
|
||||
struct debug_directory_t
|
||||
{
|
||||
debug_directory_entry_t entries[ VAR_LEN ];
|
||||
};
|
||||
|
||||
template<bool x64> struct directory_type<directory_id::directory_entry_debug, x64, void> { using type = debug_directory_t; };
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
// Copyright (c) 2020 Can Boluk
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// 2. 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.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// 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 OWNER 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.
|
||||
//
|
||||
#pragma once
|
||||
#include "../../img_common.hpp"
|
||||
#include "../data_directories.hpp"
|
||||
|
||||
WIN_STRUCT_PACKING
|
||||
namespace win
|
||||
{
|
||||
union delay_load_attributes_t
|
||||
{
|
||||
uint32_t flags;
|
||||
struct
|
||||
{
|
||||
uint32_t rva_based : 1;
|
||||
uint32_t reserved : 31;
|
||||
};
|
||||
};
|
||||
|
||||
struct delay_load_directory_t
|
||||
{
|
||||
delay_load_attributes_t attributes;
|
||||
uint32_t dll_name_rva;
|
||||
uint32_t module_handle_rva;
|
||||
uint32_t import_address_table_rva;
|
||||
uint32_t import_name_table_rva;
|
||||
uint32_t bound_import_address_table_rva;
|
||||
uint32_t unload_information_table_rva;
|
||||
uint32_t time_date_stamp;
|
||||
};
|
||||
|
||||
template<bool x64> struct directory_type<directory_id::directory_entry_delay_import, x64, void> { using type = delay_load_directory_t; };
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
|
@ -1,582 +0,0 @@
|
|||
// Copyright (c) 2020 Can Boluk
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// 2. 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.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// 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 OWNER 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.
|
||||
//
|
||||
#pragma once
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
#include <map>
|
||||
#include "../../img_common.hpp"
|
||||
#include "../data_directories.hpp"
|
||||
|
||||
WIN_STRUCT_PACKING
|
||||
namespace win
|
||||
{
|
||||
using xmm_t = std::array<uint64_t, 2>;
|
||||
|
||||
// Unwind opcodes.
|
||||
//
|
||||
enum class unwind_opcode : uint16_t // : 4
|
||||
{
|
||||
push_nonvol = 0x0, // info == register number
|
||||
alloc_large = 0x1, // no info, alloc size in next 2 slots
|
||||
alloc_small = 0x2, // info == size of allocation / 8 - 1
|
||||
set_frame = 0x3, // no info, FP = RSP + UNWIND_INFO.FPRegOffset*16
|
||||
save_nonvol = 0x4, // info == register number, offset in next slot
|
||||
save_nonvol_far = 0x5, // info == register number, offset in next 2 slots
|
||||
epilog = 0x6, // (?)
|
||||
spare_code = 0x7, // (?)
|
||||
save_xmm128 = 0x8, // info == XMM reg number, offset in next slot
|
||||
save_xmm128_far = 0x9, // info == XMM reg number, offset in next 2 slots
|
||||
push_machframe = 0xa, // info == 0: no error-code, 1: error-code
|
||||
maximum
|
||||
};
|
||||
|
||||
// Unwind register identifiers.
|
||||
//
|
||||
enum class unwind_register_id : uint8_t // : 4
|
||||
{
|
||||
amd64_rax = 0, // GP
|
||||
amd64_rcx = 1,
|
||||
amd64_rdx = 2,
|
||||
amd64_rbx = 3,
|
||||
amd64_rsp = 4,
|
||||
amd64_rbp = 5,
|
||||
amd64_rsi = 6,
|
||||
amd64_rdi = 7,
|
||||
amd64_r8 = 8,
|
||||
amd64_r9 = 9,
|
||||
amd64_r10 = 10,
|
||||
amd64_r11 = 11,
|
||||
amd64_r12 = 12,
|
||||
amd64_r13 = 13,
|
||||
amd64_r14 = 14,
|
||||
amd64_r15 = 15,
|
||||
amd64_eflags = 16, // Fake GP entries used by our helper.
|
||||
amd64_rip = 17, //
|
||||
amd64_seg_ss = 18, //
|
||||
amd64_seg_cs = 19, //
|
||||
|
||||
amd64_xmm0 = 24 + 0, // XMM, has artifical offset added.
|
||||
amd64_xmm1 = 24 + 1, //
|
||||
amd64_xmm2 = 24 + 2, //
|
||||
amd64_xmm3 = 24 + 3, //
|
||||
amd64_xmm4 = 24 + 4, //
|
||||
amd64_xmm5 = 24 + 5, //
|
||||
amd64_xmm6 = 24 + 6, //
|
||||
amd64_xmm7 = 24 + 7, //
|
||||
amd64_xmm8 = 24 + 8, //
|
||||
amd64_xmm9 = 24 + 9, //
|
||||
amd64_xmm10 = 24 + 10, //
|
||||
amd64_xmm11 = 24 + 11, //
|
||||
amd64_xmm12 = 24 + 12, //
|
||||
amd64_xmm13 = 24 + 13, //
|
||||
amd64_xmm14 = 24 + 14, //
|
||||
amd64_xmm15 = 24 + 15, //
|
||||
|
||||
nat_amd64_xmm0 = 0, // XMM, original range found in the native structure.
|
||||
nat_amd64_xmm1 = 1, //
|
||||
nat_amd64_xmm2 = 2, //
|
||||
nat_amd64_xmm3 = 3, //
|
||||
nat_amd64_xmm4 = 4, //
|
||||
nat_amd64_xmm5 = 5, //
|
||||
nat_amd64_xmm6 = 6, //
|
||||
nat_amd64_xmm7 = 7, //
|
||||
nat_amd64_xmm8 = 8, //
|
||||
nat_amd64_xmm9 = 9, //
|
||||
nat_amd64_xmm10 = 10, //
|
||||
nat_amd64_xmm11 = 11, //
|
||||
nat_amd64_xmm12 = 12, //
|
||||
nat_amd64_xmm13 = 13, //
|
||||
nat_amd64_xmm14 = 14, //
|
||||
nat_amd64_xmm15 = 15, //
|
||||
};
|
||||
|
||||
// Unwind code and info descriptors.
|
||||
//
|
||||
struct runtime_function_t;
|
||||
struct unwind_code_t
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint16_t code_offset : 8;
|
||||
unwind_opcode unwind_op : 4;
|
||||
uint16_t op_info : 4;
|
||||
};
|
||||
};
|
||||
};
|
||||
struct unwind_info_t
|
||||
{
|
||||
uint8_t version : 3;
|
||||
|
||||
uint8_t ex_handler : 1;
|
||||
uint8_t term_handler : 1;
|
||||
uint8_t chained : 1;
|
||||
uint8_t reserved_flags : 2;
|
||||
|
||||
uint8_t size_prologue;
|
||||
uint8_t num_uw_codes;
|
||||
|
||||
unwind_register_id frame_register : 4;
|
||||
uint8_t frame_offset : 4;
|
||||
|
||||
unwind_code_t unwind_code[ VAR_LEN ]; // # = align( num_uw_codes, 2 )
|
||||
|
||||
// Getter for the scaled frame offset.
|
||||
//
|
||||
int64_t get_frame_offset() const { return ( int64_t ) ( ( ( uint32_t ) frame_offset ) * 16 ); }
|
||||
|
||||
// Followed by rva of language specific information:
|
||||
//
|
||||
void* get_language_specific_data() { return &unwind_code[ ( num_uw_codes + 1 ) & ~1 ]; }
|
||||
const void* get_language_specific_data() const { return const_cast< unwind_info_t* >( this )->get_language_specific_data(); }
|
||||
|
||||
uint32_t& exception_handler_rva() { return *( uint32_t* ) get_language_specific_data(); }
|
||||
const uint32_t& exception_handler_rva() const { return const_cast< unwind_info_t* >( this )->exception_handler_rva(); }
|
||||
|
||||
runtime_function_t& chained_function_entry() { return *( runtime_function_t* ) get_language_specific_data(); }
|
||||
const runtime_function_t& chained_function_entry() const { return const_cast< unwind_info_t* >( this )->chained_function_entry(); }
|
||||
|
||||
// Followed by optional exception data.
|
||||
//
|
||||
void* exception_specific_data() { return &exception_handler_rva() + 1; }
|
||||
const void* exception_specific_data() const { return const_cast< unwind_info_t* >( this )->exception_specific_data(); }
|
||||
};
|
||||
|
||||
// High level descriptors of the opcodes.
|
||||
//
|
||||
struct amd64_unwind_code_t : unwind_code_t
|
||||
{
|
||||
// Returns the number of entries occupied by this opcode.
|
||||
//
|
||||
//size_t get_size() const = 0;
|
||||
|
||||
// Applies or reverts this record's described side effect.
|
||||
//
|
||||
struct state_t
|
||||
{
|
||||
using reg_resolver_t = void* ( * )( void* ctx, unwind_register_id reg );
|
||||
using rmemcpy_t = bool( * )( void* ctx, void* dst, uint64_t src, size_t n );
|
||||
using wmemcpy_t = bool( * )( void* ctx, uint64_t dst, const void* src, size_t n );
|
||||
|
||||
// Provided by the user.
|
||||
//
|
||||
uint8_t frame_offset = 0; // Information from the function entry.
|
||||
win::unwind_register_id frame_register = {}; //
|
||||
void* context = nullptr; // User-defined context.
|
||||
reg_resolver_t resolve_reg = nullptr; // Should get a pointer to the value of the register specified in the second argument.
|
||||
rmemcpy_t rmemcpy = nullptr; // Safe memory operations, if not set will use current process.
|
||||
wmemcpy_t wmemcpy = nullptr; //
|
||||
|
||||
// Implement wrappers for some common operations.
|
||||
//
|
||||
uint64_t& gp( unwind_register_id gp_reg ) const { return *( uint64_t* ) resolve_reg( context, gp_reg ); }
|
||||
xmm_t& xmm( unwind_register_id xmm_reg ) const { return *( xmm_t* ) resolve_reg( context, xmm_reg ); }
|
||||
uint16_t& ss() const { return *( uint16_t* ) resolve_reg( context, unwind_register_id::amd64_seg_ss ); }
|
||||
uint16_t& cs() const { return *( uint16_t* ) resolve_reg( context, unwind_register_id::amd64_seg_cs ); }
|
||||
uint32_t& flags() const { return *( uint32_t* ) resolve_reg( context, unwind_register_id::amd64_eflags ); }
|
||||
|
||||
uint64_t& sp() const { return gp( unwind_register_id::amd64_rsp ); }
|
||||
uint64_t& ip() const { return gp( unwind_register_id::amd64_rip ); }
|
||||
uint64_t& frame() const { return gp( frame_register ); }
|
||||
|
||||
template<typename T>
|
||||
bool read( T& out, uint64_t address ) const
|
||||
{
|
||||
if ( rmemcpy ) return rmemcpy( context, &out, address, sizeof( T ) );
|
||||
if ( !address ) return false;
|
||||
memcpy( &out, ( const void* ) address, sizeof( T ) );
|
||||
return true;
|
||||
}
|
||||
template<typename T>
|
||||
bool write( uint64_t address, const T& data ) const
|
||||
{
|
||||
if ( wmemcpy ) return wmemcpy( context, address, &data, sizeof( T ) );
|
||||
if ( !address ) return false;
|
||||
memcpy( ( void* ) address, &data, sizeof( T ) );
|
||||
return true;
|
||||
}
|
||||
};
|
||||
//bool rewind( const state_t& state ) const = 0;
|
||||
//bool unwind( const state_t& state ) const = 0;
|
||||
};
|
||||
using amd64_unwind_state_t = amd64_unwind_code_t::state_t;
|
||||
struct amd64_unwind_set_frame_t : amd64_unwind_code_t
|
||||
{
|
||||
// Implement the interface.
|
||||
//
|
||||
size_t get_size() const { return 1; }
|
||||
bool rewind( const state_t& state ) const
|
||||
{
|
||||
state.frame() = state.sp() + ( size_t( state.frame_offset ) * 16 );
|
||||
return true;
|
||||
}
|
||||
bool unwind( const state_t& state ) const
|
||||
{
|
||||
state.sp() = state.frame() - ( size_t( state.frame_offset ) * 16 );
|
||||
return true;
|
||||
}
|
||||
};
|
||||
struct amd64_unwind_alloc_t : amd64_unwind_code_t
|
||||
{
|
||||
// Implement helpers.
|
||||
//
|
||||
size_t get_allocation_size() const
|
||||
{
|
||||
if ( unwind_op == unwind_opcode::alloc_small )
|
||||
return uint64_t( op_info ) * 8 + 8;
|
||||
if ( op_info ) return *( uint32_t* ) ( this + 1 );
|
||||
else return 8 * ( uint64_t ) * ( uint16_t* ) ( this + 1 );
|
||||
}
|
||||
|
||||
// Implement the interface.
|
||||
//
|
||||
size_t get_size() const
|
||||
{
|
||||
if ( unwind_op == unwind_opcode::alloc_small )
|
||||
return 1;
|
||||
return op_info ? 3 : 2;
|
||||
}
|
||||
bool rewind( const state_t& state ) const
|
||||
{
|
||||
state.sp() -= get_allocation_size();
|
||||
return true;
|
||||
}
|
||||
bool unwind( const state_t& state ) const
|
||||
{
|
||||
state.sp() += get_allocation_size();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
struct amd64_unwind_push_t : amd64_unwind_code_t
|
||||
{
|
||||
// Implement helpers.
|
||||
//
|
||||
unwind_register_id get_register() const { return ( unwind_register_id ) op_info; }
|
||||
|
||||
// Implement the interface.
|
||||
//
|
||||
size_t get_size() const { return 1; }
|
||||
bool rewind( const state_t& state ) const
|
||||
{
|
||||
if ( !state.write( state.sp() - 8, state.gp( get_register() ) ) )
|
||||
return false;
|
||||
state.sp() -= 8;
|
||||
return true;
|
||||
}
|
||||
bool unwind( const state_t& state ) const
|
||||
{
|
||||
if ( !state.read( state.gp( get_register() ), state.sp() ) )
|
||||
return false;
|
||||
state.sp() += 8;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
struct amd64_unwind_save_gp_t : amd64_unwind_code_t
|
||||
{
|
||||
// Implement helpers.
|
||||
//
|
||||
int64_t get_sp_offset() const
|
||||
{
|
||||
if ( unwind_op == unwind_opcode::save_nonvol_far )
|
||||
return ( int64_t ) ( *( uint32_t* ) ( this + 1 ) );
|
||||
else
|
||||
return ( int64_t ) ( 8 * ( uint64_t ) * ( uint16_t* ) ( this + 1 ) );
|
||||
}
|
||||
unwind_register_id get_register() const { return ( unwind_register_id ) op_info; }
|
||||
|
||||
// Implement the interface.
|
||||
//
|
||||
size_t get_size() const { return unwind_op == unwind_opcode::save_nonvol_far ? 3 : 2; }
|
||||
bool rewind( const state_t& state ) const
|
||||
{
|
||||
return state.write( state.sp() + get_sp_offset(), state.gp( get_register() ) );
|
||||
}
|
||||
bool unwind( const state_t& state ) const
|
||||
{
|
||||
return state.read( state.gp( get_register() ), state.sp() + get_sp_offset() );
|
||||
}
|
||||
};
|
||||
struct amd64_unwind_save_xmm_t : amd64_unwind_code_t
|
||||
{
|
||||
// Implement helpers.
|
||||
//
|
||||
int64_t get_sp_offset() const
|
||||
{
|
||||
if ( unwind_op == unwind_opcode::save_xmm128_far )
|
||||
return ( int64_t ) ( *( uint32_t* ) ( this + 1 ) );
|
||||
else
|
||||
return ( int64_t ) ( 16 * ( uint64_t ) * ( uint16_t* ) ( this + 1 ) );
|
||||
}
|
||||
unwind_register_id get_register() const { return ( unwind_register_id ) ( size_t( unwind_register_id::amd64_xmm0 ) + op_info ); }
|
||||
|
||||
// Implement the interface.
|
||||
//
|
||||
size_t get_size() const { return unwind_op == unwind_opcode::save_xmm128_far ? 3 : 2; }
|
||||
bool rewind( const state_t& state ) const
|
||||
{
|
||||
return state.write( state.sp() + get_sp_offset(), state.xmm( get_register() ) );
|
||||
}
|
||||
bool unwind( const state_t& state ) const
|
||||
{
|
||||
return state.read( state.xmm( get_register() ), state.sp() + get_sp_offset() );
|
||||
}
|
||||
};
|
||||
struct amd64_unwind_iframe_t : amd64_unwind_code_t
|
||||
{
|
||||
// Implement helpers.
|
||||
//
|
||||
bool has_exception_code() const { return op_info; }
|
||||
|
||||
// Implement the interface.
|
||||
//
|
||||
size_t get_size() const { return 1; }
|
||||
bool rewind( [[maybe_unused]] const state_t& state ) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool unwind( const state_t& state ) const
|
||||
{
|
||||
size_t offset = 0;
|
||||
if ( has_exception_code() ) offset += 8;
|
||||
|
||||
bool success =
|
||||
state.read( state.ip(), state.sp() + offset + 8 * 0 ) &&
|
||||
state.read( state.cs(), state.sp() + offset + 8 * 1 ) &&
|
||||
state.read( state.flags(), state.sp() + offset + 8 * 2 ) &&
|
||||
state.read( state.sp(), state.sp() + offset + 8 * 3 ) &&
|
||||
state.read( state.ss(), state.sp() + offset + 8 * 4 );
|
||||
if ( !success ) return false;
|
||||
state.sp() += offset + 8 * 4;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
struct amd64_unwind_nop_t : amd64_unwind_code_t
|
||||
{
|
||||
size_t get_size() const { return 1; }
|
||||
bool rewind( [[maybe_unused]] const state_t& state ) const { return true; }
|
||||
bool unwind( [[maybe_unused]] const state_t& state ) const { return true; }
|
||||
};
|
||||
|
||||
// Special unwind helper for unwinding after the function returns.
|
||||
//
|
||||
static bool amd64_unwind_call( const amd64_unwind_state_t& state )
|
||||
{
|
||||
// Read the return pointer.
|
||||
//
|
||||
if ( !state.read( state.ip(), state.sp() ) )
|
||||
return false;
|
||||
state.sp() += 8;
|
||||
|
||||
// Basic attempt at decoding the instruction to unwind rip.
|
||||
//
|
||||
uint8_t call_region[ 16 ] = { 0 };
|
||||
for ( size_t n = 0; n != 16; n++ )
|
||||
state.read( call_region[ n ], state.ip() - n );
|
||||
|
||||
// call reg rel
|
||||
if ( call_region[ 6 ] == 0xFF && ( call_region[ 7 ] & 0xF0 ) == 0x40 )
|
||||
state.ip() -= 7;
|
||||
else if ( call_region[ 6 ] == 0xFF )
|
||||
state.ip() -= 6;
|
||||
// call imm
|
||||
else if ( call_region[ 5 ] == 0xE8 )
|
||||
state.ip() -= 5;
|
||||
// call reg
|
||||
else if ( call_region[ 2 ] == 0xFF && ( call_region[ 3 ] & 0xF0 ) == 0x40 )
|
||||
state.ip() -= 3;
|
||||
else if ( call_region[ 2 ] == 0xFF )
|
||||
state.ip() -= 2;
|
||||
// int
|
||||
else if ( call_region[ 2 ] == 0xCD )
|
||||
state.ip() -= 2;
|
||||
else if ( call_region[ 1 ] == 0xCC )
|
||||
state.ip() -= 1;
|
||||
else if ( call_region[ 1 ] == 0xF1 )
|
||||
state.ip() -= 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
template<unwind_opcode op> struct amd64_unwind;
|
||||
template<> struct amd64_unwind<unwind_opcode::push_nonvol> { using type = amd64_unwind_push_t; };
|
||||
template<> struct amd64_unwind<unwind_opcode::alloc_large> { using type = amd64_unwind_alloc_t; };
|
||||
template<> struct amd64_unwind<unwind_opcode::alloc_small> { using type = amd64_unwind_alloc_t; };
|
||||
template<> struct amd64_unwind<unwind_opcode::set_frame> { using type = amd64_unwind_set_frame_t; };
|
||||
template<> struct amd64_unwind<unwind_opcode::save_nonvol> { using type = amd64_unwind_save_gp_t; };
|
||||
template<> struct amd64_unwind<unwind_opcode::save_nonvol_far> { using type = amd64_unwind_save_gp_t; };
|
||||
template<> struct amd64_unwind<unwind_opcode::save_xmm128> { using type = amd64_unwind_save_xmm_t; };
|
||||
template<> struct amd64_unwind<unwind_opcode::save_xmm128_far> { using type = amd64_unwind_save_xmm_t; };
|
||||
template<> struct amd64_unwind<unwind_opcode::push_machframe> { using type = amd64_unwind_iframe_t; };
|
||||
template<> struct amd64_unwind<unwind_opcode::spare_code> { using type = amd64_unwind_nop_t; };
|
||||
template<> struct amd64_unwind<unwind_opcode::epilog> { using type = amd64_unwind_nop_t; };
|
||||
template<unwind_opcode op>
|
||||
using amd64_unwind_t = typename amd64_unwind<op>::type;
|
||||
|
||||
template<typename T>
|
||||
static bool visit_amd64_unwind( const unwind_code_t& code, T&& visitor )
|
||||
{
|
||||
switch ( ( unwind_opcode ) code.unwind_op )
|
||||
{
|
||||
case unwind_opcode::push_nonvol: visitor( ( const amd64_unwind_t<unwind_opcode::push_nonvol> * ) & code ); return true;
|
||||
case unwind_opcode::alloc_large: visitor( ( const amd64_unwind_t<unwind_opcode::alloc_large> * ) & code ); return true;
|
||||
case unwind_opcode::alloc_small: visitor( ( const amd64_unwind_t<unwind_opcode::alloc_small> * ) & code ); return true;
|
||||
case unwind_opcode::set_frame: visitor( ( const amd64_unwind_t<unwind_opcode::set_frame> * ) & code ); return true;
|
||||
case unwind_opcode::save_nonvol: visitor( ( const amd64_unwind_t<unwind_opcode::save_nonvol> * ) & code ); return true;
|
||||
case unwind_opcode::save_nonvol_far: visitor( ( const amd64_unwind_t<unwind_opcode::save_nonvol_far> * ) & code ); return true;
|
||||
case unwind_opcode::epilog: visitor( ( const amd64_unwind_t<unwind_opcode::epilog> * ) & code ); return true;
|
||||
case unwind_opcode::spare_code: visitor( ( const amd64_unwind_t<unwind_opcode::spare_code> * ) & code ); return true;
|
||||
case unwind_opcode::save_xmm128: visitor( ( const amd64_unwind_t<unwind_opcode::save_xmm128> * ) & code ); return true;
|
||||
case unwind_opcode::save_xmm128_far: visitor( ( const amd64_unwind_t<unwind_opcode::save_xmm128_far> * ) & code ); return true;
|
||||
case unwind_opcode::push_machframe: visitor( ( const amd64_unwind_t<unwind_opcode::push_machframe> * ) & code ); return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Very commonly used language-specific data, C scope table.
|
||||
//
|
||||
struct c_scope_table_entry_t
|
||||
{
|
||||
uint32_t rva_begin;
|
||||
uint32_t rva_end;
|
||||
uint32_t rva_handler;
|
||||
uint32_t rva_target;
|
||||
};
|
||||
struct c_scope_table_t
|
||||
{
|
||||
uint32_t num_entries;
|
||||
c_scope_table_entry_t entries[ VAR_LEN ];
|
||||
};
|
||||
|
||||
// Function table and the directory itself.
|
||||
//
|
||||
struct runtime_function_t
|
||||
{
|
||||
uint32_t rva_begin;
|
||||
uint32_t rva_end;
|
||||
union
|
||||
{
|
||||
uint32_t unwind_info;
|
||||
uint32_t rva_unwind_info;
|
||||
};
|
||||
};
|
||||
struct exception_directory_t
|
||||
{
|
||||
// Length of this array is determined by the size of the directory
|
||||
//
|
||||
runtime_function_t functions[ VAR_LEN ];
|
||||
};
|
||||
template<bool x64> struct directory_type<directory_id::directory_entry_exception, x64, void> { using type = exception_directory_t; };
|
||||
|
||||
// Wrapper around exception directory.
|
||||
//
|
||||
struct exception_directory
|
||||
{
|
||||
// std::map like traits.
|
||||
//
|
||||
struct key_compare
|
||||
{
|
||||
constexpr bool operator()( const runtime_function_t& a, const runtime_function_t& b ) const noexcept
|
||||
{
|
||||
return a.rva_begin < b.rva_begin;
|
||||
}
|
||||
};
|
||||
struct key_compare_end
|
||||
{
|
||||
constexpr bool operator()( const runtime_function_t& a, const runtime_function_t& b ) const noexcept
|
||||
{
|
||||
return a.rva_end < b.rva_end;
|
||||
}
|
||||
};
|
||||
using key_type = uint32_t;
|
||||
using mapped_type = runtime_function_t;
|
||||
using value_type = runtime_function_t;
|
||||
using size_type = size_t;
|
||||
using difference_type = ptrdiff_t;
|
||||
using iterator = const runtime_function_t*;
|
||||
using const_iterator = const runtime_function_t*;
|
||||
using pointer = const runtime_function_t*;
|
||||
using const_pointer = const runtime_function_t*;
|
||||
using reference = const runtime_function_t&;
|
||||
using const_reference = const runtime_function_t&;
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
|
||||
// The range it's viewing.
|
||||
//
|
||||
const runtime_function_t* table;
|
||||
size_t length;
|
||||
|
||||
// Constructed with a pointer to the data and the raw length in bytes.
|
||||
//
|
||||
constexpr exception_directory() : table( nullptr ), length( 0 ) {}
|
||||
constexpr exception_directory( const void* data, size_t length )
|
||||
: table( ( runtime_function_t* ) data ), length( length / sizeof( runtime_function_t ) ) {}
|
||||
|
||||
// Default copy/move.
|
||||
//
|
||||
constexpr exception_directory( exception_directory&& ) noexcept = default;
|
||||
constexpr exception_directory( const exception_directory& ) = default;
|
||||
constexpr exception_directory& operator=( exception_directory& ) noexcept = default;
|
||||
constexpr exception_directory& operator=( const exception_directory& ) = default;
|
||||
|
||||
// Make it iterable.
|
||||
//
|
||||
constexpr iterator begin() const { return table; }
|
||||
constexpr iterator end() const { return table + length; }
|
||||
constexpr reverse_iterator rbegin() const { return reverse_iterator( end() ); }
|
||||
constexpr reverse_iterator rend() const { return reverse_iterator( begin() ); }
|
||||
|
||||
// Basic properties.
|
||||
//
|
||||
constexpr size_t size() const { return length; }
|
||||
constexpr bool empty() const { return length == 0; }
|
||||
|
||||
// Finds a function using binary search.
|
||||
//
|
||||
constexpr iterator find_overlapping( uint32_t rva ) const
|
||||
{
|
||||
iterator it = std::upper_bound( begin(), end(), runtime_function_t{ .rva_end = rva }, key_compare_end{} );
|
||||
if ( it != end() && !( it->rva_begin <= rva && rva < it->rva_end ) )
|
||||
it = end();
|
||||
return it;
|
||||
}
|
||||
constexpr iterator find( uint32_t rva ) const
|
||||
{
|
||||
iterator it = std::upper_bound( begin(), end(), runtime_function_t{ .rva_end = rva }, key_compare_end{} );
|
||||
if ( it != end() && it->rva_begin != rva )
|
||||
it = end();
|
||||
return it;
|
||||
}
|
||||
constexpr bool contains( uint32_t rva ) const
|
||||
{
|
||||
return find( rva ) != end();
|
||||
}
|
||||
};
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
// Copyright (c) 2020 Can Boluk
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// 2. 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.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// 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 OWNER 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.
|
||||
//
|
||||
#pragma once
|
||||
#include "../../img_common.hpp"
|
||||
#include "../data_directories.hpp"
|
||||
|
||||
WIN_STRUCT_PACKING
|
||||
namespace win
|
||||
{
|
||||
struct export_directory_t
|
||||
{
|
||||
uint32_t characteristics;
|
||||
uint32_t timedate_stamp;
|
||||
ex_version_t version;
|
||||
uint32_t name;
|
||||
uint32_t base;
|
||||
uint32_t num_functions;
|
||||
uint32_t num_names;
|
||||
uint32_t rva_functions;
|
||||
uint32_t rva_names;
|
||||
uint32_t rva_name_ordinals;
|
||||
};
|
||||
|
||||
template<bool x64> struct directory_type<directory_id::directory_entry_export, x64, void> { using type = export_directory_t; };
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
// Copyright (c) 2020 Can Boluk
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// 2. 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.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// 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 OWNER 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.
|
||||
//
|
||||
#pragma once
|
||||
#include "../../img_common.hpp"
|
||||
#include "../data_directories.hpp"
|
||||
|
||||
WIN_STRUCT_PACKING
|
||||
namespace win
|
||||
{
|
||||
struct image_named_import_t
|
||||
{
|
||||
uint16_t hint;
|
||||
char name[ 1 ];
|
||||
};
|
||||
|
||||
struct image_thunk_data_x64_t
|
||||
{
|
||||
union
|
||||
{
|
||||
uint64_t forwarder_string;
|
||||
uint64_t function;
|
||||
uint64_t address; // -> image_named_import_t
|
||||
struct
|
||||
{
|
||||
uint64_t ordinal : 16;
|
||||
uint64_t _reserved0 : 47;
|
||||
uint64_t is_ordinal : 1;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
struct image_thunk_data_x86_t
|
||||
{
|
||||
union
|
||||
{
|
||||
uint32_t forwarder_string;
|
||||
uint32_t function;
|
||||
uint32_t address; // -> image_named_import_t
|
||||
struct
|
||||
{
|
||||
uint32_t ordinal : 16;
|
||||
uint32_t _reserved0 : 15;
|
||||
uint32_t is_ordinal : 1;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
struct bound_forwarder_ref_t
|
||||
{
|
||||
uint32_t timedate_stamp;
|
||||
uint16_t offset_module_name;
|
||||
};
|
||||
|
||||
struct bound_import_descriptor_t
|
||||
{
|
||||
uint32_t timedate_stamp;
|
||||
uint16_t offset_module_name;
|
||||
uint16_t num_module_forwarder_refs;
|
||||
};
|
||||
|
||||
template<bool x64 = default_architecture>
|
||||
using image_thunk_data_t = std::conditional_t<x64, image_thunk_data_x64_t, image_thunk_data_x86_t>;
|
||||
|
||||
template<bool x64> struct directory_type<directory_id::directory_entry_iat, x64, void> { using type = image_thunk_data_t<x64>; };
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
// Copyright (c) 2020 Can Boluk
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// 2. 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.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// 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 OWNER 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.
|
||||
//
|
||||
#pragma once
|
||||
#include "../../img_common.hpp"
|
||||
#include "../data_directories.hpp"
|
||||
|
||||
WIN_STRUCT_PACKING
|
||||
namespace win
|
||||
{
|
||||
struct import_directory_t
|
||||
{
|
||||
union
|
||||
{
|
||||
uint32_t characteristics; // 0 for terminating null import descriptor
|
||||
uint32_t rva_original_first_thunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
|
||||
};
|
||||
uint32_t timedate_stamp; // 0 if not bound,
|
||||
// -1 if bound, and real date ime stamp
|
||||
// in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)
|
||||
// O.W. date/time stamp of DLL bound to (Old BIND)
|
||||
|
||||
uint32_t forwarder_chain; // -1 if no forwarders
|
||||
uint32_t rva_name;
|
||||
uint32_t rva_first_thunk; // RVA to IAT (if bound this IAT has actual addresses)
|
||||
};
|
||||
|
||||
template<bool x64> struct directory_type<directory_id::directory_entry_import, x64, void> { using type = import_directory_t; };
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
|
@ -1,278 +0,0 @@
|
|||
// Copyright (c) 2020 Can Boluk
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// 2. 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.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// 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 OWNER 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.
|
||||
//
|
||||
#pragma once
|
||||
#include "../../img_common.hpp"
|
||||
#include "../data_directories.hpp"
|
||||
#include "dir_relocs.hpp"
|
||||
|
||||
WIN_STRUCT_PACKING
|
||||
namespace win
|
||||
{
|
||||
// Enclave configuration
|
||||
//
|
||||
struct enclave_config_x64_t
|
||||
{
|
||||
uint32_t size;
|
||||
uint32_t minimum_required_config_size;
|
||||
uint32_t policy_flags;
|
||||
uint32_t number_of_imports;
|
||||
uint32_t import_list;
|
||||
uint32_t import_entry_size;
|
||||
uint8_t family_id[ 16 ];
|
||||
uint8_t image_id[ 16 ];
|
||||
uint32_t image_version;
|
||||
uint32_t security_version;
|
||||
uint64_t enclave_size;
|
||||
uint32_t number_of_threads;
|
||||
uint32_t enclave_flags;
|
||||
};
|
||||
struct enclave_config_x86_t
|
||||
{
|
||||
uint32_t size;
|
||||
uint32_t minimum_required_config_size;
|
||||
uint32_t policy_flags;
|
||||
uint32_t number_of_imports;
|
||||
uint32_t import_list;
|
||||
uint32_t import_entry_size;
|
||||
uint8_t family_id[ 16 ];
|
||||
uint8_t image_id[ 16 ];
|
||||
uint32_t image_version;
|
||||
uint32_t security_version;
|
||||
uint32_t enclave_size;
|
||||
uint32_t number_of_threads;
|
||||
uint32_t enclave_flags;
|
||||
};
|
||||
template<bool x64 = default_architecture>
|
||||
using enclave_config_t = std::conditional_t<x64, enclave_config_x64_t, enclave_config_x86_t>;
|
||||
|
||||
// Dynamic relocations
|
||||
//
|
||||
enum class dynamic_reloc_entry_id
|
||||
{
|
||||
guard_rf_prologue = 1,
|
||||
guard_rf_epilogue = 2,
|
||||
guard_import_control_transfer = 3,
|
||||
guard_indir_control_transfer = 4,
|
||||
guard_switch_table_branch = 5,
|
||||
};
|
||||
|
||||
struct dynamic_reloc_guard_rf_prologue_t
|
||||
{
|
||||
uint8_t prologue_size;
|
||||
uint8_t prologue_bytes[ VAR_LEN ];
|
||||
};
|
||||
|
||||
struct dynamic_reloc_guard_rf_epilogue_t
|
||||
{
|
||||
uint32_t epilogue_count;
|
||||
uint8_t epilogue_size;
|
||||
uint8_t branch_descriptor_element_size;
|
||||
uint16_t branch_descriptor_count;
|
||||
uint8_t branch_descriptors[ VAR_LEN ];
|
||||
|
||||
inline uint8_t* get_branch_descriptor_bit_map() { return branch_descriptors + branch_descriptor_count * branch_descriptor_element_size; }
|
||||
inline const uint8_t* get_branch_descriptor_bit_map() const { return const_cast< dynamic_reloc_guard_rf_epilogue_t* >( this )->get_branch_descriptor_bit_map(); }
|
||||
};
|
||||
|
||||
struct dynamic_reloc_import_control_transfer_t
|
||||
{
|
||||
uint32_t page_relative_offset : 12;
|
||||
uint32_t indirect_call : 1;
|
||||
uint32_t iat_index : 19;
|
||||
};
|
||||
|
||||
struct dynamic_reloc_indir_control_transfer_t
|
||||
{
|
||||
uint16_t page_relative_offset : 12;
|
||||
uint16_t indirect_call : 1;
|
||||
uint16_t rex_w_prefix : 1;
|
||||
uint16_t cfg_check : 1;
|
||||
uint16_t _pad0 : 1;
|
||||
};
|
||||
|
||||
struct dynamic_reloc_guard_switch_table_branch_t
|
||||
{
|
||||
uint16_t page_relative_offset : 12;
|
||||
uint16_t register_number : 4;
|
||||
};
|
||||
|
||||
template<bool x64 = default_architecture>
|
||||
struct dynamic_reloc_v1_t
|
||||
{
|
||||
using va_t = std::conditional_t<x64, uint64_t, uint32_t>;
|
||||
|
||||
va_t symbol;
|
||||
uint32_t size;
|
||||
reloc_block_t first_block;
|
||||
|
||||
inline reloc_block_t* begin() { return &first_block; }
|
||||
inline const reloc_block_t* begin() const { return &first_block; }
|
||||
inline reloc_block_t* end() { return ( reloc_block_t* ) next(); }
|
||||
inline const reloc_block_t* end() const { return ( const reloc_block_t* ) next(); }
|
||||
|
||||
inline dynamic_reloc_v1_t* next() { return ( dynamic_reloc_v1_t* ) ( ( char* ) &first_block + this->size ); }
|
||||
inline const dynamic_reloc_v1_t* next() const { return const_cast< dynamic_reloc_v1_t* >( this )->next(); }
|
||||
};
|
||||
using dynamic_reloc_v1_x86_t = dynamic_reloc_v1_t<false>;
|
||||
using dynamic_reloc_v1_x64_t = dynamic_reloc_v1_t<true>;
|
||||
|
||||
template<bool x64 = default_architecture>
|
||||
struct dynamic_reloc_v2_t
|
||||
{
|
||||
using va_t = std::conditional_t<x64, uint64_t, uint32_t>;
|
||||
|
||||
uint32_t header_size;
|
||||
uint32_t fixup_info_size;
|
||||
va_t symbol;
|
||||
uint32_t symbol_group;
|
||||
uint32_t flags;
|
||||
uint8_t fixup_info[ VAR_LEN ];
|
||||
|
||||
const void* end() const { return fixup_info + fixup_info_size; }
|
||||
};
|
||||
using dynamic_reloc_v2_x86_t = dynamic_reloc_v2_t<false>;
|
||||
using dynamic_reloc_v2_x64_t = dynamic_reloc_v2_t<true>;
|
||||
|
||||
// Dynamic relocation table
|
||||
//
|
||||
template<bool x64 = default_architecture>
|
||||
struct dynamic_reloc_table_t
|
||||
{
|
||||
uint32_t version;
|
||||
uint32_t size;
|
||||
union
|
||||
{
|
||||
dynamic_reloc_v1_t<x64> v1_begin; // Variable length array.
|
||||
dynamic_reloc_v2_t<x64> v2_begin; // Variable length array.
|
||||
};
|
||||
|
||||
const void* end() const { return ( char* ) &v1_begin + size; }
|
||||
};
|
||||
using dynamic_reloc_table_x86_t = dynamic_reloc_table_t<false>;
|
||||
using dynamic_reloc_table_x64_t = dynamic_reloc_table_t<true>;
|
||||
|
||||
// Hot patch information
|
||||
//
|
||||
struct hotpatch_base_t
|
||||
{
|
||||
uint32_t sequence_number;
|
||||
uint32_t flags;
|
||||
uint32_t orginal_timedate_stamp;
|
||||
uint32_t orginal_checksum;
|
||||
uint32_t code_integrity_info;
|
||||
uint32_t code_integrity_size;
|
||||
uint32_t path_table;
|
||||
uint32_t buffer_offset;
|
||||
};
|
||||
|
||||
struct hotpatch_info_t
|
||||
{
|
||||
uint32_t version;
|
||||
uint32_t size;
|
||||
uint32_t sequence_number;
|
||||
uint32_t base_image_list;
|
||||
uint32_t base_image_count;
|
||||
uint32_t buffer_offset;
|
||||
uint32_t extra_patch_size;
|
||||
};
|
||||
|
||||
struct hotpatch_hashes_t
|
||||
{
|
||||
uint8_t sha256[ 32 ];
|
||||
uint8_t sha1[ 20 ];
|
||||
};
|
||||
|
||||
// Code integrity information
|
||||
//
|
||||
struct load_config_ci_t
|
||||
{
|
||||
uint16_t flags; // Flags to indicate if CI information is available, etc.
|
||||
uint16_t catalog; // 0xFFFF means not available
|
||||
uint32_t rva_catalog;
|
||||
uint32_t _pad0; // Additional bitmask to be defined later
|
||||
};
|
||||
|
||||
template<bool x64 = default_architecture>
|
||||
struct load_config_directory_t
|
||||
{
|
||||
// Architecture dependent typedefs
|
||||
//
|
||||
using va_t = std::conditional_t<x64, uint64_t, uint32_t>;
|
||||
using vsize_t = va_t;
|
||||
|
||||
struct table_t
|
||||
{
|
||||
va_t virtual_address;
|
||||
vsize_t count;
|
||||
};
|
||||
|
||||
// Directory description
|
||||
//
|
||||
uint32_t size;
|
||||
uint32_t timedate_stamp;
|
||||
ex_version_t version;
|
||||
uint32_t global_flags_clear;
|
||||
uint32_t global_flags_set;
|
||||
uint32_t critical_section_default_timeout;
|
||||
vsize_t decommit_free_block_threshold;
|
||||
vsize_t decommit_total_free_threshold;
|
||||
va_t lock_prefix_table;
|
||||
vsize_t maximum_allocation_size;
|
||||
vsize_t virtual_memory_threshold;
|
||||
vsize_t process_affinity_mask;
|
||||
uint32_t process_heap_flags;
|
||||
uint16_t csd_version;
|
||||
uint16_t dependent_load_flags;
|
||||
va_t edit_list;
|
||||
va_t security_cookie;
|
||||
table_t se_handler_table;
|
||||
va_t guard_cf_check_function_ptr;
|
||||
va_t guard_cf_dispatch_function_ptr;
|
||||
table_t guard_cf_function_table;
|
||||
uint32_t guard_flags;
|
||||
load_config_ci_t code_integrity;
|
||||
table_t guard_address_taken_iat_entry_table;
|
||||
table_t guard_long_jump_target_table;
|
||||
va_t dynamic_value_reloc_table;
|
||||
va_t chpe_metadata_ptr; // hybrid_metadata_ptr @ v1607
|
||||
va_t guard_rf_failure_routine;
|
||||
va_t guard_rf_failure_routine_function_ptr;
|
||||
uint32_t dynamic_value_reloc_table_offset;
|
||||
uint16_t dynamic_value_reloc_table_section;
|
||||
va_t guard_rf_verify_stack_ptr_function_ptr;
|
||||
uint32_t hotpatch_table_offset;
|
||||
uint32_t reserved;
|
||||
va_t enclave_configuration_ptr;
|
||||
va_t volatile_metadata_ptr;
|
||||
table_t guard_eh_continuation_table;
|
||||
};
|
||||
using load_config_directory_x86_t = load_config_directory_t<false>;
|
||||
using load_config_directory_x64_t = load_config_directory_t<true>;
|
||||
template<bool x64> struct directory_type<directory_id::directory_entry_load_config, x64, void> { using type = load_config_directory_t<x64>; };
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
// Copyright (c) 2020 Can Boluk
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// 2. 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.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// 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 OWNER 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.
|
||||
//
|
||||
#pragma once
|
||||
#include "../../img_common.hpp"
|
||||
#include "../data_directories.hpp"
|
||||
|
||||
WIN_STRUCT_PACKING
|
||||
namespace win
|
||||
{
|
||||
enum reloc_type_id : uint16_t
|
||||
{
|
||||
rel_based_absolute = 0,
|
||||
rel_based_high = 1,
|
||||
rel_based_low = 2,
|
||||
rel_based_high_low = 3,
|
||||
rel_based_high_adj = 4,
|
||||
rel_based_ia64_imm64 = 9,
|
||||
rel_based_dir64 = 10,
|
||||
};
|
||||
|
||||
struct reloc_entry_t
|
||||
{
|
||||
uint16_t offset : 12;
|
||||
reloc_type_id type : 4;
|
||||
};
|
||||
static_assert( sizeof( reloc_entry_t ) == 2, "Enum bitfield is not supported." );
|
||||
|
||||
struct reloc_block_t
|
||||
{
|
||||
uint32_t base_rva;
|
||||
uint32_t size_block;
|
||||
reloc_entry_t entries[ VAR_LEN ];
|
||||
|
||||
inline reloc_block_t* next() { return ( reloc_block_t* ) ( ( char* ) this + this->size_block ); }
|
||||
inline const reloc_block_t* next() const { return const_cast< reloc_block_t* >( this )->next(); }
|
||||
inline size_t num_entries() const { return ( reloc_entry_t* ) next() - &entries[ 0 ]; }
|
||||
|
||||
inline reloc_entry_t* begin() { return &entries[ 0 ]; }
|
||||
inline const reloc_entry_t* begin() const { return &entries[ 0 ]; }
|
||||
inline reloc_entry_t* end() { return ( reloc_entry_t* ) next(); }
|
||||
inline const reloc_entry_t* end() const { return ( const reloc_entry_t* ) next(); }
|
||||
};
|
||||
|
||||
struct reloc_directory_t
|
||||
{
|
||||
reloc_block_t first_block;
|
||||
};
|
||||
|
||||
template<bool x64> struct directory_type<directory_id::directory_entry_basereloc, x64, void> { using type = reloc_directory_t; };
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
|
@ -1,290 +0,0 @@
|
|||
// Copyright (c) 2020 Can Boluk
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// 2. 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.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// 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 OWNER 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.
|
||||
//
|
||||
#pragma once
|
||||
#include <type_traits>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <iterator>
|
||||
#include "../../img_common.hpp"
|
||||
#include "../data_directories.hpp"
|
||||
|
||||
WIN_STRUCT_PACKING
|
||||
namespace win
|
||||
{
|
||||
// Resource type identifiers
|
||||
//
|
||||
enum class resource_id : uint16_t
|
||||
{
|
||||
cursor = 1,
|
||||
bitmap = 2,
|
||||
icon = 3,
|
||||
menu = 4,
|
||||
dialog = 5,
|
||||
string = 6,
|
||||
font_dir = 7,
|
||||
font = 8,
|
||||
accelerator = 9,
|
||||
rcdata = 10,
|
||||
message_table = 11,
|
||||
group_cursor = 12,
|
||||
group_icon = 14,
|
||||
version = 16,
|
||||
dlg_include = 17,
|
||||
plug_play = 19,
|
||||
vxd = 20,
|
||||
ani_cursor = 21,
|
||||
ani_icon = 22,
|
||||
html = 23,
|
||||
manifest = 24,
|
||||
};
|
||||
|
||||
// String entry
|
||||
//
|
||||
struct rsrc_string_t
|
||||
{
|
||||
uint16_t length;
|
||||
wchar_t name[ VAR_LEN ];
|
||||
inline std::wstring_view view() const { return { name, length }; }
|
||||
};
|
||||
|
||||
// Data entry
|
||||
//
|
||||
struct rsrc_data_t
|
||||
{
|
||||
uint32_t rva_data;
|
||||
uint32_t size_data;
|
||||
uint32_t code_page;
|
||||
uint32_t reserved;
|
||||
};
|
||||
|
||||
// Generic entry
|
||||
//
|
||||
struct rsrc_generic_t
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t offset_name : 31;
|
||||
uint32_t is_named : 1;
|
||||
};
|
||||
uint16_t identifier;
|
||||
};
|
||||
uint32_t offset : 31;
|
||||
uint32_t is_directory : 1;
|
||||
};
|
||||
|
||||
// Directory entry
|
||||
//
|
||||
struct rsrc_directory_t
|
||||
{
|
||||
uint32_t characteristics;
|
||||
uint32_t timedate_stamp;
|
||||
ex_version_t version;
|
||||
uint16_t num_named_entries;
|
||||
uint16_t num_id_entries;
|
||||
rsrc_generic_t entries[ VAR_LEN ];
|
||||
|
||||
inline size_t num_entries() const { return ( size_t ) num_named_entries + num_id_entries; }
|
||||
|
||||
// (Tree root) Helper to resolve entry referenced by rsrc_generic_t::offset
|
||||
//
|
||||
template<typename T> inline T* at( uint32_t offset ) { return ( T* ) ( ( char* ) this + offset ); }
|
||||
template<typename T> inline const T* at( uint32_t offset ) const { return ( T* ) ( ( char* ) this + offset ); }
|
||||
|
||||
// (Tree root) Explicit optional field accessors
|
||||
//
|
||||
inline rsrc_data_t* as_data( const rsrc_generic_t& entry ) { return !entry.is_directory ? at<rsrc_data_t>( entry.offset ) : nullptr; }
|
||||
inline rsrc_string_t* get_name( const rsrc_generic_t& entry ) { return entry.is_named ? at<rsrc_string_t>( entry.offset_name ) : nullptr; }
|
||||
inline rsrc_directory_t* as_directory( const rsrc_generic_t& entry ) { return entry.is_directory ? at<rsrc_directory_t>( entry.offset ) : nullptr; }
|
||||
inline const rsrc_data_t* as_data( const rsrc_generic_t& entry ) const { return !entry.is_directory ? at<rsrc_data_t>( entry.offset ) : nullptr; }
|
||||
inline const rsrc_string_t* get_name( const rsrc_generic_t& entry ) const { return entry.is_named ? at<rsrc_string_t>( entry.offset_name ) : nullptr; }
|
||||
inline const rsrc_directory_t* as_directory( const rsrc_generic_t& entry ) const { return entry.is_directory ? at<rsrc_directory_t>( entry.offset ) : nullptr; }
|
||||
};
|
||||
|
||||
// Iterator type propagating reference to tree root
|
||||
//
|
||||
enum rsrc_directory_depth : int32_t
|
||||
{
|
||||
rsrc_null = -1,
|
||||
rsrc_type_directory = 0,
|
||||
rsrc_name_directory = 1,
|
||||
rsrc_lang_directory = 2,
|
||||
rsrc_node = 3
|
||||
};
|
||||
template<bool C>
|
||||
struct base_rsrc_iterator_t
|
||||
{
|
||||
template<typename T> using M = std::conditional_t<C, std::add_const_t<T>, T>;
|
||||
|
||||
// Declare tree traits
|
||||
//
|
||||
using entry_t = M<rsrc_generic_t>;
|
||||
using data_t = M<rsrc_data_t>;
|
||||
using directory_t = M<rsrc_directory_t>;
|
||||
|
||||
// Declare container traits
|
||||
//
|
||||
using iterator = base_rsrc_iterator_t<C>;
|
||||
using const_iterator = base_rsrc_iterator_t<true>;
|
||||
|
||||
// Declare iterator traits
|
||||
//
|
||||
using iterator_category = std::bidirectional_iterator_tag;
|
||||
using difference_type = int32_t;
|
||||
using reference = base_rsrc_iterator_t<C>;
|
||||
using pointer = void*;
|
||||
|
||||
// Tree root, current level and the current entry
|
||||
//
|
||||
directory_t* root = nullptr;
|
||||
directory_t* level = nullptr;
|
||||
size_t idx = 0;
|
||||
int32_t depth = rsrc_type_directory;
|
||||
|
||||
// Implement bidirectional iteration and basic comparison
|
||||
//
|
||||
inline iterator& operator++() { idx++; return *this; }
|
||||
inline iterator& operator--() { idx--; return *this; }
|
||||
inline iterator operator++( int ) { auto s = *this; operator++(); return s; }
|
||||
inline iterator operator--( int ) { auto s = *this; operator--(); return s; }
|
||||
inline bool operator==( const iterator& other ) const { return root == other.root && level == other.level && idx == other.idx; }
|
||||
inline bool operator!=( const iterator& other ) const { return root != other.root || level != other.level || idx != other.idx; }
|
||||
|
||||
// Implement tree interface
|
||||
//
|
||||
inline bool is_null() const { return !level; }
|
||||
inline entry_t& entry() { return level->entries[ idx ]; }
|
||||
inline const entry_t& entry() const { return level->entries[ idx ]; }
|
||||
inline bool has_name() const { return entry().is_named; }
|
||||
inline std::wstring_view name() const { return has_name() ? root->get_name( entry() )->view() : L""; }
|
||||
inline bool has_id() const { return !entry().is_named; }
|
||||
inline uint16_t id() const { return has_id() ? entry().identifier : 0; }
|
||||
inline resource_id rid() const { return ( resource_id ) id(); }
|
||||
inline bool is_data() const { return !entry().is_directory; }
|
||||
inline data_t* data() { return root->as_data( entry() ); }
|
||||
inline const data_t* data() const { return root->as_data( entry() ); }
|
||||
inline bool is_directory() const { return entry().is_directory; }
|
||||
inline directory_t* directory() { return root->as_directory( entry() ); }
|
||||
inline const directory_t* directory() const { return root->as_directory( entry() ); }
|
||||
inline explicit operator bool() const { return !is_null(); }
|
||||
|
||||
// Implement iterator interface
|
||||
//
|
||||
inline iterator& operator*() { return *this; }
|
||||
inline const_iterator& operator*() const { return *this; }
|
||||
inline data_t* operator->() { return data(); }
|
||||
inline const data_t* operator->() const { return data(); }
|
||||
inline operator const const_iterator&() const { return *( const_iterator* ) this; }
|
||||
|
||||
// Implement container interface
|
||||
// - operator[] is used for lookups.
|
||||
//
|
||||
inline bool empty() const { return size() == 0; }
|
||||
inline size_t size() const { return !is_null() && is_directory() ? directory()->num_entries() : 0; }
|
||||
inline iterator at( size_t n ) { return { .root = root, .level = directory(), .idx = n, .depth = depth + 1 }; }
|
||||
inline const_iterator at( size_t n ) const { return const_cast< iterator* >( this )->at( n ); }
|
||||
inline iterator begin() { return at( 0 ); }
|
||||
inline iterator end() { return at( size() ); }
|
||||
inline const_iterator begin() const { return at( 0 ); }
|
||||
inline const_iterator end() const { return at( size() ); }
|
||||
inline iterator front() { return at( 0 ); }
|
||||
inline iterator back() { return at( size() - 1 ); }
|
||||
inline const_iterator front() const { return at( 0 ); }
|
||||
inline const_iterator back() const { return at( size() - 1 ); }
|
||||
|
||||
// Implement lookups.
|
||||
//
|
||||
template<typename T>
|
||||
inline iterator find_if( T&& fn ) const
|
||||
{
|
||||
for ( auto it = begin(); it.idx != size(); ++it )
|
||||
if ( fn( it ) ) return it;
|
||||
return { .root = root, .level = nullptr, .idx = 0, .depth = rsrc_null };
|
||||
}
|
||||
inline iterator find( uint16_t u_id ) const { return find_if( [ & ] ( const auto& it ) { return it.has_id() && it.id() == u_id; } ); }
|
||||
inline iterator find( resource_id r_id ) const { return find( ( uint16_t ) r_id ); }
|
||||
inline iterator find( std::wstring_view name ) const { return find_if( [ & ] ( const auto& it ) { return it.has_name() && it.name() == name; } ); }
|
||||
template<typename T> inline auto operator[]( T&& v ) const { return find( std::forward<T>( v ) ); }
|
||||
};
|
||||
|
||||
// Resource directory, which is essentially the root of the tree.
|
||||
// - Type Directory
|
||||
// - Name Directory
|
||||
// - Lang Directory
|
||||
//
|
||||
struct resource_directory_t
|
||||
{
|
||||
// Container traits.
|
||||
//
|
||||
using iterator = base_rsrc_iterator_t<false>;
|
||||
using const_iterator = base_rsrc_iterator_t<true>;
|
||||
using value_type = iterator;
|
||||
|
||||
// Root entry.
|
||||
//
|
||||
rsrc_directory_t type_directory;
|
||||
|
||||
// Implement container interface
|
||||
// - operator[] is used for lookups.
|
||||
//
|
||||
inline bool empty() const { return size() == 0; }
|
||||
inline size_t size() const { return type_directory.num_entries(); }
|
||||
inline iterator at( size_t n ) { return { .root = &type_directory, .level = &type_directory, .idx = n, .depth = rsrc_type_directory }; }
|
||||
inline const_iterator at( size_t n ) const { return const_cast< resource_directory_t* >( this )->at( n ); }
|
||||
inline iterator begin() { return at( 0 ); }
|
||||
inline iterator end() { return at( size() ); }
|
||||
inline const_iterator begin() const { return at( 0 ); }
|
||||
inline const_iterator end() const { return at( size() ); }
|
||||
inline iterator front() { return at( 0 ); }
|
||||
inline iterator back() { return at( size() - 1 ); }
|
||||
inline const_iterator front() const { return at( 0 ); }
|
||||
inline const_iterator back() const { return at( size() - 1 ); }
|
||||
|
||||
// Implement lookups.
|
||||
//
|
||||
template<typename T>
|
||||
inline const_iterator find_if( T&& fn ) const
|
||||
{
|
||||
for ( auto it = begin(); it.idx != size(); ++it )
|
||||
if ( fn( it ) ) return it;
|
||||
return { .root = &type_directory, .level = nullptr, .idx = 0, .depth = rsrc_null };
|
||||
}
|
||||
inline const_iterator find( uint16_t u_id ) const { return find_if( [ & ] ( const auto& it ) { return it.has_id() && it.id() == u_id; } ); }
|
||||
inline const_iterator find( resource_id r_id ) const { return find( ( uint16_t ) r_id ); }
|
||||
inline const_iterator find( std::wstring_view name ) const { return find_if( [ & ] ( const auto& it ) { return it.has_name() && it.name() == name; } ); }
|
||||
template<typename T> inline auto find( T&& v ) { return acquire( ( ( const resource_directory_t* ) this )->find( std::forward<T>( v ) ) ); }
|
||||
template<typename T> inline auto find_if( T&& fn ) { return acquire( ( ( const resource_directory_t* ) this )->find_if( std::forward<T>( fn ) ) ); }
|
||||
template<typename T> inline auto operator[]( T&& v ) { return acquire( ( ( const resource_directory_t* ) this )->find( std::forward<T>( v ) ) ); }
|
||||
template<typename T> inline auto operator[]( T&& v ) const { return find( std::forward<T>( v ) ); }
|
||||
inline iterator acquire( const const_iterator& i ) { return *( iterator* ) &i; }
|
||||
};
|
||||
|
||||
template<bool x64> struct directory_type<directory_id::directory_entry_resource, x64, void> { using type = resource_directory_t; };
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
// Copyright (c) 2020 Can Boluk
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// 2. 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.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// 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 OWNER 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.
|
||||
//
|
||||
#pragma once
|
||||
#include "../../img_common.hpp"
|
||||
#include "../data_directories.hpp"
|
||||
|
||||
WIN_STRUCT_PACKING
|
||||
namespace win
|
||||
{
|
||||
enum class certificate_type_id : uint16_t
|
||||
{
|
||||
x509 = 0x0001,
|
||||
pkcs_signed_data = 0x0002,
|
||||
reserved_1 = 0x0003,
|
||||
ts_stack_signed = 0x0004,
|
||||
pkcs1_sign = 0x0009,
|
||||
};
|
||||
|
||||
struct win_certificate_t
|
||||
{
|
||||
uint32_t length;
|
||||
version_t revision;
|
||||
certificate_type_id certificate_type;
|
||||
uint8_t raw_data[ VAR_LEN ];
|
||||
};
|
||||
using security_directory_t = win_certificate_t;
|
||||
|
||||
template<bool x64> struct directory_type<directory_id::directory_entry_security, x64, void> { using type = security_directory_t; };
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
// Copyright (c) 2020 Can Boluk
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// 2. 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.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// 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 OWNER 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.
|
||||
//
|
||||
#pragma once
|
||||
#include "../../img_common.hpp"
|
||||
#include "../data_directories.hpp"
|
||||
|
||||
WIN_STRUCT_PACKING
|
||||
namespace win
|
||||
{
|
||||
union tls_characteristics_t
|
||||
{
|
||||
uint32_t flags;
|
||||
struct
|
||||
{
|
||||
uint32_t _reserved0 : 20;
|
||||
uint32_t alignment : 4;
|
||||
uint32_t _reserved1 : 8;
|
||||
};
|
||||
|
||||
inline size_t get_alignment() const { return convert_alignment( alignment ); }
|
||||
inline bool set_alignment( size_t align ) { return alignment = reflect_alignment( align ); }
|
||||
};
|
||||
|
||||
struct tls_directory_x64_t
|
||||
{
|
||||
uint64_t address_raw_data_start;
|
||||
uint64_t address_raw_data_end;
|
||||
uint64_t address_index;
|
||||
uint64_t address_callbacks;
|
||||
uint32_t size_zero_fill;
|
||||
tls_characteristics_t characteristics;
|
||||
};
|
||||
|
||||
struct tls_directory_x86_t
|
||||
{
|
||||
uint32_t address_raw_data_start;
|
||||
uint32_t address_raw_data_end;
|
||||
uint32_t address_index;
|
||||
uint32_t address_callbacks;
|
||||
uint32_t size_zero_fill;
|
||||
tls_characteristics_t characteristics;
|
||||
};
|
||||
|
||||
template<bool x64 = default_architecture>
|
||||
using tls_directory_t = std::conditional_t<x64, tls_directory_x64_t, tls_directory_x86_t>;
|
||||
|
||||
template<bool x64> struct directory_type<directory_id::directory_entry_tls, x64, void> { using type = tls_directory_t<x64>; };
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
|
@ -1,234 +0,0 @@
|
|||
// Copyright (c) 2020 Can Boluk
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// 2. 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.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// 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 OWNER 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.
|
||||
//
|
||||
#pragma once
|
||||
#include "../img_common.hpp"
|
||||
#include "nt_headers.hpp"
|
||||
#include "directories/dir_debug.hpp"
|
||||
#include "directories/dir_exceptions.hpp"
|
||||
#include "directories/dir_export.hpp"
|
||||
#include "directories/dir_iat.hpp"
|
||||
#include "directories/dir_import.hpp"
|
||||
#include "directories/dir_relocs.hpp"
|
||||
#include "directories/dir_tls.hpp"
|
||||
#include "directories/dir_load_config.hpp"
|
||||
#include "directories/dir_resource.hpp"
|
||||
#include "directories/dir_security.hpp"
|
||||
#include "directories/dir_delay_load.hpp"
|
||||
|
||||
namespace win {
|
||||
static constexpr uint32_t img_npos = 0xFFFFFFFF;
|
||||
|
||||
// Image wrapper
|
||||
//
|
||||
template<bool x64 = default_architecture>
|
||||
struct image_t {
|
||||
dos_header_t dos_header;
|
||||
|
||||
// Basic getters.
|
||||
//
|
||||
inline dos_header_t* get_dos_headers() { return &dos_header; }
|
||||
inline const dos_header_t* get_dos_headers() const { return &dos_header; }
|
||||
inline file_header_t* get_file_header() { return dos_header.get_file_header(); }
|
||||
inline const file_header_t* get_file_header() const { return dos_header.get_file_header(); }
|
||||
inline nt_headers_t<x64>* get_nt_headers() { return dos_header.get_nt_headers<x64>(); }
|
||||
inline const nt_headers_t<x64>* get_nt_headers() const { return dos_header.get_nt_headers<x64>(); }
|
||||
|
||||
// Calculation of optional header checksum.
|
||||
//
|
||||
inline uint32_t compute_checksum( size_t file_len ) const
|
||||
{
|
||||
// Sum over each word.
|
||||
//
|
||||
uint32_t chksum = 0;
|
||||
const uint16_t* wdata = ( const uint16_t* ) this;
|
||||
for ( size_t n = 0; n != file_len / 2; n++ ) {
|
||||
uint32_t sum = wdata[ n ] + chksum;
|
||||
chksum = ( uint16_t ) sum + ( sum >> 16 );
|
||||
}
|
||||
|
||||
// If there's a byte left append it.
|
||||
//
|
||||
uint16_t presult = chksum + ( chksum >> 16 );
|
||||
if ( file_len & 1 )
|
||||
presult += *( ( ( const char* ) this ) + file_len - 1 );
|
||||
|
||||
// Adjust for the previous .checkum field (=0)
|
||||
//
|
||||
uint16_t* adjust_sum = ( uint16_t* ) &get_nt_headers()->optional_header.checksum;
|
||||
for ( size_t i = 0; i != 2; i++ ) {
|
||||
presult -= presult < adjust_sum[ i ];
|
||||
presult -= adjust_sum[ i ];
|
||||
}
|
||||
return presult + ( uint32_t ) file_len;
|
||||
}
|
||||
inline void update_checksum( size_t file_len )
|
||||
{
|
||||
get_nt_headers()->optional_header.checksum = compute_checksum( file_len );
|
||||
}
|
||||
|
||||
// Directory getter
|
||||
//
|
||||
inline data_directory_t* get_directory( directory_id id )
|
||||
{
|
||||
auto nt_hdrs = get_nt_headers();
|
||||
if ( nt_hdrs->optional_header.num_data_directories <= id ) return nullptr;
|
||||
data_directory_t* dir = &nt_hdrs->optional_header.data_directories.entries[ id ];
|
||||
return dir->present() ? dir : nullptr;
|
||||
}
|
||||
inline const data_directory_t* get_directory( directory_id id ) const { return const_cast< image_t* >( this )->get_directory( id ); }
|
||||
|
||||
// Gets the max raw offset referenced.
|
||||
//
|
||||
inline size_t get_raw_limit() const
|
||||
{
|
||||
// Initialize the length with the header size.
|
||||
//
|
||||
auto* nt_hdrs = get_nt_headers();
|
||||
size_t max_raw = nt_hdrs->optional_header.size_headers;
|
||||
|
||||
// Calculate max length from the sections.
|
||||
//
|
||||
auto* scn = nt_hdrs->get_sections();
|
||||
for ( size_t i = 0; i != nt_hdrs->file_header.num_sections; i++ )
|
||||
max_raw = std::max<size_t>( scn[ i ].ptr_raw_data + scn[ i ].size_raw_data, max_raw );
|
||||
|
||||
// If there is a security directory, which usually is at the end of the image unmapped, also consider that.
|
||||
//
|
||||
if ( auto dir = get_directory( directory_entry_security ) )
|
||||
max_raw = std::max<size_t>( dir->rva + dir->size, max_raw );
|
||||
return max_raw;
|
||||
}
|
||||
|
||||
// Section mapping
|
||||
//
|
||||
inline section_header_t* rva_to_section( uint32_t rva )
|
||||
{
|
||||
auto nt_hdrs = get_nt_headers();
|
||||
for ( size_t i = 0; i != nt_hdrs->file_header.num_sections; i++ ) {
|
||||
auto section = nt_hdrs->get_section( i );
|
||||
if ( section->virtual_address <= rva && rva < ( section->virtual_address + section->virtual_size ) )
|
||||
return section;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
inline section_header_t* fo_to_section( uint32_t offset )
|
||||
{
|
||||
auto nt_hdrs = get_nt_headers();
|
||||
for ( size_t i = 0; i != nt_hdrs->file_header.num_sections; i++ ) {
|
||||
auto section = nt_hdrs->get_section( i );
|
||||
if ( section->ptr_raw_data <= offset && offset < ( section->ptr_raw_data + section->size_raw_data ) )
|
||||
return section;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
inline const section_header_t* rva_to_section( uint32_t rva ) const { return const_cast< image_t* >( this )->rva_to_section( rva ); }
|
||||
inline const section_header_t* fo_to_section( uint32_t offset ) const { return const_cast< image_t* >( this )->fo_to_section( offset ); }
|
||||
|
||||
// RVA mappings.
|
||||
// - Conversions using pointers are only safe on raw views.
|
||||
//
|
||||
template<typename T = uint8_t>
|
||||
inline T* rva_to_ptr( uint32_t rva, size_t length = 1 )
|
||||
{
|
||||
// Find the section, try mapping to header if none found.
|
||||
//
|
||||
auto scn = rva_to_section( rva );
|
||||
if ( !scn ) {
|
||||
uint32_t rva_hdr_end = get_nt_headers()->optional_header.size_headers;
|
||||
if ( rva < rva_hdr_end && ( rva + length ) <= rva_hdr_end )
|
||||
return ( T* ) ( ( uint8_t* ) &dos_header + rva );
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Apply the boundary check.
|
||||
//
|
||||
size_t offset = rva - scn->virtual_address;
|
||||
if ( ( offset + length ) > scn->size_raw_data )
|
||||
return nullptr;
|
||||
|
||||
// Return the final pointer.
|
||||
//
|
||||
return ( T* ) ( ( uint8_t* ) &dos_header + scn->ptr_raw_data + offset );
|
||||
}
|
||||
template<typename T = uint8_t>
|
||||
inline const T* rva_to_ptr( uint32_t rva, size_t length = 1 ) const { return const_cast< image_t* >( this )->template rva_to_ptr<const T>( rva, length ); }
|
||||
inline uint32_t rva_to_fo( uint32_t rva, size_t length = 1 ) const { return ptr_to_raw( rva_to_ptr( rva, length ) ); }
|
||||
|
||||
// RAW offset mappings.
|
||||
// - Conversions using pointers are only safe on mapped views.
|
||||
//
|
||||
template<typename T = uint8_t>
|
||||
inline T* fo_to_ptr( uint32_t offset, size_t length = 1 )
|
||||
{
|
||||
// Find the section, try mapping to header if none found.
|
||||
//
|
||||
auto scn = fo_to_section( offset );
|
||||
if ( !scn ) {
|
||||
uint32_t rva_hdr_end = get_nt_headers()->optional_header.size_headers;
|
||||
if ( offset < rva_hdr_end && ( offset + length ) <= rva_hdr_end )
|
||||
return ( T* ) ( ( uint8_t* ) &dos_header + offset );
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Apply the boundary check.
|
||||
//
|
||||
size_t soffset = offset - scn->ptr_raw_data;
|
||||
if ( ( soffset + length ) > scn->virtual_size )
|
||||
return nullptr;
|
||||
|
||||
// Return the final pointer.
|
||||
//
|
||||
return ( T* ) ( ( uint8_t* ) &dos_header + scn->virtual_address + soffset );
|
||||
}
|
||||
template<typename T = uint8_t>
|
||||
inline const T* fo_to_ptr( uint32_t offset, size_t length = 1 ) const { return const_cast< image_t* >( this )->template fo_to_ptr<const T>( offset, length ); }
|
||||
inline uint32_t fo_to_rva( uint32_t offset, size_t length = 1 ) const { return ptr_to_raw( fo_to_ptr( offset, length ) ); }
|
||||
|
||||
// Raw offset to pointer mapping, no boundary checks by default so this can
|
||||
// be used to translate RVA as well if image is mapped.
|
||||
// - If length is given, should not be used for RVA translation on mapped images.
|
||||
//
|
||||
template<typename T = uint8_t>
|
||||
inline T* raw_to_ptr( uint32_t offset, size_t length = 0 )
|
||||
{
|
||||
// Do a basic boundary check if length is given.
|
||||
//
|
||||
if ( length != 0 && ( offset + length ) > get_raw_limit() )
|
||||
return nullptr;
|
||||
|
||||
// Return the final pointer.
|
||||
//
|
||||
return ( T* ) ( ( uint8_t* ) &dos_header + offset );
|
||||
}
|
||||
template<typename T = void>
|
||||
inline const T* raw_to_ptr( uint32_t rva, size_t length = 0 ) const { return const_cast< image_t* >( this )->template raw_to_ptr<const T>( rva, length ); }
|
||||
inline uint32_t ptr_to_raw( const void* ptr ) const { return ptr ? uint32_t( uintptr_t( ptr ) - uintptr_t( &dos_header ) ) : img_npos; }
|
||||
};
|
||||
using image_x64_t = image_t<true>;
|
||||
using image_x86_t = image_t<false>;
|
||||
};
|
||||
|
|
@ -1,104 +0,0 @@
|
|||
// Copyright (c) 2020 Can Boluk
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// 2. 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.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// 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 OWNER 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.
|
||||
//
|
||||
#pragma once
|
||||
#include "../img_common.hpp"
|
||||
#include "../coff/file_header.hpp"
|
||||
#include "../coff/section_header.hpp"
|
||||
#include "optional_header.hpp"
|
||||
|
||||
WIN_STRUCT_PACKING
|
||||
namespace win
|
||||
{
|
||||
// Magic constants
|
||||
//
|
||||
static constexpr uint16_t DOS_HDR_MAGIC = 0x5A4D; // "MZ"
|
||||
static constexpr uint32_t NT_HDR_MAGIC = 0x00004550; // "PE\x0\x0"
|
||||
|
||||
// NT headers
|
||||
//
|
||||
template<bool x64 = default_architecture>
|
||||
struct nt_headers_t
|
||||
{
|
||||
uint32_t signature;
|
||||
file_header_t file_header;
|
||||
optional_header_t<x64> optional_header;
|
||||
|
||||
// Section getters
|
||||
//
|
||||
inline section_header_t* get_sections() { return ( section_header_t* ) ( ( uint8_t* ) &optional_header + file_header.size_optional_header ); }
|
||||
inline section_header_t* get_section( size_t n ) { return n >= file_header.num_sections ? nullptr : get_sections() + n; }
|
||||
inline const section_header_t* get_sections() const { return const_cast< nt_headers_t* >( this )->get_sections(); }
|
||||
inline const section_header_t* get_section( size_t n ) const { return const_cast< nt_headers_t* >( this )->get_section( n ); }
|
||||
|
||||
// Section iterator
|
||||
//
|
||||
template<typename T>
|
||||
struct proxy
|
||||
{
|
||||
T* base;
|
||||
uint16_t count;
|
||||
T* begin() const { return base; }
|
||||
T* end() const { return base + count; }
|
||||
};
|
||||
inline proxy<section_header_t> sections() { return { get_sections(), file_header.num_sections }; }
|
||||
inline proxy<const section_header_t> sections() const { return { get_sections(), file_header.num_sections }; }
|
||||
};
|
||||
using nt_headers_x64_t = nt_headers_t<true>;
|
||||
using nt_headers_x86_t = nt_headers_t<false>;
|
||||
|
||||
// DOS header
|
||||
//
|
||||
struct dos_header_t
|
||||
{
|
||||
uint16_t e_magic;
|
||||
uint16_t e_cblp;
|
||||
uint16_t e_cp;
|
||||
uint16_t e_crlc;
|
||||
uint16_t e_cparhdr;
|
||||
uint16_t e_minalloc;
|
||||
uint16_t e_maxalloc;
|
||||
uint16_t e_ss;
|
||||
uint16_t e_sp;
|
||||
uint16_t e_csum;
|
||||
uint16_t e_ip;
|
||||
uint16_t e_cs;
|
||||
uint16_t e_lfarlc;
|
||||
uint16_t e_ovno;
|
||||
uint16_t e_res[ 4 ];
|
||||
uint16_t e_oemid;
|
||||
uint16_t e_oeminfo;
|
||||
uint16_t e_res2[ 10 ];
|
||||
uint32_t e_lfanew;
|
||||
|
||||
inline file_header_t* get_file_header() { return &get_nt_headers<>()->file_header; }
|
||||
inline const file_header_t* get_file_header() const { return &get_nt_headers<>()->file_header; }
|
||||
template<bool x64 = default_architecture> inline nt_headers_t<x64>* get_nt_headers() { return ( nt_headers_t<x64>* ) ( ( uint8_t* ) this + e_lfanew ); }
|
||||
template<bool x64 = default_architecture> inline const nt_headers_t<x64>* get_nt_headers() const { return const_cast< dos_header_t* >( this )->template get_nt_headers<x64>(); }
|
||||
};
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
|
@ -1,172 +0,0 @@
|
|||
// Copyright (c) 2020 Can Boluk
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// 2. 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.
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// 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 OWNER 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.
|
||||
//
|
||||
#pragma once
|
||||
#include "../img_common.hpp"
|
||||
#include "data_directories.hpp"
|
||||
|
||||
WIN_STRUCT_PACKING
|
||||
namespace win
|
||||
{
|
||||
// Magic numbers.
|
||||
//
|
||||
static constexpr uint16_t OPT_HDR32_MAGIC = 0x010B;
|
||||
static constexpr uint16_t OPT_HDR64_MAGIC = 0x020B;
|
||||
|
||||
// Subsystems
|
||||
//
|
||||
enum class subsystem_id : uint16_t
|
||||
{
|
||||
unknown = 0x0000, // Unknown subsystem.
|
||||
native = 0x0001, // Image doesn't require a subsystem.
|
||||
windows_gui = 0x0002, // Image runs in the Windows GUI subsystem.
|
||||
windows_cui = 0x0003, // Image runs in the Windows character subsystem
|
||||
os2_cui = 0x0005, // image runs in the OS/2 character subsystem.
|
||||
posix_cui = 0x0007, // image runs in the Posix character subsystem.
|
||||
native_windows = 0x0008, // image is a native Win9x driver.
|
||||
windows_ce_gui = 0x0009, // Image runs in the Windows CE subsystem.
|
||||
efi_application = 0x000A, //
|
||||
efi_boot_service_driver = 0x000B, //
|
||||
efi_runtime_driver = 0x000C, //
|
||||
efi_rom = 0x000D,
|
||||
xbox = 0x000E,
|
||||
windows_boot_application = 0x0010,
|
||||
xbox_code_catalog = 0x0011,
|
||||
};
|
||||
|
||||
// DLL characteristics
|
||||
//
|
||||
union dll_characteristics_t
|
||||
{
|
||||
uint16_t flags;
|
||||
struct
|
||||
{
|
||||
uint16_t _pad0 : 5;
|
||||
uint16_t high_entropy_va : 1; // Image can handle a high entropy 64-bit virtual address space.
|
||||
uint16_t dynamic_base : 1; // DLL can move.
|
||||
uint16_t force_integrity : 1; // Code Integrity Image
|
||||
uint16_t nx_compat : 1; // Image is NX compatible
|
||||
uint16_t no_isolation : 1; // Image understands isolation and doesn't want it
|
||||
uint16_t no_seh : 1; // Image does not use SEH. No SE handler may reside in this image
|
||||
uint16_t no_bind : 1; // Do not bind this image.
|
||||
uint16_t appcontainer : 1; // Image should execute in an AppContainer
|
||||
uint16_t wdm_driver : 1; // Driver uses WDM model
|
||||
uint16_t guard_cf : 1; // Image supports Control Flow Guard.
|
||||
uint16_t terminal_server_aware : 1;
|
||||
};
|
||||
};
|
||||
|
||||
// Optional header
|
||||
//
|
||||
struct optional_header_x64_t
|
||||
{
|
||||
// Standard fields.
|
||||
uint16_t magic;
|
||||
version_t linker_version;
|
||||
|
||||
uint32_t size_code;
|
||||
uint32_t size_init_data;
|
||||
uint32_t size_uninit_data;
|
||||
|
||||
uint32_t entry_point;
|
||||
uint32_t base_of_code;
|
||||
|
||||
// NT additional fields.
|
||||
uint64_t image_base;
|
||||
uint32_t section_alignment;
|
||||
uint32_t file_alignment;
|
||||
|
||||
ex_version_t os_version;
|
||||
ex_version_t img_version;
|
||||
ex_version_t subsystem_version;
|
||||
uint32_t win32_version_value;
|
||||
|
||||
uint32_t size_image;
|
||||
uint32_t size_headers;
|
||||
|
||||
uint32_t checksum;
|
||||
subsystem_id subsystem;
|
||||
dll_characteristics_t characteristics;
|
||||
|
||||
uint64_t size_stack_reserve;
|
||||
uint64_t size_stack_commit;
|
||||
uint64_t size_heap_reserve;
|
||||
uint64_t size_heap_commit;
|
||||
|
||||
uint32_t ldr_flags;
|
||||
|
||||
uint32_t num_data_directories;
|
||||
data_directories_x64_t data_directories;
|
||||
};
|
||||
struct optional_header_x86_t
|
||||
{
|
||||
// Standard fields.
|
||||
uint16_t magic;
|
||||
version_t linker_version;
|
||||
|
||||
uint32_t size_code;
|
||||
uint32_t size_init_data;
|
||||
uint32_t size_uninit_data;
|
||||
|
||||
uint32_t entry_point;
|
||||
uint32_t base_of_code;
|
||||
uint32_t base_of_data;
|
||||
|
||||
// NT additional fields.
|
||||
uint32_t image_base;
|
||||
uint32_t section_alignment;
|
||||
uint32_t file_alignment;
|
||||
|
||||
ex_version_t os_version;
|
||||
ex_version_t img_version;
|
||||
ex_version_t subsystem_version;
|
||||
uint32_t win32_version_value;
|
||||
|
||||
uint32_t size_image;
|
||||
uint32_t size_headers;
|
||||
|
||||
uint32_t checksum;
|
||||
subsystem_id subsystem;
|
||||
dll_characteristics_t characteristics;
|
||||
|
||||
uint32_t size_stack_reserve;
|
||||
uint32_t size_stack_commit;
|
||||
uint32_t size_heap_reserve;
|
||||
uint32_t size_heap_commit;
|
||||
|
||||
uint32_t ldr_flags;
|
||||
|
||||
uint32_t num_data_directories;
|
||||
data_directories_x86_t data_directories;
|
||||
|
||||
inline bool has_directory( const data_directory_t* dir ) const { return &data_directories.entries[ num_data_directories ] < dir && dir->present(); }
|
||||
inline bool has_directory( directory_id id ) const { return has_directory( &data_directories.entries[ id ] ); }
|
||||
};
|
||||
template<bool x64 = default_architecture>
|
||||
using optional_header_t = std::conditional_t<x64, optional_header_x64_t, optional_header_x86_t>;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
Loading…
Reference in New Issue