From 6570427feb7a98ad9e77103b5f6c6d2f2191feac Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Jul 2026 00:44:37 +0800 Subject: fix bin2obj for some archs --- core/src/xmake/binutils/elf/bin2elf.c | 81 +++++++++++++------- core/src/xmake/binutils/elf/prefix.h | 135 ++++++++++++++++++++++++++++++++++ core/src/xmake/binutils/prefix.h | 32 +++++++- 3 files changed, 221 insertions(+), 27 deletions(-) (limited to 'core/src/xmake/binutils') diff --git a/core/src/xmake/binutils/elf/bin2elf.c b/core/src/xmake/binutils/elf/bin2elf.c index 76a75f8fe..ff3f941f1 100644 --- a/core/src/xmake/binutils/elf/bin2elf.c +++ b/core/src/xmake/binutils/elf/bin2elf.c @@ -34,11 +34,38 @@ * private implementation */ +// write an ELF struct out in the target endianness (the struct is converted in place) +static tb_bool_t xm_binutils_bin2elf_bwrit_header_32(tb_stream_ref_t ostream, xm_elf32_header_t* h, tb_bool_t be) { + xm_binutils_elf32_header_conv(h, be); + return tb_stream_bwrit(ostream, (tb_byte_t const *)h, sizeof(*h)); +} +static tb_bool_t xm_binutils_bin2elf_bwrit_section_32(tb_stream_ref_t ostream, xm_elf32_section_t* s, tb_bool_t be) { + xm_binutils_elf32_section_conv(s, be); + return tb_stream_bwrit(ostream, (tb_byte_t const *)s, sizeof(*s)); +} +static tb_bool_t xm_binutils_bin2elf_bwrit_symbol_32(tb_stream_ref_t ostream, xm_elf32_symbol_t* s, tb_bool_t be) { + xm_binutils_elf32_symbol_conv(s, be); + return tb_stream_bwrit(ostream, (tb_byte_t const *)s, sizeof(*s)); +} +static tb_bool_t xm_binutils_bin2elf_bwrit_header_64(tb_stream_ref_t ostream, xm_elf64_header_t* h, tb_bool_t be) { + xm_binutils_elf64_header_conv(h, be); + return tb_stream_bwrit(ostream, (tb_byte_t const *)h, sizeof(*h)); +} +static tb_bool_t xm_binutils_bin2elf_bwrit_section_64(tb_stream_ref_t ostream, xm_elf64_section_t* s, tb_bool_t be) { + xm_binutils_elf64_section_conv(s, be); + return tb_stream_bwrit(ostream, (tb_byte_t const *)s, sizeof(*s)); +} +static tb_bool_t xm_binutils_bin2elf_bwrit_symbol_64(tb_stream_ref_t ostream, xm_elf64_symbol_t* s, tb_bool_t be) { + xm_binutils_elf64_symbol_conv(s, be); + return tb_stream_bwrit(ostream, (tb_byte_t const *)s, sizeof(*s)); +} + static tb_bool_t xm_binutils_bin2elf_dump_32(tb_stream_ref_t istream, tb_stream_ref_t ostream, tb_char_t const *symbol_prefix, tb_char_t const *arch, tb_char_t const *basename, + tb_bool_t bigendian, tb_bool_t zeroend) { tb_assert_and_check_return_val(istream && ostream, tb_false); @@ -117,25 +144,26 @@ static tb_bool_t xm_binutils_bin2elf_dump_32(tb_stream_ref_t istream, header.e_ident[2] = 'L'; header.e_ident[3] = 'F'; header.e_ident[XM_ELF_EI_CLASS] = XM_ELF_CLASS32; - header.e_ident[5] = 1; // ELFDATA2LSB + header.e_ident[5] = bigendian? XM_ELF_DATA2MSB : XM_ELF_DATA2LSB; header.e_ident[6] = 1; // EV_CURRENT header.e_ident[7] = 0; // ELFOSABI_SYSV header.e_type = 1; // ET_REL header.e_machine = xm_binutils_elf_get_machine(arch); header.e_version = 1; + header.e_flags = xm_binutils_elf_get_flags(arch); header.e_shoff = section_headers_ofs; header.e_ehsize = header_size; header.e_shentsize = section_header_size; header.e_shnum = section_count; header.e_shstrndx = 4; // .shstrtab section index - if (!tb_stream_bwrit(ostream, (tb_byte_t const *)&header, sizeof(header))) { + if (!xm_binutils_bin2elf_bwrit_header_32(ostream, &header, bigendian)) { return tb_false; } // write section headers xm_elf32_section_t section_null; tb_memset(§ion_null, 0, sizeof(section_null)); - if (!tb_stream_bwrit(ostream, (tb_byte_t const *)§ion_null, sizeof(section_null))) { + if (!xm_binutils_bin2elf_bwrit_section_32(ostream, §ion_null, bigendian)) { return tb_false; } @@ -148,7 +176,7 @@ static tb_bool_t xm_binutils_bin2elf_dump_32(tb_stream_ref_t istream, section_rodata.sh_offset = rodata_ofs; section_rodata.sh_size = rodata_size; section_rodata.sh_addralign = 4; - if (!tb_stream_bwrit(ostream, (tb_byte_t const *)§ion_rodata, sizeof(section_rodata))) { + if (!xm_binutils_bin2elf_bwrit_section_32(ostream, §ion_rodata, bigendian)) { return tb_false; } @@ -163,7 +191,7 @@ static tb_bool_t xm_binutils_bin2elf_dump_32(tb_stream_ref_t istream, section_symtab.sh_info = 1; // first global symbol index section_symtab.sh_addralign = 4; section_symtab.sh_entsize = sizeof(xm_elf32_symbol_t); - if (!tb_stream_bwrit(ostream, (tb_byte_t const *)§ion_symtab, sizeof(section_symtab))) { + if (!xm_binutils_bin2elf_bwrit_section_32(ostream, §ion_symtab, bigendian)) { return tb_false; } @@ -175,7 +203,7 @@ static tb_bool_t xm_binutils_bin2elf_dump_32(tb_stream_ref_t istream, section_strtab.sh_offset = strtab_ofs; section_strtab.sh_size = strtab_size; section_strtab.sh_addralign = 1; - if (!tb_stream_bwrit(ostream, (tb_byte_t const *)§ion_strtab, sizeof(section_strtab))) { + if (!xm_binutils_bin2elf_bwrit_section_32(ostream, §ion_strtab, bigendian)) { return tb_false; } @@ -187,7 +215,7 @@ static tb_bool_t xm_binutils_bin2elf_dump_32(tb_stream_ref_t istream, section_shstrtab.sh_offset = shstrtab_ofs; section_shstrtab.sh_size = shstrtab_size; section_shstrtab.sh_addralign = 1; - if (!tb_stream_bwrit(ostream, (tb_byte_t const *)§ion_shstrtab, sizeof(section_shstrtab))) { + if (!xm_binutils_bin2elf_bwrit_section_32(ostream, §ion_shstrtab, bigendian)) { return tb_false; } @@ -200,7 +228,7 @@ static tb_bool_t xm_binutils_bin2elf_dump_32(tb_stream_ref_t istream, section_note_gnu_stack.sh_offset = shstrtab_ofs + shstrtab_size; // after .shstrtab section_note_gnu_stack.sh_size = 0; // empty section section_note_gnu_stack.sh_addralign = 1; - if (!tb_stream_bwrit(ostream, (tb_byte_t const *)§ion_note_gnu_stack, sizeof(section_note_gnu_stack))) { + if (!xm_binutils_bin2elf_bwrit_section_32(ostream, §ion_note_gnu_stack, bigendian)) { return tb_false; } @@ -230,7 +258,7 @@ static tb_bool_t xm_binutils_bin2elf_dump_32(tb_stream_ref_t istream, // symbol 0: NULL symbol xm_elf32_symbol_t sym_null; tb_memset(&sym_null, 0, sizeof(sym_null)); - if (!tb_stream_bwrit(ostream, (tb_byte_t const *)&sym_null, sizeof(sym_null))) { + if (!xm_binutils_bin2elf_bwrit_symbol_32(ostream, &sym_null, bigendian)) { return tb_false; } @@ -242,7 +270,7 @@ static tb_bool_t xm_binutils_bin2elf_dump_32(tb_stream_ref_t istream, sym_start.st_shndx = 1; // .rodata section index sym_start.st_value = 0; sym_start.st_size = 0; - if (!tb_stream_bwrit(ostream, (tb_byte_t const *)&sym_start, sizeof(sym_start))) { + if (!xm_binutils_bin2elf_bwrit_symbol_32(ostream, &sym_start, bigendian)) { return tb_false; } @@ -254,7 +282,7 @@ static tb_bool_t xm_binutils_bin2elf_dump_32(tb_stream_ref_t istream, sym_end.st_shndx = 1; // .rodata section index sym_end.st_value = rodata_size; sym_end.st_size = 0; - if (!tb_stream_bwrit(ostream, (tb_byte_t const *)&sym_end, sizeof(sym_end))) { + if (!xm_binutils_bin2elf_bwrit_symbol_32(ostream, &sym_end, bigendian)) { return tb_false; } @@ -339,6 +367,7 @@ static tb_bool_t xm_binutils_bin2elf_dump_64(tb_stream_ref_t istream, tb_char_t const *symbol_prefix, tb_char_t const *arch, tb_char_t const *basename, + tb_bool_t bigendian, tb_bool_t zeroend) { tb_assert_and_check_return_val(istream && ostream, tb_false); @@ -417,25 +446,26 @@ static tb_bool_t xm_binutils_bin2elf_dump_64(tb_stream_ref_t istream, header.e_ident[2] = 'L'; header.e_ident[3] = 'F'; header.e_ident[XM_ELF_EI_CLASS] = XM_ELF_CLASS64; - header.e_ident[5] = 1; // ELFDATA2LSB + header.e_ident[5] = bigendian? XM_ELF_DATA2MSB : XM_ELF_DATA2LSB; header.e_ident[6] = 1; // EV_CURRENT header.e_ident[7] = 0; // ELFOSABI_SYSV header.e_type = 1; // ET_REL header.e_machine = xm_binutils_elf_get_machine(arch); header.e_version = 1; + header.e_flags = xm_binutils_elf_get_flags(arch); header.e_shoff = section_headers_ofs; header.e_ehsize = header_size; header.e_shentsize = section_header_size; header.e_shnum = section_count; header.e_shstrndx = 4; // .shstrtab section index - if (!tb_stream_bwrit(ostream, (tb_byte_t const *)&header, sizeof(header))) { + if (!xm_binutils_bin2elf_bwrit_header_64(ostream, &header, bigendian)) { return tb_false; } // write section headers xm_elf64_section_t section_null; tb_memset(§ion_null, 0, sizeof(section_null)); - if (!tb_stream_bwrit(ostream, (tb_byte_t const *)§ion_null, sizeof(section_null))) { + if (!xm_binutils_bin2elf_bwrit_section_64(ostream, §ion_null, bigendian)) { return tb_false; } @@ -448,7 +478,7 @@ static tb_bool_t xm_binutils_bin2elf_dump_64(tb_stream_ref_t istream, section_rodata.sh_offset = rodata_ofs; section_rodata.sh_size = rodata_size; section_rodata.sh_addralign = 8; - if (!tb_stream_bwrit(ostream, (tb_byte_t const *)§ion_rodata, sizeof(section_rodata))) { + if (!xm_binutils_bin2elf_bwrit_section_64(ostream, §ion_rodata, bigendian)) { return tb_false; } @@ -463,7 +493,7 @@ static tb_bool_t xm_binutils_bin2elf_dump_64(tb_stream_ref_t istream, section_symtab.sh_info = 1; // first global symbol index section_symtab.sh_addralign = 8; section_symtab.sh_entsize = sizeof(xm_elf64_symbol_t); - if (!tb_stream_bwrit(ostream, (tb_byte_t const *)§ion_symtab, sizeof(section_symtab))) { + if (!xm_binutils_bin2elf_bwrit_section_64(ostream, §ion_symtab, bigendian)) { return tb_false; } @@ -475,7 +505,7 @@ static tb_bool_t xm_binutils_bin2elf_dump_64(tb_stream_ref_t istream, section_strtab.sh_offset = strtab_ofs; section_strtab.sh_size = strtab_size; section_strtab.sh_addralign = 1; - if (!tb_stream_bwrit(ostream, (tb_byte_t const *)§ion_strtab, sizeof(section_strtab))) { + if (!xm_binutils_bin2elf_bwrit_section_64(ostream, §ion_strtab, bigendian)) { return tb_false; } @@ -487,7 +517,7 @@ static tb_bool_t xm_binutils_bin2elf_dump_64(tb_stream_ref_t istream, section_shstrtab.sh_offset = shstrtab_ofs; // points to initial null byte section_shstrtab.sh_size = shstrtab_size; // size includes initial null and all strings section_shstrtab.sh_addralign = 1; - if (!tb_stream_bwrit(ostream, (tb_byte_t const *)§ion_shstrtab, sizeof(section_shstrtab))) { + if (!xm_binutils_bin2elf_bwrit_section_64(ostream, §ion_shstrtab, bigendian)) { return tb_false; } @@ -500,7 +530,7 @@ static tb_bool_t xm_binutils_bin2elf_dump_64(tb_stream_ref_t istream, section_note_gnu_stack.sh_offset = shstrtab_ofs + shstrtab_size; // after .shstrtab section_note_gnu_stack.sh_size = 0; // empty section section_note_gnu_stack.sh_addralign = 1; - if (!tb_stream_bwrit(ostream, (tb_byte_t const *)§ion_note_gnu_stack, sizeof(section_note_gnu_stack))) { + if (!xm_binutils_bin2elf_bwrit_section_64(ostream, §ion_note_gnu_stack, bigendian)) { return tb_false; } @@ -530,7 +560,7 @@ static tb_bool_t xm_binutils_bin2elf_dump_64(tb_stream_ref_t istream, // symbol 0: NULL symbol xm_elf64_symbol_t sym_null; tb_memset(&sym_null, 0, sizeof(sym_null)); - if (!tb_stream_bwrit(ostream, (tb_byte_t const *)&sym_null, sizeof(sym_null))) { + if (!xm_binutils_bin2elf_bwrit_symbol_64(ostream, &sym_null, bigendian)) { return tb_false; } @@ -542,7 +572,7 @@ static tb_bool_t xm_binutils_bin2elf_dump_64(tb_stream_ref_t istream, sym_start.st_shndx = 1; // .rodata section index sym_start.st_value = 0; sym_start.st_size = 0; - if (!tb_stream_bwrit(ostream, (tb_byte_t const *)&sym_start, sizeof(sym_start))) { + if (!xm_binutils_bin2elf_bwrit_symbol_64(ostream, &sym_start, bigendian)) { return tb_false; } @@ -554,7 +584,7 @@ static tb_bool_t xm_binutils_bin2elf_dump_64(tb_stream_ref_t istream, sym_end.st_shndx = 1; // .rodata section index sym_end.st_value = rodata_size; sym_end.st_size = 0; - if (!tb_stream_bwrit(ostream, (tb_byte_t const *)&sym_end, sizeof(sym_end))) { + if (!xm_binutils_bin2elf_bwrit_symbol_64(ostream, &sym_end, bigendian)) { return tb_false; } @@ -683,16 +713,17 @@ tb_int_t xm_binutils_bin2elf(lua_State *lua) { break; } - // choose 32-bit or 64-bit ELF based on architecture + // choose 32-bit or 64-bit ELF based on architecture, and little/big endian tb_bool_t is_64bit = xm_binutils_elf_is_64bit(arch); + tb_bool_t is_bigendian = xm_binutils_elf_is_bigendian(arch); if (is_64bit) { - if (!xm_binutils_bin2elf_dump_64(istream, ostream, symbol_prefix, arch, basename, zeroend)) { + if (!xm_binutils_bin2elf_dump_64(istream, ostream, symbol_prefix, arch, basename, is_bigendian, zeroend)) { lua_pushboolean(lua, tb_false); lua_pushfstring(lua, "bin2elf: dump data failed"); break; } } else { - if (!xm_binutils_bin2elf_dump_32(istream, ostream, symbol_prefix, arch, basename, zeroend)) { + if (!xm_binutils_bin2elf_dump_32(istream, ostream, symbol_prefix, arch, basename, is_bigendian, zeroend)) { lua_pushboolean(lua, tb_false); lua_pushfstring(lua, "bin2elf: dump data failed"); break; diff --git a/core/src/xmake/binutils/elf/prefix.h b/core/src/xmake/binutils/elf/prefix.h index 2072ee879..49c53c6c7 100644 --- a/core/src/xmake/binutils/elf/prefix.h +++ b/core/src/xmake/binutils/elf/prefix.h @@ -56,6 +56,19 @@ #define XM_ELF_MACHINE_WASM 0xe7 #define XM_ELF_MACHINE_LOONGARCH 0x102 +// ELF data encoding (e_ident[EI_DATA]) +#define XM_ELF_DATA2LSB 1 +#define XM_ELF_DATA2MSB 2 + +// RISC-V e_flags (arch/riscv/include/uapi/asm/elf.h) +#define XM_EF_RISCV_RVC 0x0001 +#define XM_EF_RISCV_FLOAT_ABI_SINGLE 0x0002 +#define XM_EF_RISCV_FLOAT_ABI_DOUBLE 0x0004 + +// LoongArch e_flags (LoongArch ELF psABI) +#define XM_EF_LOONGARCH_ABI_DOUBLE_FLOAT 0x3 +#define XM_EF_LOONGARCH_OBJABI_V1 0x40 + #define XM_ELF_SHT_PROGBITS 0x1 #define XM_ELF_SHT_SYMTAB 0x2 #define XM_ELF_SHT_STRTAB 0x3 @@ -297,6 +310,128 @@ static __tb_inline__ tb_bool_t xm_binutils_elf_is_64bit(tb_char_t const *arch) { return xm_binutils_arch_is_64bit(arch); } +/* check if architecture is big-endian + * + * @param arch the architecture string + * @return tb_true if big-endian, tb_false otherwise + */ +static __tb_inline__ tb_bool_t xm_binutils_elf_is_bigendian(tb_char_t const *arch) { + return xm_binutils_arch_is_bigendian(arch); +} + +/* get the default e_flags for the given architecture + * + * Some architectures (RISC-V, LoongArch) encode the ABI (e.g. float ABI) in e_flags. + * The linker refuses to merge objects whose ABI flags are incompatible, so a data-only + * object generated with e_flags == 0 (soft-float) would fail to link against a normal + * double-float toolchain. We default to the flags used by the common GNU toolchains. + * + * @param arch the architecture string + * @return the e_flags value + */ +static __tb_inline__ tb_uint32_t xm_binutils_elf_get_flags(tb_char_t const *arch) { + if (!arch) { + return 0; + } + // RISC-V: default to RVC + double-float ABI to match the common rv32/rv64 "gc" toolchains + if (tb_strncmp(arch, "riscv", 5) == 0) { + return XM_EF_RISCV_RVC | XM_EF_RISCV_FLOAT_ABI_DOUBLE; + } + // LoongArch: default to double-float ABI (lp64d/ilp32d) + object ABI v1 + else if (tb_strncmp(arch, "loongarch", 9) == 0 || tb_strncmp(arch, "loong64", 7) == 0) { + return XM_EF_LOONGARCH_ABI_DOUBLE_FLOAT | XM_EF_LOONGARCH_OBJABI_V1; + } + return 0; +} + +/* ////////////////////////////////////////////////////////////////////////////////////// + * endianness-aware serialization + * + * The dump code fills the ELF structs in the host's native byte order. Before writing them + * out, each multi-byte field must be converted to the *target* endianness (which may differ + * from the host, e.g. generating a big-endian s390x object on a little-endian host). + */ + +static __tb_inline__ tb_uint16_t xm_binutils_elf_conv_u16(tb_uint16_t x, tb_bool_t bigendian) { + return bigendian? tb_bits_ne_to_be_u16(x) : tb_bits_ne_to_le_u16(x); +} +static __tb_inline__ tb_uint32_t xm_binutils_elf_conv_u32(tb_uint32_t x, tb_bool_t bigendian) { + return bigendian? tb_bits_ne_to_be_u32(x) : tb_bits_ne_to_le_u32(x); +} +static __tb_inline__ tb_uint64_t xm_binutils_elf_conv_u64(tb_uint64_t x, tb_bool_t bigendian) { + return bigendian? tb_bits_ne_to_be_u64(x) : tb_bits_ne_to_le_u64(x); +} + +// convert a 32-bit ELF header to the target endianness in place (e_ident is byte data, untouched) +static __tb_inline__ void xm_binutils_elf32_header_conv(xm_elf32_header_t* h, tb_bool_t be) { + h->e_type = xm_binutils_elf_conv_u16(h->e_type, be); + h->e_machine = xm_binutils_elf_conv_u16(h->e_machine, be); + h->e_version = xm_binutils_elf_conv_u32(h->e_version, be); + h->e_entry = xm_binutils_elf_conv_u32(h->e_entry, be); + h->e_phoff = xm_binutils_elf_conv_u32(h->e_phoff, be); + h->e_shoff = xm_binutils_elf_conv_u32(h->e_shoff, be); + h->e_flags = xm_binutils_elf_conv_u32(h->e_flags, be); + h->e_ehsize = xm_binutils_elf_conv_u16(h->e_ehsize, be); + h->e_phentsize = xm_binutils_elf_conv_u16(h->e_phentsize, be); + h->e_phnum = xm_binutils_elf_conv_u16(h->e_phnum, be); + h->e_shentsize = xm_binutils_elf_conv_u16(h->e_shentsize, be); + h->e_shnum = xm_binutils_elf_conv_u16(h->e_shnum, be); + h->e_shstrndx = xm_binutils_elf_conv_u16(h->e_shstrndx, be); +} +static __tb_inline__ void xm_binutils_elf32_section_conv(xm_elf32_section_t* s, tb_bool_t be) { + s->sh_name = xm_binutils_elf_conv_u32(s->sh_name, be); + s->sh_type = xm_binutils_elf_conv_u32(s->sh_type, be); + s->sh_flags = xm_binutils_elf_conv_u32(s->sh_flags, be); + s->sh_addr = xm_binutils_elf_conv_u32(s->sh_addr, be); + s->sh_offset = xm_binutils_elf_conv_u32(s->sh_offset, be); + s->sh_size = xm_binutils_elf_conv_u32(s->sh_size, be); + s->sh_link = xm_binutils_elf_conv_u32(s->sh_link, be); + s->sh_info = xm_binutils_elf_conv_u32(s->sh_info, be); + s->sh_addralign = xm_binutils_elf_conv_u32(s->sh_addralign, be); + s->sh_entsize = xm_binutils_elf_conv_u32(s->sh_entsize, be); +} +static __tb_inline__ void xm_binutils_elf32_symbol_conv(xm_elf32_symbol_t* s, tb_bool_t be) { + s->st_name = xm_binutils_elf_conv_u32(s->st_name, be); + s->st_value = xm_binutils_elf_conv_u32(s->st_value, be); + s->st_size = xm_binutils_elf_conv_u32(s->st_size, be); + s->st_shndx = xm_binutils_elf_conv_u16(s->st_shndx, be); + // st_info and st_other are single bytes, untouched +} +static __tb_inline__ void xm_binutils_elf64_header_conv(xm_elf64_header_t* h, tb_bool_t be) { + h->e_type = xm_binutils_elf_conv_u16(h->e_type, be); + h->e_machine = xm_binutils_elf_conv_u16(h->e_machine, be); + h->e_version = xm_binutils_elf_conv_u32(h->e_version, be); + h->e_entry = xm_binutils_elf_conv_u64(h->e_entry, be); + h->e_phoff = xm_binutils_elf_conv_u64(h->e_phoff, be); + h->e_shoff = xm_binutils_elf_conv_u64(h->e_shoff, be); + h->e_flags = xm_binutils_elf_conv_u32(h->e_flags, be); + h->e_ehsize = xm_binutils_elf_conv_u16(h->e_ehsize, be); + h->e_phentsize = xm_binutils_elf_conv_u16(h->e_phentsize, be); + h->e_phnum = xm_binutils_elf_conv_u16(h->e_phnum, be); + h->e_shentsize = xm_binutils_elf_conv_u16(h->e_shentsize, be); + h->e_shnum = xm_binutils_elf_conv_u16(h->e_shnum, be); + h->e_shstrndx = xm_binutils_elf_conv_u16(h->e_shstrndx, be); +} +static __tb_inline__ void xm_binutils_elf64_section_conv(xm_elf64_section_t* s, tb_bool_t be) { + s->sh_name = xm_binutils_elf_conv_u32(s->sh_name, be); + s->sh_type = xm_binutils_elf_conv_u32(s->sh_type, be); + s->sh_flags = xm_binutils_elf_conv_u64(s->sh_flags, be); + s->sh_addr = xm_binutils_elf_conv_u64(s->sh_addr, be); + s->sh_offset = xm_binutils_elf_conv_u64(s->sh_offset, be); + s->sh_size = xm_binutils_elf_conv_u64(s->sh_size, be); + s->sh_link = xm_binutils_elf_conv_u32(s->sh_link, be); + s->sh_info = xm_binutils_elf_conv_u32(s->sh_info, be); + s->sh_addralign = xm_binutils_elf_conv_u64(s->sh_addralign, be); + s->sh_entsize = xm_binutils_elf_conv_u64(s->sh_entsize, be); +} +static __tb_inline__ void xm_binutils_elf64_symbol_conv(xm_elf64_symbol_t* s, tb_bool_t be) { + s->st_name = xm_binutils_elf_conv_u32(s->st_name, be); + s->st_shndx = xm_binutils_elf_conv_u16(s->st_shndx, be); + s->st_value = xm_binutils_elf_conv_u64(s->st_value, be); + s->st_size = xm_binutils_elf_conv_u64(s->st_size, be); + // st_info and st_other are single bytes, untouched +} + /* ////////////////////////////////////////////////////////////////////////////////////// * readsyms inline implementation */ diff --git a/core/src/xmake/binutils/prefix.h b/core/src/xmake/binutils/prefix.h index 608424958..bef683209 100644 --- a/core/src/xmake/binutils/prefix.h +++ b/core/src/xmake/binutils/prefix.h @@ -205,8 +205,8 @@ static __tb_inline__ tb_bool_t xm_binutils_arch_is_64bit(tb_char_t const *arch) else if (tb_strcmp(arch, "s390x") == 0) { return tb_true; } - // LoongArch64 - else if (tb_strncmp(arch, "loongarch64", 11) == 0) { + // LoongArch64 (xmake uses "loong64" as the canonical arch name) + else if (tb_strncmp(arch, "loongarch64", 11) == 0 || tb_strcmp(arch, "loong64") == 0) { return tb_true; } // WebAssembly 64 @@ -220,5 +220,33 @@ static __tb_inline__ tb_bool_t xm_binutils_arch_is_64bit(tb_char_t const *arch) return tb_false; } +/* check if architecture is big-endian + * + * @param arch the architecture string + * @return tb_true if big-endian, tb_false otherwise + */ +static __tb_inline__ tb_bool_t xm_binutils_arch_is_bigendian(tb_char_t const *arch) { + if (!arch) { + return tb_false; + } + // s390/s390x are always big-endian + if (tb_strcmp(arch, "s390x") == 0 || tb_strcmp(arch, "s390") == 0) { + return tb_true; + } + // SPARC is big-endian + else if (tb_strncmp(arch, "sparc", 5) == 0) { + return tb_true; + } + // MIPS big-endian variants (mips, mips64), the little-endian ones end with "el" (mipsel, mips64el) + else if (tb_strncmp(arch, "mips", 4) == 0) { + return tb_strstr(arch, "el") == tb_null; + } + // PowerPC big-endian variants (ppc, ppc64), the little-endian ones end with "le" (ppc64le, powerpc64le) + else if (tb_strncmp(arch, "ppc", 3) == 0 || tb_strncmp(arch, "powerpc", 7) == 0) { + return tb_strstr(arch, "le") == tb_null; + } + return tb_false; +} + #endif -- cgit v1.3.1 From 5feeecfdeaac2780a3c838751d28264ee1482cb2 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Jul 2026 18:24:16 +0800 Subject: fix ppc and mips for bin2obj --- core/src/xmake/binutils/elf/prefix.h | 27 +++++++++++++++++++++++++++ tests/modules/binutils/test.lua | 27 +++++++++++++++++++++++++-- 2 files changed, 52 insertions(+), 2 deletions(-) (limited to 'core/src/xmake/binutils') diff --git a/core/src/xmake/binutils/elf/prefix.h b/core/src/xmake/binutils/elf/prefix.h index 49c53c6c7..c26d678d2 100644 --- a/core/src/xmake/binutils/elf/prefix.h +++ b/core/src/xmake/binutils/elf/prefix.h @@ -69,6 +69,14 @@ #define XM_EF_LOONGARCH_ABI_DOUBLE_FLOAT 0x3 #define XM_EF_LOONGARCH_OBJABI_V1 0x40 +// PowerPC64 e_flags: the ELF ABI version is stored in the low 2 bits (see bfd/elf64-ppc.c) +#define XM_EF_PPC64_ABI_V1 0x1 +#define XM_EF_PPC64_ABI_V2 0x2 + +// MIPS e_flags (binutils include/elf/mips.h) +#define XM_EF_MIPS_CPIC 0x00000004 // call-PIC: linkable with both PIC and non-PIC objects +#define XM_EF_MIPS_ABI_O32 0x00001000 // the original 32-bit "o32" ABI + #define XM_ELF_SHT_PROGBITS 0x1 #define XM_ELF_SHT_SYMTAB 0x2 #define XM_ELF_SHT_STRTAB 0x3 @@ -341,6 +349,25 @@ static __tb_inline__ tb_uint32_t xm_binutils_elf_get_flags(tb_char_t const *arch else if (tb_strncmp(arch, "loongarch", 9) == 0 || tb_strncmp(arch, "loong64", 7) == 0) { return XM_EF_LOONGARCH_ABI_DOUBLE_FLOAT | XM_EF_LOONGARCH_OBJABI_V1; } + // PowerPC64: encode the ELF ABI version in e_flags. + // little-endian ppc64le uses the OpenPOWER ELFv2 ABI, big-endian ppc64 uses ELFv1, + // matching the gcc/clang defaults (-mabi=elfv2 on LE, -mabi=elfv1 on BE). + // 32-bit PowerPC does not carry an ABI version (e_flags == 0). + else if (tb_strncmp(arch, "ppc64", 5) == 0 || tb_strncmp(arch, "powerpc64", 9) == 0) { + return xm_binutils_arch_is_bigendian(arch)? XM_EF_PPC64_ABI_V1 : XM_EF_PPC64_ABI_V2; + } + // MIPS: mark the object as CPIC so it links against both PIC and non-PIC objects, and + // tag the 32-bit variants with the o32 ABI to match the common GNU toolchains (n64 is + // implied by ELFCLASS64, so mips64/mips64el carry no ABI bit). the ISA level (top nibble) + // and fp/NaN bits are left at 0 (== "any") on purpose: overclaiming them would make the + // linker reject otherwise-compatible objects. + else if (tb_strncmp(arch, "mips", 4) == 0) { + tb_uint32_t flags = XM_EF_MIPS_CPIC; + if (!xm_binutils_arch_is_64bit(arch)) { + flags |= XM_EF_MIPS_ABI_O32; + } + return flags; + } return 0; } diff --git a/tests/modules/binutils/test.lua b/tests/modules/binutils/test.lua index 1e2c0a03e..d1e13d75d 100644 --- a/tests/modules/binutils/test.lua +++ b/tests/modules/binutils/test.lua @@ -160,16 +160,39 @@ function test_bin2elf(t) t:are_equal(x86_64.flags, 0) -- mips is big-endian, mipsel is little-endian + -- 32-bit variants use the o32 ABI + CPIC (e_flags == 0x1004) local mips = _gen("mips") t:are_equal(mips.encode, 2) t:are_equal(mips.machine, 0x08) + t:are_equal(mips.flags, 0x1004) local mipsel = _gen("mipsel") t:are_equal(mipsel.encode, 1) t:are_equal(mipsel.machine, 0x08) - - -- ppc64 is big-endian + t:are_equal(mipsel.flags, 0x1004) + + -- 64-bit variants use the n64 ABI (implied by ELFCLASS64) + CPIC (e_flags == 0x4) + local mips64 = _gen("mips64") + t:are_equal(mips64.class, 2) + t:are_equal(mips64.encode, 2) + t:are_equal(mips64.machine, 0x08) + t:are_equal(mips64.flags, 0x4) + local mips64el = _gen("mips64el") + t:are_equal(mips64el.class, 2) + t:are_equal(mips64el.encode, 1) + t:are_equal(mips64el.machine, 0x08) + t:are_equal(mips64el.flags, 0x4) + + -- ppc64 is big-endian and uses the ELFv1 ABI (e_flags low bits == 1) local ppc64 = _gen("ppc64") t:are_equal(ppc64.encode, 2) + t:are_equal(ppc64.machine, 0x15) + t:are_equal(ppc64.flags, 0x1) + + -- ppc64le is little-endian and uses the OpenPOWER ELFv2 ABI (e_flags low bits == 2) + local ppc64le = _gen("ppc64le") + t:are_equal(ppc64le.encode, 1) + t:are_equal(ppc64le.machine, 0x15) + t:are_equal(ppc64le.flags, 0x2) os.tryrm(tempdir) end -- cgit v1.3.1 From 6b3632901ad14e99d306232c15cf788f6b081066 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Jul 2026 19:36:24 +0800 Subject: improve ppc --- core/src/xmake/binutils/prefix.h | 14 ++++++++++++-- tests/modules/binutils/test.lua | 16 ++++++++++++---- 2 files changed, 24 insertions(+), 6 deletions(-) (limited to 'core/src/xmake/binutils') diff --git a/core/src/xmake/binutils/prefix.h b/core/src/xmake/binutils/prefix.h index bef683209..c0f6ac356 100644 --- a/core/src/xmake/binutils/prefix.h +++ b/core/src/xmake/binutils/prefix.h @@ -241,9 +241,19 @@ static __tb_inline__ tb_bool_t xm_binutils_arch_is_bigendian(tb_char_t const *ar else if (tb_strncmp(arch, "mips", 4) == 0) { return tb_strstr(arch, "el") == tb_null; } - // PowerPC big-endian variants (ppc, ppc64), the little-endian ones end with "le" (ppc64le, powerpc64le) + // PowerPC endianness: + // - an explicit "le"/"be" suffix always wins (ppc64le/powerpc64le, ppc64be) + // - otherwise 64-bit ppc64/powerpc64 defaults to little-endian: xmake has no separate + // ppc64le arch (find_platform maps powerpc64le -> ppc64) and ppc64le is the dominant + // modern target, so a plain "ppc64" is treated as ppc64le (LE + OpenPOWER ELFv2) + // - 32-bit ppc stays traditional big-endian else if (tb_strncmp(arch, "ppc", 3) == 0 || tb_strncmp(arch, "powerpc", 7) == 0) { - return tb_strstr(arch, "le") == tb_null; + if (tb_strstr(arch, "le")) { + return tb_false; + } else if (tb_strstr(arch, "be")) { + return tb_true; + } + return !xm_binutils_arch_is_64bit(arch); } return tb_false; } diff --git a/tests/modules/binutils/test.lua b/tests/modules/binutils/test.lua index d1e13d75d..fe4a182f2 100644 --- a/tests/modules/binutils/test.lua +++ b/tests/modules/binutils/test.lua @@ -182,18 +182,26 @@ function test_bin2elf(t) t:are_equal(mips64el.machine, 0x08) t:are_equal(mips64el.flags, 0x4) - -- ppc64 is big-endian and uses the ELFv1 ABI (e_flags low bits == 1) + -- xmake has no separate ppc64le arch (find_platform maps powerpc64le -> ppc64) and + -- ppc64le is the dominant modern target, so a plain "ppc64" is treated as ppc64le: + -- little-endian + OpenPOWER ELFv2 ABI (e_flags low bits == 2) local ppc64 = _gen("ppc64") - t:are_equal(ppc64.encode, 2) + t:are_equal(ppc64.encode, 1) t:are_equal(ppc64.machine, 0x15) - t:are_equal(ppc64.flags, 0x1) + t:are_equal(ppc64.flags, 0x2) - -- ppc64le is little-endian and uses the OpenPOWER ELFv2 ABI (e_flags low bits == 2) + -- explicit ppc64le behaves the same local ppc64le = _gen("ppc64le") t:are_equal(ppc64le.encode, 1) t:are_equal(ppc64le.machine, 0x15) t:are_equal(ppc64le.flags, 0x2) + -- explicit big-endian ppc64be keeps the ELFv1 ABI + local ppc64be = _gen("ppc64be") + t:are_equal(ppc64be.encode, 2) + t:are_equal(ppc64be.machine, 0x15) + t:are_equal(ppc64be.flags, 0x1) + os.tryrm(tempdir) end -- cgit v1.3.1 From f2868ddfe82e0ce73888deebbf940dc9f511ef5e Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Jul 2026 20:56:26 +0800 Subject: detect obj flags for bin2elf --- core/src/xmake/binutils/elf/bin2elf.c | 69 ++++++++++++++++++++++++++++++---- xmake/core/base/binutils.lua | 4 +- xmake/modules/cli/binutils/bin2obj.lua | 3 +- xmake/rules/utils/bin2obj/utils.lua | 24 ++++++++++++ xmake/rules/utils/bin2obj/xmake.lua | 2 +- 5 files changed, 91 insertions(+), 11 deletions(-) (limited to 'core/src/xmake/binutils') diff --git a/core/src/xmake/binutils/elf/bin2elf.c b/core/src/xmake/binutils/elf/bin2elf.c index ff3f941f1..ee18e6113 100644 --- a/core/src/xmake/binutils/elf/bin2elf.c +++ b/core/src/xmake/binutils/elf/bin2elf.c @@ -60,12 +60,51 @@ static tb_bool_t xm_binutils_bin2elf_bwrit_symbol_64(tb_stream_ref_t ostream, xm return tb_stream_bwrit(ostream, (tb_byte_t const *)s, sizeof(*s)); } +// read the identity (class/endianness/machine/e_flags) from a reference ELF object. +// returns tb_true and updates the out-params on success; leaves them untouched on any failure +// (missing file, too small, bad magic), so the caller keeps its arch-derived defaults. +static tb_bool_t xm_binutils_bin2elf_read_refobj(tb_char_t const *refobj, + tb_bool_t *pis_64bit, tb_bool_t *pis_bigendian, tb_uint16_t *pe_machine, tb_uint32_t *pe_flags) { + tb_assert_and_check_return_val(refobj && pis_64bit && pis_bigendian && pe_machine && pe_flags, tb_false); + + tb_bool_t ok = tb_false; + tb_stream_ref_t stream = tb_stream_init_from_file(refobj, TB_FILE_MODE_RO); + do { + // the 32-bit ELF header is 52 bytes; the 64-bit e_flags ends at offset 52 too + tb_byte_t hdr[52]; + if (!stream || !tb_stream_open(stream)) break; + if (!tb_stream_bread(stream, hdr, sizeof(hdr))) break; + + // verify the ELF magic (0x7f 'E' 'L' 'F') + if (hdr[0] != 0x7f || hdr[1] != 'E' || hdr[2] != 'L' || hdr[3] != 'F') break; + + tb_bool_t is_64bit = (hdr[XM_ELF_EI_CLASS] == XM_ELF_CLASS64); + tb_bool_t is_bigendian = (hdr[5] == XM_ELF_DATA2MSB); + + // e_machine at offset 18 (2 bytes); e_flags at offset 36 (32-bit) / 48 (64-bit), in target endianness + tb_uint16_t e_machine = is_bigendian? tb_bits_get_u16_be(hdr + 18) : tb_bits_get_u16_le(hdr + 18); + tb_byte_t const *pflags = hdr + (is_64bit? 48 : 36); + tb_uint32_t e_flags = is_bigendian? tb_bits_get_u32_be(pflags) : tb_bits_get_u32_le(pflags); + + *pis_64bit = is_64bit; + *pis_bigendian = is_bigendian; + *pe_machine = e_machine; + *pe_flags = e_flags; + ok = tb_true; + + } while (0); + if (stream) tb_stream_clos(stream); + return ok; +} + static tb_bool_t xm_binutils_bin2elf_dump_32(tb_stream_ref_t istream, tb_stream_ref_t ostream, tb_char_t const *symbol_prefix, tb_char_t const *arch, tb_char_t const *basename, tb_bool_t bigendian, + tb_uint16_t e_machine, + tb_uint32_t e_flags, tb_bool_t zeroend) { tb_assert_and_check_return_val(istream && ostream, tb_false); @@ -148,9 +187,9 @@ static tb_bool_t xm_binutils_bin2elf_dump_32(tb_stream_ref_t istream, header.e_ident[6] = 1; // EV_CURRENT header.e_ident[7] = 0; // ELFOSABI_SYSV header.e_type = 1; // ET_REL - header.e_machine = xm_binutils_elf_get_machine(arch); + header.e_machine = e_machine; header.e_version = 1; - header.e_flags = xm_binutils_elf_get_flags(arch); + header.e_flags = e_flags; header.e_shoff = section_headers_ofs; header.e_ehsize = header_size; header.e_shentsize = section_header_size; @@ -368,6 +407,8 @@ static tb_bool_t xm_binutils_bin2elf_dump_64(tb_stream_ref_t istream, tb_char_t const *arch, tb_char_t const *basename, tb_bool_t bigendian, + tb_uint16_t e_machine, + tb_uint32_t e_flags, tb_bool_t zeroend) { tb_assert_and_check_return_val(istream && ostream, tb_false); @@ -450,9 +491,9 @@ static tb_bool_t xm_binutils_bin2elf_dump_64(tb_stream_ref_t istream, header.e_ident[6] = 1; // EV_CURRENT header.e_ident[7] = 0; // ELFOSABI_SYSV header.e_type = 1; // ET_REL - header.e_machine = xm_binutils_elf_get_machine(arch); + header.e_machine = e_machine; header.e_version = 1; - header.e_flags = xm_binutils_elf_get_flags(arch); + header.e_flags = e_flags; header.e_shoff = section_headers_ofs; header.e_ehsize = header_size; header.e_shentsize = section_header_size; @@ -670,7 +711,7 @@ static tb_bool_t xm_binutils_bin2elf_dump_64(tb_stream_ref_t istream, /* generate ELF object file from binary file * - * local ok, errors = binutils.bin2elf(binaryfile, outputfile, symbol_prefix, arch, basename, zeroend) + * local ok, errors = binutils.bin2elf(binaryfile, outputfile, symbol_prefix, arch, basename, zeroend, refobj) */ tb_int_t xm_binutils_bin2elf(lua_State *lua) { tb_assert_and_check_return_val(lua, 0); @@ -695,6 +736,12 @@ tb_int_t xm_binutils_bin2elf(lua_State *lua) { // get zeroend (optional, default: false) tb_bool_t zeroend = lua_toboolean(lua, 6); + // get the reference object (optional): a real object emitted by the target toolchain. + // we mirror its class/endianness/machine/e_flags so the output matches exactly, instead of + // guessing from the (sometimes ambiguous) arch name. when absent/unreadable we fall back to + // deriving everything from the arch name. + tb_char_t const *refobj = lua_isstring(lua, 7) ? lua_tostring(lua, 7) : tb_null; + // do dump tb_bool_t ok = tb_false; tb_stream_ref_t istream = tb_stream_init_from_file(binaryfile, TB_FILE_MODE_RO); @@ -713,17 +760,23 @@ tb_int_t xm_binutils_bin2elf(lua_State *lua) { break; } - // choose 32-bit or 64-bit ELF based on architecture, and little/big endian + // resolve class/endian/machine/flags: derive from the arch name, then mirror the + // reference object if one was given and is a readable ELF (it wins over the heuristic) tb_bool_t is_64bit = xm_binutils_elf_is_64bit(arch); tb_bool_t is_bigendian = xm_binutils_elf_is_bigendian(arch); + tb_uint16_t e_machine = xm_binutils_elf_get_machine(arch); + tb_uint32_t e_flags = xm_binutils_elf_get_flags(arch); + if (refobj) { + xm_binutils_bin2elf_read_refobj(refobj, &is_64bit, &is_bigendian, &e_machine, &e_flags); + } if (is_64bit) { - if (!xm_binutils_bin2elf_dump_64(istream, ostream, symbol_prefix, arch, basename, is_bigendian, zeroend)) { + if (!xm_binutils_bin2elf_dump_64(istream, ostream, symbol_prefix, arch, basename, is_bigendian, e_machine, e_flags, zeroend)) { lua_pushboolean(lua, tb_false); lua_pushfstring(lua, "bin2elf: dump data failed"); break; } } else { - if (!xm_binutils_bin2elf_dump_32(istream, ostream, symbol_prefix, arch, basename, is_bigendian, zeroend)) { + if (!xm_binutils_bin2elf_dump_32(istream, ostream, symbol_prefix, arch, basename, is_bigendian, e_machine, e_flags, zeroend)) { lua_pushboolean(lua, tb_false); lua_pushfstring(lua, "bin2elf: dump data failed"); break; diff --git a/xmake/core/base/binutils.lua b/xmake/core/base/binutils.lua index 7adfe6efa..400d48332 100644 --- a/xmake/core/base/binutils.lua +++ b/xmake/core/base/binutils.lua @@ -64,6 +64,8 @@ end -- - target_minver: the target minimum version (only for macho) -- - xcode_sdkver: the Xcode SDK version (only for macho) -- - zeroend: append null terminator (default: false) +-- - refobj: a reference elf object whose class/endianness/machine/e_flags +-- are mirrored into the output (default: derived from arch) function binutils.bin2obj(binaryfile, outputfile, opt) opt = opt or {} local format = opt.format @@ -94,7 +96,7 @@ function binutils.bin2obj(binaryfile, outputfile, opt) if not binutils._bin2elf then return nil, "binutils._bin2elf not available (C implementation not compiled)" end - return binutils._bin2elf(binaryfile, outputfile, opt.symbol_prefix or "_binary_", opt.arch or "x86_64", opt.basename, opt.zeroend or false) + return binutils._bin2elf(binaryfile, outputfile, opt.symbol_prefix or "_binary_", opt.arch or "x86_64", opt.basename, opt.zeroend or false, opt.refobj) else return nil, string.format("unsupported format '%s' (supported: coff, elf, macho)", format) end diff --git a/xmake/modules/cli/binutils/bin2obj.lua b/xmake/modules/cli/binutils/bin2obj.lua index 06493143a..c8314594f 100644 --- a/xmake/modules/cli/binutils/bin2obj.lua +++ b/xmake/modules/cli/binutils/bin2obj.lua @@ -32,7 +32,8 @@ local options = { {nil, "target_minver", "kv", nil, "Set the target minimum version (e.g., 10.0, 18.2)."}, {nil, "xcode_sdkver", "kv", nil, "Set the Xcode SDK version (e.g., 10.0, 18.2)."}, {nil, "zeroend", "k", nil, "Append a null terminator ('\\0') at the end of data."}, - {nil, "cosmocc", "k", nil, "Enable cosmocc support (generate concomitant object file)."} + {nil, "cosmocc", "k", nil, "Enable cosmocc support (generate concomitant object file)."}, + {nil, "refobj", "kv", nil, "Mirror class/endianness/machine/e_flags from a reference elf object."} } function main(...) diff --git a/xmake/rules/utils/bin2obj/utils.lua b/xmake/rules/utils/bin2obj/utils.lua index 3e8802e97..a14ba829a 100644 --- a/xmake/rules/utils/bin2obj/utils.lua +++ b/xmake/rules/utils/bin2obj/utils.lua @@ -18,6 +18,21 @@ -- @file utils.lua -- +-- pick a reference object already compiled by the target's own toolchain +-- +-- bin2obj mirrors its class/endianness/machine/e_flags, so the generated object matches the +-- toolchain exactly instead of guessing from the (sometimes ambiguous) arch name. we reuse one +-- of the target's own objects rather than compiling a dedicated probe; any object the toolchain +-- emits carries the same identity. we return the first one that already exists on disk, skipping +-- the object we are generating right now (which does not exist yet anyway). +function _get_refobj(target, objectfile) + for _, obj in ipairs(target:objectfiles()) do + if obj ~= objectfile and os.isfile(obj) then + return obj + end + end +end + -- generate object file from binary file -- -- @param target the target @@ -116,6 +131,15 @@ function generate_objectfile(target, batchcmds, binaryfile, opt) if is_cosmocc then table.insert(argv, "--cosmocc") end + + -- mirror the toolchain's elf identity (endianness/machine/e_flags) from one of the target's + -- own compiled objects, so the output matches and links regardless of how the arch name maps + if format == "elf" and not is_cosmocc then + local refobj = _get_refobj(target, objectfile) + if refobj then + table.insert(argv, "--refobj=" .. refobj) + end + end batchcmds:vlua("cli.binutils.bin2obj", argv) return objectfile diff --git a/xmake/rules/utils/bin2obj/xmake.lua b/xmake/rules/utils/bin2obj/xmake.lua index 760b9d536..b826fbd99 100644 --- a/xmake/rules/utils/bin2obj/xmake.lua +++ b/xmake/rules/utils/bin2obj/xmake.lua @@ -21,7 +21,7 @@ rule("utils.bin2obj") set_extensions(".bin") add_orders("utils.bin2obj", "c++.build.modules.builder") - on_buildcmd_file(function (target, batchcmds, sourcefile_bin, opt) + after_buildcmd_file(function (target, batchcmds, sourcefile_bin, opt) import("rules.utils.bin2obj.utils", {alias = "bin2obj_utils", rootdir = os.programdir()}) -- get zeroend (default: false) -- cgit v1.3.1 From 0641a99d357d99e96da49c22cb7d52be5f81c83f Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Jul 2026 21:43:03 +0800 Subject: modify comments --- core/src/xmake/binutils/elf/bin2elf.c | 20 +++++++++++--------- core/src/xmake/binutils/elf/prefix.h | 20 +++++++++++--------- core/src/xmake/binutils/prefix.h | 13 +++++++------ 3 files changed, 29 insertions(+), 24 deletions(-) (limited to 'core/src/xmake/binutils') diff --git a/core/src/xmake/binutils/elf/bin2elf.c b/core/src/xmake/binutils/elf/bin2elf.c index ee18e6113..ad580ba84 100644 --- a/core/src/xmake/binutils/elf/bin2elf.c +++ b/core/src/xmake/binutils/elf/bin2elf.c @@ -60,9 +60,10 @@ static tb_bool_t xm_binutils_bin2elf_bwrit_symbol_64(tb_stream_ref_t ostream, xm return tb_stream_bwrit(ostream, (tb_byte_t const *)s, sizeof(*s)); } -// read the identity (class/endianness/machine/e_flags) from a reference ELF object. -// returns tb_true and updates the out-params on success; leaves them untouched on any failure -// (missing file, too small, bad magic), so the caller keeps its arch-derived defaults. +/* read the identity (class/endianness/machine/e_flags) from a reference ELF object. + * returns tb_true and updates the out-params on success; leaves them untouched on any failure + * (missing file, too small, bad magic), so the caller keeps its arch-derived defaults. + */ static tb_bool_t xm_binutils_bin2elf_read_refobj(tb_char_t const *refobj, tb_bool_t *pis_64bit, tb_bool_t *pis_bigendian, tb_uint16_t *pe_machine, tb_uint32_t *pe_flags) { tb_assert_and_check_return_val(refobj && pis_64bit && pis_bigendian && pe_machine && pe_flags, tb_false); @@ -736,10 +737,11 @@ tb_int_t xm_binutils_bin2elf(lua_State *lua) { // get zeroend (optional, default: false) tb_bool_t zeroend = lua_toboolean(lua, 6); - // get the reference object (optional): a real object emitted by the target toolchain. - // we mirror its class/endianness/machine/e_flags so the output matches exactly, instead of - // guessing from the (sometimes ambiguous) arch name. when absent/unreadable we fall back to - // deriving everything from the arch name. + /* get the reference object (optional): a real object emitted by the target toolchain. + * we mirror its class/endianness/machine/e_flags so the output matches exactly, instead of + * guessing from the (sometimes ambiguous) arch name. when absent/unreadable we fall back to + * deriving everything from the arch name. + */ tb_char_t const *refobj = lua_isstring(lua, 7) ? lua_tostring(lua, 7) : tb_null; // do dump @@ -760,8 +762,8 @@ tb_int_t xm_binutils_bin2elf(lua_State *lua) { break; } - // resolve class/endian/machine/flags: derive from the arch name, then mirror the - // reference object if one was given and is a readable ELF (it wins over the heuristic) + /* resolve class/endian/machine/flags: derive from the arch name, then mirror the + * reference object if one was given and is a readable ELF (it wins over the heuristic) */ tb_bool_t is_64bit = xm_binutils_elf_is_64bit(arch); tb_bool_t is_bigendian = xm_binutils_elf_is_bigendian(arch); tb_uint16_t e_machine = xm_binutils_elf_get_machine(arch); diff --git a/core/src/xmake/binutils/elf/prefix.h b/core/src/xmake/binutils/elf/prefix.h index c26d678d2..9f18864df 100644 --- a/core/src/xmake/binutils/elf/prefix.h +++ b/core/src/xmake/binutils/elf/prefix.h @@ -349,18 +349,20 @@ static __tb_inline__ tb_uint32_t xm_binutils_elf_get_flags(tb_char_t const *arch else if (tb_strncmp(arch, "loongarch", 9) == 0 || tb_strncmp(arch, "loong64", 7) == 0) { return XM_EF_LOONGARCH_ABI_DOUBLE_FLOAT | XM_EF_LOONGARCH_OBJABI_V1; } - // PowerPC64: encode the ELF ABI version in e_flags. - // little-endian ppc64le uses the OpenPOWER ELFv2 ABI, big-endian ppc64 uses ELFv1, - // matching the gcc/clang defaults (-mabi=elfv2 on LE, -mabi=elfv1 on BE). - // 32-bit PowerPC does not carry an ABI version (e_flags == 0). + /* PowerPC64: encode the ELF ABI version in e_flags. + * little-endian ppc64le uses the OpenPOWER ELFv2 ABI, big-endian ppc64 uses ELFv1, + * matching the gcc/clang defaults (-mabi=elfv2 on LE, -mabi=elfv1 on BE). + * 32-bit PowerPC does not carry an ABI version (e_flags == 0). + */ else if (tb_strncmp(arch, "ppc64", 5) == 0 || tb_strncmp(arch, "powerpc64", 9) == 0) { return xm_binutils_arch_is_bigendian(arch)? XM_EF_PPC64_ABI_V1 : XM_EF_PPC64_ABI_V2; } - // MIPS: mark the object as CPIC so it links against both PIC and non-PIC objects, and - // tag the 32-bit variants with the o32 ABI to match the common GNU toolchains (n64 is - // implied by ELFCLASS64, so mips64/mips64el carry no ABI bit). the ISA level (top nibble) - // and fp/NaN bits are left at 0 (== "any") on purpose: overclaiming them would make the - // linker reject otherwise-compatible objects. + /* MIPS: mark the object as CPIC so it links against both PIC and non-PIC objects, and + * tag the 32-bit variants with the o32 ABI to match the common GNU toolchains (n64 is + * implied by ELFCLASS64, so mips64/mips64el carry no ABI bit). the ISA level (top nibble) + * and fp/NaN bits are left at 0 (== "any") on purpose: overclaiming them would make the + * linker reject otherwise-compatible objects. + */ else if (tb_strncmp(arch, "mips", 4) == 0) { tb_uint32_t flags = XM_EF_MIPS_CPIC; if (!xm_binutils_arch_is_64bit(arch)) { diff --git a/core/src/xmake/binutils/prefix.h b/core/src/xmake/binutils/prefix.h index c0f6ac356..ba7b06f12 100644 --- a/core/src/xmake/binutils/prefix.h +++ b/core/src/xmake/binutils/prefix.h @@ -241,12 +241,13 @@ static __tb_inline__ tb_bool_t xm_binutils_arch_is_bigendian(tb_char_t const *ar else if (tb_strncmp(arch, "mips", 4) == 0) { return tb_strstr(arch, "el") == tb_null; } - // PowerPC endianness: - // - an explicit "le"/"be" suffix always wins (ppc64le/powerpc64le, ppc64be) - // - otherwise 64-bit ppc64/powerpc64 defaults to little-endian: xmake has no separate - // ppc64le arch (find_platform maps powerpc64le -> ppc64) and ppc64le is the dominant - // modern target, so a plain "ppc64" is treated as ppc64le (LE + OpenPOWER ELFv2) - // - 32-bit ppc stays traditional big-endian + /* PowerPC endianness: + * - an explicit "le"/"be" suffix always wins (ppc64le/powerpc64le, ppc64be) + * - otherwise 64-bit ppc64/powerpc64 defaults to little-endian: xmake has no separate + * ppc64le arch (find_platform maps powerpc64le -> ppc64) and ppc64le is the dominant + * modern target, so a plain "ppc64" is treated as ppc64le (LE + OpenPOWER ELFv2) + * - 32-bit ppc stays traditional big-endian + */ else if (tb_strncmp(arch, "ppc", 3) == 0 || tb_strncmp(arch, "powerpc", 7) == 0) { if (tb_strstr(arch, "le")) { return tb_false; -- cgit v1.3.1 From cfebf2a690e1a0ad2255f64eec5bec43eeac0049 Mon Sep 17 00:00:00 2001 From: ruki Date: Sat, 18 Jul 2026 21:54:50 +0800 Subject: fix mem leaks --- core/src/xmake/binutils/bin2c.c | 4 ++-- core/src/xmake/binutils/coff/bin2coff.c | 4 ++-- core/src/xmake/binutils/elf/bin2elf.c | 6 +++--- core/src/xmake/binutils/macho/bin2macho.c | 4 ++-- core/src/xmake/binutils/readsyms.c | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) (limited to 'core/src/xmake/binutils') diff --git a/core/src/xmake/binutils/bin2c.c b/core/src/xmake/binutils/bin2c.c index b5054c55f..3c639d059 100644 --- a/core/src/xmake/binutils/bin2c.c +++ b/core/src/xmake/binutils/bin2c.c @@ -209,12 +209,12 @@ tb_int_t xm_binutils_bin2c(lua_State *lua) { } while (0); if (istream) { - tb_stream_clos(istream); + tb_stream_exit(istream); } istream = tb_null; if (ostream) { - tb_stream_clos(ostream); + tb_stream_exit(ostream); } ostream = tb_null; diff --git a/core/src/xmake/binutils/coff/bin2coff.c b/core/src/xmake/binutils/coff/bin2coff.c index ceb984a5c..791d4e2ba 100644 --- a/core/src/xmake/binutils/coff/bin2coff.c +++ b/core/src/xmake/binutils/coff/bin2coff.c @@ -303,12 +303,12 @@ tb_int_t xm_binutils_bin2coff(lua_State *lua) { } while (0); if (istream) { - tb_stream_clos(istream); + tb_stream_exit(istream); } istream = tb_null; if (ostream) { - tb_stream_clos(ostream); + tb_stream_exit(ostream); } ostream = tb_null; diff --git a/core/src/xmake/binutils/elf/bin2elf.c b/core/src/xmake/binutils/elf/bin2elf.c index ad580ba84..585ddc681 100644 --- a/core/src/xmake/binutils/elf/bin2elf.c +++ b/core/src/xmake/binutils/elf/bin2elf.c @@ -94,7 +94,7 @@ static tb_bool_t xm_binutils_bin2elf_read_refobj(tb_char_t const *refobj, ok = tb_true; } while (0); - if (stream) tb_stream_clos(stream); + if (stream) tb_stream_exit(stream); return ok; } @@ -791,11 +791,11 @@ tb_int_t xm_binutils_bin2elf(lua_State *lua) { } while (0); if (istream) - tb_stream_clos(istream); + tb_stream_exit(istream); istream = tb_null; if (ostream) - tb_stream_clos(ostream); + tb_stream_exit(ostream); ostream = tb_null; return ok ? 1 : 2; diff --git a/core/src/xmake/binutils/macho/bin2macho.c b/core/src/xmake/binutils/macho/bin2macho.c index 0b9dad0c2..c3c1c7a5c 100644 --- a/core/src/xmake/binutils/macho/bin2macho.c +++ b/core/src/xmake/binutils/macho/bin2macho.c @@ -606,12 +606,12 @@ tb_int_t xm_binutils_bin2macho(lua_State *lua) { } while (0); if (istream) { - tb_stream_clos(istream); + tb_stream_exit(istream); } istream = tb_null; if (ostream) { - tb_stream_clos(ostream); + tb_stream_exit(ostream); } ostream = tb_null; diff --git a/core/src/xmake/binutils/readsyms.c b/core/src/xmake/binutils/readsyms.c index 2c119a538..cac501a69 100644 --- a/core/src/xmake/binutils/readsyms.c +++ b/core/src/xmake/binutils/readsyms.c @@ -82,7 +82,7 @@ tb_int_t xm_binutils_readsyms(lua_State *lua) { lua_pushfstring(lua, "cannot detect file format"); break; } - + // create result list lua_newtable(lua); @@ -160,7 +160,7 @@ tb_int_t xm_binutils_readsyms(lua_State *lua) { } while (0); if (istream) { - tb_stream_clos(istream); + tb_stream_exit(istream); } istream = tb_null; -- cgit v1.3.1