authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-10 14:55:08+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-16 19:33:05+02:00
log5148e38751e5f9415e226a6bc7f8f8c0d104f818
tree07ca3a507df24c27b6abe623766f3792abd5abe6
parent59fcf16732b614c998088f1d4c8d59a46d460ed5

elf: create and allocate special PHDRs out of the loop


1 files changed, 93 insertions(+), 67 deletions(-)

src/link/Elf.zig+93-67
......@@ -30,15 +30,13 @@ output_sections: std.AutoArrayHashMapUnmanaged(u16, std.ArrayListUnmanaged(Atom.
3030/// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write.
3131/// Same order as in the file.
3232phdrs: std.ArrayListUnmanaged(elf.Elf64_Phdr) = .{},
33/// The index into the program headers of the PT_PHDR program header
34phdr_table_index: ?u16 = null,
33
34/// Tracked loadable segments during incremental linking.
3535/// The index into the program headers of the PT_LOAD program header containing the phdr
3636/// Most linkers would merge this with phdr_load_ro_index,
3737/// but incremental linking means we can't ensure they are consecutive.
3838/// If this segment is not needed, it won't get emitted.
3939phdr_table_load_index: ?u16 = null,
40/// The index into the program headers of the PT_TLS program header.
41phdr_tls_index: ?u16 = null,
4240/// The index into the program headers of a PT_LOAD program header with Read and Execute flags
4341phdr_load_re_zig_index: ?u16 = null,
4442/// The index into the program headers of the global offset table.
......@@ -51,6 +49,20 @@ phdr_load_rw_zig_index: ?u16 = null,
5149/// The index into the program headers of a PT_LOAD program header with zerofill data.
5250phdr_load_zerofill_zig_index: ?u16 = null,
5351
52/// Special program headers
53/// PT_PHDR
54phdr_table_index: ?u16 = null,
55/// PT_INTERP
56phdr_interp_index: ?u16 = null,
57/// PT_DYNAMIC
58phdr_dynamic_index: ?u16 = null,
59/// PT_GNU_EH_FRAME
60phdr_gnu_eh_frame_index: ?u16 = null,
61/// PT_GNU_STACK
62phdr_gnu_stack_index: ?u16 = null,
63/// PT_TLS
64phdr_tls_index: ?u16 = null,
65
5466entry_index: ?Symbol.Index = null,
5567page_size: u32,
5668default_sym_version: elf.Elf64_Versym,
......@@ -1607,6 +1619,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
16071619
16081620 // Generate and emit non-incremental sections.
16091621 try self.initSections();
1622 try self.initSpecialPhdrs();
16101623 try self.sortSections();
16111624 for (self.objects.items) |index| {
16121625 try self.file(index).?.object.addAtomsToOutputSections(self);
......@@ -1619,6 +1632,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
16191632 try self.updateSectionSizes();
16201633
16211634 try self.allocateSections();
1635 self.allocateSpecialPhdrs();
16221636 self.allocateAtoms();
16231637 self.allocateLinkerDefinedSymbols();
16241638
......@@ -4025,6 +4039,35 @@ fn initSections(self: *Elf) !void {
40254039 }
40264040}
40274041
4042fn initSpecialPhdrs(self: *Elf) !void {
4043 if (self.interp_section_index != null) {
4044 self.phdr_interp_index = try self.addPhdr(.{
4045 .type = elf.PT_INTERP,
4046 .flags = elf.PF_R,
4047 .@"align" = 1,
4048 });
4049 }
4050 if (self.dynamic_section_index != null) {
4051 self.phdr_dynamic_index = try self.addPhdr(.{
4052 .type = elf.PT_DYNAMIC,
4053 .flags = elf.PF_R | elf.PF_W,
4054 });
4055 }
4056 if (self.eh_frame_hdr_section_index != null) {
4057 self.phdr_gnu_eh_frame_index = try self.addPhdr(.{
4058 .type = elf.PT_GNU_EH_FRAME,
4059 .flags = elf.PF_R,
4060 });
4061 }
4062 self.phdr_gnu_stack_index = try self.addPhdr(.{
4063 .type = elf.PT_GNU_STACK,
4064 .flags = elf.PF_W | elf.PF_R,
4065 .memsz = self.base.options.stack_size_override orelse 0,
4066 .@"align" = 1,
4067 });
4068 // self.phdr_table_dirty = true;
4069}
4070
40284071/// We need to sort constructors/destuctors in the following sections:
40294072/// * .init_array
40304073/// * .fini_array
......@@ -4416,31 +4459,33 @@ fn updateSectionSizes(self: *Elf) !void {
44164459 }
44174460}
44184461
4462/// The assumed layout of PHDRs in file is as follows:
4463/// PT_PHDR
4464/// PT_INTERP
4465/// PT_DYNAMIC
4466/// PT_GNU_EH_FRAME
4467/// PT_GNU_STACK
4468/// PT_LOAD...
4469/// PT_TLS
44194470fn resetPhdrs(self: *Elf) !void {
44204471 const gpa = self.base.allocator;
44214472 const phdrs = try self.phdrs.toOwnedSlice(gpa);
44224473 try self.phdrs.ensureUnusedCapacity(gpa, phdrs.len);
44234474
4424 if (self.phdr_table_index) |phndx| {
4425 self.phdrs.appendAssumeCapacity(phdrs[phndx]);
4475 for (&[_]?u16{
4476 self.phdr_table_index.?,
4477 self.phdr_interp_index,
4478 self.phdr_dynamic_index,
4479 self.phdr_gnu_eh_frame_index,
4480 self.phdr_gnu_stack_index,
4481 }) |maybe_index| {
4482 if (maybe_index) |index| {
4483 self.phdrs.appendAssumeCapacity(phdrs[index]);
4484 }
44264485 }
44274486}
44284487
4429fn initPhdrs(self: *Elf) !void {
4430 // Add INTERP phdr if required
4431 if (self.interp_section_index) |index| {
4432 const shdr = self.shdrs.items[index];
4433 _ = try self.addPhdr(.{
4434 .type = elf.PT_INTERP,
4435 .flags = elf.PF_R,
4436 .@"align" = 1,
4437 .offset = shdr.sh_offset,
4438 .addr = shdr.sh_addr,
4439 .filesz = shdr.sh_size,
4440 .memsz = shdr.sh_size,
4441 });
4442 }
4443
4488fn initSegments(self: *Elf) !void {
44444489 // Add LOAD phdrs
44454490 const slice = self.shdrs.items;
44464491 {
......@@ -4503,51 +4548,6 @@ fn initPhdrs(self: *Elf) !void {
45034548 }
45044549 }
45054550 }
4506
4507 // Add DYNAMIC phdr
4508 if (self.dynamic_section_index) |index| {
4509 const shdr = self.shdrs.items[index];
4510 _ = try self.addPhdr(.{
4511 .type = elf.PT_DYNAMIC,
4512 .flags = elf.PF_R | elf.PF_W,
4513 .@"align" = shdr.sh_addralign,
4514 .offset = shdr.sh_offset,
4515 .addr = shdr.sh_addr,
4516 .memsz = shdr.sh_size,
4517 .filesz = shdr.sh_size,
4518 });
4519 }
4520
4521 // Add PT_GNU_EH_FRAME phdr if required.
4522 if (self.eh_frame_hdr_section_index) |index| {
4523 const shdr = self.shdrs.items[index];
4524 _ = try self.addPhdr(.{
4525 .type = elf.PT_GNU_EH_FRAME,
4526 .flags = elf.PF_R,
4527 .@"align" = shdr.sh_addralign,
4528 .offset = shdr.sh_offset,
4529 .addr = shdr.sh_addr,
4530 .memsz = shdr.sh_size,
4531 .filesz = shdr.sh_size,
4532 });
4533 }
4534
4535 // Add PT_GNU_STACK phdr that controls some stack attributes that apparently may or may not
4536 // be respected by the OS.
4537 _ = try self.addPhdr(.{
4538 .type = elf.PT_GNU_STACK,
4539 .flags = elf.PF_W | elf.PF_R,
4540 .memsz = self.base.options.stack_size_override orelse 0,
4541 .@"align" = 1,
4542 });
4543
4544 // Backpatch size of the PHDR phdr
4545 {
4546 const phdr = &self.phdrs.items[self.phdr_table_index.?];
4547 const size = @sizeOf(elf.Elf64_Phdr) * self.phdrs.items.len;
4548 phdr.p_filesz = size;
4549 phdr.p_memsz = size;
4550 }
45514551}
45524552
45534553fn addShdrToPhdr(self: *Elf, phdr_index: u16, shdr: *const elf.Elf64_Shdr) !void {
......@@ -4716,11 +4716,37 @@ fn allocateSections(self: *Elf) !void {
47164716 self.allocateSectionsInMemory(base_offset);
47174717 self.allocateSectionsInFile(base_offset);
47184718 try self.resetPhdrs();
4719 try self.initPhdrs();
4719 try self.initSegments();
47204720 if (nphdrs == self.phdrs.items.len) break;
47214721 }
47224722}
47234723
4724fn allocateSpecialPhdrs(self: *Elf) void {
4725 for (&[_]struct { ?u16, ?u16 }{
4726 .{ self.phdr_interp_index, self.interp_section_index },
4727 .{ self.phdr_dynamic_index, self.dynamic_section_index },
4728 .{ self.phdr_gnu_eh_frame_index, self.eh_frame_hdr_section_index },
4729 }) |pair| {
4730 if (pair[0]) |index| {
4731 const shdr = self.shdrs.items[pair[1].?];
4732 const phdr = &self.phdrs.items[index];
4733 phdr.p_align = shdr.sh_addralign;
4734 phdr.p_offset = shdr.sh_offset;
4735 phdr.p_vaddr = shdr.sh_addr;
4736 phdr.p_filesz = shdr.sh_size;
4737 phdr.p_memsz = shdr.sh_size;
4738 }
4739 }
4740
4741 {
4742 // Backpatch size of the PHDR phdr
4743 const phdr = &self.phdrs.items[self.phdr_table_index.?];
4744 const size = @sizeOf(elf.Elf64_Phdr) * self.phdrs.items.len;
4745 phdr.p_filesz = size;
4746 phdr.p_memsz = size;
4747 }
4748}
4749
47244750fn allocateAtoms(self: *Elf) void {
47254751 for (self.objects.items) |index| {
47264752 self.file(index).?.object.allocateAtoms(self);