authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-09-15 13:48:00+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-09-18 10:00:04+02:00
log618c7a3546bb5e73a4f7ff4bd38e53700f63c90c
tree9ee8cfc477555704f9068b76123af4b5c35bd55f
parente601969244d9e3da7f6c88792932297d87c821eb

macho: add logic for expanding segments in memory


3 files changed, 42 insertions(+), 3 deletions(-)

src/link/Coff.zig+1
...@@ -1135,6 +1135,7 @@ fn getDeclOutputSection(self: *Coff, decl: *Module.Decl) u16 {...@@ -1135,6 +1135,7 @@ fn getDeclOutputSection(self: *Coff, decl: *Module.Decl) u16 {
1135 }1135 }
11361136
1137 switch (zig_ty) {1137 switch (zig_ty) {
1138 // TODO: what if this is a function pointer?
1138 .Fn => break :blk self.text_section_index.?,1139 .Fn => break :blk self.text_section_index.?,
1139 else => {1140 else => {
1140 if (val.castTag(.variable)) |_| {1141 if (val.castTag(.variable)) |_| {
src/link/Elf.zig+1
...@@ -2320,6 +2320,7 @@ fn getDeclPhdrIndex(self: *Elf, decl: *Module.Decl) !u16 {...@@ -2320,6 +2320,7 @@ fn getDeclPhdrIndex(self: *Elf, decl: *Module.Decl) !u16 {
2320 }2320 }
23212321
2322 switch (zig_ty) {2322 switch (zig_ty) {
2323 // TODO: what if this is a function pointer?
2323 .Fn => break :blk self.phdr_load_re_index.?,2324 .Fn => break :blk self.phdr_load_re_index.?,
2324 else => {2325 else => {
2325 if (val.castTag(.variable)) |_| {2326 if (val.castTag(.variable)) |_| {
src/link/MachO.zig+40-3
...@@ -2839,7 +2839,9 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu...@@ -2839,7 +2839,9 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu
2839 const required_alignment = typed_value.ty.abiAlignment(self.base.options.target);2839 const required_alignment = typed_value.ty.abiAlignment(self.base.options.target);
2840 atom.size = code.len;2840 atom.size = code.len;
2841 atom.alignment = required_alignment;2841 atom.alignment = required_alignment;
2842 const sect_id = self.getDeclOutputSection(decl);2842 // TODO: work out logic for disambiguating functions from function pointers
2843 // const sect_id = self.getDeclOutputSection(decl);
2844 const sect_id = self.data_const_section_index.?;
2843 const symbol = atom.getSymbolPtr(self);2845 const symbol = atom.getSymbolPtr(self);
2844 symbol.n_strx = name_str_index;2846 symbol.n_strx = name_str_index;
2845 symbol.n_type = macho.N_SECT;2847 symbol.n_type = macho.N_SECT;
...@@ -2956,6 +2958,7 @@ fn getDeclOutputSection(self: *MachO, decl: *Module.Decl) u8 {...@@ -2956,6 +2958,7 @@ fn getDeclOutputSection(self: *MachO, decl: *Module.Decl) u8 {
2956 }2958 }
29572959
2958 switch (zig_ty) {2960 switch (zig_ty) {
2961 // TODO: what if this is a function pointer?
2959 .Fn => break :blk self.text_section_index.?,2962 .Fn => break :blk self.text_section_index.?,
2960 else => {2963 else => {
2961 if (val.castTag(.variable)) |_| {2964 if (val.castTag(.variable)) |_| {
...@@ -3709,6 +3712,41 @@ fn allocateSection(self: *MachO, segname: []const u8, sectname: []const u8, opts...@@ -3709,6 +3712,41 @@ fn allocateSection(self: *MachO, segname: []const u8, sectname: []const u8, opts
3709 return section_id;3712 return section_id;
3710}3713}
37113714
3715fn moveSectionInVirtualMemory(self: *MachO, sect_id: u32, needed_size: u64) !void {
3716 const header = &self.sections.items(.header)[sect_id];
3717 const segment = &self.segments.items[self.sections.items(.segment_index)[sect_id]];
3718 const increased_size = padToIdeal(needed_size);
3719 const old_aligned_end = segment.vmaddr + segment.vmsize;
3720 const new_aligned_end = segment.vmaddr + mem.alignForwardGeneric(u64, increased_size, self.page_size);
3721 const diff = new_aligned_end - old_aligned_end;
3722 log.debug("shifting every segment after {s},{s} in virtual memory by {x}", .{
3723 header.segName(),
3724 header.sectName(),
3725 diff,
3726 });
3727
3728 // TODO: enforce order by increasing VM addresses in self.sections container.
3729 for (self.sections.items(.header)[sect_id + 1 ..]) |*next_header, next_sect_id| {
3730 const index = sect_id + 1 + next_sect_id;
3731 const maybe_last_atom = &self.sections.items(.last_atom)[index];
3732 const next_segment = &self.segments.items[self.sections.items(.segment_index)[index]];
3733 next_header.addr += diff;
3734 next_segment.vmaddr += diff;
3735
3736 if (maybe_last_atom.*) |last_atom| {
3737 var atom = last_atom;
3738 while (true) {
3739 const sym = atom.getSymbolPtr(self);
3740 sym.n_value += diff;
3741
3742 if (atom.prev) |prev| {
3743 atom = prev;
3744 } else break;
3745 }
3746 }
3747 }
3748}
3749
3712fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64) !u64 {3750fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64) !u64 {
3713 const tracy = trace(@src());3751 const tracy = trace(@src());
3714 defer tracy.end();3752 defer tracy.end();
...@@ -3816,13 +3854,12 @@ fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64) !...@@ -3816,13 +3854,12 @@ fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64) !
3816 const sect_vm_capacity = self.allocatedVirtualSize(segment.vmaddr);3854 const sect_vm_capacity = self.allocatedVirtualSize(segment.vmaddr);
3817 if (needed_size > sect_vm_capacity) {3855 if (needed_size > sect_vm_capacity) {
3818 self.markRelocsDirtyByAddress(segment.vmaddr + needed_size);3856 self.markRelocsDirtyByAddress(segment.vmaddr + needed_size);
3819 @panic("TODO grow section in VM");3857 try self.moveSectionInVirtualMemory(sect_id, needed_size);
3820 }3858 }
38213859
3822 header.size = needed_size;3860 header.size = needed_size;
3823 segment.filesize = needed_size;3861 segment.filesize = needed_size;
3824 segment.vmsize = mem.alignForwardGeneric(u64, needed_size, self.page_size);3862 segment.vmsize = mem.alignForwardGeneric(u64, needed_size, self.page_size);
3825 log.warn("updating {s},{s}: {x}, {x}", .{ header.segName(), header.sectName(), segment.vmsize, segment.filesize });
3826 maybe_last_atom.* = atom;3863 maybe_last_atom.* = atom;
38273864
3828 self.segment_table_dirty = true;3865 self.segment_table_dirty = true;