summaryrefslogtreecommitdiff
path: root/core/src
diff options
context:
space:
mode:
authorruki <[email protected]>2025-12-11 23:42:48 +0800
committerruki <[email protected]>2025-12-12 09:00:44 +0800
commit65b4b2932a7c2fd6dab3fe60597055d1440bddc5 (patch)
tree440e1f56021740a82f79cb6ebac277645f7cf91c /core/src
parentb0eb30a4becb5b6d925aa77418ce30c7f1f79d69 (diff)
improve readsyms
Diffstat (limited to 'core/src')
-rw-r--r--core/src/xmake/binutils/ar/extractlib.c2
-rw-r--r--core/src/xmake/binutils/ar/prefix.h11
-rw-r--r--core/src/xmake/binutils/ar/readsyms.c246
-rw-r--r--core/src/xmake/binutils/coff/readsyms.c18
-rw-r--r--core/src/xmake/binutils/elf/readsyms.c37
-rw-r--r--core/src/xmake/binutils/macho/readsyms.c34
-rw-r--r--core/src/xmake/binutils/readsyms.c65
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*)&sections[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;