aboutsummaryrefslogtreecommitdiff
path: root/src/link/MachO/Object.zig
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2021-07-08 11:57:14 +0200
committerJakub Konka <kubkon@jakubkonka.com>2021-07-15 18:49:47 +0200
commit961b463fad37e00fa8a2ca2bbfcb58a2b1d2bea9 (patch)
treed519b6a8b66c585d0c1ee87175ae4d95044792af /src/link/MachO/Object.zig
parent7aeedc0912c8218773891ae98a729bb2b1be5231 (diff)
downloadzig-961b463fad37e00fa8a2ca2bbfcb58a2b1d2bea9.tar.gz
zig-961b463fad37e00fa8a2ca2bbfcb58a2b1d2bea9.zip
zld: track symbols defined within TextBlock
in case TextBlock represents an entire section with symbols defined within.
Diffstat (limited to 'src/link/MachO/Object.zig')
-rw-r--r--src/link/MachO/Object.zig72
1 files changed, 45 insertions, 27 deletions
diff --git a/src/link/MachO/Object.zig b/src/link/MachO/Object.zig
index 867821fa6f..a3b1ff4f79 100644
--- a/src/link/MachO/Object.zig
+++ b/src/link/MachO/Object.zig
@@ -430,17 +430,12 @@ const TextBlockParser = struct {
const block = try self.allocator.create(TextBlock);
errdefer self.allocator.destroy(block);
- block.* = .{
- .local_sym_index = senior_nlist.index,
- .aliases = alias_only_indices,
- .references = std.AutoArrayHashMap(u32, void).init(self.allocator),
- .code = try self.allocator.dupe(u8, code),
- .relocs = std.ArrayList(Relocation).init(self.allocator),
- .rebases = std.ArrayList(u64).init(self.allocator),
- .tlv_offsets = std.ArrayList(TextBlock.TlvOffset).init(self.allocator),
- .size = size,
- .alignment = self.section.@"align",
- };
+ block.* = TextBlock.init(self.allocator);
+ block.local_sym_index = senior_nlist.index;
+ block.aliases = alias_only_indices;
+ block.code = try self.allocator.dupe(u8, code);
+ block.size = size;
+ block.alignment = self.section.@"align";
const relocs = filterRelocs(self.relocs, start_addr, end_addr);
if (relocs.len > 0) {
@@ -499,16 +494,17 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {
_ = try self.file.?.preadAll(raw_relocs, sect.reloff);
const relocs = mem.bytesAsSlice(macho.relocation_info, raw_relocs);
+ // Symbols within this section only.
+ const filtered_nlists = NlistWithIndex.filterInSection(
+ sorted_nlists.items,
+ sect_id + 1,
+ );
+
// Is there any padding between symbols within the section?
const is_splittable = self.header.?.flags & macho.MH_SUBSECTIONS_VIA_SYMBOLS != 0;
next: {
if (is_splittable) blocks: {
- const filtered_nlists = NlistWithIndex.filterInSection(
- sorted_nlists.items,
- sect_id + 1,
- );
-
if (filtered_nlists.len == 0) break :blocks;
var parser = TextBlockParser{
@@ -528,7 +524,7 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {
if (reg.file) |file| {
if (file != self) {
log.warn("deduping definition of {s} in {s}", .{ sym.name, self.name.? });
- block.deinit(self.allocator);
+ block.deinit();
self.allocator.destroy(block);
continue;
}
@@ -583,21 +579,43 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {
const block = try self.allocator.create(TextBlock);
errdefer self.allocator.destroy(block);
- block.* = .{
- .local_sym_index = local_sym_index,
- .references = std.AutoArrayHashMap(u32, void).init(self.allocator),
- .code = try self.allocator.dupe(u8, code),
- .relocs = std.ArrayList(Relocation).init(self.allocator),
- .rebases = std.ArrayList(u64).init(self.allocator),
- .tlv_offsets = std.ArrayList(TextBlock.TlvOffset).init(self.allocator),
- .size = sect.size,
- .alignment = sect.@"align",
- };
+ block.* = TextBlock.init(self.allocator);
+ block.local_sym_index = local_sym_index;
+ block.code = try self.allocator.dupe(u8, code);
+ block.size = sect.size;
+ block.alignment = sect.@"align";
if (relocs.len > 0) {
try self.parseRelocs(zld, relocs, block, 0);
}
+ // Since this is block gets a helper local temporary symbol that didn't exist
+ // in the object file which encompasses the entire section, we need traverse
+ // the filtered symbols and note which symbol is contained within so that
+ // we can properly allocate addresses down the line.
+ // While we're at it, we need to update segment,section mapping of each symbol too.
+ if (filtered_nlists.len > 0) {
+ var contained = std.ArrayList(TextBlock.SymbolAtOffset).init(self.allocator);
+ defer contained.deinit();
+ try contained.ensureTotalCapacity(filtered_nlists.len);
+
+ for (filtered_nlists) |nlist_with_index| {
+ const sym = self.symbols.items[nlist_with_index.index];
+ assert(sym.payload == .regular);
+ const reg = &sym.payload.regular;
+
+ reg.segment_id = match.seg;
+ reg.section_id = match.sect;
+
+ contained.appendAssumeCapacity(.{
+ .local_sym_index = reg.local_sym_index,
+ .offset = nlist_with_index.nlist.n_value - sect.addr,
+ });
+ }
+
+ block.contained = contained.toOwnedSlice();
+ }
+
// Update target section's metadata
// TODO should we update segment's size here too?
// How does it tie with incremental space allocs?