Skip to content

Commit

Permalink
Get the actual static image base of modules
Browse files Browse the repository at this point in the history
  • Loading branch information
Qrox committed Mar 2, 2022
1 parent 2c922b0 commit 840e2d0
Showing 1 changed file with 79 additions and 19 deletions.
98 changes: 79 additions & 19 deletions src/debug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
# include <dbghelp.h>
# if defined(LIBBACKTRACE)
# include <backtrace.h>
# include <winnt.h>
# endif
# elif defined(__ANDROID__)
# include <unwind.h>
Expand Down Expand Up @@ -103,6 +104,63 @@ static bool capturing = false;
/** сaptured debug messages */
static std::string captured;

#if defined(_WIN32) and defined(LIBBACKTRACE)
// Get the image base of a module from its PE header
static uintptr_t get_image_base( const char *const path )
{
HANDLE file = CreateFile( path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL );
if( file == INVALID_HANDLE_VALUE ) {
return 0;
}
on_out_of_scope close_file( [file]() {
CloseHandle( file );
} );

HANDLE mapping = CreateFileMapping( file, NULL, PAGE_READONLY, 0, 0, NULL );
if( mapping == NULL ) {
return 0;
}
on_out_of_scope close_mapping( [mapping]() {
CloseHandle( mapping );
} );

LONG nt_header_offset = 0;
{
LPVOID dos_header_view = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, sizeof( IMAGE_DOS_HEADER ) );
if( dos_header_view == NULL ) {
return 0;
}
on_out_of_scope close_dos_header_view( [dos_header_view]() {
UnmapViewOfFile( dos_header_view );
} );

PIMAGE_DOS_HEADER dos_header = reinterpret_cast<PIMAGE_DOS_HEADER>( dos_header_view );
if( dos_header->e_magic != IMAGE_DOS_SIGNATURE ) {
return 0;
}
nt_header_offset = dos_header->e_lfanew;
}

LPVOID pe_header_view = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0,
nt_header_offset + sizeof( IMAGE_NT_HEADERS ) );
if( pe_header_view == NULL ) {
return 0;
}
on_out_of_scope close_pe_header_view( [pe_header_view]() {
UnmapViewOfFile( pe_header_view );
} );

PIMAGE_NT_HEADERS nt_header = reinterpret_cast<PIMAGE_NT_HEADERS>(
reinterpret_cast<uintptr_t>( pe_header_view ) + nt_header_offset );
if( nt_header->Signature != IMAGE_NT_SIGNATURE
|| nt_header->FileHeader.SizeOfOptionalHeader != sizeof( IMAGE_OPTIONAL_HEADER ) ) {
return 0;
}
return nt_header->OptionalHeader.ImageBase;
}
#endif

/**
* Class for capturing debugmsg,
* used by capture_debugmsg_during.
Expand Down Expand Up @@ -939,7 +997,11 @@ static struct {
} sym_storage;
static SYMBOL_INFO &sym = reinterpret_cast<SYMBOL_INFO &>( sym_storage );
#if defined(LIBBACKTRACE)
static std::map<DWORD64, backtrace_state *> bt_states;
struct backtrace_module_info_t {
backtrace_state *state = nullptr;
uintptr_t image_base = 0;
};
static std::map<DWORD64, backtrace_module_info_t> bt_module_info_map;
#endif
#elif !defined(__ANDROID__)
static constexpr int bt_cnt = 20;
Expand Down Expand Up @@ -1035,39 +1097,37 @@ void debug_write_backtrace( std::ostream &out )
}
out << "), ";
#if defined(LIBBACKTRACE)
backtrace_state *bt_state = nullptr;
backtrace_module_info_t bt_module_info;
if( mod_base ) {
const auto it = bt_states.find( mod_base );
if( it != bt_states.end() ) {
bt_state = it->second;
const auto it = bt_module_info_map.find( mod_base );
if( it != bt_module_info_map.end() ) {
bt_module_info = it->second;
} else {
const DWORD mod_len = GetModuleFileName( reinterpret_cast<HMODULE>( mod_base ), mod_path,
module_path_len );
if( mod_len > 0 && mod_len < module_path_len ) {
bt_state = bt_create_state( mod_path, 0,
// error callback
bt_module_info.state = bt_create_state( mod_path, 0,
// error callback
[&out]( const char *const msg, const int errnum ) {
out << "\n (backtrace_create_state failed: errno = " << errnum
<< ", msg = " << ( msg ? msg : "[no msg]" ) << "),";
} );
bt_module_info.image_base = get_image_base( mod_path );
if( bt_module_info.image_base == 0 ) {
out << "\n (cannot locate image base),";
}
} else {
out << "\n (executable path exceeds " << module_path_len << " chars),";
}
if( bt_state ) {
bt_states.emplace( mod_base, bt_state );
}
bt_module_info_map.emplace( mod_base, bt_module_info );
}
} else {
out << "\n (unable to get module base address),";
}
if( bt_state ) {
#if defined(__MINGW64__)
constexpr uint64_t static_image_base = 0x140000000ULL;
#elif defined(__MINGW32__)
constexpr uint64_t static_image_base = 0x400000ULL;
#endif
uint64_t de_aslr_pc = reinterpret_cast<uintptr_t>( bt[i] ) - mod_base + static_image_base;
bt_syminfo( bt_state, de_aslr_pc,
if( bt_module_info.state && bt_module_info.image_base != 0 ) {
const uintptr_t de_aslr_pc = reinterpret_cast<uintptr_t>( bt[i] ) - mod_base +
bt_module_info.image_base;
bt_syminfo( bt_module_info.state, de_aslr_pc,
// syminfo callback
[&out]( const uintptr_t pc, const char *const symname,
const uintptr_t symval, const uintptr_t ) {
Expand All @@ -1082,7 +1142,7 @@ void debug_write_backtrace( std::ostream &out )
<< ", msg = " << ( msg ? msg : "[no msg]" )
<< "),";
} );
bt_pcinfo( bt_state, de_aslr_pc,
bt_pcinfo( bt_module_info.state, de_aslr_pc,
// backtrace callback
[&out]( const uintptr_t pc, const char *const filename,
const int lineno, const char *const function ) -> int {
Expand Down

0 comments on commit 840e2d0

Please sign in to comment.