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/elf/deplibs.c | |
| parent | b7e9857eff9a4425237e8eeb5c666fb4570eec76 (diff) | |
add deplibs in binutils
Diffstat (limited to 'core/src/xmake/binutils/elf/deplibs.c')
| -rw-r--r-- | core/src/xmake/binutils/elf/deplibs.c | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/core/src/xmake/binutils/elf/deplibs.c b/core/src/xmake/binutils/elf/deplibs.c new file mode 100644 index 000000000..85e346192 --- /dev/null +++ b/core/src/xmake/binutils/elf/deplibs.c @@ -0,0 +1,227 @@ +/*!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_elf" +#define TB_TRACE_MODULE_DEBUG (0) + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "prefix.h" + +/* ////////////////////////////////////////////////////////////////////////////////////// + * private implementation + */ + +static tb_bool_t xm_binutils_elf_deplibs_32(tb_stream_ref_t istream, tb_hize_t base_offset, lua_State *lua) { + tb_assert_and_check_return_val(istream && lua, tb_false); + + // read ELF header + xm_elf32_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; + } + + // find .dynamic section + xm_elf32_section_t dynamic_section; + tb_bool_t found_dynamic = tb_false; + + if (!tb_stream_seek(istream, base_offset + header.e_shoff)) { + return tb_false; + } + + for (tb_uint16_t i = 0; i < header.e_shnum; i++) { + xm_elf32_section_t section; + if (!tb_stream_bread(istream, (tb_byte_t*)§ion, sizeof(section))) { + return tb_false; + } + + if (section.sh_type == XM_ELF_SHT_DYNAMIC) { + dynamic_section = section; + found_dynamic = tb_true; + break; + } + } + + if (!found_dynamic) { + return tb_true; // no dynamic section + } + + // find string table for dynamic section + // sh_link of dynamic section contains the section header index of the string table + xm_elf32_section_t strtab_section; + if (!tb_stream_seek(istream, base_offset + header.e_shoff + dynamic_section.sh_link * sizeof(xm_elf32_section_t))) { + return tb_false; + } + if (!tb_stream_bread(istream, (tb_byte_t*)&strtab_section, sizeof(strtab_section))) { + return tb_false; + } + + // read dynamic entries + tb_uint32_t count = dynamic_section.sh_size / sizeof(xm_elf32_dynamic_t); + if (!tb_stream_seek(istream, base_offset + dynamic_section.sh_offset)) { + return tb_false; + } + + tb_size_t result_count = 0; + for (tb_uint32_t i = 0; i < count; i++) { + xm_elf32_dynamic_t dyn; + if (!tb_stream_bread(istream, (tb_byte_t*)&dyn, sizeof(dyn))) { + return tb_false; + } + + if (dyn.d_tag == XM_ELF_DT_NULL) { + break; + } + + if (dyn.d_tag == XM_ELF_DT_NEEDED) { + tb_char_t name[256]; + if (xm_binutils_elf_read_string(istream, base_offset + strtab_section.sh_offset, dyn.d_un.d_val, name, sizeof(name)) && name[0]) { + lua_pushinteger(lua, result_count + 1); + lua_pushstring(lua, name); + lua_settable(lua, -3); + result_count++; + } + } + } + + return tb_true; +} + +static tb_bool_t xm_binutils_elf_deplibs_64(tb_stream_ref_t istream, tb_hize_t base_offset, lua_State *lua) { + tb_assert_and_check_return_val(istream && lua, tb_false); + + // read ELF header + xm_elf64_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; + } + + // find .dynamic section + xm_elf64_section_t dynamic_section; + tb_bool_t found_dynamic = tb_false; + + if (!tb_stream_seek(istream, base_offset + header.e_shoff)) { + return tb_false; + } + + for (tb_uint16_t i = 0; i < header.e_shnum; i++) { + xm_elf64_section_t section; + if (!tb_stream_bread(istream, (tb_byte_t*)§ion, sizeof(section))) { + return tb_false; + } + + if (section.sh_type == XM_ELF_SHT_DYNAMIC) { + dynamic_section = section; + found_dynamic = tb_true; + break; + } + } + + if (!found_dynamic) { + return tb_true; // no dynamic section + } + + // find string table for dynamic section + // sh_link of dynamic section contains the section header index of the string table + xm_elf64_section_t strtab_section; + if (!tb_stream_seek(istream, base_offset + header.e_shoff + dynamic_section.sh_link * sizeof(xm_elf64_section_t))) { + return tb_false; + } + if (!tb_stream_bread(istream, (tb_byte_t*)&strtab_section, sizeof(strtab_section))) { + return tb_false; + } + + // read dynamic entries + tb_uint32_t count = (tb_uint32_t)(dynamic_section.sh_size / sizeof(xm_elf64_dynamic_t)); + if (!tb_stream_seek(istream, base_offset + dynamic_section.sh_offset)) { + return tb_false; + } + + tb_size_t result_count = 0; + for (tb_uint32_t i = 0; i < count; i++) { + xm_elf64_dynamic_t dyn; + if (!tb_stream_bread(istream, (tb_byte_t*)&dyn, sizeof(dyn))) { + return tb_false; + } + + if (dyn.d_tag == XM_ELF_DT_NULL) { + break; + } + + if (dyn.d_tag == XM_ELF_DT_NEEDED) { + tb_char_t name[256]; + if (xm_binutils_elf_read_string(istream, base_offset + strtab_section.sh_offset, (tb_uint32_t)dyn.d_un.d_val, name, sizeof(name)) && name[0]) { + lua_pushinteger(lua, result_count + 1); + lua_pushstring(lua, name); + lua_settable(lua, -3); + result_count++; + } + } + } + + return tb_true; +} + +/* ////////////////////////////////////////////////////////////////////////////////////// + * implementation + */ +tb_bool_t xm_binutils_elf_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 and check ELF magic + tb_uint8_t magic[4]; + if (!tb_stream_seek(istream, base_offset)) { + return tb_false; + } + if (!tb_stream_bread(istream, magic, 4)) { + return tb_false; + } + if (magic[0] != 0x7f || magic[1] != 'E' || magic[2] != 'L' || magic[3] != 'F') { + return tb_false; + } + + // check ELF class (32-bit or 64-bit) + tb_uint8_t elf_class; + if (!tb_stream_seek(istream, base_offset + 4)) { + return tb_false; + } + if (!tb_stream_bread(istream, (tb_byte_t*)&elf_class, 1)) { + return tb_false; + } + + if (elf_class == 1) { + return xm_binutils_elf_deplibs_32(istream, base_offset, lua); + } else if (elf_class == 2) { + return xm_binutils_elf_deplibs_64(istream, base_offset, lua); + } + + return tb_false; +} |
