diff --git a/lib/std/build.zig b/lib/std/build.zig index 66660fc74c..54e5ea1c47 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -21,6 +21,7 @@ pub const TranslateCStep = @import("build/translate_c.zig").TranslateCStep; pub const WriteFileStep = @import("build/write_file.zig").WriteFileStep; pub const RunStep = @import("build/run.zig").RunStep; pub const CheckFileStep = @import("build/check_file.zig").CheckFileStep; +pub const InstallRawStep = @import("build/emit_raw.zig").InstallRawStep; pub const Builder = struct { install_tls: TopLevelStep, @@ -824,6 +825,10 @@ pub const Builder = struct { self.getInstallStep().dependOn(&self.addInstallFileWithDir(src_path, .Lib, dest_rel_path).step); } + pub fn installRaw(self: *Builder, artifact: *LibExeObjStep, dest_filename: []const u8) void { + self.getInstallStep().dependOn(&self.addInstallRaw(artifact, dest_filename).step); + } + ///`dest_rel_path` is relative to install prefix path pub fn addInstallFile(self: *Builder, src_path: []const u8, dest_rel_path: []const u8) *InstallFileStep { return self.addInstallFileWithDir(src_path, .Prefix, dest_rel_path); @@ -839,6 +844,10 @@ pub const Builder = struct { return self.addInstallFileWithDir(src_path, .Lib, dest_rel_path); } + pub fn addInstallRaw(self: *Builder, artifact: *LibExeObjStep, dest_filename: []const u8) *InstallRawStep { + return InstallRawStep.create(self, artifact, dest_filename); + } + pub fn addInstallFileWithDir( self: *Builder, src_path: []const u8, @@ -1407,6 +1416,10 @@ pub const LibExeObjStep = struct { self.builder.installArtifact(self); } + pub fn installRaw(self: *LibExeObjStep, dest_filename: [] const u8) void { + self.builder.installRaw(self, dest_filename); + } + /// Creates a `RunStep` with an executable built with `addExecutable`. /// Add command line arguments with `addArg`. pub fn run(exe: *LibExeObjStep) *RunStep { diff --git a/lib/std/build/emit_raw.zig b/lib/std/build/emit_raw.zig new file mode 100644 index 0000000000..54ceae3263 --- /dev/null +++ b/lib/std/build/emit_raw.zig @@ -0,0 +1,255 @@ +const std = @import("std"); + +const Allocator = std.mem.Allocator; +const ArenaAllocator = std.heap.ArenaAllocator; +const ArrayList = std.ArrayList; +const Builder = std.build.Builder; +const File = std.fs.File; +const InstallDir = std.build.InstallDir; +const LibExeObjStep = std.build.LibExeObjStep; +const Step = std.build.Step; +const elf = std.elf; +const fs = std.fs; +const io = std.io; +const sort = std.sort; +const warn = std.debug.warn; + +const BinOutStream = io.OutStream(anyerror); +const BinSeekStream = io.SeekableStream(anyerror, anyerror); +const ElfSeekStream = io.SeekableStream(anyerror, anyerror); +const ElfInStream = io.InStream(anyerror); + +const BinaryElfSection = struct { + elfOffset: u64, + binaryOffset: u64, + fileSize: usize, + segment: ?*BinaryElfSegment, +}; + +const BinaryElfSegment = struct { + physicalAddress: u64, + virtualAddress: u64, + elfOffset: u64, + binaryOffset: u64, + fileSize: usize, + firstSection: ?*BinaryElfSection, +}; + +const BinaryElfOutput = struct { + segments: ArrayList(*BinaryElfSegment), + sections: ArrayList(*BinaryElfSection), + + const Self = @This(); + + pub fn init(allocator: *Allocator) Self { + return Self{ + .segments = ArrayList(*BinaryElfSegment).init(allocator), + .sections = ArrayList(*BinaryElfSection).init(allocator), + }; + } + + pub fn deinit(self: *Self) void { + self.sections.deinit(); + self.segments.deinit(); + } + + pub fn parseElf(self: *Self, elfFile: elf.Elf) !void { + const allocator = self.segments.allocator; + + for (elfFile.section_headers) |section, i| { + if (sectionValidForOutput(section)) { + const newSection = try allocator.create(BinaryElfSection); + + newSection.binaryOffset = 0; + newSection.elfOffset = section.sh_offset; + newSection.fileSize = @intCast(usize, section.sh_size); + newSection.segment = null; + + try self.sections.append(newSection); + } + } + + for (elfFile.program_headers) |programHeader, i| { + if (programHeader.p_type == elf.PT_LOAD) { + const newSegment = try allocator.create(BinaryElfSegment); + + newSegment.physicalAddress = if (programHeader.p_paddr != 0) programHeader.p_paddr else programHeader.p_vaddr; + newSegment.virtualAddress = programHeader.p_vaddr; + newSegment.fileSize = @intCast(usize, programHeader.p_filesz); + newSegment.elfOffset = programHeader.p_offset; + newSegment.binaryOffset = 0; + newSegment.firstSection = null; + + for (self.sections.toSlice()) |section| { + if (sectionWithinSegment(section, programHeader)) { + if (section.segment) |sectionSegment| { + if (sectionSegment.elfOffset > newSegment.elfOffset) { + section.segment = newSegment; + } + } else { + section.segment = newSegment; + } + + if (newSegment.firstSection == null) { + newSegment.firstSection = section; + } + } + } + + try self.segments.append(newSegment); + } + } + + sort.sort(*BinaryElfSegment, self.segments.toSlice(), segmentSortCompare); + + if (self.segments.len > 0) { + const firstSegment = self.segments.at(0); + if (firstSegment.firstSection) |firstSection| { + const diff = firstSection.elfOffset - firstSegment.elfOffset; + + firstSegment.elfOffset += diff; + firstSegment.fileSize += diff; + firstSegment.physicalAddress += diff; + + const basePhysicalAddress = firstSegment.physicalAddress; + + for (self.segments.toSlice()) |segment| { + segment.binaryOffset = segment.physicalAddress - basePhysicalAddress; + } + } + } + + for (self.sections.toSlice()) |section| { + if (section.segment) |segment| { + section.binaryOffset = segment.binaryOffset + (section.elfOffset - segment.elfOffset); + } + } + + sort.sort(*BinaryElfSection, self.sections.toSlice(), sectionSortCompare); + } + + fn sectionWithinSegment(section: *BinaryElfSection, segment: elf.ProgramHeader) bool { + return segment.p_offset <= section.elfOffset and (segment.p_offset + segment.p_filesz) >= (section.elfOffset + section.fileSize); + } + + fn sectionValidForOutput(section: elf.SectionHeader) bool { + return section.sh_size > 0 and section.sh_type != elf.SHT_NOBITS and ((section.sh_flags & elf.SHF_ALLOC) == elf.SHF_ALLOC); + } + + fn segmentSortCompare(left: *BinaryElfSegment, right: *BinaryElfSegment) bool { + if (left.physicalAddress < right.physicalAddress) { + return true; + } + if (left.physicalAddress > right.physicalAddress) { + return false; + } + return false; + } + + fn sectionSortCompare(left: *BinaryElfSection, right: *BinaryElfSection) bool { + return left.binaryOffset < right.binaryOffset; + } +}; + +const WriteContext = struct { + inStream: *ElfInStream, + inSeekStream: *ElfSeekStream, + outStream: *BinOutStream, + outSeekStream: *BinSeekStream, +}; + +fn writeBinaryElfSection(allocator: *Allocator, context: WriteContext, section: *BinaryElfSection) !void { + var readBuffer = try allocator.alloc(u8, section.fileSize); + defer allocator.free(readBuffer); + + try context.inSeekStream.seekTo(section.elfOffset); + _ = try context.inStream.read(readBuffer); + + try context.outSeekStream.seekTo(section.binaryOffset); + try context.outStream.write(readBuffer); +} + +fn emit_raw(allocator: *Allocator, elf_path: []const u8, raw_path: []const u8) !void { + var arenaAlloc = ArenaAllocator.init(allocator); + errdefer arenaAlloc.deinit(); + var arena_allocator = &arenaAlloc.allocator; + + const currentDir = fs.cwd(); + + var file = try currentDir.openFile(elf_path, File.OpenFlags{}); + defer file.close(); + + var fileInStream = file.inStream(); + var fileSeekStream = file.seekableStream(); + + var elfFile = try elf.Elf.openStream(allocator, @ptrCast(*ElfSeekStream, &fileSeekStream.stream), @ptrCast(*ElfInStream, &fileInStream.stream)); + defer elfFile.close(); + + var outFile = try currentDir.createFile(raw_path, File.CreateFlags{}); + defer outFile.close(); + + var outFileOutStream = outFile.outStream(); + var outFileSeekStream = outFile.seekableStream(); + + const writeContext = WriteContext{ + .inStream = @ptrCast(*ElfInStream, &fileInStream.stream), + .inSeekStream = @ptrCast(*ElfSeekStream, &fileSeekStream.stream), + .outStream = @ptrCast(*BinOutStream, &outFileOutStream.stream), + .outSeekStream = @ptrCast(*BinSeekStream, &outFileSeekStream.stream), + }; + + var binaryElfOutput = BinaryElfOutput.init(arena_allocator); + defer binaryElfOutput.deinit(); + + try binaryElfOutput.parseElf(elfFile); + + for (binaryElfOutput.sections.toSlice()) |section| { + try writeBinaryElfSection(allocator, writeContext, section); + } +} + +pub const InstallRawStep = struct { + step: Step, + builder: *Builder, + artifact: *LibExeObjStep, + dest_dir: InstallDir, + dest_filename: [] const u8, + + const Self = @This(); + + pub fn create(builder: *Builder, artifact: *LibExeObjStep, dest_filename: [] const u8) *Self { + const self = builder.allocator.create(Self) catch unreachable; + self.* = Self{ + .step = Step.init(builder.fmt("install raw binary {}", .{artifact.step.name}), builder.allocator, make), + .builder = builder, + .artifact = artifact, + .dest_dir = switch (artifact.kind) { + .Obj => unreachable, + .Test => unreachable, + .Exe => .Bin, + .Lib => unreachable, + }, + .dest_filename = dest_filename, + }; + self.step.dependOn(&artifact.step); + + builder.pushInstalledFile(self.dest_dir, dest_filename); + return self; + } + + fn make(step: *Step) !void { + const self = @fieldParentPtr(Self, "step", step); + const builder = self.builder; + + if (self.artifact.target.getObjectFormat() != .elf) { + warn("InstallRawStep only works with ELF format.\n", .{}); + return error.InvalidObjectFormat; + } + + const full_src_path = self.artifact.getOutputPath(); + const full_dest_path = builder.getInstallPath(self.dest_dir, self.dest_filename); + + fs.makePath(builder.allocator, builder.getInstallPath(self.dest_dir, "")) catch unreachable; + try emit_raw(builder.allocator, full_src_path, full_dest_path); + } +}; \ No newline at end of file diff --git a/lib/std/debug.zig b/lib/std/debug.zig index 3af2a5c417..a87dbe292d 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -946,8 +946,8 @@ fn readSparseBitVector(stream: var, allocator: *mem.Allocator) ![]usize { fn findDwarfSectionFromElf(elf_file: *elf.Elf, name: []const u8) !?DwarfInfo.Section { const elf_header = (try elf_file.findSection(name)) orelse return null; return DwarfInfo.Section{ - .offset = elf_header.offset, - .size = elf_header.size, + .offset = elf_header.sh_offset, + .size = elf_header.sh_size, }; } @@ -987,12 +987,12 @@ pub fn openElfDebugInfo( var di = DwarfInfo{ .endian = efile.endian, - .debug_info = (data[@intCast(usize, debug_info.offset)..@intCast(usize, debug_info.offset + debug_info.size)]), - .debug_abbrev = (data[@intCast(usize, debug_abbrev.offset)..@intCast(usize, debug_abbrev.offset + debug_abbrev.size)]), - .debug_str = (data[@intCast(usize, debug_str.offset)..@intCast(usize, debug_str.offset + debug_str.size)]), - .debug_line = (data[@intCast(usize, debug_line.offset)..@intCast(usize, debug_line.offset + debug_line.size)]), + .debug_info = (data[@intCast(usize, debug_info.sh_offset)..@intCast(usize, debug_info.sh_offset + debug_info.sh_size)]), + .debug_abbrev = (data[@intCast(usize, debug_abbrev.sh_offset)..@intCast(usize, debug_abbrev.sh_offset + debug_abbrev.sh_size)]), + .debug_str = (data[@intCast(usize, debug_str.sh_offset)..@intCast(usize, debug_str.sh_offset + debug_str.sh_size)]), + .debug_line = (data[@intCast(usize, debug_line.sh_offset)..@intCast(usize, debug_line.sh_offset + debug_line.sh_size)]), .debug_ranges = if (opt_debug_ranges) |debug_ranges| - data[@intCast(usize, debug_ranges.offset)..@intCast(usize, debug_ranges.offset + debug_ranges.size)] + data[@intCast(usize, debug_ranges.sh_offset)..@intCast(usize, debug_ranges.sh_offset + debug_ranges.sh_size)] else null, }; diff --git a/lib/std/elf.zig b/lib/std/elf.zig index dc1638c5cb..9e4c1ac5f6 100644 --- a/lib/std/elf.zig +++ b/lib/std/elf.zig @@ -330,19 +330,8 @@ pub const ET = extern enum(u16) { pub const HIPROC = 0xffff; }; -/// TODO delete this in favor of Elf64_Shdr -pub const SectionHeader = struct { - name: u32, - sh_type: u32, - flags: u64, - addr: u64, - offset: u64, - size: u64, - link: u32, - info: u32, - addr_align: u64, - ent_size: u64, -}; +pub const SectionHeader = Elf64_Shdr; +pub const ProgramHeader = Elf64_Phdr; pub const Elf = struct { seekable_stream: *io.SeekableStream(anyerror, anyerror), @@ -357,6 +346,7 @@ pub const Elf = struct { string_section_index: usize, string_section: *SectionHeader, section_headers: []SectionHeader, + program_headers: []ProgramHeader, allocator: *mem.Allocator, /// Call close when done. @@ -421,14 +411,24 @@ pub const Elf = struct { try seekable_stream.seekBy(4); const header_size = try in.readInt(u16, elf.endian); - if ((elf.is_64 and header_size != 64) or (!elf.is_64 and header_size != 52)) { + if ((elf.is_64 and header_size != @sizeOf(Elf64_Ehdr)) or (!elf.is_64 and header_size != @sizeOf(Elf32_Ehdr))) { return error.InvalidFormat; } const ph_entry_size = try in.readInt(u16, elf.endian); const ph_entry_count = try in.readInt(u16, elf.endian); + + if ((elf.is_64 and ph_entry_size != @sizeOf(Elf64_Phdr)) or (!elf.is_64 and ph_entry_size != @sizeOf(Elf32_Phdr))) { + return error.InvalidFormat; + } + const sh_entry_size = try in.readInt(u16, elf.endian); const sh_entry_count = try in.readInt(u16, elf.endian); + + if ((elf.is_64 and sh_entry_size != @sizeOf(Elf64_Shdr)) or (!elf.is_64 and sh_entry_size != @sizeOf(Elf32_Shdr))) { + return error.InvalidFormat; + } + elf.string_section_index = @as(usize, try in.readInt(u16, elf.endian)); if (elf.string_section_index >= sh_entry_count) return error.InvalidFormat; @@ -443,47 +443,72 @@ pub const Elf = struct { return error.InvalidFormat; } + try seekable_stream.seekTo(elf.program_header_offset); + + elf.program_headers = try elf.allocator.alloc(ProgramHeader, ph_entry_count); + errdefer elf.allocator.free(elf.program_headers); + + if (elf.is_64) { + for (elf.program_headers) |*elf_program| { + elf_program.p_type = try in.readInt(Elf64_Word, elf.endian); + elf_program.p_flags = try in.readInt(Elf64_Word, elf.endian); + elf_program.p_offset = try in.readInt(Elf64_Off, elf.endian); + elf_program.p_vaddr = try in.readInt(Elf64_Addr, elf.endian); + elf_program.p_paddr = try in.readInt(Elf64_Addr, elf.endian); + elf_program.p_filesz = try in.readInt(Elf64_Xword, elf.endian); + elf_program.p_memsz = try in.readInt(Elf64_Xword, elf.endian); + elf_program.p_align = try in.readInt(Elf64_Xword, elf.endian); + } + } else { + for (elf.program_headers) |*elf_program| { + elf_program.p_type = @as(Elf64_Word, try in.readInt(Elf32_Word, elf.endian)); + elf_program.p_offset = @as(Elf64_Off, try in.readInt(Elf32_Off, elf.endian)); + elf_program.p_vaddr = @as(Elf64_Addr, try in.readInt(Elf32_Addr, elf.endian)); + elf_program.p_paddr = @as(Elf64_Addr, try in.readInt(Elf32_Addr, elf.endian)); + elf_program.p_filesz = @as(Elf64_Word, try in.readInt(Elf32_Word, elf.endian)); + elf_program.p_memsz = @as(Elf64_Word, try in.readInt(Elf32_Word, elf.endian)); + elf_program.p_flags = @as(Elf64_Word, try in.readInt(Elf32_Word, elf.endian)); + elf_program.p_align = @as(Elf64_Word, try in.readInt(Elf32_Word, elf.endian)); + } + } + try seekable_stream.seekTo(elf.section_header_offset); elf.section_headers = try elf.allocator.alloc(SectionHeader, sh_entry_count); errdefer elf.allocator.free(elf.section_headers); if (elf.is_64) { - if (sh_entry_size != 64) return error.InvalidFormat; - for (elf.section_headers) |*elf_section| { - elf_section.name = try in.readInt(u32, elf.endian); + elf_section.sh_name = try in.readInt(u32, elf.endian); elf_section.sh_type = try in.readInt(u32, elf.endian); - elf_section.flags = try in.readInt(u64, elf.endian); - elf_section.addr = try in.readInt(u64, elf.endian); - elf_section.offset = try in.readInt(u64, elf.endian); - elf_section.size = try in.readInt(u64, elf.endian); - elf_section.link = try in.readInt(u32, elf.endian); - elf_section.info = try in.readInt(u32, elf.endian); - elf_section.addr_align = try in.readInt(u64, elf.endian); - elf_section.ent_size = try in.readInt(u64, elf.endian); + elf_section.sh_flags = try in.readInt(u64, elf.endian); + elf_section.sh_addr = try in.readInt(u64, elf.endian); + elf_section.sh_offset = try in.readInt(u64, elf.endian); + elf_section.sh_size = try in.readInt(u64, elf.endian); + elf_section.sh_link = try in.readInt(u32, elf.endian); + elf_section.sh_info = try in.readInt(u32, elf.endian); + elf_section.sh_addralign = try in.readInt(u64, elf.endian); + elf_section.sh_entsize = try in.readInt(u64, elf.endian); } } else { - if (sh_entry_size != 40) return error.InvalidFormat; - for (elf.section_headers) |*elf_section| { // TODO (multiple occurrences) allow implicit cast from %u32 -> %u64 ? - elf_section.name = try in.readInt(u32, elf.endian); + elf_section.sh_name = try in.readInt(u32, elf.endian); elf_section.sh_type = try in.readInt(u32, elf.endian); - elf_section.flags = @as(u64, try in.readInt(u32, elf.endian)); - elf_section.addr = @as(u64, try in.readInt(u32, elf.endian)); - elf_section.offset = @as(u64, try in.readInt(u32, elf.endian)); - elf_section.size = @as(u64, try in.readInt(u32, elf.endian)); - elf_section.link = try in.readInt(u32, elf.endian); - elf_section.info = try in.readInt(u32, elf.endian); - elf_section.addr_align = @as(u64, try in.readInt(u32, elf.endian)); - elf_section.ent_size = @as(u64, try in.readInt(u32, elf.endian)); + elf_section.sh_flags = @as(u64, try in.readInt(u32, elf.endian)); + elf_section.sh_addr = @as(u64, try in.readInt(u32, elf.endian)); + elf_section.sh_offset = @as(u64, try in.readInt(u32, elf.endian)); + elf_section.sh_size = @as(u64, try in.readInt(u32, elf.endian)); + elf_section.sh_link = try in.readInt(u32, elf.endian); + elf_section.sh_info = try in.readInt(u32, elf.endian); + elf_section.sh_addralign = @as(u64, try in.readInt(u32, elf.endian)); + elf_section.sh_entsize = @as(u64, try in.readInt(u32, elf.endian)); } } for (elf.section_headers) |*elf_section| { if (elf_section.sh_type != SHT_NOBITS) { - const file_end_offset = try math.add(u64, elf_section.offset, elf_section.size); + const file_end_offset = try math.add(u64, elf_section.sh_offset, elf_section.sh_size); if (stream_end < file_end_offset) return error.InvalidFormat; } } @@ -499,13 +524,14 @@ pub const Elf = struct { pub fn close(elf: *Elf) void { elf.allocator.free(elf.section_headers); + elf.allocator.free(elf.program_headers); } pub fn findSection(elf: *Elf, name: []const u8) !?*SectionHeader { section_loop: for (elf.section_headers) |*elf_section| { if (elf_section.sh_type == SHT_NULL) continue; - const name_offset = elf.string_section.offset + elf_section.name; + const name_offset = elf.string_section.sh_offset + elf_section.sh_name; try elf.seekable_stream.seekTo(name_offset); for (name) |expected_c| { @@ -523,7 +549,7 @@ pub const Elf = struct { } pub fn seekToSection(elf: *Elf, elf_section: *SectionHeader) !void { - try elf.seekable_stream.seekTo(elf_section.offset); + try elf.seekable_stream.seekTo(elf_section.sh_offset); } }; @@ -578,6 +604,26 @@ pub const Elf64_Ehdr = extern struct { e_shnum: Elf64_Half, e_shstrndx: Elf64_Half, }; +pub const Elf32_Phdr = extern struct { + p_type: Elf32_Word, + p_offset: Elf32_Off, + p_vaddr: Elf32_Addr, + p_paddr: Elf32_Addr, + p_filesz: Elf32_Word, + p_memsz: Elf32_Word, + p_flags: Elf32_Word, + p_align: Elf32_Word, +}; +pub const Elf64_Phdr = extern struct { + p_type: Elf64_Word, + p_flags: Elf64_Word, + p_offset: Elf64_Off, + p_vaddr: Elf64_Addr, + p_paddr: Elf64_Addr, + p_filesz: Elf64_Xword, + p_memsz: Elf64_Xword, + p_align: Elf64_Xword, +}; pub const Elf32_Shdr = extern struct { sh_name: Elf32_Word, sh_type: Elf32_Word, @@ -655,26 +701,6 @@ pub const Elf64_Rela = extern struct { r_info: Elf64_Xword, r_addend: Elf64_Sxword, }; -pub const Elf32_Phdr = extern struct { - p_type: Elf32_Word, - p_offset: Elf32_Off, - p_vaddr: Elf32_Addr, - p_paddr: Elf32_Addr, - p_filesz: Elf32_Word, - p_memsz: Elf32_Word, - p_flags: Elf32_Word, - p_align: Elf32_Word, -}; -pub const Elf64_Phdr = extern struct { - p_type: Elf64_Word, - p_flags: Elf64_Word, - p_offset: Elf64_Off, - p_vaddr: Elf64_Addr, - p_paddr: Elf64_Addr, - p_filesz: Elf64_Xword, - p_memsz: Elf64_Xword, - p_align: Elf64_Xword, -}; pub const Elf32_Dyn = extern struct { d_tag: Elf32_Sword, d_un: extern union { @@ -833,6 +859,17 @@ pub const Elf_MIPS_ABIFlags_v0 = extern struct { flags2: Elf32_Word, }; +comptime { + debug.assert(@sizeOf(Elf32_Ehdr) == 52); + debug.assert(@sizeOf(Elf64_Ehdr) == 64); + + debug.assert(@sizeOf(Elf32_Phdr) == 32); + debug.assert(@sizeOf(Elf64_Phdr) == 56); + + debug.assert(@sizeOf(Elf32_Shdr) == 40); + debug.assert(@sizeOf(Elf64_Shdr) == 64); +} + pub const Auxv = switch (@sizeOf(usize)) { 4 => Elf32_auxv_t, 8 => Elf64_auxv_t, diff --git a/lib/std/target.zig b/lib/std/target.zig index 0b09ebf838..4c86d0c2a6 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -972,6 +972,23 @@ pub const Target = union(enum) { } } + pub fn getObjectFormat(self: Target) ObjectFormat { + switch (self) { + .Native => return @import("builtin").object_format, + .Cross => blk: { + if (self.isWindows() or self.isUefi()) { + return .coff; + } else if (self.isDarwin()) { + return .macho; + } + if (self.isWasm()) { + return .wasm; + } + return .elf; + }, + } + } + pub fn isMinGW(self: Target) bool { return self.isWindows() and self.isGnu(); } diff --git a/src-self-hosted/codegen.zig b/src-self-hosted/codegen.zig index 11bb83ae11..74eff90dc8 100644 --- a/src-self-hosted/codegen.zig +++ b/src-self-hosted/codegen.zig @@ -31,7 +31,7 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code) llvm.SetTarget(module, comp.llvm_triple.toSliceConst()); llvm.SetDataLayout(module, comp.target_layout_str); - if (util.getObjectFormat(comp.target) == .coff) { + if (comp.target.getObjectFormat() == .coff) { llvm.AddModuleCodeViewFlag(module); } else { llvm.AddModuleDebugInfoFlag(module); diff --git a/src-self-hosted/link.zig b/src-self-hosted/link.zig index 96e18514ea..0a29da4778 100644 --- a/src-self-hosted/link.zig +++ b/src-self-hosted/link.zig @@ -76,7 +76,7 @@ pub fn link(comp: *Compilation) !void { std.debug.warn("\n", .{}); } - const extern_ofmt = toExternObjectFormatType(util.getObjectFormat(comp.target)); + const extern_ofmt = toExternObjectFormatType(comp.target.getObjectFormat()); const args_slice = ctx.args.toSlice(); { @@ -128,7 +128,7 @@ fn toExternObjectFormatType(ofmt: ObjectFormat) c.ZigLLVM_ObjectFormatType { } fn constructLinkerArgs(ctx: *Context) !void { - switch (util.getObjectFormat(ctx.comp.target)) { + switch (ctx.comp.target.getObjectFormat()) { .unknown => unreachable, .coff => return constructLinkerArgsCoff(ctx), .elf => return constructLinkerArgsElf(ctx), diff --git a/src-self-hosted/util.zig b/src-self-hosted/util.zig index 85e2fc0e73..95bc72469d 100644 --- a/src-self-hosted/util.zig +++ b/src-self-hosted/util.zig @@ -32,23 +32,6 @@ pub fn getFloatAbi(self: Target) FloatAbi { }; } -pub fn getObjectFormat(target: Target) Target.ObjectFormat { - switch (target) { - .Native => return @import("builtin").object_format, - .Cross => blk: { - if (target.isWindows() or target.isUefi()) { - return .coff; - } else if (target.isDarwin()) { - return .macho; - } - if (target.isWasm()) { - return .wasm; - } - return .elf; - }, - } -} - pub fn getDynamicLinkerPath(self: Target) ?[]const u8 { const env = self.getAbi(); const arch = self.getArch();