mirror of
https://github.com/ziglang/zig.git
synced 2026-01-01 19:13:16 +00:00
elf: create and allocate special PHDRs out of the loop
This commit is contained in:
parent
59fcf16732
commit
5148e38751
160
src/link/Elf.zig
160
src/link/Elf.zig
@ -30,15 +30,13 @@ output_sections: std.AutoArrayHashMapUnmanaged(u16, std.ArrayListUnmanaged(Atom.
|
||||
/// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write.
|
||||
/// Same order as in the file.
|
||||
phdrs: std.ArrayListUnmanaged(elf.Elf64_Phdr) = .{},
|
||||
/// The index into the program headers of the PT_PHDR program header
|
||||
phdr_table_index: ?u16 = null,
|
||||
|
||||
/// Tracked loadable segments during incremental linking.
|
||||
/// The index into the program headers of the PT_LOAD program header containing the phdr
|
||||
/// Most linkers would merge this with phdr_load_ro_index,
|
||||
/// but incremental linking means we can't ensure they are consecutive.
|
||||
/// If this segment is not needed, it won't get emitted.
|
||||
phdr_table_load_index: ?u16 = null,
|
||||
/// The index into the program headers of the PT_TLS program header.
|
||||
phdr_tls_index: ?u16 = null,
|
||||
/// The index into the program headers of a PT_LOAD program header with Read and Execute flags
|
||||
phdr_load_re_zig_index: ?u16 = null,
|
||||
/// The index into the program headers of the global offset table.
|
||||
@ -51,6 +49,20 @@ phdr_load_rw_zig_index: ?u16 = null,
|
||||
/// The index into the program headers of a PT_LOAD program header with zerofill data.
|
||||
phdr_load_zerofill_zig_index: ?u16 = null,
|
||||
|
||||
/// Special program headers
|
||||
/// PT_PHDR
|
||||
phdr_table_index: ?u16 = null,
|
||||
/// PT_INTERP
|
||||
phdr_interp_index: ?u16 = null,
|
||||
/// PT_DYNAMIC
|
||||
phdr_dynamic_index: ?u16 = null,
|
||||
/// PT_GNU_EH_FRAME
|
||||
phdr_gnu_eh_frame_index: ?u16 = null,
|
||||
/// PT_GNU_STACK
|
||||
phdr_gnu_stack_index: ?u16 = null,
|
||||
/// PT_TLS
|
||||
phdr_tls_index: ?u16 = null,
|
||||
|
||||
entry_index: ?Symbol.Index = null,
|
||||
page_size: u32,
|
||||
default_sym_version: elf.Elf64_Versym,
|
||||
@ -1607,6 +1619,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
|
||||
|
||||
// Generate and emit non-incremental sections.
|
||||
try self.initSections();
|
||||
try self.initSpecialPhdrs();
|
||||
try self.sortSections();
|
||||
for (self.objects.items) |index| {
|
||||
try self.file(index).?.object.addAtomsToOutputSections(self);
|
||||
@ -1619,6 +1632,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
|
||||
try self.updateSectionSizes();
|
||||
|
||||
try self.allocateSections();
|
||||
self.allocateSpecialPhdrs();
|
||||
self.allocateAtoms();
|
||||
self.allocateLinkerDefinedSymbols();
|
||||
|
||||
@ -4025,6 +4039,35 @@ fn initSections(self: *Elf) !void {
|
||||
}
|
||||
}
|
||||
|
||||
fn initSpecialPhdrs(self: *Elf) !void {
|
||||
if (self.interp_section_index != null) {
|
||||
self.phdr_interp_index = try self.addPhdr(.{
|
||||
.type = elf.PT_INTERP,
|
||||
.flags = elf.PF_R,
|
||||
.@"align" = 1,
|
||||
});
|
||||
}
|
||||
if (self.dynamic_section_index != null) {
|
||||
self.phdr_dynamic_index = try self.addPhdr(.{
|
||||
.type = elf.PT_DYNAMIC,
|
||||
.flags = elf.PF_R | elf.PF_W,
|
||||
});
|
||||
}
|
||||
if (self.eh_frame_hdr_section_index != null) {
|
||||
self.phdr_gnu_eh_frame_index = try self.addPhdr(.{
|
||||
.type = elf.PT_GNU_EH_FRAME,
|
||||
.flags = elf.PF_R,
|
||||
});
|
||||
}
|
||||
self.phdr_gnu_stack_index = try self.addPhdr(.{
|
||||
.type = elf.PT_GNU_STACK,
|
||||
.flags = elf.PF_W | elf.PF_R,
|
||||
.memsz = self.base.options.stack_size_override orelse 0,
|
||||
.@"align" = 1,
|
||||
});
|
||||
// self.phdr_table_dirty = true;
|
||||
}
|
||||
|
||||
/// We need to sort constructors/destuctors in the following sections:
|
||||
/// * .init_array
|
||||
/// * .fini_array
|
||||
@ -4416,31 +4459,33 @@ fn updateSectionSizes(self: *Elf) !void {
|
||||
}
|
||||
}
|
||||
|
||||
/// The assumed layout of PHDRs in file is as follows:
|
||||
/// PT_PHDR
|
||||
/// PT_INTERP
|
||||
/// PT_DYNAMIC
|
||||
/// PT_GNU_EH_FRAME
|
||||
/// PT_GNU_STACK
|
||||
/// PT_LOAD...
|
||||
/// PT_TLS
|
||||
fn resetPhdrs(self: *Elf) !void {
|
||||
const gpa = self.base.allocator;
|
||||
const phdrs = try self.phdrs.toOwnedSlice(gpa);
|
||||
try self.phdrs.ensureUnusedCapacity(gpa, phdrs.len);
|
||||
|
||||
if (self.phdr_table_index) |phndx| {
|
||||
self.phdrs.appendAssumeCapacity(phdrs[phndx]);
|
||||
for (&[_]?u16{
|
||||
self.phdr_table_index.?,
|
||||
self.phdr_interp_index,
|
||||
self.phdr_dynamic_index,
|
||||
self.phdr_gnu_eh_frame_index,
|
||||
self.phdr_gnu_stack_index,
|
||||
}) |maybe_index| {
|
||||
if (maybe_index) |index| {
|
||||
self.phdrs.appendAssumeCapacity(phdrs[index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn initPhdrs(self: *Elf) !void {
|
||||
// Add INTERP phdr if required
|
||||
if (self.interp_section_index) |index| {
|
||||
const shdr = self.shdrs.items[index];
|
||||
_ = try self.addPhdr(.{
|
||||
.type = elf.PT_INTERP,
|
||||
.flags = elf.PF_R,
|
||||
.@"align" = 1,
|
||||
.offset = shdr.sh_offset,
|
||||
.addr = shdr.sh_addr,
|
||||
.filesz = shdr.sh_size,
|
||||
.memsz = shdr.sh_size,
|
||||
});
|
||||
}
|
||||
|
||||
fn initSegments(self: *Elf) !void {
|
||||
// Add LOAD phdrs
|
||||
const slice = self.shdrs.items;
|
||||
{
|
||||
@ -4503,51 +4548,6 @@ fn initPhdrs(self: *Elf) !void {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add DYNAMIC phdr
|
||||
if (self.dynamic_section_index) |index| {
|
||||
const shdr = self.shdrs.items[index];
|
||||
_ = try self.addPhdr(.{
|
||||
.type = elf.PT_DYNAMIC,
|
||||
.flags = elf.PF_R | elf.PF_W,
|
||||
.@"align" = shdr.sh_addralign,
|
||||
.offset = shdr.sh_offset,
|
||||
.addr = shdr.sh_addr,
|
||||
.memsz = shdr.sh_size,
|
||||
.filesz = shdr.sh_size,
|
||||
});
|
||||
}
|
||||
|
||||
// Add PT_GNU_EH_FRAME phdr if required.
|
||||
if (self.eh_frame_hdr_section_index) |index| {
|
||||
const shdr = self.shdrs.items[index];
|
||||
_ = try self.addPhdr(.{
|
||||
.type = elf.PT_GNU_EH_FRAME,
|
||||
.flags = elf.PF_R,
|
||||
.@"align" = shdr.sh_addralign,
|
||||
.offset = shdr.sh_offset,
|
||||
.addr = shdr.sh_addr,
|
||||
.memsz = shdr.sh_size,
|
||||
.filesz = shdr.sh_size,
|
||||
});
|
||||
}
|
||||
|
||||
// Add PT_GNU_STACK phdr that controls some stack attributes that apparently may or may not
|
||||
// be respected by the OS.
|
||||
_ = try self.addPhdr(.{
|
||||
.type = elf.PT_GNU_STACK,
|
||||
.flags = elf.PF_W | elf.PF_R,
|
||||
.memsz = self.base.options.stack_size_override orelse 0,
|
||||
.@"align" = 1,
|
||||
});
|
||||
|
||||
// Backpatch size of the PHDR phdr
|
||||
{
|
||||
const phdr = &self.phdrs.items[self.phdr_table_index.?];
|
||||
const size = @sizeOf(elf.Elf64_Phdr) * self.phdrs.items.len;
|
||||
phdr.p_filesz = size;
|
||||
phdr.p_memsz = size;
|
||||
}
|
||||
}
|
||||
|
||||
fn addShdrToPhdr(self: *Elf, phdr_index: u16, shdr: *const elf.Elf64_Shdr) !void {
|
||||
@ -4716,11 +4716,37 @@ fn allocateSections(self: *Elf) !void {
|
||||
self.allocateSectionsInMemory(base_offset);
|
||||
self.allocateSectionsInFile(base_offset);
|
||||
try self.resetPhdrs();
|
||||
try self.initPhdrs();
|
||||
try self.initSegments();
|
||||
if (nphdrs == self.phdrs.items.len) break;
|
||||
}
|
||||
}
|
||||
|
||||
fn allocateSpecialPhdrs(self: *Elf) void {
|
||||
for (&[_]struct { ?u16, ?u16 }{
|
||||
.{ self.phdr_interp_index, self.interp_section_index },
|
||||
.{ self.phdr_dynamic_index, self.dynamic_section_index },
|
||||
.{ self.phdr_gnu_eh_frame_index, self.eh_frame_hdr_section_index },
|
||||
}) |pair| {
|
||||
if (pair[0]) |index| {
|
||||
const shdr = self.shdrs.items[pair[1].?];
|
||||
const phdr = &self.phdrs.items[index];
|
||||
phdr.p_align = shdr.sh_addralign;
|
||||
phdr.p_offset = shdr.sh_offset;
|
||||
phdr.p_vaddr = shdr.sh_addr;
|
||||
phdr.p_filesz = shdr.sh_size;
|
||||
phdr.p_memsz = shdr.sh_size;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// Backpatch size of the PHDR phdr
|
||||
const phdr = &self.phdrs.items[self.phdr_table_index.?];
|
||||
const size = @sizeOf(elf.Elf64_Phdr) * self.phdrs.items.len;
|
||||
phdr.p_filesz = size;
|
||||
phdr.p_memsz = size;
|
||||
}
|
||||
}
|
||||
|
||||
fn allocateAtoms(self: *Elf) void {
|
||||
for (self.objects.items) |index| {
|
||||
self.file(index).?.object.allocateAtoms(self);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user