aboutsummaryrefslogtreecommitdiff
path: root/src/link/Elf/Object.zig
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2023-10-03 11:33:03 +0200
committerJakub Konka <kubkon@jakubkonka.com>2023-10-16 19:33:04 +0200
commit53340544c6666d9d35463f509fbe0416f607c91c (patch)
tree7ea4b34f28e779e6538deb70746603089e5a4162 /src/link/Elf/Object.zig
parent1b70ad622bd6dbc776563656a6aaee94d69c66ea (diff)
downloadzig-53340544c6666d9d35463f509fbe0416f607c91c.tar.gz
zig-53340544c6666d9d35463f509fbe0416f607c91c.zip
elf: get hello-world with LLVM in Zig working
Diffstat (limited to 'src/link/Elf/Object.zig')
-rw-r--r--src/link/Elf/Object.zig49
1 files changed, 48 insertions, 1 deletions
diff --git a/src/link/Elf/Object.zig b/src/link/Elf/Object.zig
index 0c7c3376f9..de89ee822a 100644
--- a/src/link/Elf/Object.zig
+++ b/src/link/Elf/Object.zig
@@ -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);