authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-09-13 17:53:56+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-09-13 21:51:43+02:00
log9de0df76a80947cadd50c716763604e603199dcc
tree873f8f7bcea4bf8aff0d1933a0a028f32e8f384b
parent10a99f8f64bf7cf336c990b90c72d81f5f767b4d

elf: allocate .bss section and matching PHDR


1 files changed, 49 insertions(+), 2 deletions(-)

src/link/Elf.zig+49-2
...@@ -40,6 +40,8 @@ phdr_got_index: ?u16 = null,...@@ -40,6 +40,8 @@ phdr_got_index: ?u16 = null,
40phdr_load_ro_index: ?u16 = null,40phdr_load_ro_index: ?u16 = null,
41/// The index into the program headers of a PT_LOAD program header with Write flag41/// The index into the program headers of a PT_LOAD program header with Write flag
42phdr_load_rw_index: ?u16 = null,42phdr_load_rw_index: ?u16 = null,
43/// The index into the program headers of a PT_LOAD program header with zerofill data.
44phdr_load_zerofill_index: ?u16 = null,
4345
44entry_addr: ?u64 = null,46entry_addr: ?u64 = null,
45page_size: u32,47page_size: u32,
...@@ -56,6 +58,7 @@ got: GotSection = .{},...@@ -56,6 +58,7 @@ got: GotSection = .{},
56text_section_index: ?u16 = null,58text_section_index: ?u16 = null,
57rodata_section_index: ?u16 = null,59rodata_section_index: ?u16 = null,
58data_section_index: ?u16 = null,60data_section_index: ?u16 = null,
61bss_section_index: ?u16 = null,
59eh_frame_section_index: ?u16 = null,62eh_frame_section_index: ?u16 = null,
60eh_frame_hdr_section_index: ?u16 = null,63eh_frame_hdr_section_index: ?u16 = null,
61dynamic_section_index: ?u16 = null,64dynamic_section_index: ?u16 = null,
...@@ -532,6 +535,26 @@ pub fn populateMissingMetadata(self: *Elf) !void {...@@ -532,6 +535,26 @@ pub fn populateMissingMetadata(self: *Elf) !void {
532 self.phdr_table_dirty = true;535 self.phdr_table_dirty = true;
533 }536 }
534537
538 if (self.phdr_load_zerofill_index == null) {
539 self.phdr_load_zerofill_index = @as(u16, @intCast(self.phdrs.items.len));
540 const p_align = if (self.base.options.target.os.tag == .linux) self.page_size else @as(u16, ptr_size);
541 const off = self.phdrs.items[self.phdr_load_rw_index.?].p_offset;
542 log.debug("found PT_LOAD zerofill free space 0x{x} to 0x{x}", .{ off, off });
543 // TODO Same as for GOT
544 const addr: u32 = if (self.base.options.target.ptrBitWidth() >= 32) 0x14000000 else 0xf000;
545 try self.phdrs.append(gpa, .{
546 .p_type = elf.PT_LOAD,
547 .p_offset = off,
548 .p_filesz = 0,
549 .p_vaddr = addr,
550 .p_paddr = addr,
551 .p_memsz = 0,
552 .p_align = p_align,
553 .p_flags = elf.PF_R | elf.PF_W,
554 });
555 self.phdr_table_dirty = true;
556 }
557
535 if (self.shstrtab_section_index == null) {558 if (self.shstrtab_section_index == null) {
536 self.shstrtab_section_index = @as(u16, @intCast(self.shdrs.items.len));559 self.shstrtab_section_index = @as(u16, @intCast(self.shdrs.items.len));
537 assert(self.shstrtab.buffer.items.len == 0);560 assert(self.shstrtab.buffer.items.len == 0);
...@@ -655,6 +678,26 @@ pub fn populateMissingMetadata(self: *Elf) !void {...@@ -655,6 +678,26 @@ pub fn populateMissingMetadata(self: *Elf) !void {
655 self.shdr_table_dirty = true;678 self.shdr_table_dirty = true;
656 }679 }
657680
681 if (self.bss_section_index == null) {
682 self.bss_section_index = @as(u16, @intCast(self.shdrs.items.len));
683 const phdr = &self.phdrs.items[self.phdr_load_zerofill_index.?];
684 try self.shdrs.append(gpa, .{
685 .sh_name = try self.shstrtab.insert(gpa, ".bss"),
686 .sh_type = elf.SHT_NOBITS,
687 .sh_flags = elf.SHF_WRITE | elf.SHF_ALLOC,
688 .sh_addr = phdr.p_vaddr,
689 .sh_offset = phdr.p_offset,
690 .sh_size = phdr.p_filesz,
691 .sh_link = 0,
692 .sh_info = 0,
693 .sh_addralign = @as(u16, ptr_size),
694 .sh_entsize = 0,
695 });
696 try self.phdr_to_shdr_table.putNoClobber(gpa, self.bss_section_index.?, self.phdr_load_zerofill_index.?);
697 try self.last_atom_and_free_list_table.putNoClobber(gpa, self.bss_section_index.?, .{});
698 self.shdr_table_dirty = true;
699 }
700
658 if (self.symtab_section_index == null) {701 if (self.symtab_section_index == null) {
659 self.symtab_section_index = @as(u16, @intCast(self.shdrs.items.len));702 self.symtab_section_index = @as(u16, @intCast(self.shdrs.items.len));
660 const min_align: u16 = if (small_ptr) @alignOf(elf.Elf32_Sym) else @alignOf(elf.Elf64_Sym);703 const min_align: u16 = if (small_ptr) @alignOf(elf.Elf32_Sym) else @alignOf(elf.Elf64_Sym);
...@@ -868,8 +911,9 @@ pub fn growAllocSection(self: *Elf, shdr_index: u16, needed_size: u64) !void {...@@ -868,8 +911,9 @@ pub fn growAllocSection(self: *Elf, shdr_index: u16, needed_size: u64) !void {
868 const shdr = &self.shdrs.items[shdr_index];911 const shdr = &self.shdrs.items[shdr_index];
869 const phdr_index = self.phdr_to_shdr_table.get(shdr_index).?;912 const phdr_index = self.phdr_to_shdr_table.get(shdr_index).?;
870 const phdr = &self.phdrs.items[phdr_index];913 const phdr = &self.phdrs.items[phdr_index];
914 const is_zerofill = shdr.sh_type == elf.SHT_NOBITS;
871915
872 if (needed_size > self.allocatedSize(shdr.sh_offset)) {916 if (needed_size > self.allocatedSize(shdr.sh_offset) and !is_zerofill) {
873 // Must move the entire section.917 // Must move the entire section.
874 const new_offset = self.findFreeSpace(needed_size, self.page_size);918 const new_offset = self.findFreeSpace(needed_size, self.page_size);
875 const existing_size = if (self.last_atom_and_free_list_table.get(shdr_index)) |meta| blk: {919 const existing_size = if (self.last_atom_and_free_list_table.get(shdr_index)) |meta| blk: {
...@@ -893,7 +937,10 @@ pub fn growAllocSection(self: *Elf, shdr_index: u16, needed_size: u64) !void {...@@ -893,7 +937,10 @@ pub fn growAllocSection(self: *Elf, shdr_index: u16, needed_size: u64) !void {
893937
894 shdr.sh_size = needed_size;938 shdr.sh_size = needed_size;
895 phdr.p_memsz = needed_size;939 phdr.p_memsz = needed_size;
896 phdr.p_filesz = needed_size;940
941 if (!is_zerofill) {
942 phdr.p_filesz = needed_size;
943 }
897944
898 self.markDirty(shdr_index, phdr_index);945 self.markDirty(shdr_index, phdr_index);
899}946}