diff options
| author | ruki <[email protected]> | 2025-12-11 23:42:48 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2025-12-12 09:00:44 +0800 |
| commit | 65b4b2932a7c2fd6dab3fe60597055d1440bddc5 (patch) | |
| tree | 440e1f56021740a82f79cb6ebac277645f7cf91c /core/src | |
| parent | b0eb30a4becb5b6d925aa77418ce30c7f1f79d69 (diff) | |
improve readsyms
Diffstat (limited to 'core/src')
| -rw-r--r-- | core/src/xmake/binutils/ar/extractlib.c | 2 | ||||
| -rw-r--r-- | core/src/xmake/binutils/ar/prefix.h | 11 | ||||
| -rw-r--r-- | core/src/xmake/binutils/ar/readsyms.c | 246 | ||||
| -rw-r--r-- | core/src/xmake/binutils/coff/readsyms.c | 18 | ||||
| -rw-r--r-- | core/src/xmake/binutils/elf/readsyms.c | 37 | ||||
| -rw-r--r-- | core/src/xmake/binutils/macho/readsyms.c | 34 | ||||
| -rw-r--r-- | core/src/xmake/binutils/readsyms.c | 65 |
7 files changed, 332 insertions, 81 deletions
diff --git a/core/src/xmake/binutils/ar/extractlib.c b/core/src/xmake/binutils/ar/extractlib.c index fc9657f0e..32ec4e547 100644 --- a/core/src/xmake/binutils/ar/extractlib.c +++ b/core/src/xmake/binutils/ar/extractlib.c @@ -205,7 +205,7 @@ tb_bool_t xm_binutils_ar_extract(tb_stream_ref_t istream, tb_char_t const *outpu tb_size_t outputdir_len = tb_strlen(outputdir); // check AR magic (!<arch>\n) - if (!xm_binutils_ar_check_magic(istream)) { + if (!xm_binutils_ar_check_magic(istream, 0)) { return tb_false; } diff --git a/core/src/xmake/binutils/ar/prefix.h b/core/src/xmake/binutils/ar/prefix.h index 6f4d0f35b..fd534f0bb 100644 --- a/core/src/xmake/binutils/ar/prefix.h +++ b/core/src/xmake/binutils/ar/prefix.h @@ -32,9 +32,9 @@ /* ////////////////////////////////////////////////////////////////////////////////////// * forward declarations */ -extern tb_bool_t xm_binutils_coff_read_symbols(tb_stream_ref_t istream, lua_State *lua); -extern tb_bool_t xm_binutils_elf_read_symbols(tb_stream_ref_t istream, lua_State *lua); -extern tb_bool_t xm_binutils_macho_read_symbols(tb_stream_ref_t istream, lua_State *lua); +extern tb_bool_t xm_binutils_coff_read_symbols(tb_stream_ref_t istream, tb_hize_t base_offset, lua_State *lua); +extern tb_bool_t xm_binutils_elf_read_symbols(tb_stream_ref_t istream, tb_hize_t base_offset, lua_State *lua); +extern tb_bool_t xm_binutils_macho_read_symbols(tb_stream_ref_t istream, tb_hize_t base_offset, lua_State *lua); extern tb_int_t xm_binutils_detect_format(tb_stream_ref_t istream); /* ////////////////////////////////////////////////////////////////////////////////////// @@ -81,11 +81,12 @@ static __tb_inline__ tb_int64_t xm_binutils_ar_parse_decimal(tb_char_t const *st /* check AR magic (!<arch>\n) * * @param istream the input stream + * @param base_offset the base offset * @return tb_true on success, tb_false on failure */ -static __tb_inline__ tb_bool_t xm_binutils_ar_check_magic(tb_stream_ref_t istream) { +static __tb_inline__ tb_bool_t xm_binutils_ar_check_magic(tb_stream_ref_t istream, tb_hize_t base_offset) { tb_uint8_t magic[8]; - if (!tb_stream_seek(istream, 0)) { + if (!tb_stream_seek(istream, base_offset)) { return tb_false; } if (!tb_stream_bread(istream, magic, 8)) { diff --git a/core/src/xmake/binutils/ar/readsyms.c b/core/src/xmake/binutils/ar/readsyms.c index 6d738565e..5bb5731c6 100644 --- a/core/src/xmake/binutils/ar/readsyms.c +++ b/core/src/xmake/binutils/ar/readsyms.c @@ -25,19 +25,251 @@ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// + * private implementation + */ + +/* get member name from AR header, handling extended names (#N/L format) + * + * @param istream the input stream + * @param header the AR header + * @param name output buffer for the name + * @param name_size size of the name buffer + * @param name_len output: actual name length + * @param bytes_read output: total bytes read from stream (including newline, for extended names) + * @return tb_true on success, tb_false on failure + */ +static tb_bool_t xm_binutils_ar_get_member_name(tb_stream_ref_t istream, xm_ar_header_t const* header, tb_char_t* name, tb_size_t name_size, tb_size_t* name_len, tb_hize_t* bytes_read) { + tb_assert_and_check_return_val(istream && header && name && name_size > 0 && name_len && bytes_read, tb_false); + *bytes_read = 0; + + // check for extended name format (#N/L or #1/N) + // In BSD AR format: + // - #1/N means name is directly after header, N is total length (including name) + // - #N/L means name length is N, total length is L + // - #1/N can also mean name is in long name table at offset 1 + // We'll try to read the name directly from stream first + if (header->name[0] == '#') { + // find the '/' separator + tb_size_t slash_pos = 0; + for (tb_size_t i = 1; i < 16; i++) { + if (header->name[i] == '/') { + slash_pos = i; + break; + } + } + + if (slash_pos > 0 && slash_pos < 16) { + // parse the number before '/' (could be name length or offset) + tb_int64_t first_num = xm_binutils_ar_parse_decimal(header->name + 1, slash_pos - 1); + // parse the number after '/' (total length) + tb_int64_t total_length = xm_binutils_ar_parse_decimal(header->name + slash_pos + 1, 16 - slash_pos - 1); + + if (first_num <= 0 || total_length <= 0) { + return tb_false; + } + + // In BSD AR format, extended name is directly after header + // The name data starts immediately after the header, no newline + // Read exactly total_length bytes for the name section + tb_byte_t c; + tb_size_t name_bytes = 0; + tb_hize_t bytes_read_so_far = 0; + + // Read name characters until we hit null terminator or reach total_length + while (bytes_read_so_far < (tb_hize_t)total_length && name_bytes < name_size - 1) { + if (!tb_stream_bread(istream, &c, 1)) { + return tb_false; + } + bytes_read_so_far++; + + if (c == '\0') { + // Stop reading name at null terminator, but continue reading to reach total_length + break; + } + // Include all characters in the name, including newlines if present + name[name_bytes++] = (tb_char_t)c; + } + name[name_bytes] = '\0'; + *name_len = name_bytes; + + // Skip remaining bytes to reach total_length (there may be padding or null terminators) + if (bytes_read_so_far < (tb_hize_t)total_length) { + tb_hize_t remaining_to_read = (tb_hize_t)total_length - bytes_read_so_far; + if (!tb_stream_skip(istream, remaining_to_read)) { + return tb_false; + } + } + + // Total bytes read = name + padding = total_length + *bytes_read = (tb_hize_t)total_length; + return tb_true; + } + } + + // regular name (null-terminated or space-padded) + tb_size_t i = 0; + for (i = 0; i < 16 && i < name_size - 1; i++) { + if (header->name[i] == ' ' || header->name[i] == '\0' || header->name[i] == '/') { + break; + } + name[i] = header->name[i]; + } + name[i] = '\0'; + *name_len = i; + *bytes_read = 0; // Regular names are in header, not read from stream + return tb_true; +} + +/* check if member is a symbol table (should be skipped) + * + * @param name the member name + * @return tb_true if it's a symbol table, tb_false otherwise + */ +static __tb_inline__ tb_bool_t xm_binutils_ar_is_symbol_table(tb_char_t const* name) { + tb_assert_and_check_return_val(name, tb_false); + return (tb_strcmp(name, "__.SYMDEF") == 0 || tb_strcmp(name, "__.SYMDEF SORTED") == 0 || + tb_strcmp(name, "/") == 0 || tb_strcmp(name, "//") == 0 || + tb_strncmp(name, "__.SYMDEF", 9) == 0); +} + +/* check if member is an object file (based on extension) + * + * @param name the member name + * @return tb_true if it's likely an object file, tb_false otherwise + */ +static __tb_inline__ tb_bool_t xm_binutils_ar_is_object_file(tb_char_t const* name) { + tb_assert_and_check_return_val(name, tb_false); + tb_size_t len = tb_strlen(name); + if (len == 0) return tb_false; + + // check common object file extensions + if (len >= 2 && name[len - 2] == '.' && name[len - 1] == 'o') return tb_true; + if (len >= 4 && tb_strcmp(name + len - 4, ".obj") == 0) return tb_true; + + // check if it's a COFF/ELF/Mach-O file by detecting format + // For now, we'll extract all non-symbol-table members + return tb_true; +} + +/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ /* read symbols from AR archive * - * @param istream the input stream - * @param lua the lua state - * @return tb_true on success, tb_false on failure + * @param istream the input stream + * @param base_offset the base offset + * @param lua the lua state + * @return tb_true on success, tb_false on failure */ -tb_bool_t xm_binutils_ar_read_symbols(tb_stream_ref_t istream, lua_State *lua) { +tb_bool_t xm_binutils_ar_read_symbols(tb_stream_ref_t istream, tb_hize_t base_offset, lua_State* lua) { tb_assert_and_check_return_val(istream && lua, tb_false); - // TODO: implement AR archive symbol reading - // This feature is not yet implemented - return tb_false; + // check AR magic (!<arch>\n) + if (!xm_binutils_ar_check_magic(istream, base_offset)) { + return tb_false; + } + + tb_bool_t ok = tb_true; + tb_size_t object_count = 0; + + // iterate through AR members + while (ok) { + // read AR header + // AR header is exactly 60 bytes: name[16] + date[12] + uid[6] + gid[6] + mode[8] + size[10] + fmag[2] + xm_ar_header_t header; + if (!tb_stream_bread(istream, (tb_byte_t*)&header, sizeof(header))) { + // end of file + break; + } + + // parse member size + tb_int64_t member_size = xm_binutils_ar_parse_decimal(header.size, 10); + if (member_size < 0) { + ok = tb_false; + break; + } + + // get member name + tb_char_t member_name[256] = {0}; + tb_size_t name_len = 0; + tb_hize_t name_bytes_read = 0; + + // get member name (handles both regular and extended name formats) + tb_bool_t skip = tb_false; + if (!xm_binutils_ar_get_member_name(istream, &header, member_name, sizeof(member_name), &name_len, &name_bytes_read)) { + skip = tb_true; + } else if (xm_binutils_ar_is_symbol_table(member_name)) { + // skip symbol tables + skip = tb_true; + } else if (!xm_binutils_ar_is_object_file(member_name)) { + // only extract object files + skip = tb_true; + } + + if (skip) { + // skip remaining data + padding using sequential read + tb_hize_t skip_size = (tb_hize_t)member_size - name_bytes_read; + if (member_size % 2) skip_size++; // add padding + if (!tb_stream_skip(istream, skip_size)) { + ok = tb_false; + break; + } + continue; + } + + // save current position + tb_hize_t current_pos = tb_stream_offset(istream); + + // detect format + tb_int_t format = xm_binutils_detect_format(istream); + if (format != XM_BINUTILS_FORMAT_UNKNOWN && format != XM_BINUTILS_FORMAT_AR) { + // create entry table + lua_newtable(lua); + + // object name + lua_pushstring(lua, "objectfile"); + lua_pushstring(lua, member_name); + lua_settable(lua, -3); + + // symbols + lua_pushstring(lua, "symbols"); + tb_bool_t read_ok = tb_false; + if (format == XM_BINUTILS_FORMAT_COFF) { + read_ok = xm_binutils_coff_read_symbols(istream, current_pos, lua); + } else if (format == XM_BINUTILS_FORMAT_ELF) { + read_ok = xm_binutils_elf_read_symbols(istream, current_pos, lua); + } else if (format == XM_BINUTILS_FORMAT_MACHO) { + read_ok = xm_binutils_macho_read_symbols(istream, current_pos, lua); + } + + if (read_ok) { + lua_settable(lua, -3); + lua_rawseti(lua, -2, (int)(++object_count)); + } else { + lua_pop(lua, 2); // pop symbols key and entry table + } + } + + // skip to next member + tb_hize_t member_data_read = tb_stream_offset(istream) - current_pos; + tb_hize_t remaining_size = (tb_hize_t)member_size - name_bytes_read - member_data_read; + if (member_size % 2) remaining_size++; // add padding + + if (remaining_size > 0) { + if (!tb_stream_skip(istream, remaining_size)) { + ok = tb_false; + break; + } + } else if (remaining_size < 0) { + // should not happen if readsyms functions respect boundaries, but just in case + // seek back to correct position + if (!tb_stream_seek(istream, current_pos + (tb_hize_t)member_size - name_bytes_read + (member_size % 2))) { + ok = tb_false; + break; + } + } + } + + return ok; } diff --git a/core/src/xmake/binutils/coff/readsyms.c b/core/src/xmake/binutils/coff/readsyms.c index 836fa9962..705a543ce 100644 --- a/core/src/xmake/binutils/coff/readsyms.c +++ b/core/src/xmake/binutils/coff/readsyms.c @@ -34,7 +34,7 @@ * private implementation */ -static tb_bool_t xm_binutils_coff_read_import_symbols(tb_stream_ref_t istream, lua_State *lua, xm_coff_header_t const* header) { +static tb_bool_t xm_binutils_coff_read_import_symbols(tb_stream_ref_t istream, tb_hize_t base_offset, lua_State *lua, xm_coff_header_t const* header) { // create result table lua_newtable(lua); @@ -52,7 +52,7 @@ static tb_bool_t xm_binutils_coff_read_import_symbols(tb_stream_ref_t istream, l * because it does not contain the symbol table. */ xm_coff_anon_header_t anon_header; - if (!tb_stream_seek(istream, 0)) { + if (!tb_stream_seek(istream, base_offset)) { return tb_false; } if (!tb_stream_bread(istream, (tb_byte_t*)&anon_header, sizeof(anon_header))) { @@ -61,7 +61,7 @@ static tb_bool_t xm_binutils_coff_read_import_symbols(tb_stream_ref_t istream, l } else { // import header xm_coff_import_header_t import_header; - if (!tb_stream_seek(istream, 0)) { + if (!tb_stream_seek(istream, base_offset)) { return tb_false; } if (!tb_stream_bread(istream, (tb_byte_t*)&import_header, sizeof(import_header))) { @@ -103,12 +103,12 @@ static tb_bool_t xm_binutils_coff_read_import_symbols(tb_stream_ref_t istream, l return tb_true; } -tb_bool_t xm_binutils_coff_read_symbols(tb_stream_ref_t istream, lua_State *lua) { +tb_bool_t xm_binutils_coff_read_symbols(tb_stream_ref_t istream, tb_hize_t base_offset, lua_State *lua) { tb_assert_and_check_return_val(istream && lua, tb_false); // read COFF header xm_coff_header_t header; - if (!tb_stream_seek(istream, 0)) { + if (!tb_stream_seek(istream, base_offset)) { return tb_false; } if (!tb_stream_bread(istream, (tb_byte_t*)&header, sizeof(header))) { @@ -117,7 +117,7 @@ tb_bool_t xm_binutils_coff_read_symbols(tb_stream_ref_t istream, lua_State *lua) // check if it is an import object if (header.machine == 0 && header.nsects == 0xffff) { - return xm_binutils_coff_read_import_symbols(istream, lua, &header); + return xm_binutils_coff_read_import_symbols(istream, base_offset, lua, &header); } // check if there are symbols @@ -140,7 +140,7 @@ tb_bool_t xm_binutils_coff_read_symbols(tb_stream_ref_t istream, lua_State *lua) tb_hize_t saved_pos = tb_stream_offset(istream); // section headers are after COFF header and optional header tb_uint32_t section_offset = sizeof(xm_coff_header_t) + (header.opthdr > 0 ? header.opthdr : 0); - if (tb_stream_seek(istream, section_offset)) { + if (tb_stream_seek(istream, base_offset + section_offset)) { for (tb_uint16_t i = 0; i < header.nsects; i++) { if (!tb_stream_bread(istream, (tb_byte_t*)§ions[i], sizeof(xm_coff_section_t))) { break; @@ -152,7 +152,7 @@ tb_bool_t xm_binutils_coff_read_symbols(tb_stream_ref_t istream, lua_State *lua) } // read symbols - if (!tb_stream_seek(istream, header.symtabofs)) { + if (!tb_stream_seek(istream, base_offset + header.symtabofs)) { if (sections) { tb_free(sections); } @@ -171,7 +171,7 @@ tb_bool_t xm_binutils_coff_read_symbols(tb_stream_ref_t istream, lua_State *lua) tb_bool_t skip = tb_false; tb_char_t name[256] = {0}; - if (!xm_binutils_coff_get_symbol_name(istream, &sym, strtab_offset, name, sizeof(name)) || !name[0]) { + if (!xm_binutils_coff_get_symbol_name(istream, &sym, base_offset + strtab_offset, name, sizeof(name)) || !name[0]) { skip = tb_true; } else if (name[0] == '.') { skip = tb_true; diff --git a/core/src/xmake/binutils/elf/readsyms.c b/core/src/xmake/binutils/elf/readsyms.c index 3aa489381..7e7544bea 100644 --- a/core/src/xmake/binutils/elf/readsyms.c +++ b/core/src/xmake/binutils/elf/readsyms.c @@ -34,12 +34,12 @@ * private implementation */ -tb_bool_t xm_binutils_elf_read_symbols_32(tb_stream_ref_t istream, lua_State *lua) { +tb_bool_t xm_binutils_elf_read_symbols_32(tb_stream_ref_t istream, tb_hize_t base_offset, lua_State *lua) { tb_assert_and_check_return_val(istream && lua, tb_false); // read ELF header xm_elf32_header_t header; - if (!tb_stream_seek(istream, 0)) { + if (!tb_stream_seek(istream, base_offset)) { return tb_false; } if (!tb_stream_bread(istream, (tb_byte_t*)&header, sizeof(header))) { @@ -52,7 +52,7 @@ tb_bool_t xm_binutils_elf_read_symbols_32(tb_stream_ref_t istream, lua_State *lu tb_bool_t found_symtab = tb_false; tb_bool_t found_strtab = tb_false; - if (!tb_stream_seek(istream, header.e_shoff)) { + if (!tb_stream_seek(istream, base_offset + header.e_shoff)) { return tb_false; } @@ -82,7 +82,7 @@ tb_bool_t xm_binutils_elf_read_symbols_32(tb_stream_ref_t istream, lua_State *lu // find string table if (!found_strtab && symtab_section.sh_link < header.e_shnum) { - if (!tb_stream_seek(istream, header.e_shoff + symtab_section.sh_link * sizeof(xm_elf32_section_t))) { + if (!tb_stream_seek(istream, base_offset + header.e_shoff + symtab_section.sh_link * sizeof(xm_elf32_section_t))) { return tb_false; } if (!tb_stream_bread(istream, (tb_byte_t*)&strtab_section, sizeof(strtab_section))) { @@ -101,7 +101,7 @@ tb_bool_t xm_binutils_elf_read_symbols_32(tb_stream_ref_t istream, lua_State *lu // read symbols tb_uint32_t sym_count = symtab_section.sh_size / sizeof(xm_elf32_symbol_t); - if (!tb_stream_seek(istream, symtab_section.sh_offset)) { + if (!tb_stream_seek(istream, base_offset + symtab_section.sh_offset)) { return tb_false; } @@ -125,7 +125,7 @@ tb_bool_t xm_binutils_elf_read_symbols_32(tb_stream_ref_t istream, lua_State *lu // get symbol name tb_char_t name[256]; - if (!xm_binutils_elf_read_string(istream, strtab_section.sh_offset, sym.st_name, name, sizeof(name)) || !name[0]) { + if (!xm_binutils_elf_read_string(istream, base_offset + strtab_section.sh_offset, sym.st_name, name, sizeof(name)) || !name[0]) { continue; } @@ -163,12 +163,12 @@ tb_bool_t xm_binutils_elf_read_symbols_32(tb_stream_ref_t istream, lua_State *lu return tb_true; } -tb_bool_t xm_binutils_elf_read_symbols_64(tb_stream_ref_t istream, lua_State *lua) { +tb_bool_t xm_binutils_elf_read_symbols_64(tb_stream_ref_t istream, tb_hize_t base_offset, lua_State *lua) { tb_assert_and_check_return_val(istream && lua, tb_false); // read ELF header xm_elf64_header_t header; - if (!tb_stream_seek(istream, 0)) { + if (!tb_stream_seek(istream, base_offset)) { return tb_false; } if (!tb_stream_bread(istream, (tb_byte_t*)&header, sizeof(header))) { @@ -181,7 +181,7 @@ tb_bool_t xm_binutils_elf_read_symbols_64(tb_stream_ref_t istream, lua_State *lu tb_bool_t found_symtab = tb_false; tb_bool_t found_strtab = tb_false; - if (!tb_stream_seek(istream, header.e_shoff)) { + if (!tb_stream_seek(istream, base_offset + header.e_shoff)) { return tb_false; } @@ -209,7 +209,7 @@ tb_bool_t xm_binutils_elf_read_symbols_64(tb_stream_ref_t istream, lua_State *lu // find string table if (!found_strtab && symtab_section.sh_link < header.e_shnum) { - if (!tb_stream_seek(istream, header.e_shoff + symtab_section.sh_link * sizeof(xm_elf64_section_t))) { + if (!tb_stream_seek(istream, base_offset + header.e_shoff + symtab_section.sh_link * sizeof(xm_elf64_section_t))) { return tb_false; } if (!tb_stream_bread(istream, (tb_byte_t*)&strtab_section, sizeof(strtab_section))) { @@ -228,7 +228,7 @@ tb_bool_t xm_binutils_elf_read_symbols_64(tb_stream_ref_t istream, lua_State *lu // read symbols tb_uint32_t sym_count = (tb_uint32_t)(symtab_section.sh_size / sizeof(xm_elf64_symbol_t)); - if (!tb_stream_seek(istream, symtab_section.sh_offset)) { + if (!tb_stream_seek(istream, base_offset + symtab_section.sh_offset)) { return tb_false; } @@ -252,7 +252,7 @@ tb_bool_t xm_binutils_elf_read_symbols_64(tb_stream_ref_t istream, lua_State *lu // get symbol name tb_char_t name[256]; - if (!xm_binutils_elf_read_string(istream, strtab_section.sh_offset, sym.st_name, name, sizeof(name)) || !name[0]) { + if (!xm_binutils_elf_read_string(istream, base_offset + strtab_section.sh_offset, sym.st_name, name, sizeof(name)) || !name[0]) { continue; } @@ -290,12 +290,15 @@ tb_bool_t xm_binutils_elf_read_symbols_64(tb_stream_ref_t istream, lua_State *lu return tb_true; } -tb_bool_t xm_binutils_elf_read_symbols(tb_stream_ref_t istream, lua_State *lua) { +tb_bool_t xm_binutils_elf_read_symbols(tb_stream_ref_t istream, tb_hize_t base_offset, lua_State *lua) { tb_assert_and_check_return_val(istream && lua, tb_false); // read and check ELF magic tb_uint8_t magic[4]; - if (!xm_binutils_read_magic(istream, magic, 4)) { + if (!tb_stream_seek(istream, base_offset)) { + return tb_false; + } + if (!tb_stream_bread(istream, magic, 4)) { return tb_false; } if (magic[0] != 0x7f || magic[1] != 'E' || magic[2] != 'L' || magic[3] != 'F') { @@ -304,7 +307,7 @@ tb_bool_t xm_binutils_elf_read_symbols(tb_stream_ref_t istream, lua_State *lua) // check ELF class (32-bit or 64-bit) tb_uint8_t elf_class; - if (!tb_stream_seek(istream, 4)) { + if (!tb_stream_seek(istream, base_offset + 4)) { return tb_false; } if (!tb_stream_bread(istream, (tb_byte_t*)&elf_class, 1)) { @@ -312,9 +315,9 @@ tb_bool_t xm_binutils_elf_read_symbols(tb_stream_ref_t istream, lua_State *lua) } if (elf_class == 1) { - return xm_binutils_elf_read_symbols_32(istream, lua); + return xm_binutils_elf_read_symbols_32(istream, base_offset, lua); } else if (elf_class == 2) { - return xm_binutils_elf_read_symbols_64(istream, lua); + return xm_binutils_elf_read_symbols_64(istream, base_offset, lua); } return tb_false; diff --git a/core/src/xmake/binutils/macho/readsyms.c b/core/src/xmake/binutils/macho/readsyms.c index dde7739e8..4c3fbafa6 100644 --- a/core/src/xmake/binutils/macho/readsyms.c +++ b/core/src/xmake/binutils/macho/readsyms.c @@ -92,12 +92,12 @@ static __tb_inline__ tb_void_t xm_binutils_macho_swap_nlist_64(xm_macho_nlist_64 } } -tb_bool_t xm_binutils_macho_read_symbols_32(tb_stream_ref_t istream, lua_State *lua, tb_bool_t swap_bytes) { +tb_bool_t xm_binutils_macho_read_symbols_32(tb_stream_ref_t istream, tb_hize_t base_offset, lua_State *lua, tb_bool_t swap_bytes) { tb_assert_and_check_return_val(istream && lua, tb_false); // read Mach-O header xm_macho_header_t header; - if (!tb_stream_seek(istream, 0)) { + if (!tb_stream_seek(istream, base_offset)) { return tb_false; } if (!tb_stream_bread(istream, (tb_byte_t*)&header, sizeof(header))) { @@ -114,7 +114,7 @@ tb_bool_t xm_binutils_macho_read_symbols_32(tb_stream_ref_t istream, lua_State * tb_uint32_t cmd; tb_uint32_t cmdsize; - if (!tb_stream_seek(istream, offset)) { + if (!tb_stream_seek(istream, base_offset + offset)) { return tb_false; } if (!tb_stream_bread(istream, (tb_byte_t*)&cmd, 4)) { @@ -125,7 +125,7 @@ tb_bool_t xm_binutils_macho_read_symbols_32(tb_stream_ref_t istream, lua_State * } if (cmd == XM_MACHO_LC_SYMTAB) { - if (!tb_stream_seek(istream, offset)) { + if (!tb_stream_seek(istream, base_offset + offset)) { return tb_false; } if (!tb_stream_bread(istream, (tb_byte_t*)&symtab_cmd, sizeof(symtab_cmd))) { @@ -147,7 +147,7 @@ tb_bool_t xm_binutils_macho_read_symbols_32(tb_stream_ref_t istream, lua_State * lua_newtable(lua); // read symbols - if (!tb_stream_seek(istream, symtab_cmd.symoff)) { + if (!tb_stream_seek(istream, base_offset + symtab_cmd.symoff)) { return tb_false; } @@ -166,7 +166,7 @@ tb_bool_t xm_binutils_macho_read_symbols_32(tb_stream_ref_t istream, lua_State * // get symbol name tb_char_t name[256]; - if (!xm_binutils_macho_read_string(istream, symtab_cmd.stroff, nlist.strx, name, sizeof(name)) || !name[0]) { + if (!xm_binutils_macho_read_string(istream, base_offset + symtab_cmd.stroff, nlist.strx, name, sizeof(name)) || !name[0]) { continue; } @@ -198,12 +198,12 @@ tb_bool_t xm_binutils_macho_read_symbols_32(tb_stream_ref_t istream, lua_State * return tb_true; } -tb_bool_t xm_binutils_macho_read_symbols_64(tb_stream_ref_t istream, lua_State *lua, tb_bool_t swap_bytes) { +tb_bool_t xm_binutils_macho_read_symbols_64(tb_stream_ref_t istream, tb_hize_t base_offset, lua_State *lua, tb_bool_t swap_bytes) { tb_assert_and_check_return_val(istream && lua, tb_false); // read Mach-O header xm_macho_header_64_t header; - if (!tb_stream_seek(istream, 0)) { + if (!tb_stream_seek(istream, base_offset)) { return tb_false; } if (!tb_stream_bread(istream, (tb_byte_t*)&header, sizeof(header))) { @@ -220,7 +220,7 @@ tb_bool_t xm_binutils_macho_read_symbols_64(tb_stream_ref_t istream, lua_State * tb_uint32_t cmd; tb_uint32_t cmdsize; - if (!tb_stream_seek(istream, offset)) { + if (!tb_stream_seek(istream, base_offset + offset)) { return tb_false; } if (!tb_stream_bread(istream, (tb_byte_t*)&cmd, 4)) { @@ -236,7 +236,7 @@ tb_bool_t xm_binutils_macho_read_symbols_64(tb_stream_ref_t istream, lua_State * } if (cmd == XM_MACHO_LC_SYMTAB) { - if (!tb_stream_seek(istream, offset)) { + if (!tb_stream_seek(istream, base_offset + offset)) { return tb_false; } if (!tb_stream_bread(istream, (tb_byte_t*)&symtab_cmd, sizeof(symtab_cmd))) { @@ -259,7 +259,7 @@ tb_bool_t xm_binutils_macho_read_symbols_64(tb_stream_ref_t istream, lua_State * lua_newtable(lua); // read symbols - if (!tb_stream_seek(istream, symtab_cmd.symoff)) { + if (!tb_stream_seek(istream, base_offset + symtab_cmd.symoff)) { return tb_false; } @@ -278,7 +278,7 @@ tb_bool_t xm_binutils_macho_read_symbols_64(tb_stream_ref_t istream, lua_State * // get symbol name tb_char_t name[256]; - if (!xm_binutils_macho_read_string(istream, symtab_cmd.stroff, nlist.strx, name, sizeof(name)) || !name[0]) { + if (!xm_binutils_macho_read_string(istream, base_offset + symtab_cmd.stroff, nlist.strx, name, sizeof(name)) || !name[0]) { continue; } @@ -310,9 +310,13 @@ tb_bool_t xm_binutils_macho_read_symbols_64(tb_stream_ref_t istream, lua_State * return tb_true; } -tb_bool_t xm_binutils_macho_read_symbols(tb_stream_ref_t istream, lua_State *lua) { +tb_bool_t xm_binutils_macho_read_symbols(tb_stream_ref_t istream, tb_hize_t base_offset, lua_State *lua) { tb_assert_and_check_return_val(istream && lua, tb_false); + if (!tb_stream_seek(istream, base_offset)) { + return tb_false; + } + // read and check magic tb_uint8_t magic_bytes[4]; if (!xm_binutils_read_magic(istream, magic_bytes, 4)) { @@ -327,9 +331,9 @@ tb_bool_t xm_binutils_macho_read_symbols(tb_stream_ref_t istream, lua_State *lua } if (is_32bit) { - return xm_binutils_macho_read_symbols_32(istream, lua, swap_bytes); + return xm_binutils_macho_read_symbols_32(istream, base_offset, lua, swap_bytes); } else { - return xm_binutils_macho_read_symbols_64(istream, lua, swap_bytes); + return xm_binutils_macho_read_symbols_64(istream, base_offset, lua, swap_bytes); } } diff --git a/core/src/xmake/binutils/readsyms.c b/core/src/xmake/binutils/readsyms.c index 73908a562..5a1b40d3c 100644 --- a/core/src/xmake/binutils/readsyms.c +++ b/core/src/xmake/binutils/readsyms.c @@ -36,10 +36,10 @@ /* ////////////////////////////////////////////////////////////////////////////////////// * forward declarations */ -extern tb_bool_t xm_binutils_coff_read_symbols(tb_stream_ref_t istream, lua_State *lua); -extern tb_bool_t xm_binutils_elf_read_symbols(tb_stream_ref_t istream, lua_State *lua); -extern tb_bool_t xm_binutils_macho_read_symbols(tb_stream_ref_t istream, lua_State *lua); -extern tb_bool_t xm_binutils_ar_read_symbols(tb_stream_ref_t istream, lua_State *lua); +extern tb_bool_t xm_binutils_coff_read_symbols(tb_stream_ref_t istream, tb_hize_t base_offset, lua_State *lua); +extern tb_bool_t xm_binutils_elf_read_symbols(tb_stream_ref_t istream, tb_hize_t base_offset, lua_State *lua); +extern tb_bool_t xm_binutils_macho_read_symbols(tb_stream_ref_t istream, tb_hize_t base_offset, lua_State *lua); +extern tb_bool_t xm_binutils_ar_read_symbols(tb_stream_ref_t istream, tb_hize_t base_offset, lua_State *lua); /* ////////////////////////////////////////////////////////////////////////////////////// * implementation @@ -81,40 +81,51 @@ tb_int_t xm_binutils_readsyms(lua_State *lua) { break; } + // create result list + lua_newtable(lua); + // read symbols based on format if (format == XM_BINUTILS_FORMAT_AR) { // AR archive (.a or .lib) - if (!xm_binutils_ar_read_symbols(istream, lua)) { + if (!xm_binutils_ar_read_symbols(istream, 0, lua)) { lua_pushboolean(lua, tb_false); lua_pushfstring(lua, "readsyms: read AR archive symbols failed"); break; } - } else if (format == XM_BINUTILS_FORMAT_COFF) { - // COFF - if (!xm_binutils_coff_read_symbols(istream, lua)) { - lua_pushboolean(lua, tb_false); - lua_pushfstring(lua, "readsyms: read COFF symbols failed"); - break; - } - } else if (format == XM_BINUTILS_FORMAT_ELF) { - // ELF - if (!xm_binutils_elf_read_symbols(istream, lua)) { - lua_pushboolean(lua, tb_false); - lua_pushfstring(lua, "readsyms: read ELF symbols failed"); - break; + } else { + // single object file (COFF, ELF, Mach-O) + // create entry table + lua_newtable(lua); + + // object name + lua_pushstring(lua, "objectfile"); + tb_char_t const* name = tb_strrchr(objectfile, '/'); + if (!name) name = tb_strrchr(objectfile, '\\'); + if (!name) name = objectfile; + else name++; + lua_pushstring(lua, name); + lua_settable(lua, -3); + + // symbols + lua_pushstring(lua, "symbols"); + tb_bool_t read_ok = tb_false; + if (format == XM_BINUTILS_FORMAT_COFF) { + read_ok = xm_binutils_coff_read_symbols(istream, 0, lua); + } else if (format == XM_BINUTILS_FORMAT_ELF) { + read_ok = xm_binutils_elf_read_symbols(istream, 0, lua); + } else if (format == XM_BINUTILS_FORMAT_MACHO) { + read_ok = xm_binutils_macho_read_symbols(istream, 0, lua); } - } else if (format == XM_BINUTILS_FORMAT_MACHO) { - // Mach-O - if (!xm_binutils_macho_read_symbols(istream, lua)) { + + if (read_ok) { + lua_settable(lua, -3); + lua_rawseti(lua, -2, 1); + } else { + lua_pop(lua, 2); // pop entry table and result list lua_pushboolean(lua, tb_false); - lua_pushfstring(lua, "readsyms: read Mach-O symbols failed"); + lua_pushfstring(lua, "readsyms: read symbols failed"); break; } - } else { - // unknown or unsupported format - lua_pushboolean(lua, tb_false); - lua_pushfstring(lua, "readsyms: unsupported or unknown file format"); - break; } ok = tb_true; |
