diff options
| author | ruki <[email protected]> | 2025-12-11 22:45:15 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2025-12-12 09:00:43 +0800 |
| commit | af99153ccd7fbc82c7374eac23e6308e37fc061a (patch) | |
| tree | 89004fc53742f316b4773ad564138c204c0b6b58 /core/src | |
| parent | a6262f1fadbd0ae360dc336da298b86d4b9c1628 (diff) | |
improve extractlib
Diffstat (limited to 'core/src')
| -rw-r--r-- | core/src/xmake/binutils/ar/extractlib.c | 100 | ||||
| -rw-r--r-- | core/src/xmake/binutils/extractlib.c | 42 |
2 files changed, 52 insertions, 90 deletions
diff --git a/core/src/xmake/binutils/ar/extractlib.c b/core/src/xmake/binutils/ar/extractlib.c index 5517eaceb..53dd04cc5 100644 --- a/core/src/xmake/binutils/ar/extractlib.c +++ b/core/src/xmake/binutils/ar/extractlib.c @@ -212,8 +212,7 @@ tb_bool_t xm_binutils_ar_extract(tb_stream_ref_t istream, tb_char_t const *outpu // ensure output directory exists // check if directory already exists - tb_file_info_t dir_info; - if (!tb_file_info(outputdir, &dir_info)) { + if (!tb_file_info(outputdir, tb_null)) { // directory doesn't exist, create it if (!tb_directory_create(outputdir)) { return tb_false; @@ -221,6 +220,7 @@ tb_bool_t xm_binutils_ar_extract(tb_stream_ref_t istream, tb_char_t const *outpu } tb_bool_t ok = tb_true; + tb_byte_t* buffer = tb_null; // iterate through AR members while (ok) { @@ -245,64 +245,25 @@ tb_bool_t xm_binutils_ar_extract(tb_stream_ref_t istream, tb_char_t const *outpu 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 this member using sequential read - if (member_size > name_bytes_read) { - tb_hize_t data_size = (tb_hize_t)member_size - name_bytes_read; - if (!tb_stream_skip(istream, data_size)) { - ok = tb_false; - break; - } - } - continue; + 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; } - - // check if extended name format was used (name starts with '#' and was read from stream) - // In extended format, the name is read from the stream, so we need to track bytes read - if (header.name[0] == '#') { - // find the '/' separator to confirm it's extended format - 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) { - // extended name: name was read from stream - // name_bytes_read is already set by xm_binutils_ar_get_member_name - } - } - - // skip symbol tables - if (xm_binutils_ar_is_symbol_table(member_name)) { - // Skip remaining data using sequential read - // member_size is the total size including the name section - // name_bytes_read is the size of the name section (from #N/L format) - // So we need to skip: member_size - name_bytes_read - if (member_size > name_bytes_read) { - tb_hize_t data_size = (tb_hize_t)member_size - name_bytes_read; - if (!tb_stream_skip(istream, data_size)) { - ok = tb_false; - break; - } - } - // AR format requires 2-byte alignment, but member_size already accounts for this - // So we don't need additional alignment here - continue; - } - - // only extract object files - if (!xm_binutils_ar_is_object_file(member_name)) { - // Skip remaining data using sequential read - if (member_size > name_bytes_read) { - tb_hize_t data_size = (tb_hize_t)member_size - name_bytes_read; - if (!tb_stream_skip(istream, data_size)) { - ok = tb_false; - break; - } + + 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; } - // AR format requires 2-byte alignment, but member_size already accounts for this continue; } @@ -312,9 +273,8 @@ tb_bool_t xm_binutils_ar_extract(tb_stream_ref_t istream, tb_char_t const *outpu tb_snprintf(output_path_check, sizeof(output_path_check), "%s/%s", outputdir, member_name); // check if file already exists - tb_file_info_t info; tb_uint32_t conflict_id = 1; - if (tb_file_info(output_path_check, &info)) { + if (tb_file_info(output_path_check, tb_null)) { // name conflict, try different IDs until we find an available name while (conflict_id < 10000) { // reasonable limit if (!xm_binutils_ar_generate_unique_name(member_name, conflict_id, output_name, sizeof(output_name))) { @@ -322,7 +282,7 @@ tb_bool_t xm_binutils_ar_extract(tb_stream_ref_t istream, tb_char_t const *outpu break; } tb_snprintf(output_path_check, sizeof(output_path_check), "%s/%s", outputdir, output_name); - if (!tb_file_info(output_path_check, &info)) { + if (!tb_file_info(output_path_check, tb_null)) { // found available name break; } @@ -356,10 +316,16 @@ tb_bool_t xm_binutils_ar_extract(tb_stream_ref_t istream, tb_char_t const *outpu // copy member data to output file // member_size includes the name if extended format was used, so subtract name_bytes_read - tb_byte_t buffer[4096]; + if (!buffer) buffer = tb_malloc_bytes(TB_STREAM_BLOCK_MAXN); + if (!buffer) { + tb_stream_exit(ostream); + ok = tb_false; + break; + } + tb_hize_t remaining = (tb_hize_t)member_size - name_bytes_read; while (remaining > 0) { - tb_size_t to_read = (tb_size_t)tb_min(remaining, (tb_hize_t)sizeof(buffer)); + tb_size_t to_read = (tb_size_t)tb_min(remaining, (tb_hize_t)TB_STREAM_BLOCK_MAXN); if (!tb_stream_bread(istream, buffer, to_read)) { ok = tb_false; break; @@ -379,18 +345,14 @@ tb_bool_t xm_binutils_ar_extract(tb_stream_ref_t istream, tb_char_t const *outpu } // align to 2-byte boundary (AR format requirement) - tb_hize_t current_pos = tb_stream_offset(istream); - if (current_pos & 1) { - tb_byte_t padding; - if (!tb_stream_bread(istream, &padding, 1)) { + if (member_size % 2) { + if (!tb_stream_skip(istream, 1)) { ok = tb_false; break; } } - } + if (buffer) tb_free(buffer); return ok; } - - diff --git a/core/src/xmake/binutils/extractlib.c b/core/src/xmake/binutils/extractlib.c index 9385bc60f..e1d76c28e 100644 --- a/core/src/xmake/binutils/extractlib.c +++ b/core/src/xmake/binutils/extractlib.c @@ -50,15 +50,15 @@ extern tb_bool_t xm_binutils_mslib_extract(tb_stream_ref_t istream, tb_char_t co */ tb_int_t xm_binutils_extractlib(lua_State *lua) { tb_assert_and_check_return_val(lua, 0); - + // get the library file path tb_char_t const *libraryfile = luaL_checkstring(lua, 1); tb_check_return_val(libraryfile, 0); - + // get the output directory tb_char_t const *outputdir = luaL_checkstring(lua, 2); tb_check_return_val(outputdir, 0); - + // open library file tb_stream_ref_t istream = tb_stream_init_from_file(libraryfile, TB_FILE_MODE_RO); if (!istream) { @@ -66,29 +66,27 @@ tb_int_t xm_binutils_extractlib(lua_State *lua) { lua_pushfstring(lua, "extractlib: open %s failed", libraryfile); return 2; } - + tb_bool_t ok = tb_false; + tb_char_t const* error_msg = tb_null; do { if (!tb_stream_open(istream)) { - lua_pushboolean(lua, tb_false); - lua_pushfstring(lua, "extractlib: open %s failed", libraryfile); + error_msg = "open failed"; break; } - + // detect format tb_int_t format = xm_binutils_detect_format(istream); if (format < 0) { - lua_pushboolean(lua, tb_false); - lua_pushfstring(lua, "extractlib: cannot detect format of %s", libraryfile); + error_msg = "cannot detect format"; break; } - + // extract based on format if (format == XM_BINUTILS_FORMAT_AR) { // AR archive format (.a or .lib in AR format) if (!xm_binutils_ar_extract(istream, outputdir)) { - lua_pushboolean(lua, tb_false); - lua_pushfstring(lua, "extractlib: extract AR archive %s failed", libraryfile); + error_msg = "extract AR archive failed"; break; } ok = tb_true; @@ -99,30 +97,32 @@ tb_int_t xm_binutils_extractlib(lua_State *lua) { // 1. Import libraries (different format) // 2. Static libraries (COFF archive format, similar to AR but different) if (!xm_binutils_mslib_extract(istream, outputdir)) { - lua_pushboolean(lua, tb_false); - lua_pushfstring(lua, "extractlib: extract MSVC lib %s failed", libraryfile); + error_msg = "extract MSVC lib failed"; break; } ok = tb_true; } else { - lua_pushboolean(lua, tb_false); - lua_pushfstring(lua, "extractlib: unsupported format for %s (only AR and MSVC lib are supported)", libraryfile); + error_msg = "unsupported format (only AR and MSVC lib are supported)"; break; } - + } while (0); - + if (istream) { tb_stream_clos(istream); tb_stream_exit(istream); } - + if (ok) { lua_pushboolean(lua, tb_true); return 1; } else { - // error message should already be pushed + lua_pushboolean(lua, tb_false); + if (error_msg) { + lua_pushfstring(lua, "extractlib: %s %s", error_msg, libraryfile); + } else { + lua_pushfstring(lua, "extractlib: unknown error for %s", libraryfile); + } return 2; } } - |
