Skip to content

Commit

Permalink
pe: Temporarily rework POGO dump data
Browse files Browse the repository at this point in the history
  • Loading branch information
dd86k committed Nov 11, 2024
1 parent c6ad0bb commit 224ac26
Show file tree
Hide file tree
Showing 3 changed files with 194 additions and 28 deletions.
30 changes: 22 additions & 8 deletions dumper/format/pe.d
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import adbg.objects.pe;
import adbg.objects.mz : mz_header_t;
import adbg.utils.date : ctime32;
import adbg.utils.uid, adbg.utils.bit;
import adbg.utils.strings;
import adbg.error;
import core.stdc.stdlib;
import core.stdc.string : strncmp;
Expand Down Expand Up @@ -717,9 +718,13 @@ void dump_pe_debug(adbg_object_t *o) {
debug_.SizeOfData, cast(uint)pe_debug_data_pogo_entry_t.sizeof);
continue;
}
uint sig = *cast(uint*)data;

void *pogomax = data + debug_.SizeOfData;

pe_debug_data_pogo_entry_t* pogo = cast(pe_debug_data_pogo_entry_t*)data;

const(char) *pgotypestr = void;
switch (sig) {
switch (pogo.Magic) {
case PE_IMAGE_DEBUG_MAGIC_POGO_LTCG:
pgotypestr = "POGO LTCG (Link-Time Code Generation)";
break;
Expand All @@ -729,14 +734,23 @@ void dump_pe_debug(adbg_object_t *o) {
default:
pgotypestr = "POGO (Unknown)";
}
print_x32("Signature", sig, pgotypestr);

//TODO: Check if multiple entries.
pe_debug_data_pogo_entry_t* pogo = cast(pe_debug_data_pogo_entry_t*)data;
print_x32("Signature", pogo.Magic, pgotypestr);
print_x32("RVA", pogo.Rva);
print_x32("Size", pogo.Size);
print_stringl("Size", pogo.Name.ptr,
cast(int)(debug_.SizeOfData - pe_debug_data_pogo_entry_t.sizeof));

// Temporary
hexdump("POGO data", pogo.Name.ptr, debug_.SizeOfData - pe_debug_data_pogo_entry_t.sizeof - 1);
/*
size_t pogoleft = debug_.SizeOfData - pe_debug_data_pogo_entry_t.sizeof - 1;
const(char) *pogoname = pogo.Name.ptr;
Lpogostr: // multiple string entries
size_t strl = adbg_nstrlen(pogoname, pogoleft);
print_stringl("Name", pogoname, cast(int)strl);
pogoname += strl + 1;
if (pogoname < pogomax)
goto Lpogostr;
*/
break;
case PE_IMAGE_DEBUG_TYPE_R2R_PERFMAP:
if (debug_.SizeOfData < pe_debug_data_r2r_perfmap_t.sizeof) {
Expand Down
4 changes: 2 additions & 2 deletions dumper/main.d
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import core.stdc.stdio;
import dumper;
import common.errormgmt;
import common.cli;
import common.utils : unformat64;
import common.utils;

private:

Expand Down Expand Up @@ -141,7 +141,7 @@ int cliopt_disasm_stats() {
return 0;
}
int cliopt_origin(const(char) *val) {
return unformat64(&opt_baseaddress, val);
return parse64(&opt_baseaddress, val);
}

int cliopt_extract() {
Expand Down
188 changes: 170 additions & 18 deletions src/adbg/objects/pe.d
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,10 @@ struct pe_import_entry64_t { align(1):
}
}

//
// ANCHOR Debug information
//

struct pe_debug_directory_entry_t { align(1):
uint Characteristics; /// reserved, must be zero
uint TimeDateStamp; /// time and date that the debug data was created
Expand Down Expand Up @@ -406,7 +410,7 @@ enum : uint {
/// Incremental Link Time Code Generation.
/// See: https://devblogs.microsoft.com/cppblog/speeding-up-the-incremental-developer-build-scenario/
PE_IMAGE_DEBUG_TYPE_ILTCG = 14,
/// Uses Intel MPX
/// Intel MPX
PE_IMAGE_DEBUG_TYPE_MPX = 15,
/// PE determinism or reproducibility.
PE_IMAGE_DEBUG_TYPE_REPRO = 16,
Expand Down Expand Up @@ -437,14 +441,13 @@ enum : uint {
// Mono source has it set as 0x4244504d
PE_IMAGE_DEBUG_MAGIC_EMBEDDED_PPDB = CHAR32!"MPDB", /// Portable PDB
PE_IMAGE_DEBUG_MAGIC_PPDB = CHAR32!"BSJB", /// Portable PDB
// Source: SystemInformer, except for full names
// Source: SystemInformer, except for descriptive names
PE_IMAGE_DEBUG_MAGIC_POGO_LTCG = CHAR32!"LTCG", /// Link-Time Code Generation
PE_IMAGE_DEBUG_MAGIC_POGO_PGU = CHAR32!"PGU\0", /// Profile Guided Update (/LTCG:PGUPDATE)
}

/// PDB 2.0 and above
struct pe_debug_data_codeview_pdb20_t { align(1):
// Old PE32 doc mentions "NB05" -- CodeView 4.0 or earlier?
char[4] Signature; /// Magic: "NB09"/"NB10"/"NB11" bytes
/// Offset to the start of the actual debug information from the
/// beginning of the CodeView data. Zero if it's another file.
Expand All @@ -466,13 +469,17 @@ struct pe_debug_data_codeview_pdb70_t { align(1):

// This information tells the debugger how to interpret nonstandard stack frames,
// which use the EBP register for a purpose other than as a frame pointer.
enum FRAME_FPO = 0;
enum FRAME_TRAP = 1;
enum FRAME_TSS = 2; // i286 Task Switch
enum {
FRAME_FPO = 0,
FRAME_TRAP = 1,
FRAME_TSS = 2, // i286 Task Switch
FRAME_NONFPO = 3,
}
enum SIZEOF_RFPO_DATA = 16;
struct pe_debug_data_fpo_t { // struct _FPO_DATA
uint ulOffStart; // offset 1st byte of function code
uint cbProcSize; // # bytes in function
uint cdwLocals; // # bytes in locals/4
uint ulOffStart; // offset 1st byte of function code
uint cbProcSize; // # bytes in function
uint cdwLocals; // # bytes in locals/4
ushort cdwParams; // # bytes in params/4
ushort Flags;
//WORD cbProlog : 8; // # bytes in prolog
Expand All @@ -485,17 +492,59 @@ struct pe_debug_data_fpo_t { // struct _FPO_DATA

// Debug entry 4: The location of a DBG file.

struct pe_debug_data_misc_t { align(1):
struct pe_debug_data_misc_t { align(1): // _IMAGE_DEBUG_MISC
union {
char[4] Signature; ///
uint Signature32;
}
uint DataType; /// Must be 1
uint Length; /// Multiple of four; Total length of data block
bool Unicode; /// If true, Unicode string
byte[3] Reserved;
byte[1] Data;
}
ubyte[3] Reserved;
ubyte[1] Data; // Data pointer
}

/// Header of .DBG files
struct pe_debug_data_header_t { // _IMAGE_SEPARATE_DEBUG_HEADER
ushort Signature;
ushort Flags;
ushort Machine;
ushort Characteristics;
uint TimeDateStamp;
uint CheckSum;
uint ImageBase;
uint SizeOfImage;
uint NumberOfSections;
uint ExportedNamesSize;
uint DebugDirectorySize;
uint SectionAlignment;
uint[2] Reserved;
}
///
struct pe_debug_data_non_paged_header_t { // _NON_PAGED_DEBUG_INFO
ushort Signature;
ushort Flags;
uint Size;
ushort Machine;
ushort Characteristics;
uint TimeDateStamp;
uint CheckSum;
uint SizeOfImage;
ulong ImageBase; // ULONGLONG
//DebugDirectorySize
//IMAGE_DEBUG_DIRECTORY
}

version (LittleEndian) { // #ifndef _MAC
enum PE_IMAGE_SEPARATE_DEBUG_SIGNATURE = 0x4944;
enum PE_NON_PAGED_DEBUG_SIGNATURE = 0x494E;
} else {
enum PE_IMAGE_SEPARATE_DEBUG_SIGNATURE = 0x4449; // DI
enum PE_NON_PAGED_DEBUG_SIGNATURE = 0x4E49; // NI
}

enum PE_IMAGE_SEPARATE_DEBUG_FLAGS_MASK = 0x8000;
enum PE_IMAGE_SEPARATE_DEBUG_MISMATCH = 0x8000;

// Debug entry 12: VC Features

Expand All @@ -510,6 +559,17 @@ struct pe_debug_data_vc_feat_t { align(1):

// Debug entry 13: POGO

enum { // POGO SubTypes
// POGOTypePGU represents a signature for an undocumented PGO sub type.
POGOTypePGU = CHAR32!"PGU\0", // 0x50475500
// POGOTypePGI represents a signature for an undocumented PGO sub type.
POGOTypePGI = CHAR32!"PGI\0", // 0x50474900,
// POGOTypePGO represents a signature for an undocumented PGO sub type.
POGOTypePGO = CHAR32!"PGO\0", // 0x50474F00,
// POGOTypeLTCG represents a signature for an undocumented PGO sub type.
POGOTypeLTCG = CHAR32!"LTCG", // 0x4c544347,
}

/// POGO Entry containing filename. Should be ending with .PGD (Profile-Guided Database).
struct pe_debug_data_pogo_entry_t {
uint Magic;
Expand Down Expand Up @@ -564,7 +624,16 @@ struct pe_debug_data_ppdb_stream_t {
char[1] Name;
}

// Debug type 21: R2R PerfMap
// Debug entry 20: Extended DLL characteristics bits.
// IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS

// Indicates that the image is CET compatible.
enum PE_IMAGE_DLLCHARACTARISTICS_EX_CET_COMPAT = 0x01;
enum PE_IMAGE_DLLCHARACTERISTICS_EX_CET_COMPAT_STRICT_MODE = 0x02;
enum PE_IMAGE_DLLCHARACTERISTICS_EX_CET_SET_CONTEXT_IP_VALIDATION_RELAXED_MODE = 0x04;
enum PE_IMAGE_DLLCHARACTERISTICS_EX_CET_DYNAMIC_APIS_ALLOW_IN_PROC = 0x08;

// Debug entry 21: R2R PerfMap

/// Declares that the image has an associated PerfMap file containing a table
/// mapping symbols to offsets for ready to run compilations.
Expand All @@ -583,7 +652,7 @@ struct pe_debug_data_r2r_perfmap_t { align(1):
}

//
// Load configuration directory
// ANCHOR Load configuration directory
//

struct pe_load_config_code_integrity_t { align(1):
Expand Down Expand Up @@ -815,23 +884,28 @@ struct internal_pe_t {
mz_header_t mz_header;

pe_image_data_directory_t directory;

size_t locsections;
pe_section_entry_t *sections;
bool *r_sections;

// export directory
pe_export_descriptor_t *export_directory;
bool *r_export_entries;

// import directory
pe_import_descriptor_t *import_directory; // not allocated
pe_section_entry_t *import_section; // associated section, not allocated
void *import_buffer; // section buffer
//bool *r_import_desc;
//bool *r_import_entries; // Current only, cleared when selecting other descriptor

// debug directory
pe_debug_directory_entry_t *debug_directory; // not allocated
pe_section_entry_t *debug_section;
void *debug_buffer; // section buffer
bool *r_debug_entries;

// load configuration directory
union {
pe_loadconfig32_t *load32_directory;
Expand Down Expand Up @@ -1386,7 +1460,7 @@ pe_section_entry_t* adbg_object_pe_section(adbg_object_t *o, size_t index) {
// - [ ] CLRHeader

//
// Export directory functions
// ANCHOR Export directory functions
//

// One descriptor table, multiple entries, because one module emits one table.
Expand Down Expand Up @@ -1572,7 +1646,7 @@ const(char)* adbg_object_pe_export_name_string(adbg_object_t *o,
}

//
// Import directory functions
// ANCHOR Import directory functions
//

// NOTE: Import directory handling
Expand Down Expand Up @@ -1709,7 +1783,7 @@ const(char)* adbg_object_pe_import_module_name(adbg_object_t *o, pe_import_descr
return cast(const(char)*)name;
}

//TODO: Byte-swap import look-up table entries
// TODO: Byte-swap import look-up table entries

pe_import_entry32_t* adbg_object_pe_import_entry32(adbg_object_t *o, pe_import_descriptor_t *import_, size_t index) {
if (o == null || import_ == null) {
Expand Down Expand Up @@ -2030,6 +2104,7 @@ const(char)* adbg_object_pe_import_entry_string(adbg_object_t *o, pe_import_desc

return cast(const(char)*)hint;
}

//
// Debug directory functions
//
Expand Down Expand Up @@ -2229,6 +2304,83 @@ void* adbg_object_pe_loadconfig(adbg_object_t *o) {
return internal.load32_directory;
}

//
// ANCHOR CLR/COM+ directory stuff
//

enum {// ReplacesCorHdrNumericDefines
// COM+ Header entry point flags.
COMIMAGE_FLAGS_ILONLY = 0x00000001,
COMIMAGE_FLAGS_32BITREQUIRED = 0x00000002,
COMIMAGE_FLAGS_IL_LIBRARY = 0x00000004,
COMIMAGE_FLAGS_STRONGNAMESIGNED = 0x00000008,
COMIMAGE_FLAGS_NATIVE_ENTRYPOINT = 0x00000010,
COMIMAGE_FLAGS_TRACKDEBUGDATA = 0x00010000,
COMIMAGE_FLAGS_32BITPREFERRED = 0x00020000,

// Version flags for image.
COR_VERSION_MAJOR_V2 = 2,
COR_VERSION_MAJOR = COR_VERSION_MAJOR_V2,
COR_VERSION_MINOR = 5,
COR_DELETED_NAME_LENGTH = 8,
COR_VTABLEGAP_NAME_LENGTH = 8,

// Maximum size of a NativeType descriptor.
NATIVE_TYPE_MAX_CB = 1,
COR_ILMETHOD_SECT_SMALL_MAX_DATASIZE= 0xFF,

// #defines for the MIH FLAGS
IMAGE_COR_MIH_METHODRVA = 0x01,
IMAGE_COR_MIH_EHRVA = 0x02,
IMAGE_COR_MIH_BASICBLOCK = 0x08,

// V-table constants
COR_VTABLE_32BIT = 0x01, // V-table slots are 32-bits in size.
COR_VTABLE_64BIT = 0x02, // V-table slots are 64-bits in size.
COR_VTABLE_FROM_UNMANAGED = 0x04, // If set, transition from unmanaged.
COR_VTABLE_FROM_UNMANAGED_RETAIN_APPDOMAIN = 0x08, // If set, transition from unmanaged with keeping the current appdomain.
COR_VTABLE_CALL_MOST_DERIVED = 0x10, // Call most derived method described by

// EATJ constants
IMAGE_COR_EATJ_THUNK_SIZE =32, // Size of a jump thunk reserved range.

// Max name lengths
//@todo: Change to unlimited name lengths.
MAX_CLASS_NAME = 1024,
MAX_PACKAGE_NAME = 1024,
}

// CLR 2.0 header structure.
struct pe_cor20_header_t { align(1): // IMAGE_COR20_HEADER
// Header versioning
uint cb;
ushort MajorRuntimeVersion;
ushort MinorRuntimeVersion;

// Symbol table and startup information
pe_image_data_directory_t MetaData;
uint Flags;

// If COMIMAGE_FLAGS_NATIVE_ENTRYPOINT is not set, EntryPointToken represents a managed entrypoint.
// If COMIMAGE_FLAGS_NATIVE_ENTRYPOINT is set, EntryPointRVA represents an RVA to a native entrypoint.
union {
uint EntryPointToken;
uint EntryPointRVA;
}

// Binding information
pe_image_data_directory_t Resources;
pe_image_data_directory_t StrongNameSignature;

// Regular fixup and binding information
pe_image_data_directory_t CodeManagerTable;
pe_image_data_directory_t VTableFixups;
pe_image_data_directory_t ExportAddressTableJumps;

// Precompiled image info (internal use only - set to zero)
pe_image_data_directory_t ManagedNativeHeader;
}

//
// Other helpers
//
Expand Down

0 comments on commit 224ac26

Please sign in to comment.