summaryrefslogtreecommitdiff
path: root/core/src
diff options
context:
space:
mode:
Diffstat (limited to 'core/src')
-rw-r--r--core/src/cli/xmake.lua6
-rwxr-xr-xcore/src/cli/xmake.sh3
m---------core/src/tbox/tbox0
-rw-r--r--core/src/xmake/binutils/ar/extractlib.c2
-rw-r--r--core/src/xmake/binutils/bin2c.c4
-rw-r--r--core/src/xmake/binutils/coff/bin2coff.c4
-rw-r--r--core/src/xmake/binutils/elf/bin2elf.c146
-rw-r--r--core/src/xmake/binutils/elf/prefix.h164
-rw-r--r--core/src/xmake/binutils/extractlib.c2
-rw-r--r--core/src/xmake/binutils/macho/bin2macho.c4
-rw-r--r--core/src/xmake/binutils/prefix.h43
-rw-r--r--core/src/xmake/binutils/readsyms.c4
-rw-r--r--core/src/xmake/engine.c6
-rw-r--r--core/src/xmake/engine_pool.c21
-rw-r--r--core/src/xmake/io/file_close.c2
-rw-r--r--core/src/xmake/io/file_write.c2
-rw-r--r--core/src/xmake/os/cpuinfo.c4
-rw-r--r--core/src/xmake/os/meminfo.c5
-rw-r--r--core/src/xmake/process/open.c14
-rw-r--r--core/src/xmake/semver/select.c120
-rw-r--r--core/src/xmake/utf8/width.c6
21 files changed, 474 insertions, 88 deletions
diff --git a/core/src/cli/xmake.lua b/core/src/cli/xmake.lua
index 7cd50cb2c..54b78806d 100644
--- a/core/src/cli/xmake.lua
+++ b/core/src/cli/xmake.lua
@@ -58,7 +58,8 @@ target("cli")
add_installfiles("$(projectdir)/../NOTICE.md")
add_installfiles("$(projectdir)/../xmake/(**.lua)")
add_installfiles("$(projectdir)/../xmake/(scripts/**)")
- add_installfiles("$(projectdir)/../xmake/(repository/templates/**)")
+ add_installfiles("$(projectdir)/../xmake/(templates/**)")
+ add_installfiles("$(projectdir)/../xmake/(repository/**)")
add_installfiles("$(projectdir)/../scripts/xrepo.bat")
add_installfiles("$(projectdir)/../scripts/xrepo.ps1")
set_prefixdir("/", {bindir = "/"})
@@ -68,7 +69,8 @@ target("cli")
else
add_installfiles("$(projectdir)/../(xmake/**.lua)", {prefixdir = "share"})
add_installfiles("$(projectdir)/../(xmake/scripts/**)", {prefixdir = "share"})
- add_installfiles("$(projectdir)/../(xmake/repository/templates/**)", {prefixdir = "share"})
+ add_installfiles("$(projectdir)/../(xmake/templates/**)", {prefixdir = "share"})
+ add_installfiles("$(projectdir)/../(xmake/repository/**)", {prefixdir = "share"})
add_installfiles("$(projectdir)/../scripts/xrepo.sh", {prefixdir = "bin", filename = "xrepo"})
end
diff --git a/core/src/cli/xmake.sh b/core/src/cli/xmake.sh
index af4e8ba36..a7ef02601 100755
--- a/core/src/cli/xmake.sh
+++ b/core/src/cli/xmake.sh
@@ -32,7 +32,8 @@ target "cli"
add_installfiles "${projectdir}/(xmake/scripts/virtualenvs/**)" "share"
add_installfiles "${projectdir}/(xmake/scripts/conan/**)" "share"
add_installfiles "${projectdir}/(xmake/scripts/module/**)" "share"
- add_installfiles "${projectdir}/(xmake/repository/templates/**)" "share"
+ add_installfiles "${projectdir}/(xmake/templates/**)" "share"
+ add_installfiles "${projectdir}/(xmake/repository/**)" "share"
add_installfiles "${projectdir}/scripts/xrepo.sh" "bin" "xrepo"
# fix os.exec() call incorrect program from /mingw64/bin. e.g. python, ..
diff --git a/core/src/tbox/tbox b/core/src/tbox/tbox
-Subproject 870b2b9e4337694bb381d55338364c8b9711b82
+Subproject 3330978dce512b5c7104683383a40ab2b14be73
diff --git a/core/src/xmake/binutils/ar/extractlib.c b/core/src/xmake/binutils/ar/extractlib.c
index d9629394a..830eb3275 100644
--- a/core/src/xmake/binutils/ar/extractlib.c
+++ b/core/src/xmake/binutils/ar/extractlib.c
@@ -212,7 +212,7 @@ tb_bool_t xm_binutils_ar_extract(tb_stream_ref_t istream, tb_char_t const *outpu
ok = tb_false;
}
- tb_stream_clos(ostream);
+ tb_stream_close(ostream);
tb_stream_exit(ostream);
tb_check_break(ok);
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 76a75f8fe..585ddc681 100644
--- a/core/src/xmake/binutils/elf/bin2elf.c
+++ b/core/src/xmake/binutils/elf/bin2elf.c
@@ -34,11 +34,78 @@
* 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));
+}
+
+/* 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_exit(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);
@@ -117,25 +184,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_machine = e_machine;
header.e_version = 1;
+ header.e_flags = e_flags;
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(&section_null, 0, sizeof(section_null));
- if (!tb_stream_bwrit(ostream, (tb_byte_t const *)&section_null, sizeof(section_null))) {
+ if (!xm_binutils_bin2elf_bwrit_section_32(ostream, &section_null, bigendian)) {
return tb_false;
}
@@ -148,7 +216,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 *)&section_rodata, sizeof(section_rodata))) {
+ if (!xm_binutils_bin2elf_bwrit_section_32(ostream, &section_rodata, bigendian)) {
return tb_false;
}
@@ -163,7 +231,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 *)&section_symtab, sizeof(section_symtab))) {
+ if (!xm_binutils_bin2elf_bwrit_section_32(ostream, &section_symtab, bigendian)) {
return tb_false;
}
@@ -175,7 +243,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 *)&section_strtab, sizeof(section_strtab))) {
+ if (!xm_binutils_bin2elf_bwrit_section_32(ostream, &section_strtab, bigendian)) {
return tb_false;
}
@@ -187,7 +255,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 *)&section_shstrtab, sizeof(section_shstrtab))) {
+ if (!xm_binutils_bin2elf_bwrit_section_32(ostream, &section_shstrtab, bigendian)) {
return tb_false;
}
@@ -200,7 +268,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 *)&section_note_gnu_stack, sizeof(section_note_gnu_stack))) {
+ if (!xm_binutils_bin2elf_bwrit_section_32(ostream, &section_note_gnu_stack, bigendian)) {
return tb_false;
}
@@ -230,7 +298,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 +310,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 +322,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 +407,9 @@ 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_uint16_t e_machine,
+ tb_uint32_t e_flags,
tb_bool_t zeroend) {
tb_assert_and_check_return_val(istream && ostream, tb_false);
@@ -417,25 +488,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_machine = e_machine;
header.e_version = 1;
+ header.e_flags = e_flags;
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(&section_null, 0, sizeof(section_null));
- if (!tb_stream_bwrit(ostream, (tb_byte_t const *)&section_null, sizeof(section_null))) {
+ if (!xm_binutils_bin2elf_bwrit_section_64(ostream, &section_null, bigendian)) {
return tb_false;
}
@@ -448,7 +520,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 *)&section_rodata, sizeof(section_rodata))) {
+ if (!xm_binutils_bin2elf_bwrit_section_64(ostream, &section_rodata, bigendian)) {
return tb_false;
}
@@ -463,7 +535,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 *)&section_symtab, sizeof(section_symtab))) {
+ if (!xm_binutils_bin2elf_bwrit_section_64(ostream, &section_symtab, bigendian)) {
return tb_false;
}
@@ -475,7 +547,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 *)&section_strtab, sizeof(section_strtab))) {
+ if (!xm_binutils_bin2elf_bwrit_section_64(ostream, &section_strtab, bigendian)) {
return tb_false;
}
@@ -487,7 +559,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 *)&section_shstrtab, sizeof(section_shstrtab))) {
+ if (!xm_binutils_bin2elf_bwrit_section_64(ostream, &section_shstrtab, bigendian)) {
return tb_false;
}
@@ -500,7 +572,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 *)&section_note_gnu_stack, sizeof(section_note_gnu_stack))) {
+ if (!xm_binutils_bin2elf_bwrit_section_64(ostream, &section_note_gnu_stack, bigendian)) {
return tb_false;
}
@@ -530,7 +602,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 +614,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 +626,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;
}
@@ -640,7 +712,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);
@@ -665,6 +737,13 @@ 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);
@@ -683,16 +762,23 @@ tb_int_t xm_binutils_bin2elf(lua_State *lua) {
break;
}
- // choose 32-bit or 64-bit ELF based on architecture
+ /* 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, 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, 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;
@@ -705,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/elf/prefix.h b/core/src/xmake/binutils/elf/prefix.h
index 2072ee879..9f18864df 100644
--- a/core/src/xmake/binutils/elf/prefix.h
+++ b/core/src/xmake/binutils/elf/prefix.h
@@ -56,6 +56,27 @@
#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
+
+// 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
@@ -297,6 +318,149 @@ 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;
+ }
+ /* 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;
+}
+
+/* //////////////////////////////////////////////////////////////////////////////////////
+ * 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/extractlib.c b/core/src/xmake/binutils/extractlib.c
index fbfbacfef..735859ade 100644
--- a/core/src/xmake/binutils/extractlib.c
+++ b/core/src/xmake/binutils/extractlib.c
@@ -129,7 +129,7 @@ tb_int_t xm_binutils_extractlib(lua_State *lua) {
} while (0);
if (istream) {
- tb_stream_clos(istream);
+ tb_stream_close(istream);
tb_stream_exit(istream);
}
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/prefix.h b/core/src/xmake/binutils/prefix.h
index 608424958..ba7b06f12 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,44 @@ 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 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;
+ } else if (tb_strstr(arch, "be")) {
+ return tb_true;
+ }
+ return !xm_binutils_arch_is_64bit(arch);
+ }
+ return tb_false;
+}
+
#endif
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;
diff --git a/core/src/xmake/engine.c b/core/src/xmake/engine.c
index b93b29bb0..b37817cc9 100644
--- a/core/src/xmake/engine.c
+++ b/core/src/xmake/engine.c
@@ -814,6 +814,10 @@ static tb_bool_t xm_engine_save_arguments(xm_engine_t *engine, tb_int_t argc, tb
lua_rawseti(engine->lua, -2, (int)lua_objlen(engine->lua, -2) + 1);
}
+#if defined(TB_CONFIG_OS_WINDOWS) && !defined(TB_COMPILER_LIKE_UNIX)
+ LocalFree(argvw);
+#endif
+
// _ARGV = table_new
lua_setglobal(engine->lua, "_ARGV");
return tb_true;
@@ -1445,8 +1449,8 @@ static tb_bool_t xm_engine_extract_programfiles_impl(xm_engine_t *engine,
if (tb_stream_open(stream)) {
tb_stream_bwrit(stream, p, n);
- tb_stream_exit(stream);
}
+ tb_stream_exit(stream);
p += n;
}
diff --git a/core/src/xmake/engine_pool.c b/core/src/xmake/engine_pool.c
index 39bdb1339..b9df842eb 100644
--- a/core/src/xmake/engine_pool.c
+++ b/core/src/xmake/engine_pool.c
@@ -43,6 +43,18 @@
#define XM_ENGINE_POOL (TB_SINGLETON_TYPE_USER + 4)
/* //////////////////////////////////////////////////////////////////////////////////////
+ * globals
+ */
+
+/* the engine pool lock
+ *
+ * the pool is a singleton shared by all worker threads, which may alloc/free engines
+ * concurrently (e.g. parallel batchcmds:lua/vlua jobs run in native threads), so we must
+ * protect the underlying list against data races, otherwise it will be corrupted and crash.
+ */
+static tb_spinlock_t g_engine_pool_lock = TB_SPINLOCK_INIT;
+
+/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
static tb_handle_t xm_engine_pool_instance_init(tb_cpointer_t *ppriv) {
@@ -83,17 +95,22 @@ tb_void_t xm_engine_pool_exit(xm_engine_pool_ref_t engine_pool) {
xm_engine_ref_t xm_engine_pool_alloc(xm_engine_pool_ref_t engine_pool) {
xm_engine_ref_t engine = tb_null;
+ tb_spinlock_enter(&g_engine_pool_lock);
if (tb_single_list_size(engine_pool) > 0) {
engine = (xm_engine_ref_t)tb_single_list_head(engine_pool);
tb_single_list_remove_head(engine_pool);
}
+ tb_spinlock_leave(&g_engine_pool_lock);
return engine;
}
tb_bool_t xm_engine_pool_free(xm_engine_pool_ref_t engine_pool, xm_engine_ref_t engine) {
+ tb_bool_t ok = tb_false;
+ tb_spinlock_enter(&g_engine_pool_lock);
if (tb_single_list_size(engine_pool) < XM_ENGINE_POOL_MAXN) {
tb_single_list_insert_tail(engine_pool, engine);
- return tb_true;
+ ok = tb_true;
}
- return tb_false;
+ tb_spinlock_leave(&g_engine_pool_lock);
+ return ok;
}
diff --git a/core/src/xmake/io/file_close.c b/core/src/xmake/io/file_close.c
index bb5cf1060..303f9f002 100644
--- a/core/src/xmake/io/file_close.c
+++ b/core/src/xmake/io/file_close.c
@@ -68,7 +68,7 @@ tb_int_t xm_io_file_close(lua_State *lua) {
}
// close file
- tb_stream_clos(file->u.file_ref);
+ tb_stream_close(file->u.file_ref);
file->u.file_ref = tb_null;
// exit fstream
diff --git a/core/src/xmake/io/file_write.c b/core/src/xmake/io/file_write.c
index fdfd5afe7..5f860d641 100644
--- a/core/src/xmake/io/file_write.c
+++ b/core/src/xmake/io/file_write.c
@@ -110,7 +110,7 @@ static tb_void_t xm_io_file_write_std(xm_io_file_t *file, tb_byte_t const *data,
tb_check_return(type != XM_IO_FILE_TYPE_STDIN);
// write data to stdout/stderr
- tb_stdfile_writ(file->u.std_ref, data, size);
+ tb_stdfile_write(file->u.std_ref, data, size);
}
/* //////////////////////////////////////////////////////////////////////////////////////
diff --git a/core/src/xmake/os/cpuinfo.c b/core/src/xmake/os/cpuinfo.c
index 47542a4b4..e931f7912 100644
--- a/core/src/xmake/os/cpuinfo.c
+++ b/core/src/xmake/os/cpuinfo.c
@@ -70,8 +70,9 @@ static tb_float_t xm_os_cpuinfo_usagerate() {
processor_info_array_t cpuinfo;
mach_msg_type_number_t cpuinfo_count;
static tb_hong_t s_time = 0;
+ host_t host = mach_host_self();
if (tb_mclock() - s_time > 1000 &&
- host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &cpu_count, &cpuinfo, &cpuinfo_count) ==
+ host_processor_info(host, PROCESSOR_CPU_LOAD_INFO, &cpu_count, &cpuinfo, &cpuinfo_count) ==
KERN_SUCCESS) {
static processor_info_array_t s_cpuinfo_prev = tb_null;
static mach_msg_type_number_t s_cpuinfo_count_prev = 0;
@@ -100,6 +101,7 @@ static tb_float_t xm_os_cpuinfo_usagerate() {
s_cpuinfo_prev = cpuinfo;
s_cpuinfo_count_prev = cpuinfo_count;
}
+ mach_port_deallocate(mach_task_self(), host);
return cpu_count > 0 ? usagerate / cpu_count : 0;
#elif defined(TB_CONFIG_OS_WINDOWS)
// kernel include idle_time
diff --git a/core/src/xmake/os/meminfo.c b/core/src/xmake/os/meminfo.c
index 96db76f0d..0671d5311 100644
--- a/core/src/xmake/os/meminfo.c
+++ b/core/src/xmake/os/meminfo.c
@@ -61,7 +61,10 @@ static tb_bool_t xm_os_meminfo_stats(tb_int_t *ptotalsize, tb_int_t *pavailsize)
#if defined(TB_CONFIG_OS_MACOSX)
vm_statistics64_data_t vmstat;
mach_msg_type_number_t count = HOST_VM_INFO64_COUNT;
- if (host_statistics64(mach_host_self(), HOST_VM_INFO64, (host_info_t)&vmstat, &count) == KERN_SUCCESS) {
+ host_t host = mach_host_self();
+ kern_return_t result = host_statistics64(host, HOST_VM_INFO64, (host_info_t)&vmstat, &count);
+ mach_port_deallocate(mach_task_self(), host);
+ if (result == KERN_SUCCESS) {
tb_int_t pagesize = (tb_int_t)tb_page_size();
tb_int64_t totalsize = (tb_int64_t)(vmstat.inactive_count + vmstat.free_count + vmstat.active_count +
vmstat.wire_count
diff --git a/core/src/xmake/process/open.c b/core/src/xmake/process/open.c
index b6cf272b2..5ae958f8d 100644
--- a/core/src/xmake/process/open.c
+++ b/core/src/xmake/process/open.c
@@ -75,7 +75,7 @@ tb_int_t xm_process_open(lua_State *lua) {
// get curdir
lua_pushstring(lua, "curdir");
- lua_gettable(lua, 3);
+ lua_gettable(lua, 2);
attr.curdir = lua_tostring(lua, -1);
lua_pop(lua, 1);
@@ -100,7 +100,7 @@ tb_int_t xm_process_open(lua_State *lua) {
// get infile
if (!inpath) {
lua_pushstring(lua, "infile");
- lua_gettable(lua, 3);
+ lua_gettable(lua, 2);
infile = (xm_io_file_t *)lua_touserdata(lua, -1);
lua_pop(lua, 1);
}
@@ -108,7 +108,7 @@ tb_int_t xm_process_open(lua_State *lua) {
// get outfile
if (!outpath) {
lua_pushstring(lua, "outfile");
- lua_gettable(lua, 3);
+ lua_gettable(lua, 2);
outfile = (xm_io_file_t *)lua_touserdata(lua, -1);
lua_pop(lua, 1);
}
@@ -116,7 +116,7 @@ tb_int_t xm_process_open(lua_State *lua) {
// get errfile
if (!errpath) {
lua_pushstring(lua, "errfile");
- lua_gettable(lua, 3);
+ lua_gettable(lua, 2);
errfile = (xm_io_file_t *)lua_touserdata(lua, -1);
lua_pop(lua, 1);
}
@@ -124,7 +124,7 @@ tb_int_t xm_process_open(lua_State *lua) {
// get inpipe
if (!inpath && !infile) {
lua_pushstring(lua, "inpipe");
- lua_gettable(lua, 3);
+ lua_gettable(lua, 2);
inpipe = (tb_pipe_file_ref_t)lua_touserdata(lua, -1);
lua_pop(lua, 1);
}
@@ -132,7 +132,7 @@ tb_int_t xm_process_open(lua_State *lua) {
// get outpipe
if (!outpath && !outfile) {
lua_pushstring(lua, "outpipe");
- lua_gettable(lua, 3);
+ lua_gettable(lua, 2);
outpipe = (tb_pipe_file_ref_t)lua_touserdata(lua, -1);
lua_pop(lua, 1);
}
@@ -140,7 +140,7 @@ tb_int_t xm_process_open(lua_State *lua) {
// get errpipe
if (!errpath && !errfile) {
lua_pushstring(lua, "errpipe");
- lua_gettable(lua, 3);
+ lua_gettable(lua, 2);
errpipe = (tb_pipe_file_ref_t)lua_touserdata(lua, -1);
lua_pop(lua, 1);
}
diff --git a/core/src/xmake/semver/select.c b/core/src/xmake/semver/select.c
index 283afb050..e95840eab 100644
--- a/core/src/xmake/semver/select.c
+++ b/core/src/xmake/semver/select.c
@@ -33,6 +33,69 @@
/* //////////////////////////////////////////////////////////////////////////////////////
* private implementation
*/
+static tb_char_t const *xm_semver_skip_version_prefix(tb_char_t const *version_str, tb_size_t *version_len) {
+ if (*version_len && (version_str[0] == 'v' || version_str[0] == '=')) {
+ ++version_str;
+ --*version_len;
+ }
+ return version_str;
+}
+static tb_bool_t xm_semver_is_exact_version(
+ tb_char_t const *version_str, tb_size_t version_len, tb_bool_t *is_exact_with_build) {
+ *is_exact_with_build = tb_false;
+ version_str = xm_semver_skip_version_prefix(version_str, &version_len);
+ semver_t version = { 0 };
+ if (!semvern(&version, version_str, version_len)) {
+ *is_exact_with_build = version.build.len > 0;
+ semver_dtor(&version);
+ return tb_true;
+ }
+ return tb_false;
+}
+static tb_long_t xm_semver_compare_build(semver_id_t const *left, semver_id_t const *right) {
+ while (left && right && left->len && right->len) {
+ if (left->numeric && right->numeric) {
+ if (left->num != right->num) {
+ return left->num > right->num ? 1 : -1;
+ }
+ } else {
+ tb_size_t size = left->len < right->len ? left->len : right->len;
+ tb_long_t result = tb_memcmp(left->raw, right->raw, size);
+ if (result) {
+ return result;
+ }
+ if (left->len != right->len) {
+ return left->len > right->len ? 1 : -1;
+ }
+ }
+ left = left->next;
+ right = right->next;
+ }
+ if (left && left->len) {
+ return 1;
+ }
+ if (right && right->len) {
+ return -1;
+ }
+ return 0;
+}
+static tb_long_t xm_semver_compare_with_build(semver_t const *left, semver_t const *right) {
+ tb_long_t result = semver_pcmp(left, right);
+ // xmake-repo orders build metadata as package revisions
+ return result ? result : xm_semver_compare_build(&left->build, &right->build);
+}
+static semver_t const *xm_semvers_find_newest(semvers_t const *versions) {
+ tb_assert_and_check_return_val(versions && versions->length, tb_null);
+
+ semver_t const *newest = &versions->data[0];
+ tb_size_t i = 0;
+ for (i = 1; i < versions->length; ++i) {
+ if (xm_semver_compare_with_build(&versions->data[i], newest) > 0) {
+ newest = &versions->data[i];
+ }
+ }
+ return newest;
+}
static tb_bool_t xm_semver_select_from_versions_tags1(
lua_State *lua, tb_int_t fromidx, semver_t *semver, semver_range_t const *range, semvers_t *matches) {
// clear matches
@@ -59,27 +122,24 @@ static tb_bool_t xm_semver_select_from_versions_tags1(
// no matches?
tb_check_return_val(matches->length, tb_false);
- // sort matches
- semvers_psort(matches);
-
// get the newest version
- semver_t top = semvers_ppop(matches);
+ semver_t const *top = xm_semvers_find_newest(matches);
lua_createtable(lua, 0, 2);
// return results
- lua_pushstring(lua, top.raw);
+ lua_pushstring(lua, top->raw);
lua_setfield(lua, -2, "version");
lua_pushstring(lua, fromidx == 2 ? "version" : "tag");
lua_setfield(lua, -2, "source");
- // exit the popped semver
- semver_dtor(&top);
-
return tb_true;
}
static tb_bool_t xm_semver_select_from_versions_tags2(
- lua_State *lua, tb_int_t fromidx, semver_t *semver, tb_char_t const *version_str, tb_size_t version_len) {
+ lua_State *lua, tb_int_t fromidx, tb_char_t const *version_str, tb_size_t version_len, tb_bool_t is_exact) {
+ if (is_exact) {
+ version_str = xm_semver_skip_version_prefix(version_str, &version_len);
+ }
lua_Integer i = 0;
luaL_checktype(lua, fromidx, LUA_TTABLE);
for (i = lua_objlen(lua, fromidx); i > 0; --i) {
@@ -88,8 +148,14 @@ static tb_bool_t xm_semver_select_from_versions_tags2(
tb_char_t const *source_str = luaL_checkstring(lua, -1);
tb_size_t source_len = tb_strlen(source_str);
+ tb_size_t source_version_len = source_len;
+ tb_char_t const *source_version_str = source_str;
+ // ignore a leading v/= prefix when comparing exact versions
+ if (is_exact) {
+ source_version_str = xm_semver_skip_version_prefix(source_str, &source_version_len);
+ }
lua_pop(lua, 1);
- if (source_len == version_len && tb_strncmp(source_str, version_str, version_len) == 0) {
+ if (source_version_len == version_len && tb_strncmp(source_version_str, version_str, version_len) == 0) {
lua_createtable(lua, 0, 2);
lua_pushlstring(lua, source_str, source_len);
lua_setfield(lua, -2, "version");
@@ -147,21 +213,17 @@ static tb_bool_t xm_semver_select_latest_from_versions_tags(lua_State *lua,
}
tb_check_return_val(matches->length, tb_false);
- // sort matches
- semvers_psort(matches);
-
// get the newest match
- semver_t top = semvers_ppop(matches);
+ semver_t const *top = xm_semvers_find_newest(matches);
lua_createtable(lua, 0, 2);
// return results
- lua_pushstring(lua, top.raw);
+ lua_pushstring(lua, top->raw);
lua_setfield(lua, -2, "version");
lua_pushstring(lua, fromidx == 2 ? "version" : "tag");
lua_setfield(lua, -2, "source");
- semver_dtor(&top);
return tb_true;
}
@@ -179,6 +241,8 @@ tb_int_t xm_semver_select(lua_State *lua) {
// select version
tb_bool_t ok = tb_false;
tb_bool_t is_range = tb_false;
+ tb_bool_t is_exact = tb_false;
+ tb_bool_t is_exact_with_build = tb_false;
tb_char_t const *range_str = tb_null;
semver_t semver = { 0 };
semvers_t matches = { 0 };
@@ -193,27 +257,27 @@ tb_int_t xm_semver_select(lua_State *lua) {
// parse the version range string
is_range = semver_rangen(&range, range_str, range_len) == 0;
- if (is_range) {
- // attempt to select version from the versions list first
- if (xm_semver_select_from_versions_tags1(lua, 2, &semver, &range, &matches)) {
+ is_exact = xm_semver_is_exact_version(range_str, range_len, &is_exact_with_build);
+
+ // matching order: versions exact -> tags exact -> versions range -> tags range
+ if (is_exact || !is_range) {
+ if (xm_semver_select_from_versions_tags2(lua, 2, range_str, range_len, is_exact)) {
ok = tb_true;
break;
}
-
- // attempt to select version from the tags list
- if (xm_semver_select_from_versions_tags1(lua, 3, &semver, &range, &matches)) {
+ if (xm_semver_select_from_versions_tags2(lua, 3, range_str, range_len, is_exact)) {
ok = tb_true;
break;
}
- } else {
- // attempt to select version from the versions list first
- if (xm_semver_select_from_versions_tags2(lua, 2, &semver, range_str, range_len)) {
+ }
+
+ // a build-qualified exact version identifies a specific package revision
+ if (is_range && !is_exact_with_build) {
+ if (xm_semver_select_from_versions_tags1(lua, 2, &semver, &range, &matches)) {
ok = tb_true;
break;
}
-
- // attempt to select version from the tags list
- if (xm_semver_select_from_versions_tags2(lua, 3, &semver, range_str, range_len)) {
+ if (xm_semver_select_from_versions_tags1(lua, 3, &semver, &range, &matches)) {
ok = tb_true;
break;
}
diff --git a/core/src/xmake/utf8/width.c b/core/src/xmake/utf8/width.c
index 615572462..fb79ee198 100644
--- a/core/src/xmake/utf8/width.c
+++ b/core/src/xmake/utf8/width.c
@@ -33,7 +33,11 @@
* utf8.width(codepoint)
*/
tb_int_t xm_utf8_width(lua_State* lua) {
- if (lua_isnumber(lua, 1)) {
+ /* we must not use lua_isnumber() here: it also accepts a numeric string,
+ * so utf8.width("9") would return the width of the code point 9 (a tab)
+ * instead of the width of the string "9"
+ */
+ if (lua_type(lua, 1) == LUA_TNUMBER) {
xm_utf8_int_t val = (xm_utf8_int_t)lua_tointeger(lua, 1);
lua_pushinteger(lua, xm_utf8_charwidth(val));
} else {