summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2025-12-11 23:29:42 +0800
committerruki <[email protected]>2025-12-12 09:00:44 +0800
commit0b8a0363ed4c21be9795e0b6256d4f1dcd52d722 (patch)
tree2b392230511fe671dcdf8f9c583d1b1ae8bda167
parent2821dc7bf3ccee9b725697836ac97b4036e6eb24 (diff)
improve readsyms
-rw-r--r--core/src/xmake/binutils/coff/prefix.h23
-rw-r--r--core/src/xmake/binutils/coff/readsyms.c64
-rw-r--r--core/src/xmake/binutils/prefix.h53
3 files changed, 112 insertions, 28 deletions
diff --git a/core/src/xmake/binutils/coff/prefix.h b/core/src/xmake/binutils/coff/prefix.h
index 587d724df..19ae9bc7b 100644
--- a/core/src/xmake/binutils/coff/prefix.h
+++ b/core/src/xmake/binutils/coff/prefix.h
@@ -55,6 +55,29 @@ typedef struct __xm_coff_header_t {
tb_uint16_t flags;
} __tb_packed__ xm_coff_header_t;
+typedef struct __xm_coff_import_header_t {
+ tb_uint16_t sig1; // 0
+ tb_uint16_t sig2; // 0xffff
+ tb_uint16_t version;
+ tb_uint16_t machine;
+ tb_uint32_t time;
+ tb_uint32_t size; // size of data
+ tb_uint16_t ordinal; // ordinal or hint
+ tb_uint16_t type; // type
+} __tb_packed__ xm_coff_import_header_t;
+
+typedef struct __xm_coff_anon_header_t {
+ tb_uint16_t sig1; // 0
+ tb_uint16_t sig2; // 0xffff
+ tb_uint16_t version;
+ tb_uint16_t machine;
+ tb_uint32_t time;
+ tb_uint8_t clsid[16];
+ tb_uint32_t size; // size of data
+} __tb_packed__ xm_coff_anon_header_t;
+
+
+
typedef struct __xm_coff_section_t {
tb_char_t name[8];
tb_uint32_t vsize;
diff --git a/core/src/xmake/binutils/coff/readsyms.c b/core/src/xmake/binutils/coff/readsyms.c
index 41ca5ee47..5fac470e2 100644
--- a/core/src/xmake/binutils/coff/readsyms.c
+++ b/core/src/xmake/binutils/coff/readsyms.c
@@ -46,6 +46,70 @@ tb_bool_t xm_binutils_coff_read_symbols(tb_stream_ref_t istream, lua_State *lua)
return tb_false;
}
+ // check if it is an import object
+ if (header.machine == 0 && header.nsects == 0xffff) {
+ // create result table
+ lua_newtable(lua);
+
+ // check version
+ // version is the low 16 bits of the time field (offset 4)
+ // xm_coff_header_t: machine(2), nsects(2), time(4)
+ // xm_coff_import_header_t: sig1(2), sig2(2), version(2), machine(2)
+ tb_uint16_t version = header.time & 0xffff;
+ if (version == 1) {
+ // anonymous object header (used for CLSID)
+ xm_coff_anon_header_t anon_header;
+ if (!tb_stream_seek(istream, 0)) {
+ return tb_false;
+ }
+ if (!tb_stream_bread(istream, (tb_byte_t*)&anon_header, sizeof(anon_header))) {
+ return tb_false;
+ }
+ } else {
+ // import header
+ xm_coff_import_header_t import_header;
+ if (!tb_stream_seek(istream, 0)) {
+ return tb_false;
+ }
+ if (!tb_stream_bread(istream, (tb_byte_t*)&import_header, sizeof(import_header))) {
+ return tb_false;
+ }
+ }
+
+ // read symbol name (it follows the header)
+ tb_char_t name[256] = {0};
+ tb_size_t pos = 0;
+ tb_byte_t c;
+ while (pos < sizeof(name) - 1) {
+ if (!tb_stream_bread(istream, &c, 1)) {
+ break;
+ }
+ if (c == 0) {
+ break;
+ }
+ name[pos++] = (tb_char_t)c;
+ }
+ name[pos] = '\0';
+
+ if (name[0]) {
+ lua_pushinteger(lua, 1);
+ lua_newtable(lua);
+
+ // name
+ lua_pushstring(lua, "name");
+ lua_pushstring(lua, name);
+ lua_settable(lua, -3);
+
+ // type
+ lua_pushstring(lua, "type");
+ lua_pushstring(lua, "I");
+ lua_settable(lua, -3);
+
+ lua_settable(lua, -3);
+ }
+ return tb_true;
+ }
+
// check if there are symbols
if (header.nsyms == 0 || header.symtabofs == 0) {
lua_newtable(lua);
diff --git a/core/src/xmake/binutils/prefix.h b/core/src/xmake/binutils/prefix.h
index 1733fc7b2..0a0972c6c 100644
--- a/core/src/xmake/binutils/prefix.h
+++ b/core/src/xmake/binutils/prefix.h
@@ -79,55 +79,52 @@ static __tb_inline__ tb_bool_t xm_binutils_read_magic(tb_stream_ref_t istream, t
static __tb_inline__ tb_int_t xm_binutils_detect_format(tb_stream_ref_t istream) {
tb_assert_and_check_return_val(istream, -1);
- // check AR archive format first (!<arch>\n)
- tb_uint8_t ar_magic[8];
- if (xm_binutils_read_magic(istream, ar_magic, 8)) {
- if (ar_magic[0] == '!' && ar_magic[1] == '<' && ar_magic[2] == 'a' &&
- ar_magic[3] == 'r' && ar_magic[4] == 'c' && ar_magic[5] == 'h' &&
- (ar_magic[6] == '>' || ar_magic[6] == '\n') &&
- (ar_magic[7] == '\n' || ar_magic[7] == '\r')) {
- return XM_BINUTILS_FORMAT_AR;
- }
+ // peek first 8 bytes
+ tb_byte_t* p = tb_null;
+ if (!tb_stream_peek(istream, &p, 8)) {
+ return -1;
}
- // read magic bytes
- tb_uint8_t magic[4];
- if (!xm_binutils_read_magic(istream, magic, 4)) {
- return -1;
+ // check AR archive format first (!<arch>\n)
+ if (p[0] == '!' && p[1] == '<' && p[2] == 'a' &&
+ p[3] == 'r' && p[4] == 'c' && p[5] == 'h' &&
+ (p[6] == '>' || p[6] == '\n') &&
+ (p[7] == '\n' || p[7] == '\r')) {
+ return XM_BINUTILS_FORMAT_AR;
}
// check ELF magic (0x7f 'E' 'L' 'F')
- if (magic[0] == 0x7f && magic[1] == 'E' && magic[2] == 'L' && magic[3] == 'F') {
+ if (p[0] == 0x7f && p[1] == 'E' && p[2] == 'L' && p[3] == 'F') {
return XM_BINUTILS_FORMAT_ELF;
}
// check Mach-O magic
- if (magic[0] == 0xfe && magic[1] == 0xed && magic[2] == 0xfa &&
- (magic[3] == 0xce || magic[3] == 0xcf)) {
+ if (p[0] == 0xfe && p[1] == 0xed && p[2] == 0xfa &&
+ (p[3] == 0xce || p[3] == 0xcf)) {
return XM_BINUTILS_FORMAT_MACHO; // Mach-O 32/64 (big endian)
}
- if (magic[0] == 0xce && magic[1] == 0xfa && magic[2] == 0xed && magic[3] == 0xfe) {
+ if (p[0] == 0xce && p[1] == 0xfa && p[2] == 0xed && p[3] == 0xfe) {
return XM_BINUTILS_FORMAT_MACHO; // Mach-O 32 (little endian)
}
- if (magic[0] == 0xcf && magic[1] == 0xfa && magic[2] == 0xed && magic[3] == 0xfe) {
+ if (p[0] == 0xcf && p[1] == 0xfa && p[2] == 0xed && p[3] == 0xfe) {
return XM_BINUTILS_FORMAT_MACHO; // Mach-O 64 (little endian)
}
// check COFF (object files start with machine type, not a magic number)
// COFF header: machine (2 bytes) + nsects (2 bytes) + time (4 bytes) + ...
// Read machine type to verify if it's a valid COFF file
- tb_hize_t saved_pos = tb_stream_offset(istream);
- tb_uint16_t machine;
- if (!tb_stream_seek(istream, 0)) {
- return -1;
- }
- if (!tb_stream_bread(istream, (tb_byte_t*)&machine, 2)) {
- tb_stream_seek(istream, saved_pos);
- return -1;
- }
- tb_stream_seek(istream, saved_pos);
+ tb_uint16_t machine = (p[1] << 8) | p[0];
// check if it's a valid COFF machine type
+ // Import header: 0x0000 0xffff
+ if (machine == 0x0000) {
+ // read second word to check if it is import header
+ tb_uint16_t machine2 = (p[3] << 8) | p[2];
+ if (machine2 == 0xffff) {
+ return XM_BINUTILS_FORMAT_COFF;
+ }
+ }
+
if (machine == XM_BINUTILS_COFF_MACHINE_I386 ||
machine == XM_BINUTILS_COFF_MACHINE_AMD64 ||
machine == XM_BINUTILS_COFF_MACHINE_ARM ||