Skip to content

Commit

Permalink
object: Switch mscoff to new backend funcs
Browse files Browse the repository at this point in the history
  • Loading branch information
dd86k committed Jul 3, 2024
1 parent 6ad5f1a commit ae3b7cc
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 54 deletions.
16 changes: 10 additions & 6 deletions dumper/format/mscoff.d
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand Down
71 changes: 61 additions & 10 deletions src/adbg/object/format/mscoff.d
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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.
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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
Expand All @@ -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 {
Expand All @@ -126,22 +129,70 @@ 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;
ushort Type;
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;
}
68 changes: 30 additions & 38 deletions src/adbg/object/server.d
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand All @@ -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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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;
Expand All @@ -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)
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit ae3b7cc

Please sign in to comment.