Skip to content

Commit

Permalink
object: Started re-doing object internal API
Browse files Browse the repository at this point in the history
  • Loading branch information
dd86k committed Jun 4, 2024
1 parent 4431375 commit c23ca24
Show file tree
Hide file tree
Showing 6 changed files with 331 additions and 168 deletions.
14 changes: 8 additions & 6 deletions dumper/dumper.d
Original file line number Diff line number Diff line change
Expand Up @@ -114,13 +114,13 @@ int dump(const(char)* path) {
panic_adbg("Failed to open object");

// If anything was selected to dump specifically
if (opt_selected) {
if (opt_selected || opt_settings) {
// If not in any "extract" mode, print file info
if (SETTING(Setting.extractAny) == 0) {
print_string("filename", path);
print_u64("filesize", o.file_size);
print_string("format", adbg_object_format_name(o));
print_string("short_name", adbg_object_format_shortname(o));
print_string("type", adbg_object_type_name(o));
print_string("shortname", adbg_object_type_shortname(o));
}
final switch (o.format) with (AdbgObject) {
case mz: return dump_mz(o);
Expand All @@ -142,10 +142,12 @@ int dump(const(char)* path) {
}

// Otherwise, make a basic summary
printf("%s: %s (%s), %s", path,
adbg_object_format_name(o), adbg_object_format_shortname(o),
adbg_object_format_kind_string(o));
printf("%s: %s (%s), %s",
path,
adbg_object_type_name(o), adbg_object_type_shortname(o),
adbg_object_kind_string(o));

// Print instruction set used for object
AdbgMachine mach = adbg_object_machine(o);
if (mach)
printf(", for %s (%s) machines",
Expand Down
1 change: 0 additions & 1 deletion dumper/format/elf.d
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,6 @@ void dump_elf_sections(adbg_object_t *o) {
ushort id = o.i.elf32.ehdr.e_shstrndx;
if (id >= section_count)
panic(1, "String table index out of bounds");
return;

uint offset = o.i.elf32.shdr[id].sh_offset;
if (offset < Elf32_Ehdr.sizeof || offset > o.file_size)
Expand Down
34 changes: 24 additions & 10 deletions dumper/format/mz.d
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import adbg.disassembler;
import adbg.object.server;
import adbg.machines : AdbgMachine;
import adbg.object.format.mz;
import core.stdc.stdlib;
import dumper;
import common.error;

Expand All @@ -34,7 +35,11 @@ private:
void dump_mz_hdr(adbg_object_t *o) {
print_header("Header");

with (o.i.mz.header) {
//TODO: If start of code or relocs start within extended header,
// manually cut it off from the header prints (reserved words and newloc)
mz_header_t* header = adbg_object_mz_header(o);

with (header) {
print_u16("e_cblp", e_cblp);
print_u16("e_cp", e_cp);
print_u16("e_crlc", e_crlc);
Expand All @@ -54,19 +59,28 @@ void dump_mz_hdr(adbg_object_t *o) {
void dump_mz_relocs(adbg_object_t *o) {
print_header("Relocations");

mz_reloc *reloc = void;
mz_reloc_t *reloc = void;
size_t i;
while ((reloc = adbg_object_mz_reloc(o, i++)) != null) with (reloc)
print_reloc16(cast(uint)i, segment, offset);
while ((reloc = adbg_object_mz_reloc(o, i++)) != null)
with (reloc) print_reloc16(cast(uint)i, segment, offset);
}

void dump_mz_disasm(adbg_object_t *o) {
// Get start of data
uint start = (o.i.mz.header.e_cparh << 4) + o.i.mz.header.e_cblp; // paragraphs * 16
if (start < mz_hdr.sizeof || start >= o.file_size)
mz_header_t* header = adbg_object_mz_header(o);

// Get data location
uint start = (header.e_cparh << 4) + header.e_cblp; // (paragraphs * 16) + rest
if (start < mz_header_t.sizeof)
panic(1, "Data start outside of file buffer");

// Get data length, disassembler takes care of error checking
uint len = (o.i.mz.header.e_cp << 4) + o.i.mz.header.e_cblp; // paragraphs * 16
dump_disassemble_object(o, null, 0, o.buffer + start, len, 0);
// Get data length
uint len = (header.e_cp << 4) + header.e_cblp; // (paragraphs * 16) + rest

void* buffer = malloc(len);
if (buffer == null)
panic_crt();
if (adbg_object_read_at(o, start, buffer, len))
panic_adbg();

dump_disassemble_object(o, null, 0, buffer, len, 0);
}
154 changes: 104 additions & 50 deletions src/adbg/object/format/mz.d
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,18 @@
module adbg.object.format.mz;

import adbg.error;
import adbg.object.server : adbg_object_t, AdbgObject;
import adbg.object.server;
import adbg.utils.bit;
import core.stdc.stdlib : malloc, calloc, free;

//TODO: Support compressed MZ files?

/// Minimum file size for an MZ EXE.
// NOTE: Borland EXE about 6K (includes a CRT?).
private enum MINIMUM_SIZE = mz_hdr.sizeof + PAGE;
private enum MINIMUM_SIZE = mz_header_t.sizeof + PAGE;

/// Minimum, non-extended, header size.
enum MZMHSZ = 28;

/// Magic number for MZ objects.
enum MAGIC_MZ = CHAR16!"MZ";
Expand All @@ -31,27 +35,8 @@ enum PAGE = 512;
/// in NE, LE, and PE32 executable images.
enum LFANEW_OFFSET = 0x3c;

/// Original MZ header structure.
///
/// Newer executables add these new fields:
struct mz_hdr {
ushort e_magic; /// Magic number
ushort e_cblp; /// Bytes on last page of file
ushort e_cp; /// Pages in file
ushort e_crlc; /// Number of relocation entries in the table
ushort e_cparh; /// Size of header in paragraphs
ushort e_minalloc; /// Minimum extra paragraphs needed
ushort e_maxalloc; /// Maximum extra paragraphs needed
ushort e_ss; /// Initial (relative) SS value
ushort e_sp; /// Initial SP value
ushort e_csum; /// Checksum
ushort e_ip; /// Initial IP value
ushort e_cs; /// Initial (relative) CS value
ushort e_lfarlc; /// File address of relocation table
ushort e_ovno; /// Overlay number
}
/// Extended MZ header structure featured with newer executables (NE, LE, PE).
struct mz_hdr_ext {
/// MZ header structure.
struct mz_header_t {
ushort e_magic; /// Magic number
ushort e_cblp; /// Bytes on last page of file
ushort e_cp; /// Pages in file
Expand All @@ -66,25 +51,46 @@ struct mz_hdr_ext {
ushort e_cs; /// Initial (relative) CS value
ushort e_lfarlc; /// File address of relocation table
ushort e_ovno; /// Overlay number
// Extended MZ header fields for newer executables (NE, LX, PE).
ushort[ERESWDS] e_res; /// Reserved words
uint e_lfanew; ///
}
static assert(mz_hdr_ext.e_lfanew.offsetof == LFANEW_OFFSET);
static assert(mz_header_t.e_lfanew.offsetof == LFANEW_OFFSET);

// old alias
public alias mz_hdr_ext = mz_header_t;

/// MZ relocation entry
struct mz_reloc {
struct mz_reloc_t {
ushort offset;
ushort segment;
}

// old alias
alias mz_reloc = mz_reloc_t;

private enum {
S_RELOCS_REVERSED = 1,
}
private
struct internal_mz_t {
mz_header_t header;
bool *r_relocs; /// Reversed relocations
mz_reloc *relocs;
}

int adbg_object_mz_load(adbg_object_t *o) {
import core.stdc.stdlib : calloc;

if (o.file_size < MINIMUM_SIZE)
return adbg_oops(AdbgError.objectTooSmall);
// Set format and allocate object internals
o.format = AdbgObject.mz;
o.internal = calloc(1, internal_mz_t.sizeof);
if (o.internal == null)
return adbg_oops(AdbgError.crt);
if (adbg_object_read_at(o, 0, o.internal, mz_header_t.sizeof) < 0)
return adbg_errno();

with (o.i.mz.header)
if (o.p.reversed) {
// Inverse header if required
mz_header_t* header = cast(mz_header_t*)o.internal;
if (o.status & AdbgObjectInternalFlags.reversed) with (header) {
e_magic = adbg_bswap16(e_magic);
e_cblp = adbg_bswap16(e_cblp);
e_cp = adbg_bswap16(e_cp);
Expand All @@ -101,45 +107,93 @@ int adbg_object_mz_load(adbg_object_t *o) {
e_ovno = adbg_bswap16(e_ovno);
}

o.format = AdbgObject.mz;

//TODO: Use internal API to get location
with (o.i.mz)
if (header.e_lfarlc && header.e_crlc && header.e_lfarlc < o.file_size) {
relocs = cast(mz_reloc*)(o.buffer + header.e_lfarlc);
if (o.p.reversed)
o.i.mz.reversed_relocs = cast(bool*)calloc(header.e_crlc, bool.sizeof);
}
return 0;
}

mz_hdr* adbg_object_mz_header(adbg_object_t *o) {
void adbg_object_mz_unload(adbg_object_t *o) {
if (o == null) return;
if (o.internal == null) return;

internal_mz_t *internal = cast(internal_mz_t*)o.internal;

if (internal.r_relocs) free(internal.r_relocs);
if (internal.relocs) free(internal.relocs);

free(internal);
}

mz_header_t* adbg_object_mz_header(adbg_object_t *o) {
if (o == null) {
adbg_oops(AdbgError.invalidArgument);
return null;
}
return o.i.mz.header;
if (o.internal == null) {
adbg_oops(AdbgError.uninitiated);
return null;
}
return &(cast(internal_mz_t*)o.internal).header;
}

mz_reloc* adbg_object_mz_reloc(adbg_object_t *o, size_t index) {
mz_reloc_t* adbg_object_mz_reloc(adbg_object_t *o, size_t index) {
if (o == null) {
adbg_oops(AdbgError.invalidArgument);
return null;
}
if (o.i.mz.relocs == null) {
adbg_oops(AdbgError.unavailable);
return null; // no relocations available
if (o.internal == null) {
adbg_oops(AdbgError.uninitiated);
return null;
}

internal_mz_t *internal = cast(internal_mz_t*)o.internal;

// Initiate relocs
with (internal) if (relocs == null) {
// Any relocations in object and after header?
if (header.e_crlc == 0 || header.e_lfarlc < MZMHSZ) {
adbg_oops(AdbgError.unavailable);
return null;
}
// Allocation portion to hold relocations
size_t size = mz_reloc_t.sizeof * header.e_crlc;
relocs = cast(mz_reloc_t*)malloc(size);
if (relocs == null) {
adbg_oops(AdbgError.crt);
return null;
}
// Error set by function
if (adbg_object_read_at(o, header.e_lfarlc, relocs, size) < 0) {
free(relocs);
relocs = null;
return null;
}
// Initiate reverse info if required
if (o.status & AdbgObjectInternalFlags.reversed) {
r_relocs = cast(bool*)malloc(header.e_crlc);
if (r_relocs == null) {
free(relocs);
relocs = null;
adbg_oops(AdbgError.crt);
return null;
}
}
}
if (index >= o.i.mz.header.e_crlc) {

if (index >= internal.header.e_crlc) {
adbg_oops(AdbgError.indexBounds);
return null;
}

mz_reloc *reloc = &o.i.mz.relocs[index];
if (o.p.reversed && o.i.mz.reversed_relocs[index] == false) {
mz_reloc_t *reloc = &internal.relocs[index];
if (o.status & AdbgObjectInternalFlags.reversed && internal.r_relocs[index] == false) {
reloc.offset = adbg_bswap16(reloc.offset);
reloc.segment = adbg_bswap16(reloc.segment);
o.i.mz.reversed_relocs[index] = true;
internal.r_relocs[index] = true;
}
return reloc;
}

const(char)* adbg_object_mz_kind_string(adbg_object_t *o) {
if (o == null || o.internal == null)
return null;
return (cast(mz_header_t*)o.internal).e_ovno ? `Overlayed Executable` : `Executable`;
}
Loading

0 comments on commit c23ca24

Please sign in to comment.