mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
elf: generate section symbols when writing symtab
This commit is contained in:
parent
3df53d1722
commit
c7ed7c4690
110
src/link/Elf.zig
110
src/link/Elf.zig
@ -597,7 +597,6 @@ pub fn initMetadata(self: *Elf) !void {
|
||||
const shdr = &self.shdrs.items[self.zig_text_section_index.?];
|
||||
fillSection(self, shdr, self.base.options.program_code_size_hint, self.phdr_zig_load_re_index);
|
||||
if (self.isRelocatable()) {
|
||||
try zig_object.addSectionSymbol(self.zig_text_section_index.?, self);
|
||||
self.zig_text_rela_section_index = try self.addRelaShdr(
|
||||
".rela.text.zig",
|
||||
self.zig_text_section_index.?,
|
||||
@ -609,6 +608,7 @@ pub fn initMetadata(self: *Elf) !void {
|
||||
self.phdr_zig_load_re_index.?,
|
||||
);
|
||||
}
|
||||
try self.output_sections.putNoClobber(gpa, self.zig_text_section_index.?, .{});
|
||||
try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_text_section_index.?, .{});
|
||||
}
|
||||
|
||||
@ -644,7 +644,6 @@ pub fn initMetadata(self: *Elf) !void {
|
||||
const shdr = &self.shdrs.items[self.zig_data_rel_ro_section_index.?];
|
||||
fillSection(self, shdr, 1024, self.phdr_zig_load_ro_index);
|
||||
if (self.isRelocatable()) {
|
||||
try zig_object.addSectionSymbol(self.zig_data_rel_ro_section_index.?, self);
|
||||
self.zig_data_rel_ro_rela_section_index = try self.addRelaShdr(
|
||||
".rela.data.rel.ro.zig",
|
||||
self.zig_data_rel_ro_section_index.?,
|
||||
@ -656,6 +655,7 @@ pub fn initMetadata(self: *Elf) !void {
|
||||
self.phdr_zig_load_ro_index.?,
|
||||
);
|
||||
}
|
||||
try self.output_sections.putNoClobber(gpa, self.zig_data_rel_ro_section_index.?, .{});
|
||||
try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_data_rel_ro_section_index.?, .{});
|
||||
}
|
||||
|
||||
@ -670,7 +670,6 @@ pub fn initMetadata(self: *Elf) !void {
|
||||
const shdr = &self.shdrs.items[self.zig_data_section_index.?];
|
||||
fillSection(self, shdr, 1024, self.phdr_zig_load_rw_index);
|
||||
if (self.isRelocatable()) {
|
||||
try zig_object.addSectionSymbol(self.zig_data_section_index.?, self);
|
||||
self.zig_data_rela_section_index = try self.addRelaShdr(
|
||||
".rela.data.zig",
|
||||
self.zig_data_section_index.?,
|
||||
@ -682,6 +681,7 @@ pub fn initMetadata(self: *Elf) !void {
|
||||
self.phdr_zig_load_rw_index.?,
|
||||
);
|
||||
}
|
||||
try self.output_sections.putNoClobber(gpa, self.zig_data_section_index.?, .{});
|
||||
try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_data_section_index.?, .{});
|
||||
}
|
||||
|
||||
@ -700,9 +700,9 @@ pub fn initMetadata(self: *Elf) !void {
|
||||
shdr.sh_size = phdr.p_memsz;
|
||||
try self.phdr_to_shdr_table.putNoClobber(gpa, self.zig_bss_section_index.?, phndx);
|
||||
} else {
|
||||
try zig_object.addSectionSymbol(self.zig_bss_section_index.?, self);
|
||||
shdr.sh_size = 1024;
|
||||
}
|
||||
try self.output_sections.putNoClobber(gpa, self.zig_bss_section_index.?, .{});
|
||||
try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_bss_section_index.?, .{});
|
||||
}
|
||||
|
||||
@ -724,6 +724,7 @@ pub fn initMetadata(self: *Elf) !void {
|
||||
shdr.sh_offset = off;
|
||||
shdr.sh_size = size;
|
||||
zig_object.debug_strtab_dirty = true;
|
||||
try self.output_sections.putNoClobber(gpa, self.debug_str_section_index.?, .{});
|
||||
}
|
||||
|
||||
if (self.debug_info_section_index == null) {
|
||||
@ -739,6 +740,7 @@ pub fn initMetadata(self: *Elf) !void {
|
||||
shdr.sh_offset = off;
|
||||
shdr.sh_size = size;
|
||||
zig_object.debug_info_header_dirty = true;
|
||||
try self.output_sections.putNoClobber(gpa, self.debug_info_section_index.?, .{});
|
||||
}
|
||||
|
||||
if (self.debug_abbrev_section_index == null) {
|
||||
@ -754,6 +756,7 @@ pub fn initMetadata(self: *Elf) !void {
|
||||
shdr.sh_offset = off;
|
||||
shdr.sh_size = size;
|
||||
zig_object.debug_abbrev_section_dirty = true;
|
||||
try self.output_sections.putNoClobber(gpa, self.debug_abbrev_section_index.?, .{});
|
||||
}
|
||||
|
||||
if (self.debug_aranges_section_index == null) {
|
||||
@ -769,6 +772,7 @@ pub fn initMetadata(self: *Elf) !void {
|
||||
shdr.sh_offset = off;
|
||||
shdr.sh_size = size;
|
||||
zig_object.debug_aranges_section_dirty = true;
|
||||
try self.output_sections.putNoClobber(gpa, self.debug_aranges_section_index.?, .{});
|
||||
}
|
||||
|
||||
if (self.debug_line_section_index == null) {
|
||||
@ -784,6 +788,7 @@ pub fn initMetadata(self: *Elf) !void {
|
||||
shdr.sh_offset = off;
|
||||
shdr.sh_size = size;
|
||||
zig_object.debug_line_header_dirty = true;
|
||||
try self.output_sections.putNoClobber(gpa, self.debug_line_section_index.?, .{});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1510,14 +1515,14 @@ pub fn flushStaticLib(self: *Elf) link.File.FlushError!void {
|
||||
try self.initShStrtab();
|
||||
try self.sortShdrs();
|
||||
zig_object.updateRelaSectionsSizes(self);
|
||||
self.updateSymtabSizeObject(zig_object);
|
||||
self.updateSymtabSizeZigObject(zig_object);
|
||||
self.updateShStrtabSize();
|
||||
|
||||
try self.allocateNonAllocSections();
|
||||
|
||||
try self.writeShdrTable();
|
||||
try zig_object.writeRelaSections(self);
|
||||
try self.writeSymtabObject(zig_object);
|
||||
try self.writeSymtabZigObject(zig_object);
|
||||
try self.writeShStrtab();
|
||||
try self.writeElfHeader();
|
||||
}
|
||||
@ -3579,7 +3584,8 @@ fn sortInitFini(self: *Elf) !void {
|
||||
|
||||
if (!is_init_fini and !is_ctor_dtor) continue;
|
||||
|
||||
const atom_list = self.output_sections.getPtr(@intCast(shndx)) orelse continue;
|
||||
const atom_list = self.output_sections.getPtr(@intCast(shndx)).?;
|
||||
if (atom_list.items.len == 0) continue;
|
||||
|
||||
var entries = std.ArrayList(Entry).init(gpa);
|
||||
try entries.ensureTotalCapacityPrecise(atom_list.items.len);
|
||||
@ -3909,6 +3915,20 @@ fn sortShdrs(self: *Elf) !void {
|
||||
shdr.sh_info = backlinks[shdr.sh_info];
|
||||
}
|
||||
|
||||
{
|
||||
var output_sections = try self.output_sections.clone(gpa);
|
||||
defer output_sections.deinit(gpa);
|
||||
|
||||
self.output_sections.clearRetainingCapacity();
|
||||
|
||||
var it = output_sections.iterator();
|
||||
while (it.next()) |entry| {
|
||||
const shndx = entry.key_ptr.*;
|
||||
const meta = entry.value_ptr.*;
|
||||
self.output_sections.putAssumeCapacityNoClobber(backlinks[shndx], meta);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
var last_atom_and_free_list_table = try self.last_atom_and_free_list_table.clone(gpa);
|
||||
defer last_atom_and_free_list_table.deinit(gpa);
|
||||
@ -3962,7 +3982,6 @@ fn sortShdrs(self: *Elf) !void {
|
||||
|
||||
fn updateSectionSizes(self: *Elf) !void {
|
||||
for (self.output_sections.keys(), self.output_sections.values()) |shndx, atom_list| {
|
||||
if (atom_list.items.len == 0) continue;
|
||||
const shdr = &self.shdrs.items[shndx];
|
||||
for (atom_list.items) |atom_index| {
|
||||
const atom_ptr = self.atom(atom_index) orelse continue;
|
||||
@ -4056,7 +4075,6 @@ fn updateSectionSizes(self: *Elf) !void {
|
||||
|
||||
fn updateSectionSizesObject(self: *Elf) !void {
|
||||
for (self.output_sections.keys(), self.output_sections.values()) |shndx, atom_list| {
|
||||
if (atom_list.items.len == 0) continue;
|
||||
const shdr = &self.shdrs.items[shndx];
|
||||
for (atom_list.items) |atom_index| {
|
||||
const atom_ptr = self.atom(atom_index) orelse continue;
|
||||
@ -4317,7 +4335,6 @@ fn allocateAllocSections(self: *Elf) error{OutOfMemory}!void {
|
||||
/// Allocates alloc sections when merging relocatable objects files together.
|
||||
fn allocateAllocSectionsObject(self: *Elf) !void {
|
||||
_ = self;
|
||||
@panic("TODO");
|
||||
}
|
||||
|
||||
/// Allocates non-alloc sections (debug info, symtabs, etc.).
|
||||
@ -4444,6 +4461,7 @@ fn writeAtoms(self: *Elf) !void {
|
||||
if (shdr.sh_type == elf.SHT_NOBITS) continue;
|
||||
|
||||
const atom_list = self.output_sections.get(@intCast(shndx)) orelse continue;
|
||||
if (atom_list.items.len == 0) continue;
|
||||
|
||||
log.debug("writing atoms in '{s}' section", .{self.getShString(shdr.sh_name)});
|
||||
|
||||
@ -4519,6 +4537,7 @@ fn writeAtomsObject(self: *Elf) !void {
|
||||
if (shdr.sh_type == elf.SHT_NOBITS) continue;
|
||||
|
||||
const atom_list = self.output_sections.get(@intCast(shndx)) orelse continue;
|
||||
if (atom_list.items.len == 0) continue;
|
||||
|
||||
log.debug("writing atoms in '{s}' section", .{self.getShString(shdr.sh_name)});
|
||||
|
||||
@ -4617,6 +4636,11 @@ fn updateSymtabSize(self: *Elf) void {
|
||||
sizes.add(file_ptr.linker_defined.output_symtab_size);
|
||||
}
|
||||
|
||||
// Section symbols
|
||||
for (self.output_sections.keys()) |_| {
|
||||
sizes.nlocals += 1;
|
||||
}
|
||||
|
||||
const symtab_shdr = &self.shdrs.items[self.symtab_section_index.?];
|
||||
symtab_shdr.sh_info = sizes.nlocals + 1;
|
||||
symtab_shdr.sh_link = self.strtab_section_index.?;
|
||||
@ -4632,9 +4656,16 @@ fn updateSymtabSize(self: *Elf) void {
|
||||
strtab.sh_size = sizes.strsize + 1;
|
||||
}
|
||||
|
||||
fn updateSymtabSizeObject(self: *Elf, zig_object: *ZigObject) void {
|
||||
fn updateSymtabSizeZigObject(self: *Elf, zig_object: *ZigObject) void {
|
||||
var sizes = SymtabSize{};
|
||||
|
||||
zig_object.asFile().updateSymtabSize(self);
|
||||
const sizes = zig_object.output_symtab_size;
|
||||
sizes.add(zig_object.output_symtab_size);
|
||||
|
||||
// Section symbols
|
||||
for (self.output_sections.keys()) |_| {
|
||||
sizes.nlocals += 1;
|
||||
}
|
||||
|
||||
const symtab_shdr = &self.shdrs.items[self.symtab_section_index.?];
|
||||
symtab_shdr.sh_info = sizes.nlocals + 1;
|
||||
@ -4798,7 +4829,7 @@ fn writeSyntheticSectionsObject(self: *Elf) !void {
|
||||
var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size);
|
||||
defer buffer.deinit();
|
||||
try eh_frame.writeEhFrame(self, buffer.writer());
|
||||
try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
|
||||
// try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
|
||||
}
|
||||
|
||||
try self.writeSymtab();
|
||||
@ -4812,6 +4843,16 @@ fn writeShStrtab(self: *Elf) !void {
|
||||
}
|
||||
}
|
||||
|
||||
const WriteSymtabCtx = struct {
|
||||
ilocal: usize,
|
||||
iglobal: usize,
|
||||
|
||||
fn incr(this: *@This(), ss: SymtabSize) void {
|
||||
this.ilocal += ss.nlocals;
|
||||
this.iglobal += ss.nglobals;
|
||||
}
|
||||
};
|
||||
|
||||
fn writeSymtab(self: *Elf) !void {
|
||||
const gpa = self.base.allocator;
|
||||
const symtab_shdr = self.shdrs.items[self.symtab_section_index.?];
|
||||
@ -4828,20 +4869,13 @@ fn writeSymtab(self: *Elf) !void {
|
||||
const needed_strtab_size = math.cast(usize, strtab_shdr.sh_size - 1) orelse return error.Overflow;
|
||||
try self.strtab.ensureUnusedCapacity(gpa, needed_strtab_size);
|
||||
|
||||
const Ctx = struct {
|
||||
ilocal: usize,
|
||||
iglobal: usize,
|
||||
|
||||
fn incr(this: *@This(), ss: SymtabSize) void {
|
||||
this.ilocal += ss.nlocals;
|
||||
this.iglobal += ss.nglobals;
|
||||
}
|
||||
};
|
||||
var ctx: Ctx = .{
|
||||
var ctx: WriteSymtabCtx = .{
|
||||
.ilocal = 1,
|
||||
.iglobal = symtab_shdr.sh_info,
|
||||
};
|
||||
|
||||
ctx.incr(self.writeSectionSymbols(ctx));
|
||||
|
||||
if (self.zigObjectPtr()) |zig_object| {
|
||||
zig_object.asFile().writeSymtab(self, ctx);
|
||||
ctx.incr(zig_object.output_symtab_size);
|
||||
@ -4915,7 +4949,7 @@ fn writeSymtab(self: *Elf) !void {
|
||||
try self.base.file.?.pwriteAll(self.strtab.items, strtab_shdr.sh_offset);
|
||||
}
|
||||
|
||||
fn writeSymtabObject(self: *Elf, zig_object: *ZigObject) !void {
|
||||
fn writeSymtabZigObject(self: *Elf, zig_object: *ZigObject) !void {
|
||||
const gpa = self.base.allocator;
|
||||
const symtab_shdr = self.shdrs.items[self.symtab_section_index.?];
|
||||
const strtab_shdr = self.shdrs.items[self.strtab_section_index.?];
|
||||
@ -4931,7 +4965,15 @@ fn writeSymtabObject(self: *Elf, zig_object: *ZigObject) !void {
|
||||
const needed_strtab_size = math.cast(usize, strtab_shdr.sh_size - 1) orelse return error.Overflow;
|
||||
try self.strtab.ensureUnusedCapacity(gpa, needed_strtab_size);
|
||||
|
||||
zig_object.asFile().writeSymtab(self, .{ .ilocal = 1, .iglobal = symtab_shdr.sh_info });
|
||||
var ctx: WriteSymtabCtx = .{
|
||||
.ilocal = 1,
|
||||
.iglobal = symtab_shdr.sh_info,
|
||||
};
|
||||
|
||||
ctx.incr(self.writeSectionSymbols(ctx));
|
||||
|
||||
zig_object.asFile().writeSymtab(self, ctx);
|
||||
ctx.incr(zig_object.output_symtab_size);
|
||||
|
||||
const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian();
|
||||
switch (self.ptr_width) {
|
||||
@ -4963,6 +5005,24 @@ fn writeSymtabObject(self: *Elf, zig_object: *ZigObject) !void {
|
||||
try self.base.file.?.pwriteAll(self.strtab.items, strtab_shdr.sh_offset);
|
||||
}
|
||||
|
||||
fn writeSectionSymbols(self: *Elf, ctx: WriteSymtabCtx) SymtabSize {
|
||||
var ilocal = ctx.ilocal;
|
||||
for (self.output_sections.keys()) |shndx| {
|
||||
const shdr = self.shdrs.items[shndx];
|
||||
const out_sym = &self.symtab.items[ilocal];
|
||||
out_sym.* = .{
|
||||
.st_name = 0,
|
||||
.st_value = shdr.sh_addr,
|
||||
.st_info = elf.STT_SECTION,
|
||||
.st_shndx = @intCast(shndx),
|
||||
.st_size = 0,
|
||||
.st_other = 0,
|
||||
};
|
||||
ilocal += 1;
|
||||
}
|
||||
return .{ .nlocals = @intCast(ilocal - ctx.ilocal) };
|
||||
}
|
||||
|
||||
/// Always 4 or 8 depending on whether this is 32-bit ELF or 64-bit ELF.
|
||||
fn ptrWidthBytes(self: Elf) u8 {
|
||||
return switch (self.ptr_width) {
|
||||
|
||||
@ -60,6 +60,11 @@ pub fn inputShdr(self: Atom, elf_file: *Elf) Object.ElfShdr {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn relocsShndx(self: Atom) ?u32 {
|
||||
if (self.relocs_section_index == 0) return null;
|
||||
return self.relocs_section_index;
|
||||
}
|
||||
|
||||
pub fn outputShndx(self: Atom) ?u16 {
|
||||
if (self.output_section_index == 0) return null;
|
||||
return self.output_section_index;
|
||||
@ -280,9 +285,10 @@ pub fn free(self: *Atom, elf_file: *Elf) void {
|
||||
}
|
||||
|
||||
pub fn relocs(self: Atom, elf_file: *Elf) []align(1) const elf.Elf64_Rela {
|
||||
const shndx = self.relocsShndx() orelse return &[0]elf.Elf64_Rela{};
|
||||
return switch (self.file(elf_file).?) {
|
||||
.zig_object => |x| x.relocs.items[self.relocs_section_index].items,
|
||||
.object => |x| x.getRelocs(self.relocs_section_index),
|
||||
.zig_object => |x| x.relocs.items[shndx].items,
|
||||
.object => |x| x.getRelocs(shndx),
|
||||
else => unreachable,
|
||||
};
|
||||
}
|
||||
|
||||
@ -211,6 +211,7 @@ fn addAtom(self: *Object, shdr: ElfShdr, shndx: u16, elf_file: *Elf) error{OutOf
|
||||
fn initOutputSection(self: Object, elf_file: *Elf, shdr: ElfShdr) error{OutOfMemory}!u16 {
|
||||
const name = blk: {
|
||||
const name = self.getString(shdr.sh_name);
|
||||
if (elf_file.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",
|
||||
@ -237,7 +238,10 @@ fn initOutputSection(self: Object, elf_file: *Elf, shdr: ElfShdr) error{OutOfMem
|
||||
else => shdr.sh_type,
|
||||
};
|
||||
const flags = blk: {
|
||||
const flags = shdr.sh_flags & ~@as(u64, elf.SHF_COMPRESSED | elf.SHF_GROUP | elf.SHF_GNU_RETAIN);
|
||||
var flags = shdr.sh_flags;
|
||||
if (!elf_file.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,
|
||||
@ -655,8 +659,13 @@ pub fn allocateAtoms(self: Object, elf_file: *Elf) void {
|
||||
}
|
||||
|
||||
pub fn initRelaSections(self: Object, elf_file: *Elf) !void {
|
||||
_ = self;
|
||||
_ = elf_file;
|
||||
for (self.atoms.items) |atom_index| {
|
||||
const atom = elf_file.atom(atom_index) orelse continue;
|
||||
if (!atom.flags.alive) continue;
|
||||
const shndx = atom.relocsShndx() orelse continue;
|
||||
const shdr = self.shdrs.items[shndx];
|
||||
_ = try self.initOutputSection(elf_file, shdr);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn updateRelaSectionsSizes(self: Object, elf_file: *Elf) void {
|
||||
|
||||
@ -219,8 +219,6 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void {
|
||||
const st_shndx = blk: {
|
||||
if (symbol.flags.has_copy_rel) break :blk elf_file.copy_rel_section_index.?;
|
||||
if (file_ptr == .shared_object or esym.st_shndx == elf.SHN_UNDEF) break :blk elf.SHN_UNDEF;
|
||||
// TODO I think this is wrong and obsolete
|
||||
if (elf_file.isRelocatable() and st_type == elf.STT_SECTION) break :blk symbol.outputShndx().?;
|
||||
if (symbol.atom(elf_file) == null and file_ptr != .linker_defined)
|
||||
break :blk elf.SHN_ABS;
|
||||
break :blk symbol.outputShndx() orelse elf.SHN_UNDEF;
|
||||
|
||||
@ -287,22 +287,6 @@ pub fn addAtom(self: *ZigObject, elf_file: *Elf) !Symbol.Index {
|
||||
return symbol_index;
|
||||
}
|
||||
|
||||
pub fn addSectionSymbol(self: *ZigObject, shndx: u16, elf_file: *Elf) !void {
|
||||
assert(elf_file.isRelocatable());
|
||||
const gpa = elf_file.base.allocator;
|
||||
const symbol_index = try elf_file.addSymbol();
|
||||
try self.local_symbols.append(gpa, symbol_index);
|
||||
const symbol_ptr = elf_file.symbol(symbol_index);
|
||||
symbol_ptr.file_index = self.index;
|
||||
symbol_ptr.output_section_index = shndx;
|
||||
|
||||
const esym_index = try self.addLocalEsym(gpa);
|
||||
const esym = &self.local_esyms.items(.elf_sym)[esym_index];
|
||||
esym.st_info = elf.STT_SECTION;
|
||||
esym.st_shndx = shndx;
|
||||
symbol_ptr.esym_index = esym_index;
|
||||
}
|
||||
|
||||
/// TODO actually create fake input shdrs and return that instead.
|
||||
pub fn inputShdr(self: ZigObject, atom_index: Atom.Index, elf_file: *Elf) Object.ElfShdr {
|
||||
_ = self;
|
||||
|
||||
@ -136,8 +136,7 @@ pub const File = union(enum) {
|
||||
if (local.atom(elf_file)) |atom| if (!atom.flags.alive) continue;
|
||||
const esym = local.elfSym(elf_file);
|
||||
switch (esym.st_type()) {
|
||||
elf.STT_SECTION => if (!elf_file.isRelocatable()) continue,
|
||||
elf.STT_NOTYPE => continue,
|
||||
elf.STT_SECTION, elf.STT_NOTYPE => continue,
|
||||
else => {},
|
||||
}
|
||||
local.flags.output_symtab = true;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user