mirror of
https://github.com/ziglang/zig.git
synced 2024-11-15 08:33:06 +00:00
Add InstallRawStep to Zig build system that does a similar job to llvm-objcopy. To use it, do 'exe.installRaw("kernel.bin");' where exe is a LibExeObjStep
Part of #2826
This commit is contained in:
parent
958f00f1c7
commit
9b11e5e1f1
@ -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 {
|
||||
|
255
lib/std/build/emit_raw.zig
Normal file
255
lib/std/build/emit_raw.zig
Normal file
@ -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);
|
||||
}
|
||||
};
|
@ -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,
|
||||
};
|
||||
|
155
lib/std/elf.zig
155
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,
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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),
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user