Commit e448fb9601
Changed files (5)
src/link/Elf/Atom.zig
@@ -118,10 +118,19 @@ pub fn capacity(self: Atom, elf_file: *Elf) u64 {
return @intCast(next_addr - self.address(elf_file));
}
+pub fn fileCapacity(self: Atom, elf_file: *Elf) u64 {
+ const self_off = self.offset(elf_file);
+ const next_off = if (self.nextAtom(elf_file)) |next_atom|
+ next_atom.offset(elf_file)
+ else
+ self_off + elf_file.allocatedSize(self_off);
+ return @intCast(next_off - self_off);
+}
+
pub fn freeListEligible(self: Atom, elf_file: *Elf) bool {
// No need to keep a free list node for the last block.
const next = self.nextAtom(elf_file) orelse return false;
- const cap: u64 = @intCast(next.address(elf_file) - self.address(elf_file));
+ const cap: u64 = @intCast(next.value - self.value);
const ideal_cap = Elf.padToIdeal(self.size);
if (cap <= ideal_cap) return false;
const surplus = cap - ideal_cap;
src/link/Elf/relocatable.zig
@@ -394,24 +394,14 @@ fn allocateAllocSections(elf_file: *Elf) !void {
shdr.sh_size = 0;
const new_offset = try elf_file.findFreeSpace(needed_size, shdr.sh_addralign);
- if (elf_file.zigObjectPtr()) |zo| blk: {
- const existing_size = for ([_]?Symbol.Index{
- zo.text_index,
- zo.rodata_index,
- zo.data_relro_index,
- zo.data_index,
- zo.tdata_index,
- zo.eh_frame_index,
- }) |maybe_sym_index| {
- const sect_sym_index = maybe_sym_index orelse continue;
- const sect_atom_ptr = zo.symbol(sect_sym_index).atom(elf_file).?;
- if (sect_atom_ptr.output_section_index == shndx) break sect_atom_ptr.size;
- } else break :blk;
- log.debug("moving {s} from 0x{x} to 0x{x}", .{
- elf_file.getShString(shdr.sh_name),
- shdr.sh_offset,
- new_offset,
- });
+ log.debug("moving {s} from 0x{x} to 0x{x}", .{
+ elf_file.getShString(shdr.sh_name),
+ shdr.sh_offset,
+ new_offset,
+ });
+
+ if (shdr.sh_offset > 0) {
+ const existing_size = elf_file.sectionSize(@intCast(shndx));
const amt = try elf_file.base.file.?.copyRangeAll(
shdr.sh_offset,
elf_file.base.file.?,
src/link/Elf/ZigObject.zig
@@ -130,10 +130,10 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
.entsize = 1,
.type = elf.SHT_PROGBITS,
.addralign = 1,
+ .offset = std.math.maxInt(u64),
});
self.debug_str_section_dirty = true;
self.debug_str_index = try addSectionSymbolWithAtom(self, gpa, ".debug_str", .@"1", osec);
- elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_str_index.?).ref;
}
if (self.debug_info_index == null) {
@@ -141,10 +141,10 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
.name = try elf_file.insertShString(".debug_info"),
.type = elf.SHT_PROGBITS,
.addralign = 1,
+ .offset = std.math.maxInt(u64),
});
self.debug_info_section_dirty = true;
self.debug_info_index = try addSectionSymbolWithAtom(self, gpa, ".debug_info", .@"1", osec);
- elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_info_index.?).ref;
}
if (self.debug_abbrev_index == null) {
@@ -152,10 +152,10 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
.name = try elf_file.insertShString(".debug_abbrev"),
.type = elf.SHT_PROGBITS,
.addralign = 1,
+ .offset = std.math.maxInt(u64),
});
self.debug_abbrev_section_dirty = true;
self.debug_abbrev_index = try addSectionSymbolWithAtom(self, gpa, ".debug_abbrev", .@"1", osec);
- elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_abbrev_index.?).ref;
}
if (self.debug_aranges_index == null) {
@@ -163,10 +163,10 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
.name = try elf_file.insertShString(".debug_aranges"),
.type = elf.SHT_PROGBITS,
.addralign = 16,
+ .offset = std.math.maxInt(u64),
});
self.debug_aranges_section_dirty = true;
self.debug_aranges_index = try addSectionSymbolWithAtom(self, gpa, ".debug_aranges", .@"16", osec);
- elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_aranges_index.?).ref;
}
if (self.debug_line_index == null) {
@@ -174,10 +174,10 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
.name = try elf_file.insertShString(".debug_line"),
.type = elf.SHT_PROGBITS,
.addralign = 1,
+ .offset = std.math.maxInt(u64),
});
self.debug_line_section_dirty = true;
self.debug_line_index = try addSectionSymbolWithAtom(self, gpa, ".debug_line", .@"1", osec);
- elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_line_index.?).ref;
}
if (self.debug_line_str_index == null) {
@@ -187,10 +187,10 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
.entsize = 1,
.type = elf.SHT_PROGBITS,
.addralign = 1,
+ .offset = std.math.maxInt(u64),
});
self.debug_line_str_section_dirty = true;
self.debug_line_str_index = try addSectionSymbolWithAtom(self, gpa, ".debug_line_str", .@"1", osec);
- elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_line_str_index.?).ref;
}
if (self.debug_loclists_index == null) {
@@ -198,10 +198,10 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
.name = try elf_file.insertShString(".debug_loclists"),
.type = elf.SHT_PROGBITS,
.addralign = 1,
+ .offset = std.math.maxInt(u64),
});
self.debug_loclists_section_dirty = true;
self.debug_loclists_index = try addSectionSymbolWithAtom(self, gpa, ".debug_loclists", .@"1", osec);
- elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_loclists_index.?).ref;
}
if (self.debug_rnglists_index == null) {
@@ -209,10 +209,10 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
.name = try elf_file.insertShString(".debug_rnglists"),
.type = elf.SHT_PROGBITS,
.addralign = 1,
+ .offset = std.math.maxInt(u64),
});
self.debug_rnglists_section_dirty = true;
self.debug_rnglists_index = try addSectionSymbolWithAtom(self, gpa, ".debug_rnglists", .@"1", osec);
- elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_rnglists_index.?).ref;
}
if (self.eh_frame_index == null) {
@@ -224,10 +224,10 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
elf.SHT_PROGBITS,
.flags = elf.SHF_ALLOC,
.addralign = ptr_size,
+ .offset = std.math.maxInt(u64),
});
self.eh_frame_section_dirty = true;
self.eh_frame_index = try addSectionSymbolWithAtom(self, gpa, ".eh_frame", Atom.Alignment.fromNonzeroByteUnits(ptr_size), osec);
- elf_file.sections.items(.last_atom)[osec] = self.symbol(self.eh_frame_index.?).ref;
}
try dwarf.initMetadata();
@@ -1318,7 +1318,7 @@ fn updateNavCode(
const capacity = atom_ptr.capacity(elf_file);
const need_realloc = code.len > capacity or !required_alignment.check(@intCast(atom_ptr.value));
if (need_realloc) {
- try self.growAtom(atom_ptr, elf_file);
+ try self.allocateAtom(atom_ptr, true, elf_file);
log.debug("growing {} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), old_vaddr, atom_ptr.value });
if (old_vaddr != atom_ptr.value) {
sym.value = 0;
@@ -1328,7 +1328,7 @@ fn updateNavCode(
// TODO shrink section size
}
} else {
- try self.allocateAtom(atom_ptr, elf_file);
+ try self.allocateAtom(atom_ptr, true, elf_file);
errdefer self.freeNavMetadata(elf_file, sym_index);
sym.value = 0;
esym.st_value = 0;
@@ -1403,7 +1403,7 @@ fn updateTlv(
const gop = try self.tls_variables.getOrPut(gpa, atom_ptr.atom_index);
assert(!gop.found_existing); // TODO incremental updates
- try self.allocateAtom(atom_ptr, elf_file);
+ try self.allocateAtom(atom_ptr, true, elf_file);
sym.value = 0;
esym.st_value = 0;
@@ -1729,7 +1729,7 @@ fn updateLazySymbol(
atom_ptr.size = code.len;
atom_ptr.output_section_index = output_section_index;
- try self.allocateAtom(atom_ptr, elf_file);
+ try self.allocateAtom(atom_ptr, true, elf_file);
errdefer self.freeNavMetadata(elf_file, symbol_index);
local_sym.value = 0;
@@ -1784,7 +1784,7 @@ fn lowerConst(
atom_ptr.size = code.len;
atom_ptr.output_section_index = output_section_index;
- try self.allocateAtom(atom_ptr, elf_file);
+ try self.allocateAtom(atom_ptr, true, elf_file);
errdefer self.freeNavMetadata(elf_file, sym_index);
try elf_file.base.file.?.pwriteAll(code, atom_ptr.offset(elf_file));
@@ -1981,17 +1981,27 @@ fn writeTrampoline(tr_sym: Symbol, target: Symbol, elf_file: *Elf) !void {
}
}
-fn allocateAtom(self: *ZigObject, atom_ptr: *Atom, elf_file: *Elf) !void {
+pub fn allocateAtom(self: *ZigObject, atom_ptr: *Atom, requires_padding: bool, elf_file: *Elf) !void {
+ const slice = elf_file.sections.slice();
+ const shdr = &slice.items(.shdr)[atom_ptr.output_section_index];
+ const last_atom_ref = &slice.items(.last_atom)[atom_ptr.output_section_index];
+
+ // FIXME:JK this only works if this atom is the only atom in the output section
+ // In every other case, we need to redo the prev/next links
+ if (last_atom_ref.eql(atom_ptr.ref())) last_atom_ref.* = .{};
+
const alloc_res = try elf_file.allocateChunk(.{
.shndx = atom_ptr.output_section_index,
.size = atom_ptr.size,
.alignment = atom_ptr.alignment,
+ .requires_padding = requires_padding,
});
atom_ptr.value = @intCast(alloc_res.value);
-
- const slice = elf_file.sections.slice();
- const shdr = &slice.items(.shdr)[atom_ptr.output_section_index];
- const last_atom_ref = &slice.items(.last_atom)[atom_ptr.output_section_index];
+ log.debug("allocated {s} at {x}\n placement {?}", .{
+ atom_ptr.name(elf_file),
+ atom_ptr.offset(elf_file),
+ alloc_res.placement,
+ });
const expand_section = if (elf_file.atom(alloc_res.placement)) |placement_atom|
placement_atom.nextAtom(elf_file) == null
@@ -2013,12 +2023,6 @@ fn allocateAtom(self: *ZigObject, atom_ptr: *Atom, elf_file: *Elf) !void {
}
shdr.sh_addralign = @max(shdr.sh_addralign, atom_ptr.alignment.toByteUnits().?);
- if (self.sectionSymbol(atom_ptr.output_section_index, elf_file)) |sym| {
- assert(sym.atom(elf_file) == null and sym.mergeSubsection(elf_file) == null);
- const esym = &self.symtab.items(.elf_sym)[sym.esym_index];
- esym.st_size += atom_ptr.size + Elf.padToIdeal(atom_ptr.size);
- }
-
// This function can also reallocate an atom.
// In this case we need to "unplug" it from its previous location before
// plugging it in to its new location.
@@ -2037,12 +2041,8 @@ fn allocateAtom(self: *ZigObject, atom_ptr: *Atom, elf_file: *Elf) !void {
atom_ptr.prev_atom_ref = .{ .index = 0, .file = 0 };
atom_ptr.next_atom_ref = .{ .index = 0, .file = 0 };
}
-}
-fn growAtom(self: *ZigObject, atom_ptr: *Atom, elf_file: *Elf) !void {
- if (!atom_ptr.alignment.check(@intCast(atom_ptr.value)) or atom_ptr.size > atom_ptr.capacity(elf_file)) {
- try self.allocateAtom(atom_ptr, elf_file);
- }
+ log.debug(" prev {?}, next {?}", .{ atom_ptr.prev_atom_ref, atom_ptr.next_atom_ref });
}
pub fn resetShdrIndexes(self: *ZigObject, backlinks: anytype) void {
src/link/Dwarf.zig
@@ -389,14 +389,20 @@ pub const Section = struct {
if (dwarf.bin_file.cast(.elf)) |elf_file| {
const zo = elf_file.zigObjectPtr().?;
const atom = zo.symbol(sec.index).atom(elf_file).?;
- const shndx = atom.output_section_index;
- const needed_size = len;
- const min_alignment = sec.alignment.toByteUnits().?;
- try elf_file.growSection(shndx, needed_size, min_alignment);
- const shdr = elf_file.sections.items(.shdr)[shndx];
- atom.size = needed_size;
- atom.alignment = InternPool.Alignment.fromNonzeroByteUnits(shdr.sh_addralign);
- sec.len = needed_size;
+ const old_size = atom.size;
+ atom.size = len;
+ atom.alignment = sec.alignment;
+ sec.len = len;
+ if (old_size > 0) {
+ if (!atom.alignment.check(@intCast(atom.value)) or atom.size > atom.fileCapacity(elf_file)) {
+ try zo.allocateAtom(atom, false, elf_file);
+ } else {
+ const shdr = &elf_file.sections.items(.shdr)[atom.output_section_index];
+ shdr.sh_size = (shdr.sh_size - old_size) + atom.size;
+ }
+ } else {
+ try zo.allocateAtom(atom, false, elf_file);
+ }
} else if (dwarf.bin_file.cast(.macho)) |macho_file| {
const header = if (macho_file.d_sym) |*d_sym| header: {
try d_sym.growSection(@intCast(sec.index), len, true, macho_file);
@@ -417,11 +423,15 @@ pub const Section = struct {
if (dwarf.bin_file.cast(.elf)) |elf_file| {
const zo = elf_file.zigObjectPtr().?;
const atom = zo.symbol(sec.index).atom(elf_file).?;
- const shndx = atom.output_section_index;
- const shdr = &elf_file.sections.items(.shdr)[shndx];
- atom.size = sec.len;
- shdr.sh_offset += len;
- shdr.sh_size = sec.len;
+ if (atom.prevAtom(elf_file)) |_| {
+ // FIXME:JK trimming/shrinking has to be reworked on ZigObject/Elf level
+ atom.value += len;
+ } else {
+ const shdr = &elf_file.sections.items(.shdr)[atom.output_section_index];
+ shdr.sh_offset += len;
+ atom.value = 0;
+ }
+ atom.size -= len;
} else if (dwarf.bin_file.cast(.macho)) |macho_file| {
const header = if (macho_file.d_sym) |*d_sym|
&d_sym.sections.items[sec.index]
@@ -910,11 +920,9 @@ const Entry = struct {
if (std.debug.runtime_safety) {
log.err("missing {} from {s}", .{
@as(Entry.Index, @enumFromInt(entry - unit.entries.items.ptr)),
- std.mem.sliceTo(if (dwarf.bin_file.cast(.elf)) |elf_file| sh_name: {
- const zo = elf_file.zigObjectPtr().?;
- const shndx = zo.symbol(sec.index).atom(elf_file).?.output_section_index;
- break :sh_name elf_file.shstrtab.items[elf_file.sections.items(.shdr)[shndx].sh_name..];
- } else if (dwarf.bin_file.cast(.macho)) |macho_file|
+ std.mem.sliceTo(if (dwarf.bin_file.cast(.elf)) |elf_file|
+ elf_file.zigObjectPtr().?.symbol(sec.index).name(elf_file)
+ else if (dwarf.bin_file.cast(.macho)) |macho_file|
if (macho_file.d_sym) |*d_sym|
&d_sym.sections.items[sec.index].segname
else
src/link/Elf.zig
@@ -573,10 +573,10 @@ pub fn growSection(self: *Elf, shdr_index: u32, needed_size: u64, min_alignment:
// Must move the entire section.
const new_offset = try self.findFreeSpace(needed_size, min_alignment);
- log.debug("new '{s}' file offset 0x{x} to 0x{x}", .{
+ log.debug("moving '{s}' from 0x{x} to 0x{x}", .{
self.getShString(shdr.sh_name),
+ shdr.sh_offset,
new_offset,
- new_offset + existing_size,
});
const amt = try self.base.file.?.copyRangeAll(
@@ -691,13 +691,6 @@ pub fn allocateChunk(self: *Elf, args: struct {
}
};
- log.debug("allocated chunk (size({x}),align({x})) at 0x{x} (file(0x{x}))", .{
- args.size,
- args.alignment.toByteUnits().?,
- shdr.sh_addr + res.value,
- shdr.sh_offset + res.value,
- });
-
const expand_section = if (self.atom(res.placement)) |placement_atom|
placement_atom.nextAtom(self) == null
else
@@ -707,6 +700,18 @@ pub fn allocateChunk(self: *Elf, args: struct {
try self.growSection(args.shndx, needed_size, args.alignment.toByteUnits().?);
}
+ log.debug("allocated chunk (size({x}),align({x})) in {s} at 0x{x} (file(0x{x}))", .{
+ args.size,
+ args.alignment.toByteUnits().?,
+ self.getShString(shdr.sh_name),
+ shdr.sh_addr + res.value,
+ shdr.sh_offset + res.value,
+ });
+ log.debug(" placement {}, {s}", .{
+ res.placement,
+ if (self.atom(res.placement)) |atom_ptr| atom_ptr.name(self) else "",
+ });
+
return res;
}
@@ -1796,6 +1801,7 @@ pub fn initOutputSection(self: *Elf, args: struct {
.type = @"type",
.flags = flags,
.name = try self.insertShString(name),
+ .offset = std.math.maxInt(u64),
});
return out_shndx;
}
@@ -3898,27 +3904,14 @@ pub fn allocateNonAllocSections(self: *Elf) !void {
shdr.sh_size = 0;
const new_offset = try self.findFreeSpace(needed_size, shdr.sh_addralign);
- if (self.zigObjectPtr()) |zo| blk: {
- const existing_size = for ([_]?Symbol.Index{
- zo.debug_info_index,
- zo.debug_abbrev_index,
- zo.debug_aranges_index,
- zo.debug_str_index,
- zo.debug_line_index,
- zo.debug_line_str_index,
- zo.debug_loclists_index,
- zo.debug_rnglists_index,
- }) |maybe_sym_index| {
- const sym_index = maybe_sym_index orelse continue;
- const sym = zo.symbol(sym_index);
- const atom_ptr = sym.atom(self).?;
- if (atom_ptr.output_section_index == shndx) break atom_ptr.size;
- } else break :blk;
- log.debug("moving {s} from 0x{x} to 0x{x}", .{
- self.getShString(shdr.sh_name),
- shdr.sh_offset,
- new_offset,
- });
+ log.debug("moving {s} from 0x{x} to 0x{x}", .{
+ self.getShString(shdr.sh_name),
+ shdr.sh_offset,
+ new_offset,
+ });
+
+ if (shdr.sh_offset > 0) {
+ const existing_size = self.sectionSize(@intCast(shndx));
const amt = try self.base.file.?.copyRangeAll(
shdr.sh_offset,
self.base.file.?,