diff options
| author | ruki <[email protected]> | 2025-12-14 23:37:57 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2025-12-14 23:37:57 +0800 |
| commit | 722a8f23bf29d07b5db27eeeb30e2afe8d8defc5 (patch) | |
| tree | 0852a1f6d54d3cd470e5af1c581de5ef4968c238 /core/src | |
| parent | 151a3e8ffa8f60c86232c9cca769f3649f6d5b2e (diff) | |
improve coff deplibs
Diffstat (limited to 'core/src')
| -rw-r--r-- | core/src/xmake/binutils/coff/deplibs.c | 263 |
1 files changed, 135 insertions, 128 deletions
diff --git a/core/src/xmake/binutils/coff/deplibs.c b/core/src/xmake/binutils/coff/deplibs.c index 5339540cc..0d9d67ca3 100644 --- a/core/src/xmake/binutils/coff/deplibs.c +++ b/core/src/xmake/binutils/coff/deplibs.c @@ -33,164 +33,171 @@ /* ////////////////////////////////////////////////////////////////////////////////////// * private implementation */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -tb_bool_t xm_binutils_coff_deplibs(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, base_offset)) { - return tb_false; - } - if (!tb_stream_bread(istream, (tb_byte_t*)&header, sizeof(header))) { - return tb_false; - } - - // read optional header and import rva +static tb_uint32_t xm_binutils_coff_get_import_rva(tb_stream_ref_t istream, tb_uint16_t opthdr_size) { + + // save current offset + tb_hize_t opt_offset = tb_stream_offset(istream); tb_uint32_t import_rva = 0; - if (header.opthdr > 0) { - // save current offset - tb_hize_t opt_offset = tb_stream_offset(istream); - - // read magic - tb_uint16_t magic = 0; - if (tb_stream_bread(istream, (tb_byte_t*)&magic, sizeof(magic))) { - // seek back - if (tb_stream_seek(istream, opt_offset)) { - if (magic == XM_PE32_MAGIC) { - xm_pe32_opt_header_t opt_header = {0}; - if (tb_stream_bread(istream, (tb_byte_t*)&opt_header, tb_min(sizeof(opt_header), header.opthdr))) { - if (opt_header.number_of_rva_and_sizes > 1) { - import_rva = opt_header.data_directory[1].vaddr; - } + + // read magic + tb_uint16_t magic = 0; + if (tb_stream_bread(istream, (tb_byte_t*)&magic, sizeof(magic))) { + // seek back + if (tb_stream_seek(istream, opt_offset)) { + if (magic == XM_PE32_MAGIC) { + xm_pe32_opt_header_t opt_header = {0}; + if (tb_stream_bread(istream, (tb_byte_t*)&opt_header, tb_min(sizeof(opt_header), opthdr_size))) { + if (opt_header.number_of_rva_and_sizes > 1) { + import_rva = opt_header.data_directory[1].vaddr; } - } else if (magic == XM_PE32P_MAGIC) { - xm_pe32p_opt_header_t opt_header = {0}; - if (tb_stream_bread(istream, (tb_byte_t*)&opt_header, tb_min(sizeof(opt_header), header.opthdr))) { - if (opt_header.number_of_rva_and_sizes > 1) { - import_rva = opt_header.data_directory[1].vaddr; - } + } + } else if (magic == XM_PE32P_MAGIC) { + xm_pe32p_opt_header_t opt_header = {0}; + if (tb_stream_bread(istream, (tb_byte_t*)&opt_header, tb_min(sizeof(opt_header), opthdr_size))) { + if (opt_header.number_of_rva_and_sizes > 1) { + import_rva = opt_header.data_directory[1].vaddr; } } } } } + return import_rva; +} + + +/* ////////////////////////////////////////////////////////////////////////////////////// + * implementation + */ +tb_bool_t xm_binutils_coff_deplibs(tb_stream_ref_t istream, tb_hize_t base_offset, lua_State *lua) { + tb_assert_and_check_return_val(istream && lua, tb_false); - // read section headers + tb_bool_t ok = tb_false; xm_coff_section_t* sections = tb_null; - if (header.nsects > 0) { - sections = tb_nalloc_type(header.nsects, xm_coff_section_t); - if (sections) { - tb_hize_t section_offset = base_offset + sizeof(xm_coff_header_t) + header.opthdr; - if (tb_stream_seek(istream, section_offset)) { - if (!tb_stream_bread(istream, (tb_byte_t*)sections, header.nsects * sizeof(xm_coff_section_t))) { - tb_free(sections); - sections = tb_null; - } - } else { - tb_free(sections); - sections = tb_null; - } + do { + // read COFF header + xm_coff_header_t header; + if (!tb_stream_seek(istream, base_offset)) break; + if (!tb_stream_bread(istream, (tb_byte_t*)&header, sizeof(header))) break; + + // read optional header and import rva + tb_uint32_t import_rva = 0; + if (header.opthdr > 0) { + import_rva = xm_binutils_coff_get_import_rva(istream, header.opthdr); } - } - - if (!sections) { - if (header.nsects > 0) return tb_false; - return tb_true; - } - tb_size_t result_count = 0; - for (tb_uint16_t i = 0; i < header.nsects; i++) { - xm_coff_section_t* section = §ions[i]; - // check if it is .idata section (import directory table) - tb_bool_t found_idt = tb_false; - tb_uint32_t idt_offset = 0; - if (import_rva != 0) { - // check if import rva is in this section - if (import_rva >= section->vaddr && import_rva < section->vaddr + section->vsize) { - idt_offset = section->ofs + (import_rva - section->vaddr); - found_idt = tb_true; - } - } else { - // fallback to check section name - if (tb_strncmp(section->name, ".idata", 6) == 0) { - idt_offset = section->ofs; - found_idt = tb_true; - } + // read section headers + if (header.nsects > 0) { + sections = tb_nalloc_type(header.nsects, xm_coff_section_t); + if (!sections) break; + + tb_hize_t section_offset = base_offset + sizeof(xm_coff_header_t) + header.opthdr; + if (!tb_stream_seek(istream, section_offset)) break; + if (!tb_stream_bread(istream, (tb_byte_t*)sections, header.nsects * sizeof(xm_coff_section_t))) break; } - if (found_idt) { - /* read import directory table - * The .idata section contains the Import Directory Table. - * Each entry is 20 bytes (IMAGE_IMPORT_DESCRIPTOR). - * The table ends with a null entry. - */ + if (!sections) { + if (header.nsects > 0) break; + ok = tb_true; + break; + } - /* We need to iterate over IMAGE_IMPORT_DESCRIPTOR entries. - * struct IMAGE_IMPORT_DESCRIPTOR { - * DWORD OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA) - * DWORD TimeDateStamp; // 0 if not bound, - * DWORD ForwarderChain; // -1 if no forwarders - * DWORD Name; // RVA to DLL name - * DWORD FirstThunk; // RVA to IAT (if bound this IAT has actual addresses) - * }; - */ + tb_size_t result_count = 0; + tb_bool_t failed = tb_false; + for (tb_uint16_t i = 0; i < header.nsects; i++) { + xm_coff_section_t* section = §ions[i]; - if (!tb_stream_seek(istream, idt_offset)) { - if (sections) tb_free(sections); - return tb_false; + // check if it is .idata section (import directory table) + tb_bool_t found_idt = tb_false; + tb_uint32_t idt_offset = 0; + if (import_rva != 0) { + // check if import rva is in this section + if (import_rva >= section->vaddr && import_rva < section->vaddr + section->vsize) { + idt_offset = section->ofs + (import_rva - section->vaddr); + found_idt = tb_true; + } + } else { + // fallback to check section name + if (tb_strncmp(section->name, ".idata", 6) == 0) { + idt_offset = section->ofs; + found_idt = tb_true; + } } - while (1) { - xm_coff_import_directory_table_t entry; - if (!tb_stream_bread(istream, (tb_byte_t*)&entry, sizeof(entry))) { - break; - } + if (found_idt) { + /* read import directory table + * The .idata section contains the Import Directory Table. + * Each entry is 20 bytes (IMAGE_IMPORT_DESCRIPTOR). + * The table ends with a null entry. + */ + + /* We need to iterate over IMAGE_IMPORT_DESCRIPTOR entries. + * struct IMAGE_IMPORT_DESCRIPTOR { + * DWORD OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA) + * DWORD TimeDateStamp; // 0 if not bound, + * DWORD ForwarderChain; // -1 if no forwarders + * DWORD Name; // RVA to DLL name + * DWORD FirstThunk; // RVA to IAT (if bound this IAT has actual addresses) + * }; + */ - // check for null entry (end of table) - if (entry.original_first_thunk == 0 && entry.name_rva == 0) { + if (!tb_stream_seek(istream, idt_offset)) { + failed = tb_true; break; } - tb_uint32_t name_rva = tb_bits_le_to_ne_u32(entry.name_rva); + while (1) { + xm_coff_import_directory_table_t entry; + if (!tb_stream_bread(istream, (tb_byte_t*)&entry, sizeof(entry))) { + break; + } - if (name_rva != 0) { - /* map RVA to file offset to read the name - * We need to find the section that contains this RVA. - */ + // check for null entry (end of table) + if (entry.original_first_thunk == 0 && entry.name_rva == 0) { + break; + } + + tb_uint32_t name_rva = tb_bits_le_to_ne_u32(entry.name_rva); + + if (name_rva != 0) { + /* map RVA to file offset to read the name + * We need to find the section that contains this RVA. + */ - tb_hize_t saved_pos_inner = tb_stream_offset(istream); - tb_uint32_t name_file_offset = 0; + tb_hize_t saved_pos_inner = tb_stream_offset(istream); + tb_uint32_t name_file_offset = 0; - // Find the section containing name_rva - for (tb_uint16_t k = 0; k < header.nsects; k++) { - xm_coff_section_t* s = §ions[k]; - if (name_rva >= s->vaddr && name_rva < s->vaddr + s->vsize) { - name_file_offset = s->ofs + (name_rva - s->vaddr); - break; + // Find the section containing name_rva + for (tb_uint16_t k = 0; k < header.nsects; k++) { + xm_coff_section_t* s = §ions[k]; + if (name_rva >= s->vaddr && name_rva < s->vaddr + s->vsize) { + name_file_offset = s->ofs + (name_rva - s->vaddr); + break; + } } - } - if (name_file_offset != 0) { - tb_char_t dll_name[256]; - if (xm_binutils_read_string(istream, name_file_offset, dll_name, sizeof(dll_name)) && dll_name[0]) { - lua_pushinteger(lua, result_count + 1); - lua_pushstring(lua, dll_name); - lua_settable(lua, -3); - result_count++; - } - } + if (name_file_offset != 0) { + tb_char_t dll_name[256]; + if (xm_binutils_read_string(istream, name_file_offset, dll_name, sizeof(dll_name)) && dll_name[0]) { + lua_pushinteger(lua, result_count + 1); + lua_pushstring(lua, dll_name); + lua_settable(lua, -3); + result_count++; + } + } - tb_stream_seek(istream, saved_pos_inner); + tb_stream_seek(istream, saved_pos_inner); + } } + break; } - break; } - } + + tb_check_break(!failed); + + ok = tb_true; + + } while (0); if (sections) tb_free(sections); - return tb_true; + return ok; } |
