elf: allocate .text in ZigObject similarly to .eh_frame

This commit is contained in:
Jakub Konka
2024-08-29 21:14:46 +02:00
parent 848535535d
commit 2d0f4fc9c0
2 changed files with 48 additions and 84 deletions

View File

@@ -54,10 +54,6 @@ shdr_table_offset: ?u64 = null,
/// Same order as in the file.
phdrs: std.ArrayListUnmanaged(elf.Elf64_Phdr) = .{},
/// Tracked loadable segments during incremental linking.
/// The index into the program headers of a PT_LOAD program header with Read and Execute flags
phdr_zig_load_re_index: ?u16 = null,
/// Special program headers
/// PT_PHDR
phdr_table_index: ?u16 = null,
@@ -118,10 +114,6 @@ rela_plt: std.ArrayListUnmanaged(elf.Elf64_Rela) = .{},
/// Applies only to a relocatable.
comdat_group_sections: std.ArrayListUnmanaged(ComdatGroupSection) = .{},
/// Tracked section headers with incremental updates to Zig object.
/// .rela.* sections are only used when emitting a relocatable object file.
zig_text_section_index: ?u32 = null,
debug_info_section_index: ?u32 = null,
debug_abbrev_section_index: ?u32 = null,
debug_str_section_index: ?u32 = null,
@@ -3356,7 +3348,6 @@ fn sortPhdrs(self: *Elf) error{OutOfMemory}!void {
}
for (&[_]*?u16{
&self.phdr_zig_load_re_index,
&self.phdr_table_index,
&self.phdr_table_load_index,
&self.phdr_interp_index,
@@ -3482,7 +3473,6 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void {
&self.copy_rel_section_index,
&self.versym_section_index,
&self.verneed_section_index,
&self.zig_text_section_index,
&self.debug_info_section_index,
&self.debug_abbrev_section_index,
&self.debug_str_section_index,
@@ -3734,10 +3724,9 @@ fn getMaxNumberOfPhdrs() u64 {
/// We permit a maximum of 3**2 number of segments.
fn calcNumberOfSegments(self: *Elf) usize {
var covers: [9]bool = [_]bool{false} ** 9;
for (self.sections.items(.shdr), 0..) |shdr, shndx| {
for (self.sections.items(.shdr)) |shdr| {
if (shdr.sh_type == elf.SHT_NULL) continue;
if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue;
if (self.isZigSection(@intCast(shndx))) continue;
const flags = shdrToPhdrFlags(shdr.sh_flags);
covers[flags - 1] = true;
}
@@ -3835,7 +3824,6 @@ pub fn allocateAllocSections(self: *Elf) !void {
for (slice.items(.shdr), 0..) |shdr, shndx| {
if (shdr.sh_type == elf.SHT_NULL) continue;
if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue;
if (self.isZigSection(@intCast(shndx))) continue;
const flags = shdrToPhdrFlags(shdr.sh_flags);
try covers[flags - 1].append(@intCast(shndx));
}
@@ -4813,15 +4801,6 @@ pub fn isEffectivelyDynLib(self: Elf) bool {
};
}
pub fn isZigSection(self: Elf, shndx: u32) bool {
inline for (&[_]?u32{
self.zig_text_section_index,
}) |index| {
if (index == shndx) return true;
}
return false;
}
pub fn isDebugSection(self: Elf, shndx: u32) bool {
inline for (&[_]?u32{
self.debug_info_section_index,

View File

@@ -51,6 +51,12 @@ debug_loclists_section_dirty: bool = false,
debug_rnglists_section_dirty: bool = false,
eh_frame_section_dirty: bool = false,
text_index: ?Symbol.Index = null,
data_relro_index: ?Symbol.Index = null,
rodata_index: ?Symbol.Index = null,
data_index: ?Symbol.Index = null,
bss_index: ?Symbol.Index = null,
eh_frame_index: ?Symbol.Index = null,
debug_info_index: ?Symbol.Index = null,
debug_abbrev_index: ?Symbol.Index = null,
debug_aranges_index: ?Symbol.Index = null,
@@ -59,11 +65,6 @@ debug_line_index: ?Symbol.Index = null,
debug_line_str_index: ?Symbol.Index = null,
debug_loclists_index: ?Symbol.Index = null,
debug_rnglists_index: ?Symbol.Index = null,
eh_frame_index: ?Symbol.Index = null,
bss_index: ?Symbol.Index = null,
data_index: ?Symbol.Index = null,
data_relro_index: ?Symbol.Index = null,
rodata_index: ?Symbol.Index = null,
pub const global_symbol_bit: u32 = 0x80000000;
pub const symbol_mask: u32 = 0x7fffffff;
@@ -75,6 +76,7 @@ const InitOptions = struct {
};
pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
_ = options;
const comp = elf_file.base.comp;
const gpa = comp.gpa;
const ptr_size = elf_file.ptrWidthBytes();
@@ -92,60 +94,6 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void {
esym.st_shndx = elf.SHN_ABS;
}
const fillSection = struct {
fn fillSection(ef: *Elf, shdr: *elf.Elf64_Shdr, size: u64, phndx: ?u16) !void {
if (ef.base.isRelocatable()) {
const off = try ef.findFreeSpace(size, shdr.sh_addralign);
shdr.sh_offset = off;
shdr.sh_size = size;
} else {
const phdr = ef.phdrs.items[phndx.?];
shdr.sh_addr = phdr.p_vaddr;
shdr.sh_offset = phdr.p_offset;
shdr.sh_size = phdr.p_memsz;
}
}
}.fillSection;
comptime assert(Elf.number_of_zig_segments == 2);
if (!elf_file.base.isRelocatable()) {
if (elf_file.phdr_zig_load_re_index == null) {
const filesz = options.program_code_size_hint;
const off = try elf_file.findFreeSpace(filesz, elf_file.page_size);
elf_file.phdr_zig_load_re_index = try elf_file.addPhdr(.{
.type = elf.PT_LOAD,
.offset = off,
.filesz = filesz,
.addr = if (ptr_size >= 4) 0x4000000 else 0x4000,
.memsz = filesz,
.@"align" = elf_file.page_size,
.flags = elf.PF_X | elf.PF_R | elf.PF_W,
});
}
}
if (elf_file.zig_text_section_index == null) {
elf_file.zig_text_section_index = try elf_file.addSection(.{
.name = try elf_file.insertShString(".text.zig"),
.type = elf.SHT_PROGBITS,
.flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,
.addralign = 1,
.offset = std.math.maxInt(u64),
});
const shdr = &elf_file.sections.items(.shdr)[elf_file.zig_text_section_index.?];
const phndx = &elf_file.sections.items(.phndx)[elf_file.zig_text_section_index.?];
try fillSection(elf_file, shdr, options.program_code_size_hint, elf_file.phdr_zig_load_re_index);
if (elf_file.base.isRelocatable()) {
_ = try elf_file.addRelaShdr(
try elf_file.insertShString(".rela.text.zig"),
elf_file.zig_text_section_index.?,
);
} else {
phndx.* = elf_file.phdr_zig_load_re_index.?;
}
}
switch (comp.config.debug_format) {
.strip => {},
.dwarf => |v| {
@@ -1196,7 +1144,19 @@ fn getNavShdrIndex(
const ip = &zcu.intern_pool;
const any_non_single_threaded = elf_file.base.comp.config.any_non_single_threaded;
const nav_val = zcu.navValue(nav_index);
if (ip.isFunctionType(nav_val.typeOf(zcu).toIntern())) return elf_file.zig_text_section_index.?;
if (ip.isFunctionType(nav_val.typeOf(zcu).toIntern())) {
if (self.text_index) |symbol_index|
return self.symbol(symbol_index).atom(elf_file).?.output_section_index;
const osec = try elf_file.addSection(.{
.type = elf.SHT_PROGBITS,
.flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,
.name = try elf_file.insertShString(".text"),
.addralign = 1,
.offset = std.math.maxInt(u64),
});
self.text_index = try self.addSectionSymbol(gpa, ".text", .@"1", osec);
return osec;
}
const is_const, const is_threadlocal, const nav_init = switch (ip.indexToKey(nav_val.toIntern())) {
.variable => |variable| .{ false, variable.is_threadlocal, variable.init },
.@"extern" => |@"extern"| .{ @"extern".is_const, @"extern".is_threadlocal, .none },
@@ -1538,6 +1498,19 @@ pub fn updateFunc(
self.symbol(sym_index).name(elf_file),
});
defer gpa.free(name);
const osec = if (self.text_index) |sect_sym_index|
self.symbol(sect_sym_index).atom(elf_file).?.output_section_index
else osec: {
const osec = try elf_file.addSection(.{
.name = try elf_file.insertShString(".text"),
.flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,
.type = elf.SHT_PROGBITS,
.addralign = 1,
.offset = std.math.maxInt(u64),
});
self.text_index = try self.addSectionSymbol(gpa, ".text", .@"1", osec);
break :osec osec;
};
const name_off = try self.addString(gpa, name);
const tr_size = trampolineSize(elf_file.getTarget().cpu.arch);
const tr_sym_index = try self.newSymbolWithAtom(gpa, name_off);
@@ -1549,7 +1522,7 @@ pub fn updateFunc(
tr_atom_ptr.value = old_rva;
tr_atom_ptr.alive = true;
tr_atom_ptr.alignment = old_alignment;
tr_atom_ptr.output_section_index = elf_file.zig_text_section_index.?;
tr_atom_ptr.output_section_index = osec;
tr_atom_ptr.size = tr_size;
const target_sym = self.symbol(sym_index);
target_sym.addExtra(.{ .trampoline = tr_sym_index }, elf_file);
@@ -1703,7 +1676,19 @@ fn updateLazySymbol(
};
const output_section_index = switch (sym.kind) {
.code => elf_file.zig_text_section_index.?,
.code => if (self.text_index) |sym_index|
self.symbol(sym_index).atom(elf_file).?.output_section_index
else osec: {
const osec = try elf_file.addSection(.{
.name = try elf_file.insertShString(".text"),
.type = elf.SHT_PROGBITS,
.addralign = 1,
.flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,
.offset = std.math.maxInt(u64),
});
self.text_index = try self.addSectionSymbol(gpa, ".text", .@"1", osec);
break :osec osec;
},
.const_data => if (self.rodata_index) |sym_index|
self.symbol(sym_index).atom(elf_file).?.output_section_index
else osec: {