macho: copy snapshots of segment commands

This commit is contained in:
Jakub Konka 2020-12-27 10:59:54 +01:00
parent a7bae1b857
commit d9ce7a021b
2 changed files with 76 additions and 4 deletions

View File

@ -1427,7 +1427,7 @@ pub fn populateMissingMetadata(self: *MachO) !void {
.addr = text_segment.inner.vmaddr + off,
.size = needed_size,
.offset = @intCast(u32, off),
.@"align" = @sizeOf(u64),
.@"align" = 3, // 2^@sizeOf(u64)
.reloff = 0,
.nreloc = 0,
.flags = flags,
@ -1749,8 +1749,14 @@ fn allocateTextBlock(self: *MachO, text_block: *TextBlock, new_block_size: u64,
self.last_text_block = text_block;
text_section.size = needed_size;
self.load_commands_dirty = true; // TODO Make more granular.
if (self.d_sym) |*ds| {
const debug_text_seg = &ds.load_commands.items[ds.text_segment_cmd_index.?].Segment;
const debug_text_sect = &debug_text_seg.sections.items[ds.text_section_index.?];
debug_text_sect.size = needed_size;
ds.load_commands_dirty = true;
}
}
text_block.size = new_block_size;

View File

@ -26,17 +26,20 @@ load_commands: std.ArrayListUnmanaged(LoadCommand) = .{},
pagezero_segment_cmd_index: ?u16 = null,
/// __TEXT segment
text_segment_cmd_index: ?u16 = null,
/// __DWARF segment
dwarf_segment_cmd_index: ?u16 = null,
/// __DATA segment
data_segment_cmd_index: ?u16 = null,
/// __LINKEDIT segment
linkedit_segment_cmd_index: ?u16 = null,
/// __DWARF segment
dwarf_segment_cmd_index: ?u16 = null,
/// Symbol table
symtab_cmd_index: ?u16 = null,
/// UUID load command
uuid_cmd_index: ?u16 = null,
/// Index into __TEXT,__text section.
text_section_index: ?u16 = null,
header_dirty: bool = false,
load_commands_dirty: bool = false,
@ -58,6 +61,22 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
self.header = header;
self.header_dirty = true;
}
if (self.pagezero_segment_cmd_index == null) {
self.pagezero_segment_cmd_index = @intCast(u16, self.load_commands.items.len);
const base_cmd = self.base.load_commands.items[self.base.pagezero_segment_cmd_index.?].Segment;
try self.copySegmentCommand(allocator, base_cmd);
}
if (self.text_segment_cmd_index == null) {
self.text_segment_cmd_index = @intCast(u16, self.load_commands.items.len);
const base_cmd = self.base.load_commands.items[self.base.text_segment_cmd_index.?].Segment;
try self.copySegmentCommand(allocator, base_cmd);
}
if (self.data_segment_cmd_index == null) outer: {
if (self.base.data_segment_cmd_index == null) break :outer; // __DATA is optional
self.data_segment_cmd_index = @intCast(u16, self.load_commands.items.len);
const base_cmd = self.base.load_commands.items[self.base.data_segment_cmd_index.?].Segment;
try self.copySegmentCommand(allocator, base_cmd);
}
if (self.uuid_cmd_index == null) {
const base_cmd = self.base.load_commands.items[self.base.uuid_cmd_index.?];
self.uuid_cmd_index = @intCast(u16, self.load_commands.items.len);
@ -81,6 +100,53 @@ pub fn deinit(self: *DebugSymbols, allocator: *Allocator) void {
self.file.close();
}
fn copySegmentCommand(self: *DebugSymbols, allocator: *Allocator, base_cmd: SegmentCommand) !void {
var cmd = SegmentCommand.empty(.{
.cmd = macho.LC_SEGMENT_64,
.cmdsize = base_cmd.inner.cmdsize,
.segname = undefined,
.vmaddr = base_cmd.inner.vmaddr,
.vmsize = base_cmd.inner.vmsize,
.fileoff = 0,
.filesize = 0,
.maxprot = base_cmd.inner.maxprot,
.initprot = base_cmd.inner.initprot,
.nsects = base_cmd.inner.nsects,
.flags = base_cmd.inner.flags,
});
mem.copy(u8, &cmd.inner.segname, &base_cmd.inner.segname);
try cmd.sections.ensureCapacity(allocator, cmd.inner.nsects);
for (base_cmd.sections.items) |base_sect, i| {
var sect = macho.section_64{
.sectname = undefined,
.segname = undefined,
.addr = base_sect.addr,
.size = base_sect.size,
.offset = 0,
.@"align" = base_sect.@"align",
.reloff = 0,
.nreloc = 0,
.flags = base_sect.flags,
.reserved1 = base_sect.reserved1,
.reserved2 = base_sect.reserved2,
.reserved3 = base_sect.reserved3,
};
mem.copy(u8, &sect.sectname, &base_sect.sectname);
mem.copy(u8, &sect.segname, &base_sect.segname);
if (self.base.text_section_index.? == i) {
self.text_section_index = @intCast(u16, i);
}
cmd.sections.appendAssumeCapacity(sect);
}
try self.load_commands.append(allocator, .{ .Segment = cmd });
self.header_dirty = true;
self.load_commands_dirty = true;
}
/// Writes all load commands and section headers.
fn writeLoadCommands(self: *DebugSymbols, allocator: *Allocator) !void {
if (!self.load_commands_dirty) return;