From ae3b7cc0ab4f9f0a22d73e36d30aa8ad8d4d23a1 Mon Sep 17 00:00:00 2001
From: dd86k
Date: Tue, 2 Jul 2024 20:29:11 -0400
Subject: [PATCH] object: Switch mscoff to new backend funcs
---
dumper/format/mscoff.d | 16 +++++---
src/adbg/object/format/mscoff.d | 71 ++++++++++++++++++++++++++++-----
src/adbg/object/server.d | 68 ++++++++++++++-----------------
3 files changed, 101 insertions(+), 54 deletions(-)
diff --git a/dumper/format/mscoff.d b/dumper/format/mscoff.d
index 3e94dc40..594cdb5f 100644
--- a/dumper/format/mscoff.d
+++ b/dumper/format/mscoff.d
@@ -15,19 +15,21 @@ import dumper;
int dump_mscoff(adbg_object_t *o) {
if (SELECTED(Select.headers))
- dump_mscoff_hdr(o);
+ dump_mscoff_header(o);
return 0;
}
private:
-void dump_mscoff_hdr(adbg_object_t *o) {
+void dump_mscoff_header(adbg_object_t *o) {
print_header("Header");
- switch (o.i.mscoff.import_header.Version) {
+ mscoff_import_header_t *header = cast(mscoff_import_header_t*)adbg_object_mscoff_header(o);
+
+ switch (header.Version) {
case MSCOFF_VERSION_IMPORT: // 0
- with (o.i.mscoff.import_header) {
+ with (header) {
print_x16("Sig1", Sig1);
print_x16("Sig2", Sig2);
print_u16("Version", Version);
@@ -39,7 +41,8 @@ void dump_mscoff_hdr(adbg_object_t *o) {
}
break;
case MSCOFF_VERSION_ANON: // 1
- with (o.i.mscoff.anon_header) {
+ mscoff_anon_header_t *header1 = cast(mscoff_anon_header_t*)header;
+ with (header1) {
print_x16("Sig1", Sig1);
print_x16("Sig2", Sig2);
print_u16("Version", Version);
@@ -52,7 +55,8 @@ void dump_mscoff_hdr(adbg_object_t *o) {
}
break;
case MSCOFF_VERSION_ANONV2: // 2
- with (o.i.mscoff.anon_v2_header) {
+ mscoff_anon_header_v2_t *header2 = cast(mscoff_anon_header_v2_t*)header;
+ with (header2) {
print_x16("Sig1", Sig1);
print_x16("Sig2", Sig2);
print_u16("Version", Version);
diff --git a/src/adbg/object/format/mscoff.d b/src/adbg/object/format/mscoff.d
index e6988fd6..3ecb8c66 100644
--- a/src/adbg/object/format/mscoff.d
+++ b/src/adbg/object/format/mscoff.d
@@ -11,8 +11,11 @@ module adbg.object.format.mscoff;
// NOTE: PE32/PE-COFF is an extension of COFF and MZ
-import adbg.object.server : AdbgObject, adbg_object_t;
+import adbg.object.server;
import adbg.utils.uid;
+import adbg.utils.math;
+import adbg.error;
+import core.stdc.stdlib;
//
// Non-COFF Object file headers (.obj from VS2002-VS2015, mscoff)
@@ -44,7 +47,7 @@ enum {
MSCOFF_IMPORT_NAME_EXPORTAS = 4,
}
-struct mscoff_import_header { // IMPORT_OBJECT_HEADER
+struct mscoff_import_header_t { // IMPORT_OBJECT_HEADER
/// Must be IMAGE_FILE_MACHINE_UNKNOWN.
ushort Sig1;
/// Must be 0xFFFF.
@@ -64,7 +67,7 @@ struct mscoff_import_header { // IMPORT_OBJECT_HEADER
ulong Flags;
}
-struct mscoff_anon_header { // ANON_OBJECT_HEADER
+struct mscoff_anon_header_t { // ANON_OBJECT_HEADER
ushort Sig1; // Must be IMAGE_FILE_MACHINE_UNKNOWN
ushort Sig2; // Must be 0xffff
ushort Version; // >= 1 (implies the CLSID field is present)
@@ -75,7 +78,7 @@ struct mscoff_anon_header { // ANON_OBJECT_HEADER
uint SizeOfData; // Size of data that follows the header
}
-struct mscoff_anon_header_v2 { // ANON_OBJECT_HEADER_V2
+struct mscoff_anon_header_v2_t { // ANON_OBJECT_HEADER_V2
ushort Sig1; // Must be IMAGE_FILE_MACHINE_UNKNOWN
ushort Sig2; // Must be 0xffff
ushort Version; // >= 2 (implies the Flags field is present - otherwise V1)
@@ -89,7 +92,7 @@ struct mscoff_anon_header_v2 { // ANON_OBJECT_HEADER_V2
uint MetaDataOffset; // Offset of CLR metadata
}
-struct mscoff_anon_header_bigobj { // ANON_OBJECT_HEADER_BIGOBJ
+struct mscoff_anon_header_bigobj_t { // ANON_OBJECT_HEADER_BIGOBJ
/* same as ANON_OBJECT_HEADER_V2 */
ushort Sig1; // Must be IMAGE_FILE_MACHINE_UNKNOWN
ushort Sig2; // Must be 0xffff
@@ -112,7 +115,7 @@ struct mscoff_anon_header_bigobj { // ANON_OBJECT_HEADER_BIGOBJ
// Same as PE32
enum SYMNMLEN = 8;
-struct mscoff_anon_symbol_table32 {
+struct mscoff_anon_symbol_table32_t {
union {
ubyte[SYMNMLEN] Name;
struct {
@@ -126,9 +129,9 @@ struct mscoff_anon_symbol_table32 {
ubyte StorageClass;
ubyte NumberOfAuxSymbols;
}
-static assert(mscoff_anon_symbol_table32.sizeof == 20);
+static assert(mscoff_anon_symbol_table32_t.sizeof == 20);
-struct mscoff_anon_symbol_table { align(1):
+struct mscoff_anon_symbol_table_t { align(1):
ubyte[SYMNMLEN] Name;
uint Value;
short SectionNumber;
@@ -136,12 +139,60 @@ struct mscoff_anon_symbol_table { align(1):
ubyte StorageClass;
ubyte NumberOfAuxSymbols;
}
-static assert(mscoff_anon_symbol_table.sizeof == 18);
+static assert(mscoff_anon_symbol_table_t.sizeof == 18);
+
+private
+struct internal_mscoff_t {
+ union {
+ mscoff_import_header_t import_header;
+ mscoff_anon_header_t anon_header;
+ mscoff_anon_header_v2_t anonv2_header;
+ }
+}
+
+private enum MAX1 = MAX!(mscoff_anon_header_t.sizeof, mscoff_anon_header_v2_t.sizeof);
+private enum MAX2 = MAX!(MAX1, mscoff_import_header_t.sizeof);
int adbg_object_mscoff_load(adbg_object_t *o) {
+ o.internal = calloc(1, internal_mscoff_t.sizeof);
+ if (o.internal == null)
+ return adbg_oops(AdbgError.crt);
+ if (adbg_object_read_at(o, 0, o.internal, MAX2))
+ return adbg_errno();
+
o.format = AdbgObject.mscoff;
- // NOTE: No swapping is done because there is currently no sane way of detecting it
+ // TODO: Support swapping
return 0;
}
+void adbg_object_mscoff_unload(adbg_object_t *o) {
+ if (o == null) return;
+ if (o.internal == null) return;
+ free(o.internal);
+}
+
+uint adbg_object_mscoff_version(adbg_object_t *o) {
+ if (o == null) {
+ adbg_oops(AdbgError.invalidArgument);
+ return -1;
+ }
+ if (o.internal == null) {
+ adbg_oops(AdbgError.uninitiated);
+ return -1;
+ }
+ internal_mscoff_t *internal = cast(internal_mscoff_t*)o.internal;
+ return internal.anon_header.Version;
+}
+
+void* adbg_object_mscoff_header(adbg_object_t *o) {
+ if (o == null) {
+ adbg_oops(AdbgError.invalidArgument);
+ return null;
+ }
+ if (o.internal == null) {
+ adbg_oops(AdbgError.uninitiated);
+ return null;
+ }
+ return o.internal;
+}
diff --git a/src/adbg/object/server.d b/src/adbg/object/server.d
index a3de2618..b72dcede 100644
--- a/src/adbg/object/server.d
+++ b/src/adbg/object/server.d
@@ -43,13 +43,17 @@ extern (C):
// (e.g., pe, elf, etc.) to make things consistent. This is why
// auxiliary names are simply "adbg_object_offset", for example.
-//TODO: Consider structure definition, using a template
+// TODO: Consider structure definition, using a template
// Uses:
// - For swapping, uses less code than inlining it
// - For displaying and using field offsets
-//TODO: adbg_object_endiannes
-// Why? Machine module do not include endianness.
-// And would be beneficial when host has incompatible endianness.
+// TODO: adbg_object_endiannes
+// Why? Machine module do not include endianness.
+// And would be beneficial when host has incompatible endianness.
+// TODO: adbg_object_open_process(int pid, ...)
+// TODO: adbg_object_open_buffer(void *buffer, size_t size, ...)
+// TODO: Consider function to ease submodule setup
+// adbg_object_setup(AdbgObject type, size_t internal_buffer_size, void function(adbg_object_t*) fclose)
/// Executable or object file format.
enum AdbgObject {
@@ -87,16 +91,7 @@ enum AdbgObject {
mscoff,
}
-//
-/*enum AdbgObjectKind {
- unknown,
- executable,
-}*/
-
-// NOTE: This enum is a little weird but should be used as an I/O strategy
-/// Object origin. (or "load mode")
-///
-/// How was the object loaded or hooked.
+/// Object origin. Used in adbg_object_read.
private
enum AdbgObjectOrigin {
/// Object is unloaded, or the loading method is unknown.
@@ -161,6 +156,10 @@ struct adbg_object_t {
adbg_process_t *process;
size_t location;
}
+ struct {
+ void *user_buffer;
+ size_t user_size;
+ }
}
/// Object's loading origin.
@@ -176,6 +175,11 @@ struct adbg_object_t {
/// Managed by the object handler.
void *internal;
+ package:
+
+ /// Used to attach the unload function
+ void function(adbg_object_t*) func_unload;
+
//TODO: Deprecate *all* of this
// Object properties.
@@ -230,14 +234,6 @@ struct adbg_object_t {
int firstentry;
}
omf_t omf;
-
- union mscoff_t {
- mscoff_import_header *import_header;
- mscoff_anon_header *anon_header;
- mscoff_anon_header_v2 *anon_v2_header;
- mscoff_anon_header_bigobj *anon_big_header;
- }
- mscoff_t mscoff;
}
/// Internal object definitions.
deprecated
@@ -389,11 +385,6 @@ adbg_object_t* adbg_object_open_file(const(char) *path, ...) {
return o;
}
-/*adbg_object_t* adbg_object_open_process(adbg_process_t *proc) {
- adbg_oops(AdbgError.unimplemented);
- return null;
-}*/
-
/// Close object instance.
/// Params: o = Object instance.
export
@@ -457,7 +448,9 @@ int adbg_object_read(adbg_object_t *o, void *buffer, size_t rdsize, int flags =
return adbg_oops(AdbgError.unimplemented);
}
-//TODO: adbg_object_read_at: Add flag to allocate memory. Or make a new function (new signature)
+//TODO: adbg_object_readalloc_at: Allocate memory and read.
+// void* adbg_object_readalloc_at(adbg_object_t *o, long location, size_t rdsize, int flags)
+
/// Read raw data from object at absolute position.
/// Params:
/// o = Object instance.
@@ -491,10 +484,13 @@ int adbg_object_read_at(adbg_object_t *o, long location, void *buffer, size_t rd
return adbg_object_read(o, buffer, rdsize);
}
-///
+/// Size of signature buffer.
+private enum SIGMAX = MAX!(PDB20_MAGIC.length, PDB70_MAGIC.length);
+
+/// Used in signature detection.
private
union SIGNATURE {
- ubyte[64] buffer;
+ ubyte[SIGMAX] buffer;
ulong u64;
uint u32;
ushort u16;
@@ -509,14 +505,12 @@ int adbg_object_loadv(adbg_object_t *o) {
return adbg_oops(AdbgError.invalidArgument);
o.status = 0;
- memset(&o.p, 0, o.p.sizeof); // Init object properties
- memset(&o.i, 0, o.i.sizeof); // Init object internal structures
// Load minimum for signature detection
// Also tests seeking in case this is a streamed input
SIGNATURE sig = void;
int siglen = osfread(o.file, &sig, SIGNATURE.sizeof); /// signature size
- version (Trace) trace("siglen=%d", siglen);
+ version (Trace) trace("siglen=%d sigmax=%u", siglen, cast(uint)SIGMAX);
if (siglen < 0)
return adbg_oops(AdbgError.os);
if (siglen <= uint.sizeof)
@@ -564,11 +558,9 @@ int adbg_object_loadv(adbg_object_t *o) {
if (siglen > ushort.sizeof) switch (sig.u16) {
// Anonymous MSCOFF
case 0:
- if (o.file_size < mscoff_anon_header_bigobj.sizeof)
- return adbg_oops(AdbgError.objectUnknownFormat);
- if (o.i.mscoff.import_header.Sig2 != 0xffff)
- return adbg_oops(AdbgError.objectUnknownFormat);
- return adbg_object_mscoff_load(o);
+ if (siglen > uint.sizeof && (sig.u32 >> 16) == 0xffff)
+ return adbg_object_mscoff_load(o);
+ break;
// MZ executables
case MAGIC_MZ:
version (Trace) trace("e_lfarlc=%#x", sig.mzheader.e_lfarlc);