| ... | ... | @@ -3053,7 +3053,51 @@ fn allocateSection(self: *MachO, segname: []const u8, sectname: []const u8, opts |
| 3053 | 3053 | return section_id; |
| 3054 | 3054 | } |
| 3055 | 3055 | |
| 3056 | | fn moveSectionInVirtualMemory(self: *MachO, sect_id: u8, needed_size: u64) !void { |
| 3056 | fn growSection(self: *MachO, sect_id: u8, needed_size: u64) !void { |
| 3057 | const header = &self.sections.items(.header)[sect_id]; |
| 3058 | const segment_index = self.sections.items(.segment_index)[sect_id]; |
| 3059 | const segment = &self.segments.items[segment_index]; |
| 3060 | const maybe_last_atom_index = self.sections.items(.last_atom_index)[sect_id]; |
| 3061 | const sect_capacity = self.allocatedSize(header.offset); |
| 3062 | |
| 3063 | if (needed_size > sect_capacity) { |
| 3064 | const new_offset = self.findFreeSpace(needed_size, self.page_size); |
| 3065 | const current_size = if (maybe_last_atom_index) |last_atom_index| blk: { |
| 3066 | const last_atom = self.getAtom(last_atom_index); |
| 3067 | const sym = last_atom.getSymbol(self); |
| 3068 | break :blk (sym.n_value + last_atom.size) - segment.vmaddr; |
| 3069 | } else 0; |
| 3070 | |
| 3071 | log.debug("moving {s},{s} from 0x{x} to 0x{x}", .{ |
| 3072 | header.segName(), |
| 3073 | header.sectName(), |
| 3074 | header.offset, |
| 3075 | new_offset, |
| 3076 | }); |
| 3077 | |
| 3078 | const amt = try self.base.file.?.copyRangeAll( |
| 3079 | header.offset, |
| 3080 | self.base.file.?, |
| 3081 | new_offset, |
| 3082 | current_size, |
| 3083 | ); |
| 3084 | if (amt != current_size) return error.InputOutput; |
| 3085 | header.offset = @intCast(u32, new_offset); |
| 3086 | segment.fileoff = new_offset; |
| 3087 | } |
| 3088 | |
| 3089 | const sect_vm_capacity = self.allocatedVirtualSize(segment.vmaddr); |
| 3090 | if (needed_size > sect_vm_capacity) { |
| 3091 | self.markRelocsDirtyByAddress(segment.vmaddr + needed_size); |
| 3092 | try self.growSectionVirtualMemory(sect_id, needed_size); |
| 3093 | } |
| 3094 | |
| 3095 | header.size = needed_size; |
| 3096 | segment.filesize = mem.alignForwardGeneric(u64, needed_size, self.page_size); |
| 3097 | segment.vmsize = mem.alignForwardGeneric(u64, needed_size, self.page_size); |
| 3098 | } |
| 3099 | |
| 3100 | fn growSectionVirtualMemory(self: *MachO, sect_id: u8, needed_size: u64) !void { |
| 3057 | 3101 | const header = &self.sections.items(.header)[sect_id]; |
| 3058 | 3102 | const segment = self.getSegmentPtr(sect_id); |
| 3059 | 3103 | const increased_size = padToIdeal(needed_size); |
| ... | ... | @@ -3172,45 +3216,9 @@ fn allocateAtom(self: *MachO, atom_index: Atom.Index, new_atom_size: u64, alignm |
| 3172 | 3216 | else |
| 3173 | 3217 | true; |
| 3174 | 3218 | if (expand_section) { |
| 3175 | | const sect_capacity = self.allocatedSize(header.offset); |
| 3176 | 3219 | const needed_size = (vaddr + new_atom_size) - segment.vmaddr; |
| 3177 | | if (needed_size > sect_capacity) { |
| 3178 | | const new_offset = self.findFreeSpace(needed_size, self.page_size); |
| 3179 | | const current_size = if (maybe_last_atom_index.*) |last_atom_index| blk: { |
| 3180 | | const last_atom = self.getAtom(last_atom_index); |
| 3181 | | const sym = last_atom.getSymbol(self); |
| 3182 | | break :blk (sym.n_value + last_atom.size) - segment.vmaddr; |
| 3183 | | } else 0; |
| 3184 | | |
| 3185 | | log.debug("moving {s},{s} from 0x{x} to 0x{x}", .{ |
| 3186 | | header.segName(), |
| 3187 | | header.sectName(), |
| 3188 | | header.offset, |
| 3189 | | new_offset, |
| 3190 | | }); |
| 3191 | | |
| 3192 | | const amt = try self.base.file.?.copyRangeAll( |
| 3193 | | header.offset, |
| 3194 | | self.base.file.?, |
| 3195 | | new_offset, |
| 3196 | | current_size, |
| 3197 | | ); |
| 3198 | | if (amt != current_size) return error.InputOutput; |
| 3199 | | header.offset = @intCast(u32, new_offset); |
| 3200 | | segment.fileoff = new_offset; |
| 3201 | | } |
| 3202 | | |
| 3203 | | const sect_vm_capacity = self.allocatedVirtualSize(segment.vmaddr); |
| 3204 | | if (needed_size > sect_vm_capacity) { |
| 3205 | | self.markRelocsDirtyByAddress(segment.vmaddr + needed_size); |
| 3206 | | try self.moveSectionInVirtualMemory(sect_id, needed_size); |
| 3207 | | } |
| 3208 | | |
| 3209 | | header.size = needed_size; |
| 3210 | | segment.filesize = mem.alignForwardGeneric(u64, needed_size, self.page_size); |
| 3211 | | segment.vmsize = mem.alignForwardGeneric(u64, needed_size, self.page_size); |
| 3220 | try self.growSection(sect_id, needed_size); |
| 3212 | 3221 | maybe_last_atom_index.* = atom_index; |
| 3213 | | |
| 3214 | 3222 | self.segment_table_dirty = true; |
| 3215 | 3223 | } |
| 3216 | 3224 | |
| ... | ... | @@ -3218,10 +3226,7 @@ fn allocateAtom(self: *MachO, atom_index: Atom.Index, new_atom_size: u64, alignm |
| 3218 | 3226 | if (header.@"align" < align_pow) { |
| 3219 | 3227 | header.@"align" = align_pow; |
| 3220 | 3228 | } |
| 3221 | | { |
| 3222 | | const atom_ptr = self.getAtomPtr(atom_index); |
| 3223 | | atom_ptr.size = new_atom_size; |
| 3224 | | } |
| 3229 | self.getAtomPtr(atom_index).size = new_atom_size; |
| 3225 | 3230 | |
| 3226 | 3231 | if (atom.prev_index) |prev_index| { |
| 3227 | 3232 | const prev = self.getAtomPtr(prev_index); |