diff options
| author | ruki <[email protected]> | 2025-12-14 23:23:38 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2025-12-14 23:23:38 +0800 |
| commit | 65d966f76661b4756a5154a44155a87ff7cdd0b0 (patch) | |
| tree | a791b0dba58071633b38e405c41450c863fe8dee | |
| parent | e9bf831cc47fa3f4c45d1fee4b6db29dae60319b (diff) | |
improve coff deplibs
| -rw-r--r-- | core/src/xmake/binutils/coff/deplibs.c | 156 | ||||
| -rw-r--r-- | core/src/xmake/binutils/coff/prefix.h | 80 |
2 files changed, 143 insertions, 93 deletions
diff --git a/core/src/xmake/binutils/coff/deplibs.c b/core/src/xmake/binutils/coff/deplibs.c index 44809a535..969702e98 100644 --- a/core/src/xmake/binutils/coff/deplibs.c +++ b/core/src/xmake/binutils/coff/deplibs.c @@ -49,72 +49,78 @@ tb_bool_t xm_binutils_coff_deplibs(tb_stream_ref_t istream, tb_hize_t base_offse return tb_false; } - // read section headers - tb_hize_t section_offset = base_offset + sizeof(xm_coff_header_t) + header.opthdr; - if (!tb_stream_seek(istream, section_offset)) { - return tb_false; - } - - // try to get import directory rva from optional header + // read optional header and import rva tb_uint32_t import_rva = 0; if (header.opthdr > 0) { - // save pos - tb_hize_t saved_pos = tb_stream_offset(istream); - - // seek to optional header - if (tb_stream_seek(istream, base_offset + sizeof(xm_coff_header_t))) { - tb_uint16_t magic = 0; - if (tb_stream_bread(istream, (tb_byte_t*)&magic, 2)) { - // magic is little endian - magic = tb_bits_le_to_ne_u16(magic); - - tb_uint32_t data_dir_offset = 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) { - data_dir_offset = 96; + 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; + } + } } else if (magic == XM_PE32P_MAGIC) { - data_dir_offset = 112; - } - - /* check if optional header is large enough to contain import directory entry (index 1) - * export(0) + import(1) -> 2 entries -> 16 bytes - */ - if (data_dir_offset != 0 && header.opthdr >= data_dir_offset + 16) { - /* seek to Import Directory (Index 1) - * Data Directory Array starts at optional_header_start + data_dir_offset - * Index 1 is at + 8 bytes (sizeof(IMAGE_DATA_DIRECTORY) * 1) - */ - if (tb_stream_seek(istream, base_offset + sizeof(xm_coff_header_t) + data_dir_offset + 8)) { - if (tb_stream_bread(istream, (tb_byte_t*)&import_rva, 4)) { - import_rva = tb_bits_le_to_ne_u32(import_rva); + 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; } } } } } - // restore pos - tb_stream_seek(istream, saved_pos); } + // read section headers + 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; + } + } + } + + if (!sections) { + if (header.nsects > 0) return tb_false; + lua_newtable(lua); + return tb_true; + } + + lua_newtable(lua); tb_size_t result_count = 0; for (tb_uint16_t i = 0; i < header.nsects; i++) { - xm_coff_section_t section; - if (!tb_stream_bread(istream, (tb_byte_t*)§ion, sizeof(section))) { - return tb_false; - } + 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); + 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; + if (tb_strncmp(section->name, ".idata", 6) == 0) { + idt_offset = section->ofs; found_idt = tb_true; } } @@ -137,67 +143,37 @@ tb_bool_t xm_binutils_coff_deplibs(tb_stream_ref_t istream, tb_hize_t base_offse */ if (!tb_stream_seek(istream, idt_offset)) { - return tb_false; + break; } while (1) { - tb_uint32_t original_first_thunk; - tb_uint32_t time_date_stamp; - tb_uint32_t forwarder_chain; - tb_uint32_t name_rva; - tb_uint32_t first_thunk; - - if (!tb_stream_bread(istream, (tb_byte_t*)&original_first_thunk, 4)) { break; } - if (!tb_stream_bread(istream, (tb_byte_t*)&time_date_stamp, 4)) { break; } - if (!tb_stream_bread(istream, (tb_byte_t*)&forwarder_chain, 4)) { break; } - if (!tb_stream_bread(istream, (tb_byte_t*)&name_rva, 4)) { break; } - if (!tb_stream_bread(istream, (tb_byte_t*)&first_thunk, 4)) { break; } + xm_coff_import_directory_table_t entry; + if (!tb_stream_bread(istream, (tb_byte_t*)&entry, sizeof(entry))) { + break; + } // check for null entry (end of table) - if (original_first_thunk == 0 && name_rva == 0) { + if (entry.original_first_thunk == 0 && entry.name_rva == 0) { break; } - name_rva = tb_bits_le_to_ne_u32(name_rva); + 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. - * Since we are iterating sections, we might need to seek back to read section headers again or cache them. - * For simplicity, we assume the name string is within the same .idata section or we can find it by scanning sections. - */ - - /* To do this correctly, we should scan all sections to find which one contains the RVA. - * But here we are inside a loop iterating sections. - * We can save current position and iterate sections from the beginning (or cached) to find the RVA. */ - // Optimization: usually the name is in the same .idata section or a nearby .rdata section. - tb_hize_t saved_pos_inner = tb_stream_offset(istream); - - // Find the section containing name_rva tb_uint32_t name_file_offset = 0; - // check current section first - if (name_rva >= section.vaddr && name_rva < section.vaddr + section.vsize) { - name_file_offset = section.ofs + (name_rva - section.vaddr); - } else { - // Scan all sections to find the RVA - tb_hize_t saved_pos_sections = tb_stream_offset(istream); - if (tb_stream_seek(istream, section_offset)) { - for (tb_uint16_t k = 0; k < header.nsects; k++) { - xm_coff_section_t s; - if (!tb_stream_bread(istream, (tb_byte_t*)&s, sizeof(s))) { - break; - } - 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; } - tb_stream_seek(istream, saved_pos_sections); // restore to current descriptor } if (name_file_offset != 0) { @@ -213,16 +189,10 @@ tb_bool_t xm_binutils_coff_deplibs(tb_stream_ref_t istream, tb_hize_t base_offse tb_stream_seek(istream, saved_pos_inner); } } - /* We found .idata and processed it. Usually there is only one import table. - * But we should continue just in case or break? - * Typically break is enough after processing the import table. - */ break; } } - if (result_count == 0) { - lua_newtable(lua); - } + if (sections) tb_free(sections); return tb_true; } diff --git a/core/src/xmake/binutils/coff/prefix.h b/core/src/xmake/binutils/coff/prefix.h index f991ac26d..8017beeff 100644 --- a/core/src/xmake/binutils/coff/prefix.h +++ b/core/src/xmake/binutils/coff/prefix.h @@ -59,6 +59,86 @@ typedef struct __xm_coff_header_t { tb_uint16_t flags; } __tb_packed__ xm_coff_header_t; +typedef struct __xm_pe32_data_directory_t { + tb_uint32_t vaddr; + tb_uint32_t size; +} __tb_packed__ xm_pe32_data_directory_t; + +typedef struct __xm_pe32_opt_header_t { + tb_uint16_t magic; + tb_uint8_t major_linker_version; + tb_uint8_t minor_linker_version; + tb_uint32_t size_of_code; + tb_uint32_t size_of_initialized_data; + tb_uint32_t size_of_uninitialized_data; + tb_uint32_t address_of_entry_point; + tb_uint32_t base_of_code; + tb_uint32_t base_of_data; + tb_uint32_t image_base; + tb_uint32_t section_alignment; + tb_uint32_t file_alignment; + tb_uint16_t major_operating_system_version; + tb_uint16_t minor_operating_system_version; + tb_uint16_t major_image_version; + tb_uint16_t minor_image_version; + tb_uint16_t major_subsystem_version; + tb_uint16_t minor_subsystem_version; + tb_uint32_t win32_version_value; + tb_uint32_t size_of_image; + tb_uint32_t size_of_headers; + tb_uint32_t checksum; + tb_uint16_t subsystem; + tb_uint16_t dll_characteristics; + tb_uint32_t size_of_stack_reserve; + tb_uint32_t size_of_stack_commit; + tb_uint32_t size_of_heap_reserve; + tb_uint32_t size_of_heap_commit; + tb_uint32_t loader_flags; + tb_uint32_t number_of_rva_and_sizes; + xm_pe32_data_directory_t data_directory[16]; +} __tb_packed__ xm_pe32_opt_header_t; + +typedef struct __xm_pe32p_opt_header_t { + tb_uint16_t magic; + tb_uint8_t major_linker_version; + tb_uint8_t minor_linker_version; + tb_uint32_t size_of_code; + tb_uint32_t size_of_initialized_data; + tb_uint32_t size_of_uninitialized_data; + tb_uint32_t address_of_entry_point; + tb_uint32_t base_of_code; + tb_uint64_t image_base; + tb_uint32_t section_alignment; + tb_uint32_t file_alignment; + tb_uint16_t major_operating_system_version; + tb_uint16_t minor_operating_system_version; + tb_uint16_t major_image_version; + tb_uint16_t minor_image_version; + tb_uint16_t major_subsystem_version; + tb_uint16_t minor_subsystem_version; + tb_uint32_t win32_version_value; + tb_uint32_t size_of_image; + tb_uint32_t size_of_headers; + tb_uint32_t checksum; + tb_uint16_t subsystem; + tb_uint16_t dll_characteristics; + tb_uint64_t size_of_stack_reserve; + tb_uint64_t size_of_stack_commit; + tb_uint64_t size_of_heap_reserve; + tb_uint64_t size_of_heap_commit; + tb_uint32_t loader_flags; + tb_uint32_t number_of_rva_and_sizes; + xm_pe32_data_directory_t data_directory[16]; +} __tb_packed__ xm_pe32p_opt_header_t; + +typedef struct __xm_coff_import_directory_table_t { + tb_uint32_t original_first_thunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA) + tb_uint32_t time_date_stamp; // 0 if not bound, -1 if bound, and real date\time stamp in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND) O.W. date/time stamp of DLL bound to (Old BIND) + tb_uint32_t forwarder_chain; // -1 if no forwarders + tb_uint32_t name_rva; // RVA to name + tb_uint32_t first_thunk; // RVA to IAT (if bound this IAT has actual addresses) +} __tb_packed__ xm_coff_import_directory_table_t; + typedef struct __xm_coff_import_header_t { tb_uint16_t sig1; // 0 tb_uint16_t sig2; // 0xffff |
