summaryrefslogtreecommitdiff
path: root/core/src
diff options
context:
space:
mode:
authorruki <[email protected]>2025-12-14 23:37:57 +0800
committerruki <[email protected]>2025-12-14 23:37:57 +0800
commit722a8f23bf29d07b5db27eeeb30e2afe8d8defc5 (patch)
tree0852a1f6d54d3cd470e5af1c581de5ef4968c238 /core/src
parent151a3e8ffa8f60c86232c9cca769f3649f6d5b2e (diff)
improve coff deplibs
Diffstat (limited to 'core/src')
-rw-r--r--core/src/xmake/binutils/coff/deplibs.c263
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 = &sections[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 = &sections[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 = &sections[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 = &sections[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;
}