elf: get hello-world with LLVM in Zig working
This commit is contained in:
@@ -1245,6 +1245,9 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
|
||||
// Generate and emit non-incremental sections.
|
||||
try self.initSections();
|
||||
try self.sortSections();
|
||||
for (self.objects.items) |index| {
|
||||
try self.file(index).?.object.addAtomsToOutputSections(self);
|
||||
}
|
||||
try self.updateSectionSizes();
|
||||
|
||||
try self.allocateSections();
|
||||
@@ -1424,7 +1427,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
|
||||
phdr_table_load.p_filesz = 0;
|
||||
|
||||
self.phdr_table_dirty = false;
|
||||
}
|
||||
} else try self.writePhdrs();
|
||||
|
||||
if (self.shdr_table_dirty) {
|
||||
const shsize: u64 = switch (self.ptr_width) {
|
||||
@@ -1476,8 +1479,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
|
||||
self.shdr_table_dirty = false;
|
||||
}
|
||||
|
||||
try self.writeAtoms();
|
||||
try self.writeSyntheticSections();
|
||||
try self.writeObjects();
|
||||
|
||||
if (self.entry_addr == null and self.base.options.effectiveOutputMode() == .Exe) {
|
||||
log.debug("flushing. no_entry_point_found = true", .{});
|
||||
@@ -1485,7 +1488,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
|
||||
} else {
|
||||
log.debug("flushing. no_entry_point_found = false", .{});
|
||||
self.error_flags.no_entry_point_found = false;
|
||||
try self.writeElfHeader();
|
||||
try self.writeHeader();
|
||||
}
|
||||
|
||||
// Dump the state for easy debugging.
|
||||
@@ -1756,30 +1759,6 @@ fn scanRelocs(self: *Elf) !void {
|
||||
}
|
||||
}
|
||||
|
||||
fn writeObjects(self: *Elf) !void {
|
||||
const gpa = self.base.allocator;
|
||||
|
||||
for (self.objects.items) |index| {
|
||||
const object = self.file(index).?.object;
|
||||
for (object.atoms.items) |atom_index| {
|
||||
const atom_ptr = self.atom(atom_index) orelse continue;
|
||||
if (!atom_ptr.flags.alive) continue;
|
||||
|
||||
const shdr = &self.shdrs.items[atom_ptr.outputShndx().?];
|
||||
if (shdr.sh_type == elf.SHT_NOBITS) continue;
|
||||
if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; // TODO we don't yet know how to handle non-alloc sections
|
||||
|
||||
const file_offset = shdr.sh_offset + atom_ptr.value - shdr.sh_addr;
|
||||
log.debug("writing atom({d}) at 0x{x}", .{ atom_ptr.atom_index, file_offset });
|
||||
const code = try object.codeDecompressAlloc(self, atom_ptr.atom_index);
|
||||
defer gpa.free(code);
|
||||
|
||||
try atom_ptr.resolveRelocs(self, code);
|
||||
try self.base.file.?.pwriteAll(code, file_offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !void {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
@@ -2480,7 +2459,14 @@ fn writeDwarfAddrAssumeCapacity(self: *Elf, buf: *std.ArrayList(u8), addr: u64)
|
||||
}
|
||||
}
|
||||
|
||||
fn writeElfHeader(self: *Elf) !void {
|
||||
fn writePhdrs(self: *Elf) !void {
|
||||
const phoff = @sizeOf(elf.Elf64_Ehdr);
|
||||
const phdrs_size = self.phdrs.items.len * @sizeOf(elf.Elf64_Phdr);
|
||||
log.debug("writing program headers from 0x{x} to 0x{x}", .{ phoff, phoff + phdrs_size });
|
||||
try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.phdrs.items), phoff);
|
||||
}
|
||||
|
||||
fn writeHeader(self: *Elf) !void {
|
||||
var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 = undefined;
|
||||
|
||||
var index: usize = 0;
|
||||
@@ -2532,7 +2518,11 @@ fn writeElfHeader(self: *Elf) !void {
|
||||
|
||||
const e_entry = if (elf_type == .REL) 0 else self.entry_addr.?;
|
||||
|
||||
const phdr_table_offset = self.phdrs.items[self.phdr_table_index.?].p_offset;
|
||||
// TODO
|
||||
const phdr_table_offset = if (self.phdr_table_index) |ind|
|
||||
self.phdrs.items[ind].p_offset
|
||||
else
|
||||
@sizeOf(elf.Elf64_Ehdr);
|
||||
switch (self.ptr_width) {
|
||||
.p32 => {
|
||||
mem.writeInt(u32, hdr_buf[index..][0..4], @as(u32, @intCast(e_entry)), endian);
|
||||
@@ -3401,13 +3391,7 @@ fn initSections(self: *Elf) !void {
|
||||
};
|
||||
|
||||
for (self.objects.items) |index| {
|
||||
const object = self.file(index).?.object;
|
||||
for (object.atoms.items) |atom_index| {
|
||||
const atom_ptr = self.atom(atom_index) orelse continue;
|
||||
if (!atom_ptr.flags.alive) continue;
|
||||
const shdr = atom_ptr.inputShdr(self);
|
||||
atom_ptr.output_section_index = try object.initOutputSection(self, shdr);
|
||||
}
|
||||
try self.file(index).?.object.initOutputSections(self);
|
||||
}
|
||||
|
||||
if (self.got.entries.items.len > 0 and self.got_section_index == null) {
|
||||
@@ -3525,14 +3509,6 @@ fn sortSections(self: *Elf) !void {
|
||||
self.shdrs.appendAssumeCapacity(slice[sorted.shndx]);
|
||||
}
|
||||
|
||||
for (self.objects.items) |index| {
|
||||
for (self.file(index).?.atoms()) |atom_index| {
|
||||
const atom_ptr = self.atom(atom_index) orelse continue;
|
||||
if (!atom_ptr.flags.alive) continue;
|
||||
atom_ptr.output_section_index = backlinks[atom_ptr.output_section_index];
|
||||
}
|
||||
}
|
||||
|
||||
for (&[_]*?u16{
|
||||
&self.eh_frame_section_index,
|
||||
&self.eh_frame_hdr_section_index,
|
||||
@@ -3891,6 +3867,31 @@ fn allocateAtoms(self: *Elf) void {
|
||||
}
|
||||
}
|
||||
|
||||
fn writeAtoms(self: *Elf) !void {
|
||||
const gpa = self.base.allocator;
|
||||
for (self.shdrs.items, 0..) |shdr, shndx| {
|
||||
if (shdr.sh_type == elf.SHT_NULL) continue;
|
||||
if (shdr.sh_type == elf.SHT_NOBITS) continue;
|
||||
|
||||
log.debug("writing atoms in '{s}' section", .{self.shstrtab.getAssumeExists(shdr.sh_name)});
|
||||
|
||||
const buffer = try gpa.alloc(u8, shdr.sh_size);
|
||||
defer gpa.free(buffer);
|
||||
const padding_byte: u8 = if (shdr.sh_type == elf.SHT_PROGBITS and
|
||||
shdr.sh_flags & elf.SHF_EXECINSTR != 0)
|
||||
0xcc // int3
|
||||
else
|
||||
0;
|
||||
@memset(buffer, padding_byte);
|
||||
|
||||
for (self.objects.items) |index| {
|
||||
try self.file(index).?.object.writeAtoms(self, @intCast(shndx), buffer);
|
||||
}
|
||||
|
||||
try self.base.file.?.pwriteAll(buffer, shdr.sh_offset);
|
||||
}
|
||||
}
|
||||
|
||||
fn updateSymtabSize(self: *Elf) !void {
|
||||
var sizes = SymtabSize{};
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ cies: std.ArrayListUnmanaged(Cie) = .{},
|
||||
alive: bool = true,
|
||||
num_dynrelocs: u32 = 0,
|
||||
|
||||
output_sections: std.AutoArrayHashMapUnmanaged(u16, std.ArrayListUnmanaged(Atom.Index)) = .{},
|
||||
output_symtab_size: Elf.SymtabSize = .{},
|
||||
|
||||
pub fn isObject(file: std.fs.File) bool {
|
||||
@@ -42,6 +43,10 @@ pub fn deinit(self: *Object, allocator: Allocator) void {
|
||||
self.comdat_groups.deinit(allocator);
|
||||
self.fdes.deinit(allocator);
|
||||
self.cies.deinit(allocator);
|
||||
for (self.output_sections.values()) |*list| {
|
||||
list.deinit(allocator);
|
||||
}
|
||||
self.output_sections.deinit(allocator);
|
||||
}
|
||||
|
||||
pub fn parse(self: *Object, elf_file: *Elf) !void {
|
||||
@@ -193,7 +198,7 @@ fn addAtom(
|
||||
}
|
||||
}
|
||||
|
||||
pub fn initOutputSection(self: Object, elf_file: *Elf, shdr: elf.Elf64_Shdr) error{OutOfMemory}!u16 {
|
||||
fn initOutputSection(self: Object, elf_file: *Elf, shdr: elf.Elf64_Shdr) error{OutOfMemory}!u16 {
|
||||
const name = blk: {
|
||||
const name = self.strings.getAssumeExists(shdr.sh_name);
|
||||
if (shdr.sh_flags & elf.SHF_MERGE != 0) break :blk name;
|
||||
@@ -601,6 +606,30 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn initOutputSections(self: Object, elf_file: *Elf) !void {
|
||||
for (self.atoms.items) |atom_index| {
|
||||
const atom = elf_file.atom(atom_index) orelse continue;
|
||||
if (!atom.flags.alive) continue;
|
||||
const shdr = atom.inputShdr(elf_file);
|
||||
_ = try self.initOutputSection(elf_file, shdr);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn addAtomsToOutputSections(self: *Object, elf_file: *Elf) !void {
|
||||
for (self.atoms.items) |atom_index| {
|
||||
const atom = elf_file.atom(atom_index) orelse continue;
|
||||
if (!atom.flags.alive) continue;
|
||||
const shdr = atom.inputShdr(elf_file);
|
||||
atom.output_section_index = self.initOutputSection(elf_file, shdr) catch unreachable;
|
||||
|
||||
if (shdr.sh_type == elf.SHT_NOBITS) continue;
|
||||
const gpa = elf_file.base.allocator;
|
||||
const gop = try self.output_sections.getOrPut(gpa, atom.output_section_index);
|
||||
if (!gop.found_existing) gop.value_ptr.* = .{};
|
||||
try gop.value_ptr.append(gpa, atom_index);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn updateSectionSizes(self: Object, elf_file: *Elf) void {
|
||||
for (self.atoms.items) |atom_index| {
|
||||
const atom = elf_file.atom(atom_index) orelse continue;
|
||||
@@ -640,6 +669,24 @@ pub fn allocateAtoms(self: Object, elf_file: *Elf) void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn writeAtoms(self: Object, elf_file: *Elf, output_section_index: u16, buffer: []u8) !void {
|
||||
const gpa = elf_file.base.allocator;
|
||||
const atom_list = self.output_sections.get(output_section_index) orelse return;
|
||||
const shdr = elf_file.shdrs.items[output_section_index];
|
||||
for (atom_list.items) |atom_index| {
|
||||
const atom = elf_file.atom(atom_index).?;
|
||||
assert(atom.flags.alive);
|
||||
const offset = atom.value - shdr.sh_addr;
|
||||
log.debug("writing atom({d}) at 0x{x}", .{ atom_index, shdr.sh_offset + offset });
|
||||
// TODO decompress directly into provided buffer
|
||||
const out_code = buffer[offset..][0..atom.size];
|
||||
const in_code = try self.codeDecompressAlloc(elf_file, atom_index);
|
||||
defer gpa.free(in_code);
|
||||
@memcpy(out_code, in_code);
|
||||
try atom.resolveRelocs(elf_file, out_code);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn updateSymtabSize(self: *Object, elf_file: *Elf) void {
|
||||
for (self.locals()) |local_index| {
|
||||
const local = elf_file.symbol(local_index);
|
||||
|
||||
Reference in New Issue
Block a user