diff --git a/src/link/Elf.zig b/src/link/Elf.zig index d4cace5abe..3883f76268 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1208,14 +1208,15 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node } } + try self.initOutputSections(); try self.addLinkerDefinedSymbols(); self.claimUnresolved(); // Scan and create missing synthetic entries such as GOT indirection. try self.scanRelocs(); - // Generate and emit non-incremental sections. - try self.initSections(); + // Generate and emit synthetic sections. + try self.initSyntheticSections(); try self.initSpecialPhdrs(); try self.sortShdrs(); for (self.objects.items) |index| { @@ -3210,21 +3211,18 @@ fn addLinkerDefinedSymbols(self: *Elf) !void { self.rela_iplt_start_index = try linker_defined.addGlobal("__rela_iplt_start", self); self.rela_iplt_end_index = try linker_defined.addGlobal("__rela_iplt_end", self); - for (self.objects.items) |index| { - const object = self.file(index).?.object; - for (object.atoms.items) |atom_index| { - if (self.getStartStopBasename(atom_index)) |name| { - const gpa = self.base.allocator; - try self.start_stop_indexes.ensureUnusedCapacity(gpa, 2); + for (self.shdrs.items) |shdr| { + if (self.getStartStopBasename(shdr)) |name| { + const gpa = self.base.allocator; + try self.start_stop_indexes.ensureUnusedCapacity(gpa, 2); - const start = try std.fmt.allocPrintZ(gpa, "__start_{s}", .{name}); - defer gpa.free(start); - const stop = try std.fmt.allocPrintZ(gpa, "__stop_{s}", .{name}); - defer gpa.free(stop); + const start = try std.fmt.allocPrintZ(gpa, "__start_{s}", .{name}); + defer gpa.free(start); + const stop = try std.fmt.allocPrintZ(gpa, "__stop_{s}", .{name}); + defer gpa.free(stop); - self.start_stop_indexes.appendAssumeCapacity(try linker_defined.addGlobal(start, self)); - self.start_stop_indexes.appendAssumeCapacity(try linker_defined.addGlobal(stop, self)); - } + self.start_stop_indexes.appendAssumeCapacity(try linker_defined.addGlobal(start, self)); + self.start_stop_indexes.appendAssumeCapacity(try linker_defined.addGlobal(stop, self)); } } @@ -3354,12 +3352,14 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { } } -fn initSections(self: *Elf) !void { - const ptr_size = self.ptrWidthBytes(); - +fn initOutputSections(self: *Elf) !void { for (self.objects.items) |index| { try self.file(index).?.object.initOutputSections(self); } +} + +fn initSyntheticSections(self: *Elf) !void { + const ptr_size = self.ptrWidthBytes(); const needs_eh_frame = for (self.objects.items) |index| { if (self.file(index).?.object.cies.items.len > 0) break true; @@ -3394,6 +3394,14 @@ fn initSections(self: *Elf) !void { }); } + self.got_plt_section_index = try self.addSection(.{ + .name = ".got.plt", + .type = elf.SHT_PROGBITS, + .flags = elf.SHF_ALLOC | elf.SHF_WRITE, + .addralign = @alignOf(u64), + .offset = std.math.maxInt(u64), + }); + const needs_rela_dyn = blk: { if (self.got.flags.needs_rela or self.got.flags.needs_tlsld or self.zig_got.flags.needs_rela or self.copy_rel.symbols.items.len > 0) break :blk true; @@ -3424,13 +3432,6 @@ fn initSections(self: *Elf) !void { .addralign = 16, .offset = std.math.maxInt(u64), }); - self.got_plt_section_index = try self.addSection(.{ - .name = ".got.plt", - .type = elf.SHT_PROGBITS, - .flags = elf.SHF_ALLOC | elf.SHF_WRITE, - .addralign = @alignOf(u64), - .offset = std.math.maxInt(u64), - }); self.rela_plt_section_index = try self.addSection(.{ .name = ".rela.plt", .type = elf.SHT_RELA, @@ -4819,15 +4820,12 @@ fn updateSymtabSize(self: *Elf) !void { const gpa = self.base.allocator; var files = std.ArrayList(File.Index).init(gpa); defer files.deinit(); - try files.ensureTotalCapacityPrecise(self.objects.items.len + self.shared_objects.items.len + 1); + try files.ensureTotalCapacityPrecise(self.objects.items.len + self.shared_objects.items.len + 2); if (self.zig_object_index) |index| files.appendAssumeCapacity(index); - for (self.objects.items) |index| { - files.appendAssumeCapacity(index); - } - for (self.shared_objects.items) |index| { - files.appendAssumeCapacity(index); - } + for (self.objects.items) |index| files.appendAssumeCapacity(index); + for (self.shared_objects.items) |index| files.appendAssumeCapacity(index); + if (self.linker_defined_index) |index| files.appendAssumeCapacity(index); // Section symbols for (self.output_sections.keys()) |_| { @@ -5166,6 +5164,11 @@ fn writeSymtab(self: *Elf) !void { file_ptr.writeSymtab(self); } + if (self.linker_defined_index) |index| { + const file_ptr = self.file(index).?; + file_ptr.writeSymtab(self); + } + if (self.zig_got_section_index) |_| { self.zig_got.writeSymtab(self); } @@ -5182,11 +5185,6 @@ fn writeSymtab(self: *Elf) !void { self.plt_got.writeSymtab(self); } - if (self.linker_defined_index) |index| { - const file_ptr = self.file(index).?; - file_ptr.writeSymtab(self); - } - const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian(); switch (self.ptr_width) { .p32 => { @@ -5750,10 +5748,9 @@ pub fn isCIdentifier(name: []const u8) bool { return true; } -fn getStartStopBasename(self: *Elf, atom_index: Atom.Index) ?[]const u8 { - const atom_ptr = self.atom(atom_index) orelse return null; - const name = atom_ptr.name(self); - if (atom_ptr.inputShdr(self).sh_flags & elf.SHF_ALLOC != 0 and name.len > 0) { +fn getStartStopBasename(self: *Elf, shdr: elf.Elf64_Shdr) ?[]const u8 { + const name = self.getShString(shdr.sh_name); + if (shdr.sh_flags & elf.SHF_ALLOC != 0 and name.len > 0) { if (isCIdentifier(name)) return name; } return null; diff --git a/src/link/Elf/LinkerDefined.zig b/src/link/Elf/LinkerDefined.zig index 938f22985f..bc51cfc1f1 100644 --- a/src/link/Elf/LinkerDefined.zig +++ b/src/link/Elf/LinkerDefined.zig @@ -48,10 +48,42 @@ pub fn resolveSymbols(self: *LinkerDefined, elf_file: *Elf) void { } } -pub fn globals(self: *LinkerDefined) []const Symbol.Index { +pub fn globals(self: LinkerDefined) []const Symbol.Index { return self.symbols.items; } +pub fn updateSymtabSize(self: *LinkerDefined, elf_file: *Elf) !void { + for (self.globals()) |global_index| { + const global = elf_file.symbol(global_index); + const file_ptr = global.file(elf_file) orelse continue; + if (file_ptr.index() != self.index) continue; + global.flags.output_symtab = true; + if (global.isLocal(elf_file)) { + try global.setOutputSymtabIndex(self.output_symtab_ctx.nlocals, elf_file); + self.output_symtab_ctx.nlocals += 1; + } else { + try global.setOutputSymtabIndex(self.output_symtab_ctx.nglobals, elf_file); + self.output_symtab_ctx.nglobals += 1; + } + self.output_symtab_ctx.strsize += @as(u32, @intCast(global.name(elf_file).len)) + 1; + } +} + +pub fn writeSymtab(self: LinkerDefined, elf_file: *Elf) void { + for (self.globals()) |global_index| { + const global = elf_file.symbol(global_index); + const file_ptr = global.file(elf_file) orelse continue; + if (file_ptr.index() != self.index) continue; + const idx = global.outputSymtabIndex(elf_file) orelse continue; + const st_name = @as(u32, @intCast(elf_file.strtab.items.len)); + elf_file.strtab.appendSliceAssumeCapacity(global.name(elf_file)); + elf_file.strtab.appendAssumeCapacity(0); + const out_sym = &elf_file.symtab.items[idx]; + out_sym.st_name = st_name; + global.setOutputSym(elf_file, out_sym); + } +} + pub fn asFile(self: *LinkerDefined) File { return .{ .linker_defined = self }; } diff --git a/src/link/Elf/Object.zig b/src/link/Elf/Object.zig index f595988e82..2bcc56b038 100644 --- a/src/link/Elf/Object.zig +++ b/src/link/Elf/Object.zig @@ -741,6 +741,63 @@ pub fn writeAr(self: Object, writer: anytype) !void { try writer.writeAll(self.data); } +pub fn updateSymtabSize(self: *Object, elf_file: *Elf) !void { + for (self.locals()) |local_index| { + const local = elf_file.symbol(local_index); + if (local.atom(elf_file)) |atom| if (!atom.flags.alive) continue; + const esym = local.elfSym(elf_file); + switch (esym.st_type()) { + elf.STT_SECTION, elf.STT_NOTYPE => continue, + else => {}, + } + local.flags.output_symtab = true; + try local.setOutputSymtabIndex(self.output_symtab_ctx.nlocals, elf_file); + self.output_symtab_ctx.nlocals += 1; + self.output_symtab_ctx.strsize += @as(u32, @intCast(local.name(elf_file).len)) + 1; + } + + for (self.globals()) |global_index| { + const global = elf_file.symbol(global_index); + const file_ptr = global.file(elf_file) orelse continue; + if (file_ptr.index() != self.index) continue; + if (global.atom(elf_file)) |atom| if (!atom.flags.alive) continue; + global.flags.output_symtab = true; + if (global.isLocal(elf_file)) { + try global.setOutputSymtabIndex(self.output_symtab_ctx.nlocals, elf_file); + self.output_symtab_ctx.nlocals += 1; + } else { + try global.setOutputSymtabIndex(self.output_symtab_ctx.nglobals, elf_file); + self.output_symtab_ctx.nglobals += 1; + } + self.output_symtab_ctx.strsize += @as(u32, @intCast(global.name(elf_file).len)) + 1; + } +} + +pub fn writeSymtab(self: Object, elf_file: *Elf) void { + for (self.locals()) |local_index| { + const local = elf_file.symbol(local_index); + const idx = local.outputSymtabIndex(elf_file) orelse continue; + const out_sym = &elf_file.symtab.items[idx]; + out_sym.st_name = @intCast(elf_file.strtab.items.len); + elf_file.strtab.appendSliceAssumeCapacity(local.name(elf_file)); + elf_file.strtab.appendAssumeCapacity(0); + local.setOutputSym(elf_file, out_sym); + } + + for (self.globals()) |global_index| { + const global = elf_file.symbol(global_index); + const file_ptr = global.file(elf_file) orelse continue; + if (file_ptr.index() != self.index) continue; + const idx = global.outputSymtabIndex(elf_file) orelse continue; + const st_name = @as(u32, @intCast(elf_file.strtab.items.len)); + elf_file.strtab.appendSliceAssumeCapacity(global.name(elf_file)); + elf_file.strtab.appendAssumeCapacity(0); + const out_sym = &elf_file.symtab.items[idx]; + out_sym.st_name = st_name; + global.setOutputSym(elf_file, out_sym); + } +} + pub fn locals(self: Object) []const Symbol.Index { if (self.symbols.items.len == 0) return &[0]Symbol.Index{}; const end = self.first_global orelse self.symbols.items.len; diff --git a/src/link/Elf/SharedObject.zig b/src/link/Elf/SharedObject.zig index 2317719012..b3302b88d4 100644 --- a/src/link/Elf/SharedObject.zig +++ b/src/link/Elf/SharedObject.zig @@ -191,6 +191,34 @@ pub fn globals(self: SharedObject) []const Symbol.Index { return self.symbols.items; } +pub fn updateSymtabSize(self: *SharedObject, elf_file: *Elf) !void { + for (self.globals()) |global_index| { + const global = elf_file.symbol(global_index); + const file_ptr = global.file(elf_file) orelse continue; + if (file_ptr.index() != self.index) continue; + if (global.isLocal(elf_file)) continue; + global.flags.output_symtab = true; + try global.setOutputSymtabIndex(self.output_symtab_ctx.nglobals, elf_file); + self.output_symtab_ctx.nglobals += 1; + self.output_symtab_ctx.strsize += @as(u32, @intCast(global.name(elf_file).len)) + 1; + } +} + +pub fn writeSymtab(self: SharedObject, elf_file: *Elf) void { + for (self.globals()) |global_index| { + const global = elf_file.symbol(global_index); + const file_ptr = global.file(elf_file) orelse continue; + if (file_ptr.index() != self.index) continue; + const idx = global.outputSymtabIndex(elf_file) orelse continue; + const st_name = @as(u32, @intCast(elf_file.strtab.items.len)); + elf_file.strtab.appendSliceAssumeCapacity(global.name(elf_file)); + elf_file.strtab.appendAssumeCapacity(0); + const out_sym = &elf_file.symtab.items[idx]; + out_sym.st_name = st_name; + global.setOutputSym(elf_file, out_sym); + } +} + pub fn shdrContents(self: SharedObject, index: u16) []const u8 { const shdr = self.shdrs.items[index]; return self.data[shdr.sh_offset..][0..shdr.sh_size]; diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig index 98bc779ee7..7f2a5efee8 100644 --- a/src/link/Elf/ZigObject.zig +++ b/src/link/Elf/ZigObject.zig @@ -528,6 +528,63 @@ pub fn globals(self: ZigObject) []const Symbol.Index { return self.global_symbols.items; } +pub fn updateSymtabSize(self: *ZigObject, elf_file: *Elf) !void { + for (self.locals()) |local_index| { + const local = elf_file.symbol(local_index); + if (local.atom(elf_file)) |atom| if (!atom.flags.alive) continue; + const esym = local.elfSym(elf_file); + switch (esym.st_type()) { + elf.STT_SECTION, elf.STT_NOTYPE => continue, + else => {}, + } + local.flags.output_symtab = true; + try local.setOutputSymtabIndex(self.output_symtab_ctx.nlocals, elf_file); + self.output_symtab_ctx.nlocals += 1; + self.output_symtab_ctx.strsize += @as(u32, @intCast(local.name(elf_file).len)) + 1; + } + + for (self.globals()) |global_index| { + const global = elf_file.symbol(global_index); + const file_ptr = global.file(elf_file) orelse continue; + if (file_ptr.index() != self.index) continue; + if (global.atom(elf_file)) |atom| if (!atom.flags.alive) continue; + global.flags.output_symtab = true; + if (global.isLocal(elf_file)) { + try global.setOutputSymtabIndex(self.output_symtab_ctx.nlocals, elf_file); + self.output_symtab_ctx.nlocals += 1; + } else { + try global.setOutputSymtabIndex(self.output_symtab_ctx.nglobals, elf_file); + self.output_symtab_ctx.nglobals += 1; + } + self.output_symtab_ctx.strsize += @as(u32, @intCast(global.name(elf_file).len)) + 1; + } +} + +pub fn writeSymtab(self: ZigObject, elf_file: *Elf) void { + for (self.locals()) |local_index| { + const local = elf_file.symbol(local_index); + const idx = local.outputSymtabIndex(elf_file) orelse continue; + const out_sym = &elf_file.symtab.items[idx]; + out_sym.st_name = @intCast(elf_file.strtab.items.len); + elf_file.strtab.appendSliceAssumeCapacity(local.name(elf_file)); + elf_file.strtab.appendAssumeCapacity(0); + local.setOutputSym(elf_file, out_sym); + } + + for (self.globals()) |global_index| { + const global = elf_file.symbol(global_index); + const file_ptr = global.file(elf_file) orelse continue; + if (file_ptr.index() != self.index) continue; + const idx = global.outputSymtabIndex(elf_file) orelse continue; + const st_name = @as(u32, @intCast(elf_file.strtab.items.len)); + elf_file.strtab.appendSliceAssumeCapacity(global.name(elf_file)); + elf_file.strtab.appendAssumeCapacity(0); + const out_sym = &elf_file.symtab.items[idx]; + out_sym.st_name = st_name; + global.setOutputSym(elf_file, out_sym); + } +} + pub fn asFile(self: *ZigObject) File { return .{ .zig_object = self }; } diff --git a/src/link/Elf/file.zig b/src/link/Elf/file.zig index 29a76daad9..cb83e945d7 100644 --- a/src/link/Elf/file.zig +++ b/src/link/Elf/file.zig @@ -128,63 +128,15 @@ pub const File = union(enum) { } pub fn updateSymtabSize(file: File, elf_file: *Elf) !void { - const output_symtab_ctx = switch (file) { - inline else => |x| &x.output_symtab_ctx, + return switch (file) { + inline else => |x| x.updateSymtabSize(elf_file), }; - for (file.locals()) |local_index| { - const local = elf_file.symbol(local_index); - if (local.atom(elf_file)) |atom| if (!atom.flags.alive) continue; - const esym = local.elfSym(elf_file); - switch (esym.st_type()) { - elf.STT_SECTION, elf.STT_NOTYPE => continue, - else => {}, - } - local.flags.output_symtab = true; - try local.setOutputSymtabIndex(output_symtab_ctx.nlocals, elf_file); - output_symtab_ctx.nlocals += 1; - output_symtab_ctx.strsize += @as(u32, @intCast(local.name(elf_file).len)) + 1; - } - - for (file.globals()) |global_index| { - const global = elf_file.symbol(global_index); - const file_ptr = global.file(elf_file) orelse continue; - if (file_ptr.index() != file.index()) continue; - if (global.atom(elf_file)) |atom| if (!atom.flags.alive) continue; - global.flags.output_symtab = true; - if (global.isLocal(elf_file)) { - try global.setOutputSymtabIndex(output_symtab_ctx.nlocals, elf_file); - output_symtab_ctx.nlocals += 1; - } else { - try global.setOutputSymtabIndex(output_symtab_ctx.nglobals, elf_file); - output_symtab_ctx.nglobals += 1; - } - output_symtab_ctx.strsize += @as(u32, @intCast(global.name(elf_file).len)) + 1; - } } pub fn writeSymtab(file: File, elf_file: *Elf) void { - for (file.locals()) |local_index| { - const local = elf_file.symbol(local_index); - const idx = local.outputSymtabIndex(elf_file) orelse continue; - const out_sym = &elf_file.symtab.items[idx]; - out_sym.st_name = @intCast(elf_file.strtab.items.len); - elf_file.strtab.appendSliceAssumeCapacity(local.name(elf_file)); - elf_file.strtab.appendAssumeCapacity(0); - local.setOutputSym(elf_file, out_sym); - } - - for (file.globals()) |global_index| { - const global = elf_file.symbol(global_index); - const file_ptr = global.file(elf_file) orelse continue; - if (file_ptr.index() != file.index()) continue; - const idx = global.outputSymtabIndex(elf_file) orelse continue; - const st_name = @as(u32, @intCast(elf_file.strtab.items.len)); - elf_file.strtab.appendSliceAssumeCapacity(global.name(elf_file)); - elf_file.strtab.appendAssumeCapacity(0); - const out_sym = &elf_file.symtab.items[idx]; - out_sym.st_name = st_name; - global.setOutputSym(elf_file, out_sym); - } + return switch (file) { + inline else => |x| x.writeSymtab(elf_file), + }; } pub fn updateArSymtab(file: File, ar_symtab: *Archive.ArSymtab, elf_file: *Elf) !void { diff --git a/src/link/Elf/synthetic_sections.zig b/src/link/Elf/synthetic_sections.zig index 47e72cb1e3..25a9975f01 100644 --- a/src/link/Elf/synthetic_sections.zig +++ b/src/link/Elf/synthetic_sections.zig @@ -917,8 +917,7 @@ pub const PltSection = struct { } pub fn writeSymtab(plt: PltSection, elf_file: *Elf) void { - var ilocal = plt.output_symtab_ctx.ilocal; - for (plt.symbols.items) |sym_index| { + for (plt.symbols.items, plt.output_symtab_ctx.ilocal..) |sym_index, ilocal| { const sym = elf_file.symbol(sym_index); const st_name = @as(u32, @intCast(elf_file.strtab.items.len)); elf_file.strtab.appendSliceAssumeCapacity(sym.name(elf_file)); @@ -932,7 +931,6 @@ pub const PltSection = struct { .st_value = sym.pltAddress(elf_file), .st_size = 16, }; - ilocal += 1; } } @@ -1046,8 +1044,7 @@ pub const PltGotSection = struct { } pub fn writeSymtab(plt_got: PltGotSection, elf_file: *Elf) void { - var ilocal = plt_got.output_symtab_ctx.ilocal; - for (plt_got.symbols.items) |sym_index| { + for (plt_got.symbols.items, plt_got.output_symtab_ctx.ilocal..) |sym_index, ilocal| { const sym = elf_file.symbol(sym_index); const st_name = @as(u32, @intCast(elf_file.strtab.items.len)); elf_file.strtab.appendSliceAssumeCapacity(sym.name(elf_file)); @@ -1061,7 +1058,6 @@ pub const PltGotSection = struct { .st_value = sym.pltGotAddress(elf_file), .st_size = 16, }; - ilocal += 1; } } };