| ... | @@ -30,15 +30,13 @@ output_sections: std.AutoArrayHashMapUnmanaged(u16, std.ArrayListUnmanaged(Atom. | ... | @@ -30,15 +30,13 @@ output_sections: std.AutoArrayHashMapUnmanaged(u16, std.ArrayListUnmanaged(Atom. |
| 30 | /// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write. | 30 | /// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write. |
| 31 | /// Same order as in the file. | 31 | /// Same order as in the file. |
| 32 | phdrs: std.ArrayListUnmanaged(elf.Elf64_Phdr) = .{}, | 32 | phdrs: std.ArrayListUnmanaged(elf.Elf64_Phdr) = .{}, |
| 33 | /// The index into the program headers of the PT_PHDR program header | 33 | |
| 34 | phdr_table_index: ?u16 = null, | 34 | /// Tracked loadable segments during incremental linking. |
| 35 | /// The index into the program headers of the PT_LOAD program header containing the phdr | 35 | /// The index into the program headers of the PT_LOAD program header containing the phdr |
| 36 | /// Most linkers would merge this with phdr_load_ro_index, | 36 | /// Most linkers would merge this with phdr_load_ro_index, |
| 37 | /// but incremental linking means we can't ensure they are consecutive. | 37 | /// but incremental linking means we can't ensure they are consecutive. |
| 38 | /// If this segment is not needed, it won't get emitted. | 38 | /// If this segment is not needed, it won't get emitted. |
| 39 | phdr_table_load_index: ?u16 = null, | 39 | phdr_table_load_index: ?u16 = null, |
| 40 | /// The index into the program headers of the PT_TLS program header. | | |
| 41 | phdr_tls_index: ?u16 = null, | | |
| 42 | /// The index into the program headers of a PT_LOAD program header with Read and Execute flags | 40 | /// The index into the program headers of a PT_LOAD program header with Read and Execute flags |
| 43 | phdr_load_re_zig_index: ?u16 = null, | 41 | phdr_load_re_zig_index: ?u16 = null, |
| 44 | /// The index into the program headers of the global offset table. | 42 | /// The index into the program headers of the global offset table. |
| ... | @@ -51,6 +49,20 @@ phdr_load_rw_zig_index: ?u16 = null, | ... | @@ -51,6 +49,20 @@ phdr_load_rw_zig_index: ?u16 = null, |
| 51 | /// The index into the program headers of a PT_LOAD program header with zerofill data. | 49 | /// The index into the program headers of a PT_LOAD program header with zerofill data. |
| 52 | phdr_load_zerofill_zig_index: ?u16 = null, | 50 | phdr_load_zerofill_zig_index: ?u16 = null, |
| 53 | | 51 | |
| | 52 | /// Special program headers |
| | 53 | /// PT_PHDR |
| | 54 | phdr_table_index: ?u16 = null, |
| | 55 | /// PT_INTERP |
| | 56 | phdr_interp_index: ?u16 = null, |
| | 57 | /// PT_DYNAMIC |
| | 58 | phdr_dynamic_index: ?u16 = null, |
| | 59 | /// PT_GNU_EH_FRAME |
| | 60 | phdr_gnu_eh_frame_index: ?u16 = null, |
| | 61 | /// PT_GNU_STACK |
| | 62 | phdr_gnu_stack_index: ?u16 = null, |
| | 63 | /// PT_TLS |
| | 64 | phdr_tls_index: ?u16 = null, |
| | 65 | |
| 54 | entry_index: ?Symbol.Index = null, | 66 | entry_index: ?Symbol.Index = null, |
| 55 | page_size: u32, | 67 | page_size: u32, |
| 56 | default_sym_version: elf.Elf64_Versym, | 68 | default_sym_version: elf.Elf64_Versym, |
| ... | @@ -1607,6 +1619,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node | ... | @@ -1607,6 +1619,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1607 | | 1619 | |
| 1608 | // Generate and emit non-incremental sections. | 1620 | // Generate and emit non-incremental sections. |
| 1609 | try self.initSections(); | 1621 | try self.initSections(); |
| | 1622 | try self.initSpecialPhdrs(); |
| 1610 | try self.sortSections(); | 1623 | try self.sortSections(); |
| 1611 | for (self.objects.items) |index| { | 1624 | for (self.objects.items) |index| { |
| 1612 | try self.file(index).?.object.addAtomsToOutputSections(self); | 1625 | try self.file(index).?.object.addAtomsToOutputSections(self); |
| ... | @@ -1619,6 +1632,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node | ... | @@ -1619,6 +1632,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1619 | try self.updateSectionSizes(); | 1632 | try self.updateSectionSizes(); |
| 1620 | | 1633 | |
| 1621 | try self.allocateSections(); | 1634 | try self.allocateSections(); |
| | 1635 | self.allocateSpecialPhdrs(); |
| 1622 | self.allocateAtoms(); | 1636 | self.allocateAtoms(); |
| 1623 | self.allocateLinkerDefinedSymbols(); | 1637 | self.allocateLinkerDefinedSymbols(); |
| 1624 | | 1638 | |
| ... | @@ -4025,6 +4039,35 @@ fn initSections(self: *Elf) !void { | ... | @@ -4025,6 +4039,35 @@ fn initSections(self: *Elf) !void { |
| 4025 | } | 4039 | } |
| 4026 | } | 4040 | } |
| 4027 | | 4041 | |
| | 4042 | fn 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 | |
| 4028 | /// We need to sort constructors/destuctors in the following sections: | 4071 | /// We need to sort constructors/destuctors in the following sections: |
| 4029 | /// * .init_array | 4072 | /// * .init_array |
| 4030 | /// * .fini_array | 4073 | /// * .fini_array |
| ... | @@ -4416,31 +4459,33 @@ fn updateSectionSizes(self: *Elf) !void { | ... | @@ -4416,31 +4459,33 @@ fn updateSectionSizes(self: *Elf) !void { |
| 4416 | } | 4459 | } |
| 4417 | } | 4460 | } |
| 4418 | | 4461 | |
| | 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 |
| 4419 | fn resetPhdrs(self: *Elf) !void { | 4470 | fn resetPhdrs(self: *Elf) !void { |
| 4420 | const gpa = self.base.allocator; | 4471 | const gpa = self.base.allocator; |
| 4421 | const phdrs = try self.phdrs.toOwnedSlice(gpa); | 4472 | const phdrs = try self.phdrs.toOwnedSlice(gpa); |
| 4422 | try self.phdrs.ensureUnusedCapacity(gpa, phdrs.len); | 4473 | try self.phdrs.ensureUnusedCapacity(gpa, phdrs.len); |
| 4423 | | 4474 | |
| 4424 | if (self.phdr_table_index) |phndx| { | 4475 | for (&[_]?u16{ |
| 4425 | self.phdrs.appendAssumeCapacity(phdrs[phndx]); | 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 | } |
| 4426 | } | 4485 | } |
| 4427 | } | 4486 | } |
| 4428 | | 4487 | |
| 4429 | fn initPhdrs(self: *Elf) !void { | 4488 | fn initSegments(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 | | | |
| 4444 | // Add LOAD phdrs | 4489 | // Add LOAD phdrs |
| 4445 | const slice = self.shdrs.items; | 4490 | const slice = self.shdrs.items; |
| 4446 | { | 4491 | { |
| ... | @@ -4503,51 +4548,6 @@ fn initPhdrs(self: *Elf) !void { | ... | @@ -4503,51 +4548,6 @@ fn initPhdrs(self: *Elf) !void { |
| 4503 | } | 4548 | } |
| 4504 | } | 4549 | } |
| 4505 | } | 4550 | } |
| 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 | } | | |
| 4551 | } | 4551 | } |
| 4552 | | 4552 | |
| 4553 | fn addShdrToPhdr(self: *Elf, phdr_index: u16, shdr: *const elf.Elf64_Shdr) !void { | 4553 | fn addShdrToPhdr(self: *Elf, phdr_index: u16, shdr: *const elf.Elf64_Shdr) !void { |
| ... | @@ -4716,11 +4716,37 @@ fn allocateSections(self: *Elf) !void { | ... | @@ -4716,11 +4716,37 @@ fn allocateSections(self: *Elf) !void { |
| 4716 | self.allocateSectionsInMemory(base_offset); | 4716 | self.allocateSectionsInMemory(base_offset); |
| 4717 | self.allocateSectionsInFile(base_offset); | 4717 | self.allocateSectionsInFile(base_offset); |
| 4718 | try self.resetPhdrs(); | 4718 | try self.resetPhdrs(); |
| 4719 | try self.initPhdrs(); | 4719 | try self.initSegments(); |
| 4720 | if (nphdrs == self.phdrs.items.len) break; | 4720 | if (nphdrs == self.phdrs.items.len) break; |
| 4721 | } | 4721 | } |
| 4722 | } | 4722 | } |
| 4723 | | 4723 | |
| | 4724 | fn 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 | |
| 4724 | fn allocateAtoms(self: *Elf) void { | 4750 | fn allocateAtoms(self: *Elf) void { |
| 4725 | for (self.objects.items) |index| { | 4751 | for (self.objects.items) |index| { |
| 4726 | self.file(index).?.object.allocateAtoms(self); | 4752 | self.file(index).?.object.allocateAtoms(self); |