diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2024-08-27 15:22:33 +0200 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2024-09-04 13:34:25 +0200 |
| commit | d32af9ea2ade7c447ac8b882076dba337a10dc51 (patch) | |
| tree | c514a34fdfe5c3e13e973b6c0e252bccc4002371 /src/link | |
| parent | b44dd599ad4a0f8a6684acd6e3c5a02f3c7b8f04 (diff) | |
| download | zig-d32af9ea2ade7c447ac8b882076dba337a10dc51.tar.gz zig-d32af9ea2ade7c447ac8b882076dba337a10dc51.zip | |
elf: move initOutputSection into Elf from Object
Diffstat (limited to 'src/link')
| -rw-r--r-- | src/link/Elf.zig | 53 | ||||
| -rw-r--r-- | src/link/Elf/Object.zig | 76 |
2 files changed, 73 insertions, 56 deletions
diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 4957811e7a..1ef5a562a8 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1827,6 +1827,59 @@ fn scanRelocs(self: *Elf) !void { } } +pub fn initOutputSection(self: *Elf, args: struct { + name: [:0]const u8, + flags: u64, + type: u32, +}) error{OutOfMemory}!u32 { + const name = blk: { + if (self.base.isRelocatable()) break :blk args.name; + if (args.flags & elf.SHF_MERGE != 0) break :blk args.name; + const name_prefixes: []const [:0]const u8 = &.{ + ".text", ".data.rel.ro", ".data", ".rodata", ".bss.rel.ro", ".bss", + ".init_array", ".fini_array", ".tbss", ".tdata", ".gcc_except_table", ".ctors", + ".dtors", ".gnu.warning", + }; + inline for (name_prefixes) |prefix| { + if (std.mem.eql(u8, args.name, prefix) or std.mem.startsWith(u8, args.name, prefix ++ ".")) { + break :blk prefix; + } + } + break :blk args.name; + }; + const @"type" = tt: { + if (self.getTarget().cpu.arch == .x86_64 and + args.type == elf.SHT_X86_64_UNWIND) break :tt elf.SHT_PROGBITS; + switch (args.type) { + elf.SHT_NULL => unreachable, + elf.SHT_PROGBITS => { + if (std.mem.eql(u8, args.name, ".init_array") or std.mem.startsWith(u8, args.name, ".init_array.")) + break :tt elf.SHT_INIT_ARRAY; + if (std.mem.eql(u8, args.name, ".fini_array") or std.mem.startsWith(u8, args.name, ".fini_array.")) + break :tt elf.SHT_FINI_ARRAY; + break :tt args.type; + }, + else => break :tt args.type, + } + }; + const flags = blk: { + var flags = args.flags; + if (!self.base.isRelocatable()) { + flags &= ~@as(u64, elf.SHF_COMPRESSED | elf.SHF_GROUP | elf.SHF_GNU_RETAIN); + } + break :blk switch (@"type") { + elf.SHT_INIT_ARRAY, elf.SHT_FINI_ARRAY => flags | elf.SHF_WRITE, + else => flags, + }; + }; + const out_shndx = self.sectionByName(name) orelse try self.addSection(.{ + .type = @"type", + .flags = flags, + .name = try self.insertShString(name), + }); + return out_shndx; +} + fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) !void { dev.check(.lld_linker); diff --git a/src/link/Elf/Object.zig b/src/link/Elf/Object.zig index 40d09c8ec4..c4443bb67e 100644 --- a/src/link/Elf/Object.zig +++ b/src/link/Elf/Object.zig @@ -311,58 +311,6 @@ fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file: }; } -fn initOutputSection(self: Object, elf_file: *Elf, shdr: elf.Elf64_Shdr) error{OutOfMemory}!u32 { - const name = blk: { - const name = self.getString(shdr.sh_name); - if (elf_file.base.isRelocatable()) break :blk name; - if (shdr.sh_flags & elf.SHF_MERGE != 0) break :blk name; - const sh_name_prefixes: []const [:0]const u8 = &.{ - ".text", ".data.rel.ro", ".data", ".rodata", ".bss.rel.ro", ".bss", - ".init_array", ".fini_array", ".tbss", ".tdata", ".gcc_except_table", ".ctors", - ".dtors", ".gnu.warning", - }; - inline for (sh_name_prefixes) |prefix| { - if (std.mem.eql(u8, name, prefix) or std.mem.startsWith(u8, name, prefix ++ ".")) { - break :blk prefix; - } - } - break :blk name; - }; - const @"type" = tt: { - if (elf_file.getTarget().cpu.arch == .x86_64 and - shdr.sh_type == elf.SHT_X86_64_UNWIND) break :tt elf.SHT_PROGBITS; - - const @"type" = switch (shdr.sh_type) { - elf.SHT_NULL => unreachable, - elf.SHT_PROGBITS => blk: { - if (std.mem.eql(u8, name, ".init_array") or std.mem.startsWith(u8, name, ".init_array.")) - break :blk elf.SHT_INIT_ARRAY; - if (std.mem.eql(u8, name, ".fini_array") or std.mem.startsWith(u8, name, ".fini_array.")) - break :blk elf.SHT_FINI_ARRAY; - break :blk shdr.sh_type; - }, - else => shdr.sh_type, - }; - break :tt @"type"; - }; - const flags = blk: { - var flags = shdr.sh_flags; - if (!elf_file.base.isRelocatable()) { - flags &= ~@as(u64, elf.SHF_COMPRESSED | elf.SHF_GROUP | elf.SHF_GNU_RETAIN); - } - break :blk switch (@"type") { - elf.SHT_INIT_ARRAY, elf.SHT_FINI_ARRAY => flags | elf.SHF_WRITE, - else => flags, - }; - }; - const out_shndx = elf_file.sectionByName(name) orelse try elf_file.addSection(.{ - .type = @"type", - .flags = flags, - .name = try elf_file.insertShString(name), - }); - return out_shndx; -} - fn skipShdr(self: *Object, index: u32, elf_file: *Elf) bool { const comp = elf_file.base.comp; const shdr = self.shdrs.items[index]; @@ -985,7 +933,11 @@ pub fn initOutputSections(self: *Object, elf_file: *Elf) !void { const atom_ptr = self.atom(atom_index) orelse continue; if (!atom_ptr.alive) continue; const shdr = atom_ptr.inputShdr(elf_file); - _ = try self.initOutputSection(elf_file, shdr); + _ = try elf_file.initOutputSection(.{ + .name = self.getString(shdr.sh_name), + .flags = shdr.sh_flags, + .type = shdr.sh_type, + }); } } @@ -994,7 +946,11 @@ pub fn addAtomsToOutputSections(self: *Object, elf_file: *Elf) !void { const atom_ptr = self.atom(atom_index) orelse continue; if (!atom_ptr.alive) continue; const shdr = atom_ptr.inputShdr(elf_file); - atom_ptr.output_section_index = self.initOutputSection(elf_file, shdr) catch unreachable; + atom_ptr.output_section_index = elf_file.initOutputSection(.{ + .name = self.getString(shdr.sh_name), + .flags = shdr.sh_flags, + .type = shdr.sh_type, + }) catch unreachable; const comp = elf_file.base.comp; const gpa = comp.gpa; @@ -1009,7 +965,11 @@ pub fn initRelaSections(self: *Object, elf_file: *Elf) !void { if (!atom_ptr.alive) continue; const shndx = atom_ptr.relocsShndx() orelse continue; const shdr = self.shdrs.items[shndx]; - const out_shndx = try self.initOutputSection(elf_file, shdr); + const out_shndx = try elf_file.initOutputSection(.{ + .name = self.getString(shdr.sh_name), + .flags = shdr.sh_flags, + .type = shdr.sh_type, + }); const out_shdr = &elf_file.sections.items(.shdr)[out_shndx]; out_shdr.sh_type = elf.SHT_RELA; out_shdr.sh_addralign = @alignOf(elf.Elf64_Rela); @@ -1025,7 +985,11 @@ pub fn addAtomsToRelaSections(self: *Object, elf_file: *Elf) !void { const shndx = blk: { const shndx = atom_ptr.relocsShndx() orelse continue; const shdr = self.shdrs.items[shndx]; - break :blk self.initOutputSection(elf_file, shdr) catch unreachable; + break :blk elf_file.initOutputSection(.{ + .name = self.getString(shdr.sh_name), + .flags = shdr.sh_flags, + .type = shdr.sh_type, + }) catch unreachable; }; const slice = elf_file.sections.slice(); const shdr = &slice.items(.shdr)[shndx]; |
