mirror of
https://github.com/WerWolv/ImHex-Patterns.git
synced 2026-03-27 23:37:04 -05:00
patterns: Added Java HPROF pattern
This commit is contained in:
@@ -84,6 +84,7 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi
|
||||
| Halo Tag || [`patterns/hinf_tag.hexpat`](patterns/hinf_tag.hexpat) | Halo Infinite Tag Files |
|
||||
| Halo Module || [`patterns/hinf_module.hexpat`](patterns/hinf_module.hexpat) | Halo Infinite Module Archive Files |
|
||||
| Halo HavokScript || [`patterns/hinf_luas.hexpat`](patterns/hinf_luas.hexpat) | Halo Infinite HavokScript 5.1 Bytecode |
|
||||
| HPROF || [`patterns/hprof.hexpat`](patterns/hprof.hexpat) | Java HPROF Profiler Data Format |
|
||||
| HSDT || [`patterns/hsdt.hexpat`](patterns/hsdt.hexpat) | HiSilicon device-tree table images |
|
||||
| ICO | | [`patterns/ico.hexpat`](patterns/ico.hexpat) | Icon (.ico) or Cursor (.cur) files |
|
||||
| ID3 | `audio/mpeg` | [`patterns/id3.hexpat`](patterns/id3.hexpat) | ID3 tags in MP3 files |
|
||||
|
||||
362
patterns/hprof.hexpat
Normal file
362
patterns/hprof.hexpat
Normal file
@@ -0,0 +1,362 @@
|
||||
#pragma author WerWolv
|
||||
#pragma description Java HPROF Profiler Data Format
|
||||
#pragma endian big
|
||||
#pragma magic [ "JAVA PROFILE" ] @ 0x00
|
||||
|
||||
#pragma array_limit 0
|
||||
#pragma pattern_limit 0
|
||||
|
||||
import std.mem;
|
||||
import std.io;
|
||||
import std.sys;
|
||||
import std.core;
|
||||
|
||||
enum Tag : u8 {
|
||||
STRING_IN_UTF8 = 0x01,
|
||||
LOAD_CLASS = 0x02,
|
||||
UNLOAD_CLASS = 0x03,
|
||||
STACK_FRAME = 0x04,
|
||||
STACK_TRACE = 0x05,
|
||||
ALLOC_SITES = 0x06,
|
||||
HEAP_SUMMARY = 0x07,
|
||||
START_THREAD = 0x0A,
|
||||
END_THREAD = 0x0B,
|
||||
HEAP_DUMP = 0x0C,
|
||||
HEAP_DUMP_SEGMENT = 0x1C,
|
||||
HEAP_DUMP_END = 0x2C,
|
||||
CPU_SAMPLES = 0x0D,
|
||||
CONTROL_SETTINGS = 0x0E,
|
||||
};
|
||||
|
||||
u32 id_size = 0;
|
||||
struct ID {
|
||||
match (id_size) {
|
||||
(1): u8 value;
|
||||
(2): u16 value;
|
||||
(4): u32 value;
|
||||
(8): u64 value;
|
||||
(_): std::error("Invalid ID size");
|
||||
}
|
||||
} [[sealed, format("format_id")]];
|
||||
|
||||
fn format_id(ref auto id) {
|
||||
return std::format("0x{:0{}X}", id.value, id_size * 2);
|
||||
};
|
||||
|
||||
struct StringInUTF8 {
|
||||
ID id;
|
||||
char string[parent.length - sizeof(id)];
|
||||
};
|
||||
|
||||
struct LoadClass {
|
||||
u32 classSerialNumber;
|
||||
ID classObjectId;
|
||||
u32 stackTraceSerialNumber;
|
||||
ID classNameStringID;
|
||||
};
|
||||
|
||||
struct StackFrame {
|
||||
ID stackFrameId;
|
||||
ID methodNameStringId;
|
||||
ID methodSignatureStringId;
|
||||
ID sourceFileNameStringId;
|
||||
u32 classSerialNumber;
|
||||
u32 lineInformation;
|
||||
};
|
||||
|
||||
struct StackTrace {
|
||||
u32 stackTraceSerialNumber;
|
||||
u32 threadSerialNumber;
|
||||
u32 numberOfFrames;
|
||||
ID stackFrameIds[while(!std::mem::reached(addressof(this) + parent.length))];
|
||||
};
|
||||
|
||||
enum SubTag : u8 {
|
||||
RootUnknown = 0xFF,
|
||||
RootJNIGlobal = 0x01,
|
||||
RootJNILocal = 0x02,
|
||||
RootJavaFrame = 0x03,
|
||||
RootNativeStack = 0x04,
|
||||
RootStickyClass = 0x05,
|
||||
RootThreadBlock = 0x06,
|
||||
RootMonitorUsed = 0x07,
|
||||
RootThreadObject = 0x08,
|
||||
ClassDump = 0x20,
|
||||
InstanceDump = 0x21,
|
||||
ObjectArrayDump = 0x22,
|
||||
PrimitiveArrayDump = 0x23
|
||||
};
|
||||
|
||||
enum EntryType : u8 {
|
||||
Object = 2,
|
||||
Boolean = 4,
|
||||
Char = 5,
|
||||
Float = 6,
|
||||
Double = 7,
|
||||
Byte = 8,
|
||||
Short = 9,
|
||||
Int = 10,
|
||||
Long = 11
|
||||
};
|
||||
|
||||
struct BasicType<auto Tag> {
|
||||
match (Tag) {
|
||||
(EntryType::Object): ID value;
|
||||
(EntryType::Boolean): bool value;
|
||||
(EntryType::Char): { padding[1]; char value; }
|
||||
(EntryType::Float): float value;
|
||||
(EntryType::Double): double value;
|
||||
(EntryType::Byte): u8 value;
|
||||
(EntryType::Short): u16 value;
|
||||
(EntryType::Int): u32 value;
|
||||
(EntryType::Long): u64 value;
|
||||
(_): std::error("Invalid BasicType type");
|
||||
}
|
||||
} [[sealed, format("format_basic_type")]];
|
||||
|
||||
fn format_basic_type(ref auto basicType) {
|
||||
return std::format("{}", basicType.value);
|
||||
};
|
||||
|
||||
struct ConstantPoolEntry {
|
||||
u16 constantPoolIndex;
|
||||
EntryType type;
|
||||
BasicType<type> value;
|
||||
};
|
||||
|
||||
struct ConstantPoolArray {
|
||||
u16 size;
|
||||
ConstantPoolEntry entries[size];
|
||||
};
|
||||
|
||||
struct StaticFieldEntry {
|
||||
ID staticFieldNameStringId;
|
||||
EntryType type;
|
||||
BasicType<type> value;
|
||||
};
|
||||
|
||||
struct StaicFieldArray {
|
||||
u16 size;
|
||||
StaticFieldEntry entries[size];
|
||||
};
|
||||
|
||||
struct InstanceField {
|
||||
ID fieldNameStringId;
|
||||
EntryType fieldType;
|
||||
};
|
||||
|
||||
struct InstanceFieldsArray {
|
||||
u16 size;
|
||||
InstanceField instanceFields[size];
|
||||
};
|
||||
|
||||
struct HeapDump {
|
||||
SubTag subTag;
|
||||
match (subTag) {
|
||||
(SubTag::RootUnknown): {
|
||||
ID objectId;
|
||||
}
|
||||
(SubTag::RootJNIGlobal): {
|
||||
ID objectId;
|
||||
ID jniGlobalRefId;
|
||||
}
|
||||
(SubTag::RootJNILocal): {
|
||||
ID objectId;
|
||||
u32 threadSerialNumber;
|
||||
u32 frameNumberInStackTrace;
|
||||
}
|
||||
(SubTag::RootJavaFrame): {
|
||||
ID objectId;
|
||||
u32 threadSerialNumber;
|
||||
u32 frameNumberInStackTrace;
|
||||
}
|
||||
(SubTag::RootNativeStack): {
|
||||
ID objectId;
|
||||
u32 threadSerialNumber;
|
||||
}
|
||||
(SubTag::RootStickyClass): {
|
||||
ID objectId;
|
||||
}
|
||||
(SubTag::RootThreadBlock): {
|
||||
ID objectId;
|
||||
u32 threadSerialNumber;
|
||||
}
|
||||
(SubTag::RootMonitorUsed): {
|
||||
ID objectId;
|
||||
}
|
||||
(SubTag::RootThreadObject): {
|
||||
ID threadObjectId;
|
||||
u32 threadSerialNumber;
|
||||
u32 stackTraceSerialNumber;
|
||||
}
|
||||
(SubTag::ClassDump): {
|
||||
ID classObjectId;
|
||||
u32 stackTraceSerialNumber;
|
||||
ID superClassObjectId;
|
||||
ID classLoaderObjectId;
|
||||
ID signersObjectId;
|
||||
ID protectionDomainObjectId;
|
||||
ID reserved[2];
|
||||
u32 instanceSize;
|
||||
ConstantPoolArray constantPool;
|
||||
StaicFieldArray staticFields;
|
||||
InstanceFieldsArray instanceFields;
|
||||
}
|
||||
(SubTag::InstanceDump): {
|
||||
ID objectId;
|
||||
u32 stackTraceSerialNumber;
|
||||
ID classObjectId;
|
||||
u32 numBytes;
|
||||
std::mem::Bytes<numBytes> instanceFieldValues;
|
||||
}
|
||||
(SubTag::ObjectArrayDump): {
|
||||
ID arrayObjectId;
|
||||
u32 stackTraceSerialNumber;
|
||||
u32 numberOfElements;
|
||||
ID arrayClassObjectId;
|
||||
ID elements[numberOfElements];
|
||||
}
|
||||
(SubTag::PrimitiveArrayDump): {
|
||||
ID arrayObjectId;
|
||||
u32 stackTraceSerialNumber;
|
||||
u32 numberOfElements;
|
||||
EntryType type;
|
||||
BasicType<type> value[numberOfElements];
|
||||
}
|
||||
(_): std::error(std::format("Heap Dump Sub Tag {:02X} at 0x{:08X} {}", u32(subTag), $, std::core::array_index()));
|
||||
}
|
||||
|
||||
if ($ - addressof(parent.length) + sizeof(parent.length) >= parent.length)
|
||||
break;
|
||||
|
||||
u8 endTag [[no_unique_address, hidden]];
|
||||
if (endTag == 0x2C) {
|
||||
padding[1];
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
struct UnloadClass {
|
||||
u32 classSerialNumber;
|
||||
};
|
||||
|
||||
bitfield AllocSitesFlags {
|
||||
completeInsteadOfIncremental : 1;
|
||||
sortedByLineInsteadOfAllocation : 1;
|
||||
forceGc : 1;
|
||||
padding : 13;
|
||||
};
|
||||
|
||||
struct AllocSite {
|
||||
bool arrayIndicator;
|
||||
u32 classSerialNumber;
|
||||
u32 stackTraceSerialNumber;
|
||||
u32 numberOfLiveBytes;
|
||||
u32 numberOfLiveInstances;
|
||||
u32 numberOfBytesAllocated;
|
||||
u32 numberOfInstancesAllocated;
|
||||
};
|
||||
|
||||
struct AllocSites {
|
||||
AllocSitesFlags flags;
|
||||
float cutoffRatio;
|
||||
u32 totalLiveBytes;
|
||||
u32 totalLiveInstances;
|
||||
u64 totalBytesAllocated;
|
||||
u64 totalInstancesAllocated;
|
||||
u32 numSites;
|
||||
AllocSite sites[numSites];
|
||||
};
|
||||
|
||||
struct HeapSummary {
|
||||
u32 totalLiveBytes;
|
||||
u32 totalLiveInstances;
|
||||
u64 totalBytesAllocated;
|
||||
u64 totalInstancesAllocated;
|
||||
};
|
||||
|
||||
struct StartThread {
|
||||
u32 threadSerialNumber;
|
||||
ID threadObjectId;
|
||||
u32 stackTraceSerialNumber;
|
||||
ID threadNameStringId;
|
||||
ID threadGroupNameId;
|
||||
ID threadParentGroupNameId;
|
||||
};
|
||||
|
||||
struct EndThread {
|
||||
u32 threadSerialNumber;
|
||||
};
|
||||
|
||||
struct Sample {
|
||||
u32 numberOfSamples;
|
||||
u32 stackTraceSerialNumber;
|
||||
};
|
||||
|
||||
struct CpuSamples {
|
||||
u32 numSamples;
|
||||
Sample samples[numSamples];
|
||||
};
|
||||
|
||||
bitfield ControlSettingsFlags {
|
||||
allocTraces : 1;
|
||||
cpuSampling : 1;
|
||||
padding : 30;
|
||||
};
|
||||
|
||||
struct ControlSettings {
|
||||
ControlSettingsFlags flags;
|
||||
u16 stackTraceDepth;
|
||||
};
|
||||
|
||||
struct Record {
|
||||
Tag tag;
|
||||
u32 time;
|
||||
u32 length;
|
||||
|
||||
match (tag) {
|
||||
(Tag::STRING_IN_UTF8):
|
||||
StringInUTF8 body;
|
||||
(Tag::LOAD_CLASS):
|
||||
LoadClass body;
|
||||
(Tag::UNLOAD_CLASS):
|
||||
UnloadClass body;
|
||||
(Tag::STACK_FRAME):
|
||||
StackFrame body;
|
||||
(Tag::STACK_TRACE):
|
||||
StackTrace body;
|
||||
(Tag::ALLOC_SITES):
|
||||
AllocSites body;
|
||||
(Tag::HEAP_SUMMARY):
|
||||
HeapSummary body;
|
||||
(Tag::START_THREAD):
|
||||
StartThread body;
|
||||
(Tag::END_THREAD):
|
||||
EndThread body;
|
||||
(Tag::HEAP_DUMP | Tag::HEAP_DUMP_SEGMENT):
|
||||
HeapDump heapDumps[while(true)];
|
||||
(Tag::HEAP_DUMP_END):
|
||||
std::error("HEAP_DUMP_END Tag without previous HEAP_DUMP or HEAP_DUMP_SEGMENT Tag");
|
||||
(Tag::CPU_SAMPLES):
|
||||
CpuSamples body;
|
||||
(Tag::CONTROL_SETTINGS):
|
||||
ControlSettings body;
|
||||
(_):
|
||||
std::error(std::format("Unknown record type {:02X} at address 0x{:08X}, index {}", u8(tag), addressof(tag), std::core::array_index()));
|
||||
}
|
||||
};
|
||||
|
||||
struct Header {
|
||||
char format_name[];
|
||||
u32 identifier_size;
|
||||
id_size = identifier_size;
|
||||
u32 timestamp_high;
|
||||
u32 time_stamp_low;
|
||||
};
|
||||
|
||||
struct HPROF {
|
||||
Header header;
|
||||
Record records[while(!std::mem::eof())];
|
||||
};
|
||||
|
||||
HPROF hprof @ 0x00;
|
||||
BIN
tests/patterns/test_data/hprof.hexpat.bin
Normal file
BIN
tests/patterns/test_data/hprof.hexpat.bin
Normal file
Binary file not shown.
Reference in New Issue
Block a user