diff --git a/build.zig b/build.zig
index d0d9c8c..5a1d829 100644
--- a/build.zig
+++ b/build.zig
@@ -1,6 +1,6 @@
const std = @import("std");
-const version: std.SemanticVersion = .{ .major = 2, .minor = 44, .patch = 0 };
+const version: std.SemanticVersion = .{ .major = 2, .minor = 45, .patch = 0 };
pub fn build(b: *std.Build) void {
const upstream = b.dependency("binutils", .{});
@@ -14,6 +14,21 @@ pub fn build(b: *std.Build) void {
// Plugins have a dependency on the install prefix so they have been disabled by default in this port.
const enable_plugins = b.option(bool, "plugins", "Enable plugins") orelse false;
+ const gnu_cpu = switch (target.result.cpu.arch) {
+ .x86 => "i386",
+ else => @tagName(target.result.cpu.arch),
+ };
+ const gnu_vendor = switch (target.result.cpu.arch) {
+ .x86, .x86_64 => "pc",
+ else => "unknown",
+ };
+ const gnu_triple = b.fmt("{s}-{s}-{s}-{s}", .{
+ gnu_cpu,
+ gnu_vendor,
+ @tagName(target.result.os.tag),
+ @tagName(target.result.abi),
+ });
+
const libsframe_config_header = b.addConfigHeader(.{}, .{
.HAVE_BYTESWAP_H = if (target.result.os.tag == .linux or target.result.os.tag == .wasi) true else null,
.HAVE_DECL_BSWAP_16 = target.result.os.tag == .linux or target.result.os.tag == .wasi,
@@ -619,7 +634,6 @@ pub fn build(b: *std.Build) void {
// "pex-djgpp.c",
// "pex-msdos.c",
"pex-one.c",
- // if (target.result.os.tag == .windows) "pex-win32.c" else "pex-unix.c",
"physmem.c",
// "putenv.c",
// "random.c",
@@ -668,7 +682,7 @@ pub fn build(b: *std.Build) void {
"vfork.c",
// "vfprintf.c",
// "vprintf.c",
- // "vprintf-support.c",
+ "vprintf-support.c",
// "vsnprintf.c",
// "vsprintf.c",
// "waitpid.c",
@@ -683,6 +697,12 @@ pub fn build(b: *std.Build) void {
"xvasprintf.c",
},
});
+ iberty.root_module.addCSourceFile(.{
+ .file = upstream.path(if (target.result.os.tag == .windows)
+ "libiberty/pex-win32.c"
+ else
+ "libiberty/pex-unix.c"),
+ });
const bfd_header = b.addConfigHeader(.{
.style = .{ .autoconf_at = upstream.path("bfd/bfd-in2.h") },
@@ -699,9 +719,9 @@ pub fn build(b: *std.Build) void {
.style = .{ .autoconf_at = upstream.path("bfd/version.h") },
.include_path = "bfdver.h",
}, .{
- .bfd_version = 244000000,
+ .bfd_version = @as(i64, version.major * 100 + version.minor) * 1000000 + version.patch * 10000,
.bfd_version_package = "\"(GNU Binutils) \"",
- .bfd_version_string = "\"2.44.0.20250215\"",
+ .bfd_version_string = b.fmt("\"{f}\"", .{version}),
.report_bugs_to = "\"\"",
});
@@ -889,27 +909,19 @@ pub fn build(b: *std.Build) void {
else => std.debug.panic("TODO '{s}-{s}'", .{ @tagName(target.result.cpu.arch), @tagName(target.result.os.tag) }),
};
- const find_replace_exe = b.addExecutable(.{
- .name = "find-replace",
- .root_module = b.createModule(.{
- .root_source_file = b.path("find_replace.zig"),
- .target = b.graph.host,
- }),
- });
-
const generated_header_files: []const std.Build.LazyPath = &.{
- runFindReplace(b, find_replace_exe, upstream.path("bfd/elfxx-target.h"), "elf32-target.h", "NN", "32"),
- runFindReplace(b, find_replace_exe, upstream.path("bfd/elfxx-target.h"), "elf64-target.h", "NN", "64"),
- runFindReplace(b, find_replace_exe, upstream.path("bfd/elfxx-aarch64.h"), "elf32-aarch64.h", "NN", "32"),
- runFindReplace(b, find_replace_exe, upstream.path("bfd/elfxx-aarch64.h"), "elf64-aarch64.h", "NN", "64"),
- runFindReplace(b, find_replace_exe, upstream.path("bfd/elfxx-ia64.h"), "elf32-ia64.h", "NN", "32"),
- runFindReplace(b, find_replace_exe, upstream.path("bfd/elfxx-ia64.h"), "elf64-ia64.h", "NN", "64"),
- runFindReplace(b, find_replace_exe, upstream.path("bfd/elfxx-kvx.h"), "elf32-kvx.h", "NN", "32"),
- runFindReplace(b, find_replace_exe, upstream.path("bfd/elfxx-kvx.h"), "elf64-kvx.h", "NN", "64"),
- runFindReplace(b, find_replace_exe, upstream.path("bfd/elfxx-loongarch.h"), "elf32-loongarch.h", "NN", "32"),
- runFindReplace(b, find_replace_exe, upstream.path("bfd/elfxx-loongarch.h"), "elf64-loongarch.h", "NN", "64"),
- runFindReplace(b, find_replace_exe, upstream.path("bfd/elfxx-riscv.h"), "elf32-riscv.h", "NN", "32"),
- runFindReplace(b, find_replace_exe, upstream.path("bfd/elfxx-riscv.h"), "elf64-riscv.h", "NN", "64"),
+ runFindReplace(b, upstream.path("bfd/elfxx-target.h"), "elf32-target.h", "NN", "32"),
+ runFindReplace(b, upstream.path("bfd/elfxx-target.h"), "elf64-target.h", "NN", "64"),
+ runFindReplace(b, upstream.path("bfd/elfxx-aarch64.h"), "elf32-aarch64.h", "NN", "32"),
+ runFindReplace(b, upstream.path("bfd/elfxx-aarch64.h"), "elf64-aarch64.h", "NN", "64"),
+ runFindReplace(b, upstream.path("bfd/elfxx-ia64.h"), "elf32-ia64.h", "NN", "32"),
+ runFindReplace(b, upstream.path("bfd/elfxx-ia64.h"), "elf64-ia64.h", "NN", "64"),
+ runFindReplace(b, upstream.path("bfd/elfxx-kvx.h"), "elf32-kvx.h", "NN", "32"),
+ runFindReplace(b, upstream.path("bfd/elfxx-kvx.h"), "elf64-kvx.h", "NN", "64"),
+ runFindReplace(b, upstream.path("bfd/elfxx-loongarch.h"), "elf32-loongarch.h", "NN", "32"),
+ runFindReplace(b, upstream.path("bfd/elfxx-loongarch.h"), "elf64-loongarch.h", "NN", "64"),
+ runFindReplace(b, upstream.path("bfd/elfxx-riscv.h"), "elf32-riscv.h", "NN", "32"),
+ runFindReplace(b, upstream.path("bfd/elfxx-riscv.h"), "elf64-riscv.h", "NN", "64"),
};
for (generated_header_files) |header_file| {
@@ -918,12 +930,12 @@ pub fn build(b: *std.Build) void {
}
const generated_sources = std.StaticStringMap(std.Build.LazyPath).init(&[_]struct { []const u8, std.Build.LazyPath }{
- .{ "peigen.c", runFindReplace(b, find_replace_exe, upstream.path("bfd/peXXigen.c"), "peigen.c", "XX", "pe") },
- .{ "pepigen.c", runFindReplace(b, find_replace_exe, upstream.path("bfd/peXXigen.c"), "pepigen.c", "XX", "pep") },
- .{ "pex64igen.c", runFindReplace(b, find_replace_exe, upstream.path("bfd/peXXigen.c"), "pex64igen.c", "XX", "pex64") },
- .{ "pe-aarch64igen.c", runFindReplace(b, find_replace_exe, upstream.path("bfd/peXXigen.c"), "pe-aarch64igen.c", "XX", "peAArch64") },
- .{ "pe-loongarch64igen.c", runFindReplace(b, find_replace_exe, upstream.path("bfd/peXXigen.c"), "pe-loongarch64igen.c", "XX", "peLoongArch64") },
- .{ "pe-riscv64igen.c", runFindReplace(b, find_replace_exe, upstream.path("bfd/peXXigen.c"), "pe-riscv64igen.c", "XX", "peRiscV64") },
+ .{ "peigen.c", runFindReplace(b, upstream.path("bfd/peXXigen.c"), "peigen.c", "XX", "pe") },
+ .{ "pepigen.c", runFindReplace(b, upstream.path("bfd/peXXigen.c"), "pepigen.c", "XX", "pep") },
+ .{ "pex64igen.c", runFindReplace(b, upstream.path("bfd/peXXigen.c"), "pex64igen.c", "XX", "pex64") },
+ .{ "pe-aarch64igen.c", runFindReplace(b, upstream.path("bfd/peXXigen.c"), "pe-aarch64igen.c", "XX", "peAArch64") },
+ .{ "pe-loongarch64igen.c", runFindReplace(b, upstream.path("bfd/peXXigen.c"), "pe-loongarch64igen.c", "XX", "peLoongArch64") },
+ .{ "pe-riscv64igen.c", runFindReplace(b, upstream.path("bfd/peXXigen.c"), "pe-riscv64igen.c", "XX", "peRiscV64") },
}, b.allocator) catch @panic("OOM");
for (std.mem.concat(b.allocator, []const u8, &.{ &.{default_vector}, select_vectors }) catch @panic("OOM")) |target_vector| {
@@ -1050,7 +1062,7 @@ pub fn build(b: *std.Build) void {
var arch_define = select_architecture;
arch_define = std.mem.replaceOwned(u8, b.allocator, arch_define, "bfd_", "") catch @panic("OOM");
arch_define = std.mem.replaceOwned(u8, b.allocator, arch_define, "_arch", "") catch @panic("OOM");
- opcodes_arch_defines.append(b.allocator, b.fmt("-D{s}=1", .{arch_define})) catch @panic("OOM");
+ opcodes_arch_defines.append(b.allocator, b.fmt("-DARCH_{s}", .{arch_define})) catch @panic("OOM");
libopcodes.root_module.addCSourceFiles(.{
.root = upstream.path("opcodes"),
@@ -1062,18 +1074,567 @@ pub fn build(b: *std.Build) void {
.file = upstream.path("opcodes/disassemble.c"),
.flags = opcodes_arch_defines.items,
});
-}
-fn runFindReplace(b: *std.Build, find_replace_exe: *std.Build.Step.Compile, input: std.Build.LazyPath, output_filename: []const u8, needle: []const u8, replacement: []const u8) std.Build.LazyPath {
- const run_find_replace = b.addRunArtifact(find_replace_exe);
+ const binutils_config_header = b.addConfigHeader(.{
+ .style = .{ .autoconf_undef = upstream.path("binutils/config.in") },
+ }, .{
+ .AC_APPLE_UNIVERSAL_BUILD = null,
+ .DEFAULT_AR_DETERMINISTIC = 0,
+ .DEFAULT_FOR_COLORED_DISASSEMBLY = 0,
+ .DEFAULT_FOR_FOLLOW_LINKS = 1,
+ .DEFAULT_F_FOR_IFUNC_SYMBOLS = 0,
+ .DEFAULT_STRINGS_ALL = 1,
+ .ENABLE_CHECKING = null,
+ .ENABLE_LIBCTF = null,
+ .ENABLE_NLS = null,
+ .EXECUTABLE_SUFFIX = "",
+ .HAVE_CFLOCALECOPYPREFERREDLANGUAGES = null,
+ .HAVE_CFPREFERENCESCOPYAPPVALUE = null,
+ .HAVE_DCGETTEXT = null,
+ .HAVE_DECL_ENVIRON = target.result.os.tag != .windows,
+ .HAVE_DECL_GETC_UNLOCKED = true,
+ .HAVE_DECL_GETOPT = true,
+ .HAVE_DECL_STPCPY = true,
+ .HAVE_DECL_STRNLEN = true,
+ .HAVE_DLFCN_H = true,
+ .HAVE_EXECUTABLE_SUFFIX = null,
+ .HAVE_FCNTL_H = true,
+ .HAVE_FSEEKO = true,
+ .HAVE_FSEEKO64 = if (target.result.isGnuLibC()) true else null,
+ .HAVE_GETC_UNLOCKED = true,
+ .HAVE_GETPAGESIZE = true,
+ .HAVE_GETTEXT = null,
+ .HAVE_GOOD_UTIME_H = true,
+ .HAVE_ICONV = null,
+ .HAVE_INTTYPES_H = true,
+ .HAVE_LC_MESSAGES = true,
+ .HAVE_LIBDEBUGINFOD = null,
+ .HAVE_LIBDEBUGINFOD_FIND_SECTION = null,
+ .HAVE_MBSTATE_T = true,
+ .HAVE_MEMORY_H = true,
+ .HAVE_MKDTEMP = true,
+ .HAVE_MKSTEMP = true,
+ .HAVE_MMAP = if (target.result.os.tag == .linux) true else null,
+ .HAVE_MSGPACK = null,
+ .HAVE_STDINT_H = true,
+ .HAVE_STDLIB_H = true,
+ .HAVE_STRINGS_H = true,
+ .HAVE_STRING_H = true,
+ .HAVE_STRUCT_STAT_ST_ATIMENSEC = null,
+ .HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC = null,
+ .HAVE_STRUCT_STAT_ST_ATIM_ST__TIM_TV_NSEC = null,
+ .HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC = if (target.result.os.tag == .linux) true else null,
+ .HAVE_SYS_FILE_H = true,
+ .HAVE_SYS_PARAM_H = true,
+ .HAVE_SYS_STAT_H = true,
+ .HAVE_SYS_TIME_H = true,
+ .HAVE_SYS_TYPES_H = true,
+ .HAVE_SYS_WAIT_H = true,
+ .HAVE_UNISTD_H = true,
+ .HAVE_UTIMENSAT = if (target.result.os.tag == .linux) true else null,
+ .HAVE_UTIMES = true,
+ .HAVE_WINDOWS_H = null,
+ .HAVE_ZSTD = null,
+ .ICONV_CONST = null,
+ .LT_OBJDIR = ".libs/",
+ .PACKAGE = "binutils",
+ .PACKAGE_BUGREPORT = "",
+ .PACKAGE_NAME = "binutils",
+ .PACKAGE_STRING = b.fmt("binutils {f}", .{version}),
+ .PACKAGE_TARNAME = "binutils",
+ .PACKAGE_URL = "",
+ .PACKAGE_VERSION = b.fmt("{f}", .{version}),
+ .STDC_HEADERS = true,
+ .TARGET = gnu_triple,
+ .TARGET_PREPENDS_UNDERSCORE = 0,
+ .TYPEOF_STRUCT_STAT_ST_ATIM_IS_STRUCT_TIMESPEC = if (target.result.os.tag == .linux) true else null,
+ .USE_BINARY_FOPEN = null,
+ .VERSION = b.fmt("{f}", .{version}),
+ .YYTEXT_POINTER = true,
+ ._FILE_OFFSET_BITS = 64,
+ ._LARGE_FILES = null,
+ ._MINIX = null,
+ ._POSIX_1_SOURCE = null,
+ ._POSIX_SOURCE = null,
+ ._ALL_SOURCE = true,
+ ._GNU_SOURCE = true,
+ ._POSIX_PTHREAD_SEMANTICS = true,
+ ._TANDEM_SOURCE = true,
+ .__EXTENSIONS__ = true,
+ .WORDS_BIGENDIAN = if (target.result.cpu.arch.endian() == .big) @as(i64, 1) else null,
+ });
+
+ for (binutils_programs) |program| {
+ const exe = b.addExecutable(.{
+ .name = program[0],
+ .version = version,
+ .root_module = b.createModule(.{
+ .target = target,
+ .optimize = optimize,
+ .strip = strip,
+ .pic = pic,
+ .link_libc = true,
+ }),
+ });
+ b.installArtifact(exe);
+ exe.root_module.addCMacro("HAVE_CONFIG_H", "1");
+ exe.root_module.addConfigHeader(binutils_config_header);
+ exe.root_module.addConfigHeader(bfd_header);
+ exe.root_module.addConfigHeader(bfdver_header);
+ exe.root_module.addIncludePath(upstream.path("binutils"));
+ exe.root_module.addIncludePath(upstream.path("bfd"));
+ exe.root_module.addIncludePath(upstream.path("include"));
+ exe.root_module.linkLibrary(bfd);
+ exe.root_module.linkLibrary(libopcodes);
+ exe.root_module.linkLibrary(iberty);
+ exe.root_module.linkLibrary(libsframe);
+ if (b.systemIntegrationOption("zlib", .{})) {
+ exe.root_module.linkSystemLibrary("z", .{});
+ } else if (b.lazyDependency("zlib", .{
+ .target = target,
+ .optimize = optimize,
+ })) |zlib_dependency| {
+ exe.root_module.linkLibrary(zlib_dependency.artifact("z"));
+ }
+ exe.root_module.addCSourceFiles(.{
+ .root = upstream.path("binutils"),
+ .files = program[1],
+ .flags = &.{
+ "-DOBJDUMP_PRIVATE_VECTORS=",
+ "-Dbin_dummy_emulation=bin_vanilla_emulation",
+ },
+ });
+ }
+
+ const gas_cpu = switch (target.result.cpu.arch) {
+ .x86, .x86_64 => "i386",
+ else => std.debug.panic("TODO gas for '{s}'", .{@tagName(target.result.cpu.arch)}),
+ };
+ const gas_env = switch (target.result.os.tag) {
+ .linux => "linux",
+ else => std.debug.panic("TODO gas for '{s}'", .{@tagName(target.result.os.tag)}),
+ };
+
+ const gas_headers = b.addWriteFiles();
+ _ = gas_headers.add("targ-cpu.h", b.fmt("#include \"tc-{s}.h\"\n", .{gas_cpu}));
+ _ = gas_headers.add("targ-env.h", b.fmt("#include \"te-{s}.h\"\n", .{gas_env}));
+ _ = gas_headers.add("obj-format.h", "#include \"obj-elf.h\"\n");
+
+ const gas_config_header = b.addConfigHeader(.{
+ .style = .{ .autoconf_undef = upstream.path("gas/config.in") },
+ }, .{
+ .AC_APPLE_UNIVERSAL_BUILD = null,
+ .AIX_WEAK_SUPPORT = null,
+ .BROKEN_ASSERT = null,
+ .CROSS_COMPILE = null,
+ .DEFAULT_ARCH = switch (target.result.cpu.arch) {
+ .x86_64 => "x86_64",
+ else => "i386",
+ },
+ .DEFAULT_COMPRESSED_DEBUG_ALGORITHM = .COMPRESS_DEBUG_GABI_ZLIB,
+ .DEFAULT_CRIS_ARCH = null,
+ .DEFAULT_EMULATION = "",
+ .DEFAULT_FLAG_COMPRESS_DEBUG = 1,
+ .DEFAULT_GENERATE_BUILD_NOTES = 0,
+ .DEFAULT_GENERATE_ELF_STT_COMMON = 0,
+ .DEFAULT_GENERATE_X86_RELAX_RELOCATIONS = 1,
+ .DEFAULT_MIPS_FIX_LOONGSON3_LLSC = 0,
+ .DEFAULT_RISCV_ARCH_WITH_EXT = null,
+ .DEFAULT_RISCV_ATTR = 1,
+ .DEFAULT_RISCV_ISA_SPEC = null,
+ .DEFAULT_RISCV_PRIV_SPEC = null,
+ .DEFAULT_X86_TLS_CHECK = 1,
+ .DEFAULT_X86_USED_NOTE = 1,
+ .EMULATIONS = null,
+ .ENABLE_CHECKING = null,
+ .ENABLE_NLS = null,
+ .HAVE_CFLOCALECOPYPREFERREDLANGUAGES = null,
+ .HAVE_CFPREFERENCESCOPYAPPVALUE = null,
+ .HAVE_DCGETTEXT = null,
+ .HAVE_DECL_GETOPT = true,
+ .HAVE_DECL_MEMPCPY = target.result.isGnuLibC(),
+ .HAVE_DECL_STPCPY = true,
+ .HAVE_DLFCN_H = true,
+ .HAVE_GETTEXT = null,
+ .HAVE_ICONV = null,
+ .HAVE_INTTYPES_H = true,
+ .HAVE_LC_MESSAGES = true,
+ .HAVE_MEMORY_H = true,
+ .HAVE_STDINT_H = true,
+ .HAVE_STDLIB_H = true,
+ .HAVE_STRINGS_H = true,
+ .HAVE_STRING_H = true,
+ .HAVE_STRSIGNAL = true,
+ .HAVE_ST_MTIM_TV_NSEC = if (target.result.os.tag == .linux) true else null,
+ .HAVE_ST_MTIM_TV_SEC = if (target.result.os.tag == .linux) true else null,
+ .HAVE_SYS_STAT_H = true,
+ .HAVE_SYS_TYPES_H = true,
+ .HAVE_TM_GMTOFF = true,
+ .HAVE_UNISTD_H = true,
+ .HAVE_WINDOWS_H = null,
+ .HAVE_ZSTD = null,
+ .I386COFF = null,
+ .LT_OBJDIR = ".libs/",
+ .MIPS_CPU_STRING_DEFAULT = null,
+ .MIPS_DEFAULT_64BIT = null,
+ .MIPS_DEFAULT_ABI = null,
+ .NDS32_DEFAULT_ARCH_NAME = null,
+ .NDS32_DEFAULT_AUDIO_EXT = null,
+ .NDS32_DEFAULT_DSP_EXT = null,
+ .NDS32_DEFAULT_DX_REGS = null,
+ .NDS32_DEFAULT_PERF_EXT = null,
+ .NDS32_DEFAULT_PERF_EXT2 = null,
+ .NDS32_DEFAULT_STRING_EXT = null,
+ .NDS32_DEFAULT_ZOL_EXT = null,
+ .NDS32_LINUX_TOOLCHAIN = null,
+ .NEED_DECLARATION_ENVIRON = null,
+ .NEED_DECLARATION_FFS = null,
+ .OBJ_MAYBE_AOUT = null,
+ .OBJ_MAYBE_COFF = null,
+ .OBJ_MAYBE_ECOFF = null,
+ .OBJ_MAYBE_ELF = null,
+ .OBJ_MAYBE_GENERIC = null,
+ .OBJ_MAYBE_SOM = null,
+ .PACKAGE = "gas",
+ .PACKAGE_BUGREPORT = "",
+ .PACKAGE_NAME = "gas",
+ .PACKAGE_STRING = b.fmt("gas {f}", .{version}),
+ .PACKAGE_TARNAME = "gas",
+ .PACKAGE_URL = "",
+ .PACKAGE_VERSION = b.fmt("{f}", .{version}),
+ .STDC_HEADERS = true,
+ .STRICTCOFF = null,
+ .TARGET_ALIAS = gnu_triple,
+ .TARGET_BYTES_BIG_ENDIAN = if (target.result.cpu.arch.endian() == .big) @as(i64, 1) else @as(i64, 0),
+ .TARGET_CANONICAL = gnu_triple,
+ .TARGET_CPU = gnu_cpu,
+ .TARGET_OS = b.fmt("{s}-{s}", .{ @tagName(target.result.os.tag), @tagName(target.result.abi) }),
+ .TARGET_SOLARIS_COMMENT = null,
+ .TARGET_VENDOR = gnu_vendor,
+ .TARGET_WITH_CPU = null,
+ .USE_BINARY_FOPEN = null,
+ .USE_EF_MIPS_ABI_O32 = null,
+ .USE_EMULATIONS = null,
+ .USING_CGEN = null,
+ .VERSION = b.fmt("{f}", .{version}),
+ .YYTEXT_POINTER = true,
+ ._FILE_OFFSET_BITS = 64,
+ ._LARGE_FILES = null,
+ ._MINIX = null,
+ ._POSIX_1_SOURCE = null,
+ ._POSIX_SOURCE = null,
+ ._ALL_SOURCE = true,
+ ._GNU_SOURCE = true,
+ ._POSIX_PTHREAD_SEMANTICS = true,
+ ._TANDEM_SOURCE = true,
+ .__EXTENSIONS__ = true,
+ .WORDS_BIGENDIAN = if (target.result.cpu.arch.endian() == .big) @as(i64, 1) else null,
+ });
+
+ const as = b.addExecutable(.{
+ .name = "as",
+ .version = version,
+ .root_module = b.createModule(.{
+ .target = target,
+ .optimize = optimize,
+ .strip = strip,
+ .pic = pic,
+ .link_libc = true,
+ }),
+ });
+ b.installArtifact(as);
+ as.root_module.addCMacro("HAVE_CONFIG_H", "1");
+ as.root_module.addConfigHeader(gas_config_header);
+ as.root_module.addConfigHeader(bfd_header);
+ as.root_module.addConfigHeader(bfdver_header);
+ as.root_module.addIncludePath(gas_headers.getDirectory());
+ as.root_module.addIncludePath(upstream.path("gas"));
+ as.root_module.addIncludePath(upstream.path("gas/config"));
+ as.root_module.addIncludePath(upstream.path("bfd"));
+ as.root_module.addIncludePath(upstream.path("include"));
+ as.root_module.addIncludePath(upstream.path("."));
+ as.root_module.linkLibrary(bfd);
+ as.root_module.linkLibrary(libopcodes);
+ as.root_module.linkLibrary(iberty);
+ as.root_module.linkLibrary(libsframe);
+ if (b.systemIntegrationOption("zlib", .{})) {
+ as.root_module.linkSystemLibrary("z", .{});
+ } else if (b.lazyDependency("zlib", .{
+ .target = target,
+ .optimize = optimize,
+ })) |zlib_dependency| {
+ as.root_module.linkLibrary(zlib_dependency.artifact("z"));
+ }
+ as.root_module.addCSourceFiles(.{ .root = upstream.path("gas"), .files = gas_sources });
+ as.root_module.addCSourceFiles(.{
+ .root = upstream.path("gas/config"),
+ .files = &.{ b.fmt("tc-{s}.c", .{gas_cpu}), "obj-elf.c", "atof-ieee.c" },
+ });
+
+ const ld_emulations = switch (target.result.cpu.arch) {
+ .x86_64 => "elf_x86_64 elf_i386",
+ .x86 => "elf_i386",
+ else => std.debug.panic("TODO ld for '{s}'", .{@tagName(target.result.cpu.arch)}),
+ };
+
+ const genscripts_exe = b.addExecutable(.{
+ .name = "genscripts",
+ .root_module = b.createModule(.{
+ .root_source_file = b.path("genscripts.zig"),
+ .target = b.graph.host,
+ .optimize = .ReleaseFast,
+ }),
+ });
+
+ const run_genscripts = b.addRunArtifact(genscripts_exe);
+ const emulations = run_genscripts.addOutputDirectoryArg("ld");
+ run_genscripts.addDirectoryArg(upstream.path("ld"));
+ run_genscripts.addArgs(&.{ ld_emulations, gnu_triple });
+
+ var declarations: std.ArrayListUnmanaged(u8) = .empty;
+ var list: std.ArrayListUnmanaged(u8) = .empty;
+ var names = std.mem.tokenizeScalar(u8, ld_emulations, ' ');
+ while (names.next()) |name| {
+ declarations.appendSlice(b.allocator, b.fmt(
+ "extern ld_emulation_xfer_type ld_{s}_emulation;\n",
+ .{name},
+ )) catch @panic("OOM");
+ list.appendSlice(b.allocator, b.fmt(" &ld_{s}_emulation, \\\n", .{name})) catch @panic("OOM");
+ }
+
+ const ld_headers = b.addWriteFiles();
+ _ = ld_headers.add("ldemul-list.h", b.fmt(
+ "/* This file is automatically generated. DO NOT EDIT! */\n{s}\n#define EMULATION_LIST \\\n{s} 0\n",
+ .{ declarations.items, list.items },
+ ));
+
+ const ld_config_header = b.addConfigHeader(.{
+ .style = .{ .autoconf_undef = upstream.path("ld/config.in") },
+ }, .{
+ .DEFAULT_COMPRESSED_DEBUG_ALGORITHM = .COMPRESS_DEBUG_GABI_ZLIB,
+ .DEFAULT_EMIT_GNU_HASH = 1,
+ .DEFAULT_EMIT_SYSV_HASH = 1,
+ .DEFAULT_FLAG_COMPRESS_DEBUG = 0,
+ .DEFAULT_LD_ERROR_EXECSTACK = 0,
+ .DEFAULT_LD_ERROR_RWX_SEGMENTS = 0,
+ .DEFAULT_LD_EXECSTACK = 1,
+ .DEFAULT_LD_ROSEGMENT = 0,
+ .DEFAULT_LD_TEXTREL_CHECK = .textrel_check_warning,
+ .DEFAULT_LD_TEXTREL_CHECK_WARNING = 1,
+ .DEFAULT_LD_WARN_EXECSTACK = 2,
+ .DEFAULT_LD_WARN_RWX_SEGMENTS = 1,
+ .DEFAULT_LD_Z_MARK_PLT = 0,
+ .DEFAULT_LD_Z_MEMORY_SEAL = 0,
+ .DEFAULT_LD_Z_RELRO = 1,
+ .DEFAULT_LD_Z_SEPARATE_CODE = if (target.result.os.tag == .linux) @as(i64, 1) else @as(i64, 0),
+ .DEFAULT_NEW_DTAGS = 0,
+ .ENABLE_CHECKING = null,
+ .ENABLE_LIBCTF = null,
+ .ENABLE_NLS = null,
+ .EXTRA_SHLIB_EXTENSION = null,
+ .GOT_HANDLING_DEFAULT = .GOT_HANDLING_TARGET_DEFAULT,
+ .HAVE_CFLOCALECOPYPREFERREDLANGUAGES = null,
+ .HAVE_CFPREFERENCESCOPYAPPVALUE = null,
+ .HAVE_CLOSE = true,
+ .HAVE_DCGETTEXT = null,
+ .HAVE_DECL_ENVIRON = target.result.os.tag != .windows,
+ .HAVE_DECL_GETOPT = true,
+ .HAVE_DECL_STPCPY = true,
+ .HAVE_DLFCN_H = true,
+ .HAVE_ELF_HINTS_H = null,
+ .HAVE_FCNTL_H = true,
+ .HAVE_GETPAGESIZE = true,
+ .HAVE_GETRUSAGE = true,
+ .HAVE_GETTEXT = null,
+ .HAVE_GLOB = true,
+ .HAVE_ICONV = null,
+ .HAVE_INITFINI_ARRAY = true,
+ .HAVE_INTTYPES_H = true,
+ .HAVE_JANSSON = null,
+ .HAVE_LC_MESSAGES = true,
+ .HAVE_LIMITS_H = true,
+ .HAVE_LSEEK = true,
+ .HAVE_MEMORY_H = true,
+ .HAVE_MKSTEMP = true,
+ .HAVE_MMAP = if (target.result.os.tag == .linux) true else null,
+ .HAVE_OPEN = true,
+ .HAVE_REALPATH = true,
+ .HAVE_STDINT_H = true,
+ .HAVE_STDLIB_H = true,
+ .HAVE_STRINGS_H = true,
+ .HAVE_STRING_H = true,
+ .HAVE_SYS_FILE_H = true,
+ .HAVE_SYS_MMAN_H = true,
+ .HAVE_SYS_PARAM_H = true,
+ .HAVE_SYS_STAT_H = true,
+ .HAVE_SYS_TIME_H = true,
+ .HAVE_SYS_TYPES_H = true,
+ .HAVE_UNISTD_H = true,
+ .HAVE_WAITPID = true,
+ .HAVE_WINDOWS_H = null,
+ .HAVE_ZSTD = null,
+ .LT_OBJDIR = ".libs/",
+ .PACKAGE = "ld",
+ .PACKAGE_BUGREPORT = "",
+ .PACKAGE_NAME = "ld",
+ .PACKAGE_STRING = b.fmt("ld {f}", .{version}),
+ .PACKAGE_TARNAME = "ld",
+ .PACKAGE_URL = "",
+ .PACKAGE_VERSION = b.fmt("{f}", .{version}),
+ .STDC_HEADERS = true,
+ .SUPPORT_ERROR_HANDLING_SCRIPT = true,
+ .USE_BINARY_FOPEN = null,
+ .VERSION = b.fmt("{f}", .{version}),
+ .WITH_XXHASH = null,
+ .YYTEXT_POINTER = true,
+ ._FILE_OFFSET_BITS = 64,
+ ._LARGE_FILES = null,
+ ._MINIX = null,
+ ._POSIX_1_SOURCE = null,
+ ._POSIX_SOURCE = null,
+ ._ALL_SOURCE = true,
+ ._GNU_SOURCE = true,
+ ._POSIX_PTHREAD_SEMANTICS = true,
+ ._TANDEM_SOURCE = true,
+ .__EXTENSIONS__ = true,
+ });
+
+ const ld = b.addExecutable(.{
+ .name = "ld",
+ .version = version,
+ .root_module = b.createModule(.{
+ .target = target,
+ .optimize = optimize,
+ .strip = strip,
+ .pic = pic,
+ .link_libc = true,
+ }),
+ });
+ b.installArtifact(ld);
+ ld.root_module.addCMacro("HAVE_CONFIG_H", "1");
+ ld.root_module.addConfigHeader(ld_config_header);
+ ld.root_module.addConfigHeader(bfd_header);
+ ld.root_module.addConfigHeader(bfdver_header);
+ ld.root_module.addIncludePath(ld_headers.getDirectory());
+ ld.root_module.addIncludePath(emulations);
+ ld.root_module.addIncludePath(upstream.path("ld"));
+ ld.root_module.addIncludePath(upstream.path("bfd"));
+ ld.root_module.addIncludePath(upstream.path("include"));
+ ld.root_module.addIncludePath(upstream.path("."));
+ ld.root_module.linkLibrary(bfd);
+ ld.root_module.linkLibrary(iberty);
+ ld.root_module.linkLibrary(libsframe);
+ if (b.systemIntegrationOption("zlib", .{})) {
+ ld.root_module.linkSystemLibrary("z", .{});
+ } else if (b.lazyDependency("zlib", .{
+ .target = target,
+ .optimize = optimize,
+ })) |zlib_dependency| {
+ ld.root_module.linkLibrary(zlib_dependency.artifact("z"));
+ }
+ ld.root_module.addCSourceFiles(.{
+ .root = upstream.path("ld"),
+ .files = ld_sources,
+ .flags = &.{
+ b.fmt("-DDEFAULT_EMULATION=\"{s}\"", .{std.mem.sliceTo(ld_emulations, ' ')}),
+ b.fmt("-DTARGET=\"{s}\"", .{gnu_triple}),
+ "-DBINDIR=\"/usr/bin\"",
+ "-DTOOLBINDIR=\"/usr/bin\"",
+ "-DSCRIPTDIR=\"/usr/lib\"",
+ "-DELF_LIST_OPTIONS=true",
+ "-DELF_SHLIB_LIST_OPTIONS=true",
+ "-DELF_PLT_UNWIND_LIST_OPTIONS=true",
+ },
+ });
+ names.reset();
+ while (names.next()) |name| {
+ ld.root_module.addCSourceFile(.{
+ .file = emulations.path(b, b.fmt("e{s}.c", .{name})),
+ });
+ }
+}
- run_find_replace.addFileArg(input);
- const output = run_find_replace.addOutputFileArg(output_filename);
- run_find_replace.addArg(needle);
- run_find_replace.addArg(replacement);
- return output;
+// The substitution bfd's own Makefile makes: sed -e s/NN/32/g < elfxx-target.h
+fn runFindReplace(b: *std.Build, input: std.Build.LazyPath, output_filename: []const u8, needle: []const u8, replacement: []const u8) std.Build.LazyPath {
+ const sed = b.addSystemCommand(&.{ "sed", "-e", b.fmt("s/{s}/{s}/g", .{ needle, replacement }) });
+ sed.addFileArg(input);
+ return sed.captureStdOut(.{ .basename = output_filename });
}
+const ld_sources: []const []const u8 = &.{
+ "ldgram.c",
+ "ldlex-wrapper.c",
+ "lexsup.c",
+ "ldlang.c",
+ "mri.c",
+ "ldctor.c",
+ "ldmain.c",
+ "ldwrite.c",
+ "ldexp.c",
+ "ldemul.c",
+ "ldver.c",
+ "ldmisc.c",
+ "ldfile.c",
+ "ldcref.c",
+ "plugin.c",
+ "ldbuildid.c",
+ "ldelf.c",
+ "ldelfgen.c",
+};
+
+const gas_sources: []const []const u8 = &.{
+ "app.c",
+ "as.c",
+ "atof-generic.c",
+ "codeview.c",
+ "compress-debug.c",
+ "cond.c",
+ "depend.c",
+ "dwarf2dbg.c",
+ "dw2gencfi.c",
+ "ecoff.c",
+ "ehopt.c",
+ "expr.c",
+ "flonum-copy.c",
+ "flonum-konst.c",
+ "flonum-mult.c",
+ "frags.c",
+ "gen-sframe.c",
+ "ginsn.c",
+ "hash.c",
+ "input-file.c",
+ "input-scrub.c",
+ "listing.c",
+ "literal.c",
+ "macro.c",
+ "messages.c",
+ "output-file.c",
+ "read.c",
+ "remap.c",
+ "sb.c",
+ "scfidw2gen.c",
+ "scfi.c",
+ "sframe-opt.c",
+ "stabs.c",
+ "subsegs.c",
+ "symbols.c",
+ "write.c",
+};
+
+const bulibs = [_][]const u8{ "bucomm.c", "version.c", "filemode.c" };
+const elflibs = [_][]const u8{"elfcomm.c"};
+const debug_sources = [_][]const u8{ "rddbg.c", "debug.c", "stabs.c", "rdcoff.c" };
+const write_debug_sources = debug_sources ++ [_][]const u8{"wrstabs.c"};
+
+const binutils_programs: []const struct { []const u8, []const []const u8 } = &.{
+ .{ "ar", &([_][]const u8{ "arparse.c", "arlex.c", "not-ranlib.c", "arsup.c", "rename.c", "binemul.c", "emul_vanilla.c" } ++ bulibs) },
+ .{ "nm", &([_][]const u8{ "nm.c", "demanguse.c" } ++ bulibs) },
+ .{ "objcopy", &([_][]const u8{ "not-strip.c", "rename.c" } ++ write_debug_sources ++ bulibs) },
+ .{ "strip", &([_][]const u8{ "is-strip.c", "rename.c" } ++ write_debug_sources ++ bulibs) },
+ .{ "objdump", &([_][]const u8{ "objdump.c", "dwarf.c", "prdbg.c", "demanguse.c" } ++ debug_sources ++ bulibs ++ elflibs) },
+ .{ "readelf", &([_][]const u8{ "readelf.c", "version.c", "unwind-ia64.c", "dwarf.c", "demanguse.c" } ++ elflibs) },
+};
+
const elf_sources: []const []const u8 = &.{
"elf.c",
"elflink.c",
diff --git a/build.zig.zon b/build.zig.zon
index 7b46058..8ec5425 100644
--- a/build.zig.zon
+++ b/build.zig.zon
@@ -28,6 +28,7 @@
"README.md",
"include/targmatch.h",
"find_replace.zig",
+ "genscripts.zig",
},
.fingerprint = 0x4911b3458854c64a, // Changing this has security and trust implications.
}
diff --git a/find_replace.zig b/find_replace.zig
deleted file mode 100644
index 42c3fd7..0000000
--- a/find_replace.zig
+++ /dev/null
@@ -1,31 +0,0 @@
-//! This is used as a replacement for `sed`
-
-const std = @import("std");
-
-pub fn main(init: std.process.Init) !void {
- const gpa = init.gpa;
- const io = init.io;
- const cwd = std.Io.Dir.cwd();
- const args = try init.minimal.args.toSlice(init.arena.allocator());
-
- if (args.len != 5) {
- std.debug.print("usage: {s} \n", .{args[0]});
- std.process.exit(1);
- }
-
- const input_filename = args[1];
- const output_filename = args[2];
- const before = args[3];
- const after = args[4];
-
- const input = try cwd.readFileAlloc(io, input_filename, gpa, .limited(std.math.maxInt(u32)));
- defer gpa.free(input);
-
- const output = try std.mem.replaceOwned(u8, gpa, input, before, after);
- defer gpa.free(output);
-
- try cwd.writeFile(io, .{
- .sub_path = output_filename,
- .data = output,
- });
-}
diff --git a/genscripts.zig b/genscripts.zig
new file mode 100644
index 0000000..d3121af
--- /dev/null
+++ b/genscripts.zig
@@ -0,0 +1,51 @@
+//! Runs upstream's genscripts.sh, which writes into the current directory
+
+const std = @import("std");
+
+pub fn main(init: std.process.Init) !void {
+ const io = init.io;
+ const arena = init.arena.allocator();
+ const args = try init.minimal.args.toSlice(arena);
+
+ if (args.len != 5) {
+ std.debug.print("usage: {s} \n", .{args[0]});
+ std.process.exit(1);
+ }
+
+ const out = args[1];
+ const source = try std.Io.Dir.cwd().realPathFileAlloc(io, args[2], arena);
+ const emulations = args[3];
+ const triple = args[4];
+
+ try std.Io.Dir.cwd().createDirPath(io, try std.fmt.allocPrint(arena, "{s}/ldscripts", .{out}));
+
+ var it = std.mem.tokenizeScalar(u8, emulations, ' ');
+ while (it.next()) |emulation| {
+ var child = try std.process.spawn(io, .{
+ .cwd = .{ .path = out },
+ .argv = &.{
+ "sh",
+ try std.fmt.allocPrint(arena, "{s}/genscripts.sh", .{source}),
+ source,
+ "/usr/lib",
+ "/usr",
+ "/usr",
+ triple,
+ triple,
+ triple,
+ "",
+ "",
+ emulations,
+ "",
+ "no",
+ "yes",
+ emulation,
+ triple,
+ },
+ });
+ switch (try child.wait(io)) {
+ .exited => |code| if (code != 0) return error.GenscriptsFailed,
+ else => return error.GenscriptsFailed,
+ }
+ }
+}