| ... | @@ -4369,6 +4369,19 @@ fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -4369,6 +4369,19 @@ fn populateMissingMetadata(self: *MachO) !void { |
| 4369 | self.load_commands_dirty = true; | 4369 | self.load_commands_dirty = true; |
| 4370 | } | 4370 | } |
| 4371 | | 4371 | |
| | 4372 | if (self.function_starts_cmd_index == null) { |
| | 4373 | self.function_starts_cmd_index = @intCast(u16, self.load_commands.items.len); |
| | 4374 | try self.load_commands.append(self.base.allocator, .{ |
| | 4375 | .LinkeditData = .{ |
| | 4376 | .cmd = macho.LC_FUNCTION_STARTS, |
| | 4377 | .cmdsize = @sizeOf(macho.linkedit_data_command), |
| | 4378 | .dataoff = 0, |
| | 4379 | .datasize = 0, |
| | 4380 | }, |
| | 4381 | }); |
| | 4382 | self.load_commands_dirty = true; |
| | 4383 | } |
| | 4384 | |
| 4372 | if (self.data_in_code_cmd_index == null) { | 4385 | if (self.data_in_code_cmd_index == null) { |
| 4373 | self.data_in_code_cmd_index = @intCast(u16, self.load_commands.items.len); | 4386 | self.data_in_code_cmd_index = @intCast(u16, self.load_commands.items.len); |
| 4374 | try self.load_commands.append(self.base.allocator, .{ | 4387 | try self.load_commands.append(self.base.allocator, .{ |
| ... | @@ -5324,6 +5337,95 @@ fn populateLazyBindOffsetsInStubHelper(self: *MachO, buffer: []const u8) !void { | ... | @@ -5324,6 +5337,95 @@ fn populateLazyBindOffsetsInStubHelper(self: *MachO, buffer: []const u8) !void { |
| 5324 | } | 5337 | } |
| 5325 | } | 5338 | } |
| 5326 | | 5339 | |
| | 5340 | fn writeFunctionStarts(self: *MachO) !void { |
| | 5341 | var atom = self.atoms.get(.{ |
| | 5342 | .seg = self.text_segment_cmd_index orelse return, |
| | 5343 | .sect = self.text_section_index orelse return, |
| | 5344 | }) orelse return; |
| | 5345 | |
| | 5346 | const tracy = trace(@src()); |
| | 5347 | defer tracy.end(); |
| | 5348 | |
| | 5349 | while (atom.prev) |prev| { |
| | 5350 | atom = prev; |
| | 5351 | } |
| | 5352 | |
| | 5353 | var offsets = std.ArrayList(u32).init(self.base.allocator); |
| | 5354 | defer offsets.deinit(); |
| | 5355 | |
| | 5356 | const text_seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| | 5357 | var last_off: u32 = 0; |
| | 5358 | |
| | 5359 | while (true) { |
| | 5360 | const atom_sym = self.locals.items[atom.local_sym_index]; |
| | 5361 | |
| | 5362 | if (atom_sym.n_strx != 0) blk: { |
| | 5363 | if (self.symbol_resolver.get(atom_sym.n_strx)) |resolv| { |
| | 5364 | assert(resolv.where == .global); |
| | 5365 | if (resolv.local_sym_index != atom.local_sym_index) break :blk; |
| | 5366 | } |
| | 5367 | |
| | 5368 | const offset = @intCast(u32, atom_sym.n_value - text_seg.inner.vmaddr); |
| | 5369 | const diff = offset - last_off; |
| | 5370 | |
| | 5371 | if (diff == 0) break :blk; |
| | 5372 | |
| | 5373 | try offsets.append(diff); |
| | 5374 | last_off = offset; |
| | 5375 | } |
| | 5376 | |
| | 5377 | for (atom.contained.items) |cont| { |
| | 5378 | const cont_sym = self.locals.items[cont.local_sym_index]; |
| | 5379 | |
| | 5380 | if (cont_sym.n_strx == 0) continue; |
| | 5381 | if (self.symbol_resolver.get(cont_sym.n_strx)) |resolv| { |
| | 5382 | assert(resolv.where == .global); |
| | 5383 | if (resolv.local_sym_index != cont.local_sym_index) continue; |
| | 5384 | } |
| | 5385 | |
| | 5386 | const offset = @intCast(u32, cont_sym.n_value - text_seg.inner.vmaddr); |
| | 5387 | const diff = offset - last_off; |
| | 5388 | |
| | 5389 | if (diff == 0) continue; |
| | 5390 | |
| | 5391 | try offsets.append(diff); |
| | 5392 | last_off = offset; |
| | 5393 | } |
| | 5394 | |
| | 5395 | if (atom.next) |next| { |
| | 5396 | atom = next; |
| | 5397 | } else break; |
| | 5398 | } |
| | 5399 | |
| | 5400 | const max_size = @intCast(usize, offsets.items.len * @sizeOf(u64)); |
| | 5401 | var buffer = try self.base.allocator.alloc(u8, max_size); |
| | 5402 | defer self.base.allocator.free(buffer); |
| | 5403 | mem.set(u8, buffer, 0); |
| | 5404 | |
| | 5405 | var stream = std.io.fixedBufferStream(buffer); |
| | 5406 | var writer = stream.writer(); |
| | 5407 | |
| | 5408 | for (offsets.items) |offset| { |
| | 5409 | try std.leb.writeULEB128(writer, offset); |
| | 5410 | } |
| | 5411 | |
| | 5412 | const needed_size = @intCast(u32, mem.alignForwardGeneric(u64, stream.pos, @sizeOf(u64))); |
| | 5413 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; |
| | 5414 | const fn_cmd = &self.load_commands.items[self.function_starts_cmd_index.?].LinkeditData; |
| | 5415 | |
| | 5416 | fn_cmd.dataoff = @intCast(u32, seg.inner.fileoff + seg.inner.filesize); |
| | 5417 | fn_cmd.datasize = needed_size; |
| | 5418 | seg.inner.filesize += needed_size; |
| | 5419 | |
| | 5420 | log.debug("writing function starts info from 0x{x} to 0x{x}", .{ |
| | 5421 | fn_cmd.dataoff, |
| | 5422 | fn_cmd.dataoff + fn_cmd.datasize, |
| | 5423 | }); |
| | 5424 | |
| | 5425 | try self.base.file.?.pwriteAll(buffer[0..needed_size], fn_cmd.dataoff); |
| | 5426 | self.load_commands_dirty = true; |
| | 5427 | } |
| | 5428 | |
| 5327 | fn writeDices(self: *MachO) !void { | 5429 | fn writeDices(self: *MachO) !void { |
| 5328 | if (!self.has_dices) return; | 5430 | if (!self.has_dices) return; |
| 5329 | | 5431 | |
| ... | @@ -5591,6 +5693,7 @@ fn writeLinkeditSegment(self: *MachO) !void { | ... | @@ -5591,6 +5693,7 @@ fn writeLinkeditSegment(self: *MachO) !void { |
| 5591 | seg.inner.filesize = 0; | 5693 | seg.inner.filesize = 0; |
| 5592 | | 5694 | |
| 5593 | try self.writeDyldInfoData(); | 5695 | try self.writeDyldInfoData(); |
| | 5696 | try self.writeFunctionStarts(); |
| 5594 | try self.writeDices(); | 5697 | try self.writeDices(); |
| 5595 | try self.writeSymbolTable(); | 5698 | try self.writeSymbolTable(); |
| 5596 | try self.writeStringTable(); | 5699 | try self.writeStringTable(); |