authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-12-08 17:08:40+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-12-08 23:24:40+01:00
log64e2bfaa236c14b403103c92691fa6774e1fdc83
tree6d4539883ffa1268e54e57e21fdd33994dd7ac7a
parent98e36ea6b9aff3403685af3a76ffa998249c9b84

macho: write out LC_FUNCTION_START data


1 files changed, 103 insertions(+), 0 deletions(-)

src/link/MachO.zig+103
......@@ -4369,6 +4369,19 @@ fn populateMissingMetadata(self: *MachO) !void {
43694369 self.load_commands_dirty = true;
43704370 }
43714371
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
43724385 if (self.data_in_code_cmd_index == null) {
43734386 self.data_in_code_cmd_index = @intCast(u16, self.load_commands.items.len);
43744387 try self.load_commands.append(self.base.allocator, .{
......@@ -5324,6 +5337,95 @@ fn populateLazyBindOffsetsInStubHelper(self: *MachO, buffer: []const u8) !void {
53245337 }
53255338}
53265339
5340fn 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
53275429fn writeDices(self: *MachO) !void {
53285430 if (!self.has_dices) return;
53295431
......@@ -5591,6 +5693,7 @@ fn writeLinkeditSegment(self: *MachO) !void {
55915693 seg.inner.filesize = 0;
55925694
55935695 try self.writeDyldInfoData();
5696 try self.writeFunctionStarts();
55945697 try self.writeDices();
55955698 try self.writeSymbolTable();
55965699 try self.writeStringTable();