diff options
| author | ruki <[email protected]> | 2025-12-11 23:29:42 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2025-12-12 09:00:44 +0800 |
| commit | 0b8a0363ed4c21be9795e0b6256d4f1dcd52d722 (patch) | |
| tree | 2b392230511fe671dcdf8f9c583d1b1ae8bda167 | |
| parent | 2821dc7bf3ccee9b725697836ac97b4036e6eb24 (diff) | |
improve readsyms
| -rw-r--r-- | core/src/xmake/binutils/coff/prefix.h | 23 | ||||
| -rw-r--r-- | core/src/xmake/binutils/coff/readsyms.c | 64 | ||||
| -rw-r--r-- | core/src/xmake/binutils/prefix.h | 53 |
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 || |
