authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-09-12 17:35:56+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-09-12 17:35:56+02:00
log472d326a8c88570f629d58539b9829c69730a96b
tree754ec0aa4c6d9018d44cf3ade1d6d0d1235bee8e
parent44e84af874bc01fe0657d20548f69801cf18dccd

elf: set output section index when parsing objects


2 files changed, 64 insertions(+), 25 deletions(-)

src/link/Elf.zig+9-2
...@@ -1043,14 +1043,17 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1043,14 +1043,17 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1043 self.linker_defined_index = index;1043 self.linker_defined_index = index;
1044 }1044 }
10451045
1046 // Symbol resolution happens here
1046 try self.addLinkerDefinedSymbols();1047 try self.addLinkerDefinedSymbols();
1047
1048 // Resolve symbols
1049 self.resolveSymbols();1048 self.resolveSymbols();
1050 self.markImportsExports();1049 self.markImportsExports();
1051 self.claimUnresolved();1050 self.claimUnresolved();
1051
1052 // Scan and create missing synthetic entries such as GOT indirection
1052 try self.scanRelocs();1053 try self.scanRelocs();
10531054
1055 // Allocate atoms parsed from input object files
1056 self.allocateObjects();
1054 self.allocateLinkerDefinedSymbols();1057 self.allocateLinkerDefinedSymbols();
10551058
1056 // Beyond this point, everything has been allocated a virtual address and we can resolve1059 // Beyond this point, everything has been allocated a virtual address and we can resolve
...@@ -1402,6 +1405,10 @@ fn scanRelocs(self: *Elf) !void {...@@ -1402,6 +1405,10 @@ fn scanRelocs(self: *Elf) !void {
1402 }1405 }
1403}1406}
14041407
1408fn allocateObjects(self: *Elf) void {
1409 _ = self;
1410}
1411
1405fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !void {1412fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !void {
1406 const tracy = trace(@src());1413 const tracy = trace(@src());
1407 defer tracy.end();1414 defer tracy.end();
src/link/Elf/Object.zig+55-23
...@@ -17,7 +17,6 @@ comdat_groups: std.ArrayListUnmanaged(Elf.ComdatGroup.Index) = .{},...@@ -17,7 +17,6 @@ comdat_groups: std.ArrayListUnmanaged(Elf.ComdatGroup.Index) = .{},
17fdes: std.ArrayListUnmanaged(Fde) = .{},17fdes: std.ArrayListUnmanaged(Fde) = .{},
18cies: std.ArrayListUnmanaged(Cie) = .{},18cies: std.ArrayListUnmanaged(Cie) = .{},
1919
20needs_exec_stack: bool = false,
21alive: bool = true,20alive: bool = true,
22num_dynrelocs: u32 = 0,21num_dynrelocs: u32 = 0,
2322
...@@ -80,12 +79,12 @@ pub fn parse(self: *Object, elf_file: *Elf) !void {...@@ -80,12 +79,12 @@ pub fn parse(self: *Object, elf_file: *Elf) !void {
80 try self.initAtoms(elf_file);79 try self.initAtoms(elf_file);
81 try self.initSymtab(elf_file);80 try self.initSymtab(elf_file);
8281
83 for (self.shdrs.items, 0..) |shdr, i| {82 // for (self.shdrs.items, 0..) |shdr, i| {
84 const atom = elf_file.atom(self.atoms.items[i]) orelse continue;83 // const atom = elf_file.atom(self.atoms.items[i]) orelse continue;
85 if (!atom.alive) continue;84 // if (!atom.alive) continue;
86 if (shdr.sh_type == elf.SHT_X86_64_UNWIND or mem.eql(u8, atom.name(elf_file), ".eh_frame"))85 // if (shdr.sh_type == elf.SHT_X86_64_UNWIND or mem.eql(u8, atom.name(elf_file), ".eh_frame"))
87 try self.parseEhFrame(@as(u16, @intCast(i)), elf_file);86 // try self.parseEhFrame(@as(u16, @intCast(i)), elf_file);
88 }87 // }
89}88}
9089
91fn initAtoms(self: *Object, elf_file: *Elf) !void {90fn initAtoms(self: *Object, elf_file: *Elf) !void {
...@@ -148,20 +147,6 @@ fn initAtoms(self: *Object, elf_file: *Elf) !void {...@@ -148,20 +147,6 @@ fn initAtoms(self: *Object, elf_file: *Elf) !void {
148 else => {147 else => {
149 const name = self.strings.getAssumeExists(shdr.sh_name);148 const name = self.strings.getAssumeExists(shdr.sh_name);
150 const shndx = @as(u16, @intCast(i));149 const shndx = @as(u16, @intCast(i));
151
152 // if (mem.eql(u8, ".note.GNU-stack", name)) {
153 // if (shdr.sh_flags & elf.SHF_EXECINSTR != 0) {
154 // if (!elf_file.options.z_execstack or !elf_file.options.z_execstack_if_needed) {
155 // elf_file.base.warn(
156 // "{}: may cause segmentation fault as this file requested executable stack",
157 // .{self.fmtPath()},
158 // );
159 // }
160 // self.needs_exec_stack = true;
161 // }
162 // continue;
163 // }
164
165 if (self.skipShdr(shndx, elf_file)) continue;150 if (self.skipShdr(shndx, elf_file)) continue;
166 try self.addAtom(shdr, shndx, name, elf_file);151 try self.addAtom(shdr, shndx, name, elf_file);
167 },152 },
...@@ -187,6 +172,7 @@ fn addAtom(self: *Object, shdr: elf.Elf64_Shdr, shndx: u16, name: [:0]const u8,...@@ -187,6 +172,7 @@ fn addAtom(self: *Object, shdr: elf.Elf64_Shdr, shndx: u16, name: [:0]const u8,
187 atom.name_offset = try elf_file.strtab.insert(elf_file.base.allocator, name);172 atom.name_offset = try elf_file.strtab.insert(elf_file.base.allocator, name);
188 atom.file_index = self.index;173 atom.file_index = self.index;
189 atom.input_section_index = shndx;174 atom.input_section_index = shndx;
175 atom.output_section_index = self.getOutputSectionIndex(elf_file, shdr);
190 atom.alive = true;176 atom.alive = true;
191 self.atoms.items[shndx] = atom_index;177 self.atoms.items[shndx] = atom_index;
192178
...@@ -201,15 +187,61 @@ fn addAtom(self: *Object, shdr: elf.Elf64_Shdr, shndx: u16, name: [:0]const u8,...@@ -201,15 +187,61 @@ fn addAtom(self: *Object, shdr: elf.Elf64_Shdr, shndx: u16, name: [:0]const u8,
201 }187 }
202}188}
203189
190fn getOutputSectionIndex(self: *Object, elf_file: *Elf, shdr: elf.Elf64_Shdr) u16 {
191 const name = blk: {
192 const name = self.strings.getAssumeExists(shdr.sh_name);
193 // if (shdr.sh_flags & elf.SHF_MERGE != 0) break :blk name;
194 const sh_name_prefixes: []const [:0]const u8 = &.{
195 ".text", ".data.rel.ro", ".data", ".rodata", ".bss.rel.ro", ".bss",
196 ".init_array", ".fini_array", ".tbss", ".tdata", ".gcc_except_table", ".ctors",
197 ".dtors", ".gnu.warning",
198 };
199 inline for (sh_name_prefixes) |prefix| {
200 if (std.mem.eql(u8, name, prefix) or std.mem.startsWith(u8, name, prefix ++ ".")) {
201 break :blk prefix;
202 }
203 }
204 break :blk name;
205 };
206 const @"type" = switch (shdr.sh_type) {
207 elf.SHT_NULL => unreachable,
208 elf.SHT_PROGBITS => blk: {
209 if (std.mem.eql(u8, name, ".init_array") or std.mem.startsWith(u8, name, ".init_array."))
210 break :blk elf.SHT_INIT_ARRAY;
211 if (std.mem.eql(u8, name, ".fini_array") or std.mem.startsWith(u8, name, ".fini_array."))
212 break :blk elf.SHT_FINI_ARRAY;
213 break :blk shdr.sh_type;
214 },
215 elf.SHT_X86_64_UNWIND => elf.SHT_PROGBITS,
216 else => shdr.sh_type,
217 };
218 const flags = blk: {
219 const flags = shdr.sh_flags & ~@as(u64, elf.SHF_COMPRESSED | elf.SHF_GROUP | elf.SHF_GNU_RETAIN);
220 break :blk switch (@"type") {
221 elf.SHT_INIT_ARRAY, elf.SHT_FINI_ARRAY => flags | elf.SHF_WRITE,
222 else => flags,
223 };
224 };
225 _ = flags;
226 const out_shndx = elf_file.sectionByName(name) orelse {
227 log.err("{}: output section {s} not found", .{ self.fmtPath(), name });
228 @panic("TODO: missing output section!");
229 };
230 return out_shndx;
231}
232
204fn skipShdr(self: *Object, index: u16, elf_file: *Elf) bool {233fn skipShdr(self: *Object, index: u16, elf_file: *Elf) bool {
234 _ = elf_file;
205 const shdr = self.shdrs.items[index];235 const shdr = self.shdrs.items[index];
206 const name = self.strings.getAssumeExists(shdr.sh_name);236 const name = self.strings.getAssumeExists(shdr.sh_name);
207 const ignore = blk: {237 const ignore = blk: {
208 if (mem.startsWith(u8, name, ".note")) break :blk true;238 if (mem.startsWith(u8, name, ".note")) break :blk true;
209 if (mem.startsWith(u8, name, ".comment")) break :blk true;239 if (mem.startsWith(u8, name, ".comment")) break :blk true;
210 if (mem.startsWith(u8, name, ".llvm_addrsig")) break :blk true;240 if (mem.startsWith(u8, name, ".llvm_addrsig")) break :blk true;
211 if (elf_file.base.options.strip and shdr.sh_flags & elf.SHF_ALLOC == 0 and241 if (mem.startsWith(u8, name, ".eh_frame")) break :blk true;
212 mem.startsWith(u8, name, ".debug")) break :blk true;242 // if (elf_file.base.options.strip and shdr.sh_flags & elf.SHF_ALLOC == 0 and
243 // mem.startsWith(u8, name, ".debug")) break :blk true;
244 if (shdr.sh_flags & elf.SHF_ALLOC == 0 and mem.startsWith(u8, name, ".debug")) break :blk true;
213 break :blk false;245 break :blk false;
214 };246 };
215 return ignore;247 return ignore;