mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
macho: don't allocate atoms when parsing objects
This commit is contained in:
parent
23be9cae34
commit
1efdb137d1
@ -2594,30 +2594,64 @@ fn resolveDyldStubBinder(self: *MachO) !void {
|
||||
}
|
||||
|
||||
fn parseTextBlocks(self: *MachO) !void {
|
||||
var parsed_atoms = Object.ParsedAtoms.init(self.base.allocator);
|
||||
defer parsed_atoms.deinit();
|
||||
|
||||
var first_atoms = Object.ParsedAtoms.init(self.base.allocator);
|
||||
defer first_atoms.deinit();
|
||||
|
||||
var section_metadata = std.AutoHashMap(MatchingSection, struct {
|
||||
size: u64,
|
||||
alignment: u32,
|
||||
}).init(self.base.allocator);
|
||||
defer section_metadata.deinit();
|
||||
|
||||
for (self.objects.items) |object| {
|
||||
const seg = object.load_commands.items[object.segment_cmd_index.?].Segment;
|
||||
for (seg.sections.items) |sect| {
|
||||
const match = (try self.getMatchingSection(sect)) orelse {
|
||||
log.debug("unhandled section", .{});
|
||||
continue;
|
||||
};
|
||||
const res = try section_metadata.getOrPut(match);
|
||||
if (!res.found_existing) {
|
||||
res.value_ptr.* = .{
|
||||
for (self.objects.items) |*object, object_id| {
|
||||
var atoms_in_objects = try object.parseTextBlocks(self.base.allocator, @intCast(u16, object_id), self);
|
||||
defer atoms_in_objects.deinit();
|
||||
|
||||
var it = atoms_in_objects.iterator();
|
||||
while (it.next()) |entry| {
|
||||
const match = entry.key_ptr.*;
|
||||
const last_atom = entry.value_ptr.*;
|
||||
var atom = last_atom;
|
||||
|
||||
const metadata = try section_metadata.getOrPut(match);
|
||||
if (!metadata.found_existing) {
|
||||
metadata.value_ptr.* = .{
|
||||
.size = 0,
|
||||
.alignment = 0,
|
||||
};
|
||||
}
|
||||
const size = padToIdeal(sect.size);
|
||||
const alignment = try math.powi(u32, 2, sect.@"align");
|
||||
res.value_ptr.size += mem.alignForwardGeneric(u64, size, alignment);
|
||||
res.value_ptr.alignment = math.max(res.value_ptr.alignment, sect.@"align");
|
||||
|
||||
while (true) {
|
||||
const alignment = try math.powi(u32, 2, atom.alignment);
|
||||
metadata.value_ptr.size += mem.alignForwardGeneric(u64, atom.size, alignment);
|
||||
metadata.value_ptr.alignment = math.max(metadata.value_ptr.alignment, atom.alignment);
|
||||
|
||||
const sym = self.locals.items[atom.local_sym_index];
|
||||
log.debug(" {s}: n_value=0x{x}, size=0x{x}, alignment=0x{x}", .{
|
||||
self.getString(sym.n_strx),
|
||||
sym.n_value,
|
||||
atom.size,
|
||||
atom.alignment,
|
||||
});
|
||||
|
||||
if (atom.prev) |prev| {
|
||||
atom = prev;
|
||||
} else break;
|
||||
}
|
||||
|
||||
if (parsed_atoms.getPtr(match)) |last| {
|
||||
last.*.next = atom;
|
||||
atom.prev = last.*;
|
||||
last.* = atom;
|
||||
}
|
||||
_ = try parsed_atoms.put(match, last_atom);
|
||||
|
||||
if (!first_atoms.contains(match)) {
|
||||
try first_atoms.putNoClobber(match, atom);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2625,63 +2659,69 @@ fn parseTextBlocks(self: *MachO) !void {
|
||||
while (it.next()) |entry| {
|
||||
const match = entry.key_ptr.*;
|
||||
const metadata = entry.value_ptr.*;
|
||||
const seg = self.load_commands.items[match.seg].Segment;
|
||||
const sect = seg.sections.items[match.sect];
|
||||
const seg = &self.load_commands.items[match.seg].Segment;
|
||||
const sect = &seg.sections.items[match.sect];
|
||||
log.debug("{s},{s} => size: 0x{x}, alignment: 0x{x}", .{
|
||||
commands.segmentName(sect),
|
||||
commands.sectionName(sect),
|
||||
commands.segmentName(sect.*),
|
||||
commands.sectionName(sect.*),
|
||||
metadata.size,
|
||||
metadata.alignment,
|
||||
});
|
||||
sect.@"align" = math.max(sect.@"align", metadata.alignment);
|
||||
try self.growSection(match, @intCast(u32, metadata.size));
|
||||
|
||||
var base_vaddr = if (self.blocks.get(match)) |last| blk: {
|
||||
const last_atom_sym = self.locals.items[last.local_sym_index];
|
||||
break :blk last_atom_sym.n_value + last.size;
|
||||
} else sect.addr;
|
||||
const n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1);
|
||||
|
||||
var atom = first_atoms.get(match).?;
|
||||
while (true) {
|
||||
const alignment = try math.powi(u32, 2, atom.alignment);
|
||||
base_vaddr = mem.alignForwardGeneric(u64, base_vaddr, alignment);
|
||||
|
||||
const sym = &self.locals.items[atom.local_sym_index];
|
||||
sym.n_value = base_vaddr;
|
||||
sym.n_sect = n_sect;
|
||||
|
||||
log.debug(" {s}: start=0x{x}, end=0x{x}, size=0x{x}, alignment=0x{x}", .{
|
||||
self.getString(sym.n_strx),
|
||||
base_vaddr,
|
||||
base_vaddr + atom.size,
|
||||
atom.size,
|
||||
atom.alignment,
|
||||
});
|
||||
|
||||
// Update each alias (if any)
|
||||
for (atom.aliases.items) |index| {
|
||||
const alias_sym = &self.locals.items[index];
|
||||
alias_sym.n_value = base_vaddr;
|
||||
alias_sym.n_sect = n_sect;
|
||||
}
|
||||
|
||||
// Update each symbol contained within the TextBlock
|
||||
for (atom.contained.items) |sym_at_off| {
|
||||
const contained_sym = &self.locals.items[sym_at_off.local_sym_index];
|
||||
contained_sym.n_value = base_vaddr + sym_at_off.offset;
|
||||
contained_sym.n_sect = n_sect;
|
||||
}
|
||||
|
||||
base_vaddr += atom.size;
|
||||
|
||||
if (atom.next) |next| {
|
||||
atom = next;
|
||||
} else break;
|
||||
}
|
||||
|
||||
if (self.blocks.getPtr(match)) |last| {
|
||||
const first_atom = first_atoms.get(match).?;
|
||||
last.*.next = first_atom;
|
||||
first_atom.prev = last.*;
|
||||
last.* = first_atom;
|
||||
}
|
||||
_ = try self.blocks.put(self.base.allocator, match, parsed_atoms.get(match).?);
|
||||
}
|
||||
|
||||
for (self.objects.items) |*object, object_id| {
|
||||
try object.parseTextBlocks(self.base.allocator, @intCast(u16, object_id), self);
|
||||
}
|
||||
|
||||
// it = section_metadata.iterator();
|
||||
// while (it.next()) |entry| {
|
||||
// const match = entry.key_ptr.*;
|
||||
// const metadata = entry.value_ptr.*;
|
||||
// const seg = self.load_commands.items[match.seg].Segment;
|
||||
// const sect = seg.sections.items[match.sect];
|
||||
|
||||
// var buffer = try self.base.allocator.alloc(u8, metadata.size);
|
||||
// defer self.base.allocator.free(buffer);
|
||||
// log.warn("{s},{s} buffer size 0x{x}", .{
|
||||
// commands.segmentName(sect),
|
||||
// commands.sectionName(sect),
|
||||
// metadata.size,
|
||||
// });
|
||||
|
||||
// var atom = self.blocks.get(match).?;
|
||||
|
||||
// while (atom.prev) |prev| {
|
||||
// atom = prev;
|
||||
// }
|
||||
|
||||
// const base = blk: {
|
||||
// const sym = self.locals.items[atom.local_sym_index];
|
||||
// break :blk sym.n_value;
|
||||
// };
|
||||
|
||||
// while (true) {
|
||||
// const sym = self.locals.items[atom.local_sym_index];
|
||||
// const offset = sym.n_value - base;
|
||||
// try atom.resolveRelocs(self);
|
||||
// log.warn("writing atom for symbol {s} at buffer offset 0x{x}", .{
|
||||
// self.getString(sym.n_strx),
|
||||
// offset,
|
||||
// });
|
||||
// mem.copy(u8, buffer[offset..][0..atom.code.items.len], atom.code.items);
|
||||
// atom.dirty = false;
|
||||
|
||||
// if (atom.next) |next| {
|
||||
// atom = next;
|
||||
// } else break;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
fn addDataInCodeLC(self: *MachO) !void {
|
||||
|
||||
@ -317,6 +317,7 @@ const Context = struct {
|
||||
object: *Object,
|
||||
macho_file: *MachO,
|
||||
match: MachO.MatchingSection,
|
||||
parsed_atoms: *ParsedAtoms,
|
||||
};
|
||||
|
||||
const TextBlockParser = struct {
|
||||
@ -430,6 +431,7 @@ const TextBlockParser = struct {
|
||||
.allocator = context.allocator,
|
||||
.object = context.object,
|
||||
.macho_file = context.macho_file,
|
||||
.parsed_atoms = context.parsed_atoms,
|
||||
});
|
||||
|
||||
if (context.macho_file.has_dices) {
|
||||
@ -455,12 +457,15 @@ const TextBlockParser = struct {
|
||||
}
|
||||
};
|
||||
|
||||
pub const ParsedAtoms = std.AutoHashMap(MachO.MatchingSection, *TextBlock);
|
||||
|
||||
pub fn parseTextBlocks(
|
||||
self: *Object,
|
||||
allocator: *Allocator,
|
||||
object_id: u16,
|
||||
macho_file: *MachO,
|
||||
) !void {
|
||||
) !ParsedAtoms {
|
||||
var parsed_atoms = ParsedAtoms.init(allocator);
|
||||
const seg = self.load_commands.items[self.segment_cmd_index.?].Segment;
|
||||
|
||||
log.debug("analysing {s}", .{self.name});
|
||||
@ -589,6 +594,7 @@ pub fn parseTextBlocks(
|
||||
.allocator = allocator,
|
||||
.object = self,
|
||||
.macho_file = macho_file,
|
||||
.parsed_atoms = &parsed_atoms,
|
||||
});
|
||||
|
||||
if (macho_file.has_dices) {
|
||||
@ -604,7 +610,13 @@ pub fn parseTextBlocks(
|
||||
}
|
||||
}
|
||||
|
||||
_ = try macho_file.allocateAtom(block, match);
|
||||
if (parsed_atoms.getPtr(match)) |last| {
|
||||
last.*.next = block;
|
||||
block.prev = last.*;
|
||||
last.* = block;
|
||||
} else {
|
||||
try parsed_atoms.putNoClobber(match, block);
|
||||
}
|
||||
try self.text_blocks.append(allocator, block);
|
||||
}
|
||||
|
||||
@ -620,6 +632,7 @@ pub fn parseTextBlocks(
|
||||
.object = self,
|
||||
.macho_file = macho_file,
|
||||
.match = match,
|
||||
.parsed_atoms = &parsed_atoms,
|
||||
})) |block| {
|
||||
const sym = macho_file.locals.items[block.local_sym_index];
|
||||
const is_ext = blk: {
|
||||
@ -651,7 +664,13 @@ pub fn parseTextBlocks(
|
||||
}
|
||||
}
|
||||
|
||||
_ = try macho_file.allocateAtom(block, match);
|
||||
if (parsed_atoms.getPtr(match)) |last| {
|
||||
last.*.next = block;
|
||||
block.prev = last.*;
|
||||
last.* = block;
|
||||
} else {
|
||||
try parsed_atoms.putNoClobber(match, block);
|
||||
}
|
||||
try self.text_blocks.append(allocator, block);
|
||||
}
|
||||
|
||||
@ -696,6 +715,7 @@ pub fn parseTextBlocks(
|
||||
.allocator = allocator,
|
||||
.object = self,
|
||||
.macho_file = macho_file,
|
||||
.parsed_atoms = &parsed_atoms,
|
||||
});
|
||||
|
||||
if (macho_file.has_dices) {
|
||||
@ -747,10 +767,18 @@ pub fn parseTextBlocks(
|
||||
});
|
||||
}
|
||||
|
||||
_ = try macho_file.allocateAtom(block, match);
|
||||
if (parsed_atoms.getPtr(match)) |last| {
|
||||
last.*.next = block;
|
||||
block.prev = last.*;
|
||||
last.* = block;
|
||||
} else {
|
||||
try parsed_atoms.putNoClobber(match, block);
|
||||
}
|
||||
try self.text_blocks.append(allocator, block);
|
||||
}
|
||||
}
|
||||
|
||||
return parsed_atoms;
|
||||
}
|
||||
|
||||
fn parseSymtab(self: *Object, allocator: *Allocator) !void {
|
||||
|
||||
@ -628,6 +628,7 @@ const RelocContext = struct {
|
||||
allocator: *Allocator,
|
||||
object: *Object,
|
||||
macho_file: *MachO,
|
||||
parsed_atoms: *Object.ParsedAtoms,
|
||||
};
|
||||
|
||||
fn initRelocFromObject(rel: macho.relocation_info, context: RelocContext) !Relocation {
|
||||
@ -855,7 +856,14 @@ pub fn parseRelocs(self: *TextBlock, relocs: []macho.relocation_info, context: R
|
||||
.seg = context.macho_file.data_const_segment_cmd_index.?,
|
||||
.sect = context.macho_file.got_section_index.?,
|
||||
};
|
||||
_ = try context.macho_file.allocateAtom(atom, match);
|
||||
|
||||
if (context.parsed_atoms.getPtr(match)) |last| {
|
||||
last.*.next = atom;
|
||||
atom.prev = last.*;
|
||||
last.* = atom;
|
||||
} else {
|
||||
try context.parsed_atoms.putNoClobber(match, atom);
|
||||
}
|
||||
} else if (parsed_rel.payload == .unsigned) {
|
||||
switch (parsed_rel.where) {
|
||||
.undef => {
|
||||
@ -918,18 +926,46 @@ pub fn parseRelocs(self: *TextBlock, relocs: []macho.relocation_info, context: R
|
||||
);
|
||||
const stub_atom = try context.macho_file.createStubAtom(laptr_atom.local_sym_index);
|
||||
try context.macho_file.stubs_map.putNoClobber(context.allocator, parsed_rel.where_index, stub_atom);
|
||||
_ = try context.macho_file.allocateAtom(stub_helper_atom, .{
|
||||
// TODO clean this up!
|
||||
if (context.parsed_atoms.getPtr(.{
|
||||
.seg = context.macho_file.text_segment_cmd_index.?,
|
||||
.sect = context.macho_file.stub_helper_section_index.?,
|
||||
});
|
||||
_ = try context.macho_file.allocateAtom(laptr_atom, .{
|
||||
.seg = context.macho_file.data_segment_cmd_index.?,
|
||||
.sect = context.macho_file.la_symbol_ptr_section_index.?,
|
||||
});
|
||||
_ = try context.macho_file.allocateAtom(stub_atom, .{
|
||||
})) |last| {
|
||||
last.*.next = stub_helper_atom;
|
||||
stub_helper_atom.prev = last.*;
|
||||
last.* = stub_helper_atom;
|
||||
} else {
|
||||
try context.parsed_atoms.putNoClobber(.{
|
||||
.seg = context.macho_file.text_segment_cmd_index.?,
|
||||
.sect = context.macho_file.stub_helper_section_index.?,
|
||||
}, stub_helper_atom);
|
||||
}
|
||||
if (context.parsed_atoms.getPtr(.{
|
||||
.seg = context.macho_file.text_segment_cmd_index.?,
|
||||
.sect = context.macho_file.stubs_section_index.?,
|
||||
});
|
||||
})) |last| {
|
||||
last.*.next = stub_atom;
|
||||
stub_atom.prev = last.*;
|
||||
last.* = stub_atom;
|
||||
} else {
|
||||
try context.parsed_atoms.putNoClobber(.{
|
||||
.seg = context.macho_file.text_segment_cmd_index.?,
|
||||
.sect = context.macho_file.stubs_section_index.?,
|
||||
}, stub_atom);
|
||||
}
|
||||
if (context.parsed_atoms.getPtr(.{
|
||||
.seg = context.macho_file.data_segment_cmd_index.?,
|
||||
.sect = context.macho_file.la_symbol_ptr_section_index.?,
|
||||
})) |last| {
|
||||
last.*.next = laptr_atom;
|
||||
laptr_atom.prev = last.*;
|
||||
last.* = laptr_atom;
|
||||
} else {
|
||||
try context.parsed_atoms.putNoClobber(.{
|
||||
.seg = context.macho_file.data_segment_cmd_index.?,
|
||||
.sect = context.macho_file.la_symbol_ptr_section_index.?,
|
||||
}, laptr_atom);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user