diff options
| author | ruki <[email protected]> | 2025-12-12 23:12:57 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2025-12-12 23:12:57 +0800 |
| commit | 97c17dc338a66bbbae36eef59c4d4ca537bff8ec (patch) | |
| tree | 3cb7a0c517871c44265d709bb91102cac520b73c /core/src/xmake/binutils/macho | |
| parent | b7e9857eff9a4425237e8eeb5c666fb4570eec76 (diff) | |
add deplibs in binutils
Diffstat (limited to 'core/src/xmake/binutils/macho')
| -rw-r--r-- | core/src/xmake/binutils/macho/deplibs.c | 155 | ||||
| -rw-r--r-- | core/src/xmake/binutils/macho/prefix.h | 96 | ||||
| -rw-r--r-- | core/src/xmake/binutils/macho/readsyms.c | 58 |
3 files changed, 251 insertions, 58 deletions
diff --git a/core/src/xmake/binutils/macho/deplibs.c b/core/src/xmake/binutils/macho/deplibs.c new file mode 100644 index 000000000..fbea979c7 --- /dev/null +++ b/core/src/xmake/binutils/macho/deplibs.c @@ -0,0 +1,155 @@ +/*!A cross-platform build utility based on Lua + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (C) 2015-present, Xmake Open Source Community. + * + * @author ruki + * @file deplibs.c + * + */ + +/* ////////////////////////////////////////////////////////////////////////////////////// + * trace + */ +#define TB_TRACE_MODULE_NAME "deplibs_macho" +#define TB_TRACE_MODULE_DEBUG (0) + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "prefix.h" + +/* ////////////////////////////////////////////////////////////////////////////////////// + * private implementation + */ + +/* ////////////////////////////////////////////////////////////////////////////////////// + * implementation + */ +tb_bool_t xm_binutils_macho_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 Mach-O header + xm_macho_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; + } + + tb_bool_t swap = tb_false; + tb_bool_t is64 = tb_false; + + // check magic + if (header.magic == XM_MACHO_MAGIC_32) { + is64 = tb_false; + } else if (header.magic == XM_MACHO_MAGIC_32_BE) { + is64 = tb_false; + swap = tb_true; + } else if (header.magic == XM_MACHO_MAGIC_64) { + is64 = tb_true; + } else if (header.magic == XM_MACHO_MAGIC_64_BE) { + is64 = tb_true; + swap = tb_true; + } else { + return tb_false; // Not a Mach-O file + } + + // re-read header for 64-bit if needed, or just use 32-bit part and skip reserved + tb_uint32_t ncmds = 0; + + if (is64) { + xm_macho_header_64_t header64; + if (!tb_stream_seek(istream, base_offset)) { + return tb_false; + } + if (!tb_stream_bread(istream, (tb_byte_t*)&header64, sizeof(header64))) { + return tb_false; + } + xm_binutils_macho_swap_header_64(&header64, swap); + ncmds = header64.ncmds; + } else { + xm_binutils_macho_swap_header_32(&header, swap); + ncmds = header.ncmds; + } + + // skip header to reach load commands + tb_size_t header_size = is64 ? sizeof(xm_macho_header_64_t) : sizeof(xm_macho_header_t); + if (!tb_stream_seek(istream, base_offset + header_size)) { + return tb_false; + } + + lua_newtable(lua); + tb_size_t result_count = 0; + + // iterate load commands + for (tb_uint32_t i = 0; i < ncmds; i++) { + xm_macho_load_command_t lc; + tb_hize_t current_cmd_offset = tb_stream_offset(istream); + + if (!tb_stream_bread(istream, (tb_byte_t*)&lc, sizeof(lc))) { + break; + } + xm_binutils_macho_swap_load_command(&lc, swap); + + // check for LC_LOAD_DYLIB, LC_LOAD_WEAK_DYLIB, LC_REEXPORT_DYLIB + // LC_LOAD_DYLIB = 0xc + // LC_LOAD_WEAK_DYLIB = 0x18 | 0x80000000 + // LC_REEXPORT_DYLIB = 0x1f | 0x80000000 + + if (lc.cmd == 0xc || lc.cmd == (0x18 | 0x80000000) || lc.cmd == (0x1f | 0x80000000)) { + + xm_macho_dylib_command_t dc; + if (tb_stream_seek(istream, current_cmd_offset)) { + if (tb_stream_bread(istream, (tb_byte_t*)&dc, sizeof(dc))) { + xm_binutils_macho_swap_dylib_command(&dc, swap); + + tb_uint32_t name_offset = dc.dylib.offset; + if (name_offset < lc.cmdsize) { + // name is at current_cmd_offset + name_offset + if (tb_stream_seek(istream, current_cmd_offset + name_offset)) { + tb_char_t dylib_path[1024]; + tb_size_t max_len = lc.cmdsize - name_offset; + if (max_len > sizeof(dylib_path) - 1) max_len = sizeof(dylib_path) - 1; + + tb_size_t pos = 0; + tb_byte_t c; + while (pos < max_len) { + if (!tb_stream_bread(istream, &c, 1)) break; + if (c == 0) break; + dylib_path[pos++] = (tb_char_t)c; + } + dylib_path[pos] = '\0'; + + if (pos > 0) { + lua_pushinteger(lua, result_count + 1); + lua_pushstring(lua, dylib_path); + lua_settable(lua, -3); + result_count++; + } + } + } + } + } + } + + // move to next command + if (!tb_stream_seek(istream, current_cmd_offset + lc.cmdsize)) { + break; + } + } + + return tb_true; +} diff --git a/core/src/xmake/binutils/macho/prefix.h b/core/src/xmake/binutils/macho/prefix.h index 2d224ff77..d8b8fa157 100644 --- a/core/src/xmake/binutils/macho/prefix.h +++ b/core/src/xmake/binutils/macho/prefix.h @@ -184,12 +184,108 @@ typedef struct __xm_macho_nlist_64_t { tb_uint16_t desc; tb_uint64_t value; } __tb_packed__ xm_macho_nlist_64_t; + +typedef struct __xm_macho_load_command_t { + tb_uint32_t cmd; + tb_uint32_t cmdsize; +} __tb_packed__ xm_macho_load_command_t; + +typedef struct __xm_macho_dylib_t { + tb_uint32_t offset; + tb_uint32_t timestamp; + tb_uint32_t current_version; + tb_uint32_t compatibility_version; +} __tb_packed__ xm_macho_dylib_t; + +typedef struct __xm_macho_dylib_command_t { + tb_uint32_t cmd; + tb_uint32_t cmdsize; + xm_macho_dylib_t dylib; +} __tb_packed__ xm_macho_dylib_command_t; #include "tbox/prefix/packed.h" + /* ////////////////////////////////////////////////////////////////////////////////////// * inline implementation */ +/* byte-swap Mach-O header fields if needed */ +static __tb_inline__ tb_void_t xm_binutils_macho_swap_header_32(xm_macho_header_t *header, tb_bool_t swap) { + if (swap) { + header->magic = tb_bits_swap_u32(header->magic); + header->cputype = tb_bits_swap_u32(header->cputype); + header->cpusubtype = tb_bits_swap_u32(header->cpusubtype); + header->filetype = tb_bits_swap_u32(header->filetype); + header->ncmds = tb_bits_swap_u32(header->ncmds); + header->sizeofcmds = tb_bits_swap_u32(header->sizeofcmds); + header->flags = tb_bits_swap_u32(header->flags); + } +} + +/* byte-swap Mach-O header 64 fields if needed */ +static __tb_inline__ tb_void_t xm_binutils_macho_swap_header_64(xm_macho_header_64_t *header, tb_bool_t swap) { + if (swap) { + header->magic = tb_bits_swap_u32(header->magic); + header->cputype = tb_bits_swap_u32(header->cputype); + header->cpusubtype = tb_bits_swap_u32(header->cpusubtype); + header->filetype = tb_bits_swap_u32(header->filetype); + header->ncmds = tb_bits_swap_u32(header->ncmds); + header->sizeofcmds = tb_bits_swap_u32(header->sizeofcmds); + header->flags = tb_bits_swap_u32(header->flags); + header->reserved = tb_bits_swap_u32(header->reserved); + } +} + +/* byte-swap load command fields if needed */ +static __tb_inline__ tb_void_t xm_binutils_macho_swap_load_command(xm_macho_load_command_t *lc, tb_bool_t swap) { + if (swap) { + lc->cmd = tb_bits_swap_u32(lc->cmd); + lc->cmdsize = tb_bits_swap_u32(lc->cmdsize); + } +} + +/* byte-swap dylib command fields if needed */ +static __tb_inline__ tb_void_t xm_binutils_macho_swap_dylib_command(xm_macho_dylib_command_t *dc, tb_bool_t swap) { + if (swap) { + dc->cmd = tb_bits_swap_u32(dc->cmd); + dc->cmdsize = tb_bits_swap_u32(dc->cmdsize); + dc->dylib.offset = tb_bits_swap_u32(dc->dylib.offset); + dc->dylib.timestamp = tb_bits_swap_u32(dc->dylib.timestamp); + dc->dylib.current_version = tb_bits_swap_u32(dc->dylib.current_version); + dc->dylib.compatibility_version = tb_bits_swap_u32(dc->dylib.compatibility_version); + } +} + +/* byte-swap symtab command fields if needed */ +static __tb_inline__ tb_void_t xm_binutils_macho_swap_symtab_command(xm_macho_symtab_command_t *cmd, tb_bool_t swap) { + if (swap) { + cmd->cmd = tb_bits_swap_u32(cmd->cmd); + cmd->cmdsize = tb_bits_swap_u32(cmd->cmdsize); + cmd->symoff = tb_bits_swap_u32(cmd->symoff); + cmd->nsyms = tb_bits_swap_u32(cmd->nsyms); + cmd->stroff = tb_bits_swap_u32(cmd->stroff); + cmd->strsize = tb_bits_swap_u32(cmd->strsize); + } +} + +/* byte-swap nlist 32 fields if needed */ +static __tb_inline__ tb_void_t xm_binutils_macho_swap_nlist_32(xm_macho_nlist_t *nlist, tb_bool_t swap) { + if (swap) { + nlist->strx = tb_bits_swap_u32(nlist->strx); + nlist->desc = tb_bits_swap_u16(nlist->desc); + nlist->value = tb_bits_swap_u32(nlist->value); + } +} + +/* byte-swap nlist 64 fields if needed */ +static __tb_inline__ tb_void_t xm_binutils_macho_swap_nlist_64(xm_macho_nlist_64_t *nlist, tb_bool_t swap) { + if (swap) { + nlist->strx = tb_bits_swap_u32(nlist->strx); + nlist->desc = tb_bits_swap_u16(nlist->desc); + nlist->value = tb_bits_swap_u64(nlist->value); + } +} + /* get CPU type from architecture string * * @param arch the architecture string (e.g., "x86_64", "i386", "arm64") diff --git a/core/src/xmake/binutils/macho/readsyms.c b/core/src/xmake/binutils/macho/readsyms.c index 2d4889c58..216975d2a 100644 --- a/core/src/xmake/binutils/macho/readsyms.c +++ b/core/src/xmake/binutils/macho/readsyms.c @@ -29,69 +29,11 @@ * includes */ #include "prefix.h" -#include "tbox/utils/bits.h" /* ////////////////////////////////////////////////////////////////////////////////////// * private implementation */ -/* byte-swap Mach-O header fields if needed */ -static __tb_inline__ tb_void_t xm_binutils_macho_swap_header_32(xm_macho_header_t *header, tb_bool_t swap) { - if (swap) { - header->magic = tb_bits_swap_u32(header->magic); - header->cputype = tb_bits_swap_u32(header->cputype); - header->cpusubtype = tb_bits_swap_u32(header->cpusubtype); - header->filetype = tb_bits_swap_u32(header->filetype); - header->ncmds = tb_bits_swap_u32(header->ncmds); - header->sizeofcmds = tb_bits_swap_u32(header->sizeofcmds); - header->flags = tb_bits_swap_u32(header->flags); - } -} - -/* byte-swap Mach-O header 64 fields if needed */ -static __tb_inline__ tb_void_t xm_binutils_macho_swap_header_64(xm_macho_header_64_t *header, tb_bool_t swap) { - if (swap) { - header->magic = tb_bits_swap_u32(header->magic); - header->cputype = tb_bits_swap_u32(header->cputype); - header->cpusubtype = tb_bits_swap_u32(header->cpusubtype); - header->filetype = tb_bits_swap_u32(header->filetype); - header->ncmds = tb_bits_swap_u32(header->ncmds); - header->sizeofcmds = tb_bits_swap_u32(header->sizeofcmds); - header->flags = tb_bits_swap_u32(header->flags); - header->reserved = tb_bits_swap_u32(header->reserved); - } -} - -/* byte-swap symtab command fields if needed */ -static __tb_inline__ tb_void_t xm_binutils_macho_swap_symtab_command(xm_macho_symtab_command_t *cmd, tb_bool_t swap) { - if (swap) { - cmd->cmd = tb_bits_swap_u32(cmd->cmd); - cmd->cmdsize = tb_bits_swap_u32(cmd->cmdsize); - cmd->symoff = tb_bits_swap_u32(cmd->symoff); - cmd->nsyms = tb_bits_swap_u32(cmd->nsyms); - cmd->stroff = tb_bits_swap_u32(cmd->stroff); - cmd->strsize = tb_bits_swap_u32(cmd->strsize); - } -} - -/* byte-swap nlist 32 fields if needed */ -static __tb_inline__ tb_void_t xm_binutils_macho_swap_nlist_32(xm_macho_nlist_t *nlist, tb_bool_t swap) { - if (swap) { - nlist->strx = tb_bits_swap_u32(nlist->strx); - nlist->desc = tb_bits_swap_u16(nlist->desc); - nlist->value = tb_bits_swap_u32(nlist->value); - } -} - -/* byte-swap nlist 64 fields if needed */ -static __tb_inline__ tb_void_t xm_binutils_macho_swap_nlist_64(xm_macho_nlist_64_t *nlist, tb_bool_t swap) { - if (swap) { - nlist->strx = tb_bits_swap_u32(nlist->strx); - nlist->desc = tb_bits_swap_u16(nlist->desc); - nlist->value = tb_bits_swap_u64(nlist->value); - } -} - 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); |
