diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2021-06-10 08:30:25 +0200 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2021-06-10 09:13:35 +0200 |
| commit | 96bb81b6ef0896d0b63c54bfd5d1ac0fa267d68a (patch) | |
| tree | 8d751f4925f3c05ff04dca9db3560af21593ef5f /src | |
| parent | 88aec4a1ee49088685b16d744f35c902c4900a09 (diff) | |
| download | zig-96bb81b6ef0896d0b63c54bfd5d1ac0fa267d68a.tar.gz zig-96bb81b6ef0896d0b63c54bfd5d1ac0fa267d68a.zip | |
zld: moving target seg,sect mapping into Object.Section
Diffstat (limited to 'src')
| -rw-r--r-- | src/link/MachO/Object.zig | 5 | ||||
| -rw-r--r-- | src/link/MachO/Zld.zig | 207 |
2 files changed, 94 insertions, 118 deletions
diff --git a/src/link/MachO/Object.zig b/src/link/MachO/Object.zig index 5241fea582..1277423b09 100644 --- a/src/link/MachO/Object.zig +++ b/src/link/MachO/Object.zig @@ -54,6 +54,11 @@ pub const Section = struct { inner: macho.section_64, code: []u8, relocs: ?[]*Relocation, + target_map: ?struct { + segment_id: u16, + section_id: u16, + offset: u32, + } = null, pub fn deinit(self: *Section, allocator: *Allocator) void { allocator.free(self.code); diff --git a/src/link/MachO/Zld.zig b/src/link/MachO/Zld.zig index c5362b8d7d..9f676f3fc2 100644 --- a/src/link/MachO/Zld.zig +++ b/src/link/MachO/Zld.zig @@ -95,9 +95,6 @@ got_entries: std.ArrayListUnmanaged(*Symbol) = .{}, stub_helper_stubs_start_off: ?u64 = null, -mappings: std.AutoHashMapUnmanaged(MappingKey, SectionMapping) = .{}, -unhandled_sections: std.AutoHashMapUnmanaged(MappingKey, u0) = .{}, - const TlvOffset = struct { source_addr: u64, offset: u64, @@ -107,18 +104,6 @@ const TlvOffset = struct { } }; -const MappingKey = struct { - object_id: u16, - source_sect_id: u16, -}; - -pub const SectionMapping = struct { - source_sect_id: u16, - target_seg_id: u16, - target_sect_id: u16, - offset: u32, -}; - /// Default path to dyld const DEFAULT_DYLD_PATH: [*:0]const u8 = "/usr/lib/dyld"; @@ -159,9 +144,6 @@ pub fn deinit(self: *Zld) void { } self.dylibs.deinit(self.allocator); - self.mappings.deinit(self.allocator); - self.unhandled_sections.deinit(self.allocator); - self.globals.deinit(self.allocator); self.imports.deinit(self.allocator); self.unresolved.deinit(self.allocator); @@ -407,46 +389,39 @@ fn parseLibs(self: *Zld, libs: []const []const u8) !void { fn mapAndUpdateSections( self: *Zld, - object_id: u16, + object: *Object, source_sect_id: u16, target_seg_id: u16, target_sect_id: u16, ) !void { - const object = self.objects.items[object_id]; - const source_seg = object.load_commands.items[object.segment_cmd_index.?].Segment; - const source_sect = source_seg.sections.items[source_sect_id]; + const source_sect = &object.sections.items[source_sect_id]; const target_seg = &self.load_commands.items[target_seg_id].Segment; const target_sect = &target_seg.sections.items[target_sect_id]; const alignment = try math.powi(u32, 2, target_sect.@"align"); const offset = mem.alignForwardGeneric(u64, target_sect.size, alignment); - const size = mem.alignForwardGeneric(u64, source_sect.size, alignment); - const key = MappingKey{ - .object_id = object_id, - .source_sect_id = source_sect_id, - }; - try self.mappings.putNoClobber(self.allocator, key, .{ - .source_sect_id = source_sect_id, - .target_seg_id = target_seg_id, - .target_sect_id = target_sect_id, - .offset = @intCast(u32, offset), - }); - log.debug("{s}: {s},{s} mapped to {s},{s} from 0x{x} to 0x{x}", .{ - object.name, - parseName(&source_sect.segname), - parseName(&source_sect.sectname), + const size = mem.alignForwardGeneric(u64, source_sect.inner.size, alignment); + + log.debug("{s}: '{s},{s}' mapped to '{s},{s}' from 0x{x} to 0x{x}", .{ + object.name.?, + parseName(&source_sect.inner.segname), + parseName(&source_sect.inner.sectname), parseName(&target_sect.segname), parseName(&target_sect.sectname), offset, offset + size, }); + source_sect.target_map = .{ + .segment_id = target_seg_id, + .section_id = target_sect_id, + .offset = @intCast(u32, offset), + }; target_sect.size = offset + size; } fn updateMetadata(self: *Zld) !void { - for (self.objects.items) |object, id| { - const object_id = @intCast(u16, id); + for (self.objects.items) |object| { const object_seg = object.load_commands.items[object.segment_cmd_index.?].Segment; const text_seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; const data_const_seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; @@ -699,19 +674,14 @@ fn updateMetadata(self: *Zld) !void { for (object_seg.sections.items) |source_sect, sect_id| { const source_sect_id = @intCast(u16, sect_id); if (self.getMatchingSection(source_sect)) |res| { - try self.mapAndUpdateSections(object_id, source_sect_id, res.seg, res.sect); + try self.mapAndUpdateSections(object, source_sect_id, res.seg, res.sect); continue; } - const segname = parseName(&source_sect.segname); - const sectname = parseName(&source_sect.sectname); - - log.debug("section '{s}/{s}' will be unmapped", .{ segname, sectname }); - - try self.unhandled_sections.putNoClobber(self.allocator, .{ - .object_id = object_id, - .source_sect_id = source_sect_id, - }, 0); + log.debug("section '{s},{s}' will be unmapped", .{ + parseName(&source_sect.segname), + parseName(&source_sect.sectname), + }); } } @@ -954,18 +924,34 @@ fn sortSections(self: *Zld) !void { } } - var it = self.mappings.valueIterator(); - while (it.next()) |mapping| { - if (self.text_segment_cmd_index.? == mapping.target_seg_id) { - const new_index = text_index_mapping.get(mapping.target_sect_id) orelse unreachable; - mapping.target_sect_id = new_index; - } else if (self.data_const_segment_cmd_index.? == mapping.target_seg_id) { - const new_index = data_const_index_mapping.get(mapping.target_sect_id) orelse unreachable; - mapping.target_sect_id = new_index; - } else if (self.data_segment_cmd_index.? == mapping.target_seg_id) { - const new_index = data_index_mapping.get(mapping.target_sect_id) orelse unreachable; - mapping.target_sect_id = new_index; - } else unreachable; + for (self.objects.items) |object| { + for (object.sections.items) |*sect| { + const target_map = sect.target_map orelse continue; + + const new_index = blk: { + if (self.text_segment_cmd_index.? == target_map.segment_id) { + break :blk text_index_mapping.get(target_map.section_id) orelse unreachable; + } else if (self.data_const_segment_cmd_index.? == target_map.segment_id) { + break :blk data_const_index_mapping.get(target_map.section_id) orelse unreachable; + } else if (self.data_segment_cmd_index.? == target_map.segment_id) { + break :blk data_index_mapping.get(target_map.section_id) orelse unreachable; + } else unreachable; + }; + + log.debug("remapping in {s}: '{s},{s}': {} => {}", .{ + object.name.?, + parseName(§.inner.segname), + parseName(§.inner.sectname), + target_map.section_id, + new_index, + }); + + sect.target_map = .{ + .segment_id = target_map.segment_id, + .section_id = new_index, + .offset = target_map.offset, + }; + } } } @@ -1080,30 +1066,24 @@ fn allocateSegment(self: *Zld, index: u16, offset: u64) !void { } fn allocateSymbols(self: *Zld) !void { - for (self.objects.items) |object, object_id| { + for (self.objects.items) |object| { for (object.symbols.items) |sym| { const reg = sym.cast(Symbol.Regular) orelse continue; - // TODO I am more and more convinced we should store the mapping as part of the Object struct. - const target_mapping = self.mappings.get(.{ - .object_id = @intCast(u16, object_id), - .source_sect_id = reg.section, - }) orelse { - if (self.unhandled_sections.get(.{ - .object_id = @intCast(u16, object_id), - .source_sect_id = reg.section, - }) != null) continue; - - log.err("section not mapped for symbol '{s}'", .{sym.name}); - return error.SectionNotMappedForSymbol; + const source_sect = &object.sections.items[reg.section]; + const target_map = source_sect.target_map orelse { + log.debug("section '{s},{s}' not mapped for symbol '{s}'", .{ + parseName(&source_sect.inner.segname), + parseName(&source_sect.inner.sectname), + sym.name, + }); + continue; }; - const source_seg = object.load_commands.items[object.segment_cmd_index.?].Segment; - const source_sect = source_seg.sections.items[reg.section]; - const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment; - const target_sect = target_seg.sections.items[target_mapping.target_sect_id]; - const target_addr = target_sect.addr + target_mapping.offset; - const address = reg.address - source_sect.addr + target_addr; + const target_seg = self.load_commands.items[target_map.segment_id].Segment; + const target_sect = target_seg.sections.items[target_map.section_id]; + const target_addr = target_sect.addr + target_map.offset; + const address = reg.address - source_sect.inner.addr + target_addr; log.debug("resolving symbol '{s}' at 0x{x}", .{ sym.name, address }); @@ -1111,8 +1091,8 @@ fn allocateSymbols(self: *Zld) !void { var section: u8 = 0; for (self.load_commands.items) |cmd, cmd_id| { if (cmd != .Segment) break; - if (cmd_id == target_mapping.target_seg_id) { - section += @intCast(u8, target_mapping.target_sect_id) + 1; + if (cmd_id == target_map.segment_id) { + section += @intCast(u8, target_map.section_id) + 1; break; } section += @intCast(u8, cmd.Segment.sections.items.len); @@ -1602,10 +1582,10 @@ fn resolveStubsAndGotEntries(self: *Zld) !void { } fn resolveRelocsAndWriteSections(self: *Zld) !void { - for (self.objects.items) |object, object_id| { + for (self.objects.items) |object| { log.debug("relocating object {s}", .{object.name}); - for (object.sections.items) |sect, source_sect_id| { + for (object.sections.items) |sect| { if (sect.inner.flags == macho.S_MOD_INIT_FUNC_POINTERS or sect.inner.flags == macho.S_MOD_TERM_FUNC_POINTERS) continue; @@ -1614,18 +1594,15 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void { log.debug("relocating section '{s},{s}'", .{ segname, sectname }); - // Get mapping - const target_mapping = self.mappings.get(.{ - .object_id = @intCast(u16, object_id), - .source_sect_id = @intCast(u16, source_sect_id), - }) orelse { - log.debug("no mapping for {s},{s}; skipping", .{ segname, sectname }); + // Get target mapping + const target_map = sect.target_map orelse { + log.debug("no mapping for '{s},{s}'; skipping", .{ segname, sectname }); continue; }; - const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment; - const target_sect = target_seg.sections.items[target_mapping.target_sect_id]; - const target_sect_addr = target_sect.addr + target_mapping.offset; - const target_sect_off = target_sect.offset + target_mapping.offset; + const target_seg = self.load_commands.items[target_map.segment_id].Segment; + const target_sect = target_seg.sections.items[target_map.section_id]; + const target_sect_addr = target_sect.addr + target_map.offset; + const target_sect_off = target_sect.offset + target_map.offset; if (sect.relocs) |relocs| { for (relocs) |rel| { @@ -1638,11 +1615,11 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void { switch (rel.@"type") { .unsigned => { - args.target_addr = try self.relocTargetAddr(@intCast(u16, object_id), rel.target); + args.target_addr = try self.relocTargetAddr(object, rel.target); const unsigned = rel.cast(reloc.Unsigned) orelse unreachable; if (unsigned.subtractor) |subtractor| { - args.subtractor = try self.relocTargetAddr(@intCast(u16, object_id), subtractor); + args.subtractor = try self.relocTargetAddr(object, subtractor); } if (rel.target == .section) { const source_sect = object.sections.items[rel.target.section]; @@ -1652,14 +1629,14 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void { rebases: { var hit: bool = false; - if (target_mapping.target_seg_id == self.data_segment_cmd_index.?) { + if (target_map.segment_id == self.data_segment_cmd_index.?) { if (self.data_section_index) |index| { - if (index == target_mapping.target_sect_id) hit = true; + if (index == target_map.section_id) hit = true; } } - if (target_mapping.target_seg_id == self.data_const_segment_cmd_index.?) { + if (target_map.segment_id == self.data_const_segment_cmd_index.?) { if (self.data_const_section_index) |index| { - if (index == target_mapping.target_sect_id) hit = true; + if (index == target_map.section_id) hit = true; } } @@ -1667,7 +1644,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void { try self.local_rebases.append(self.allocator, .{ .offset = source_addr - target_seg.inner.vmaddr, - .segment_id = target_mapping.target_seg_id, + .segment_id = target_map.segment_id, }); } // TLV is handled via a separate offset mechanism. @@ -1705,7 +1682,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void { args.source_source_sect_addr = sect.inner.addr; args.source_target_sect_addr = source_sect.inner.addr; } - args.target_addr = try self.relocTargetAddr(@intCast(u16, object_id), rel.target); + args.target_addr = try self.relocTargetAddr(object, rel.target); }, } @@ -1744,7 +1721,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void { } } -fn relocTargetAddr(self: *Zld, object_id: u16, target: reloc.Relocation.Target) !u64 { +fn relocTargetAddr(self: *Zld, object: *const Object, target: reloc.Relocation.Target) !u64 { const target_addr = blk: { switch (target) { .symbol => |sym| { @@ -1770,13 +1747,11 @@ fn relocTargetAddr(self: *Zld, object_id: u16, target: reloc.Relocation.Target) } }, .section => |sect_id| { - const target_mapping = self.mappings.get(.{ - .object_id = object_id, - .source_sect_id = sect_id, - }) orelse unreachable; - const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment; - const target_sect = target_seg.sections.items[target_mapping.target_sect_id]; - break :blk target_sect.addr + target_mapping.offset; + const source_sect = object.sections.items[sect_id]; + const target_map = source_sect.target_map orelse unreachable; + const target_seg = self.load_commands.items[target_map.segment_id].Segment; + const target_sect = target_seg.sections.items[target_map.section_id]; + break :blk target_sect.addr + target_map.offset; }, } }; @@ -2901,20 +2876,16 @@ fn writeDataInCode(self: *Zld) !void { const text_seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment; const text_sect = text_seg.sections.items[self.text_section_index.?]; - for (self.objects.items) |object, object_id| { - const source_seg = object.load_commands.items[object.segment_cmd_index.?].Segment; - const source_sect = source_seg.sections.items[object.text_section_index.?]; - const target_mapping = self.mappings.get(.{ - .object_id = @intCast(u16, object_id), - .source_sect_id = object.text_section_index.?, - }) orelse continue; + for (self.objects.items) |object| { + const source_sect = object.sections.items[object.text_section_index.?]; + const target_map = source_sect.target_map orelse continue; try buf.ensureCapacity( buf.items.len + object.data_in_code_entries.items.len * @sizeOf(macho.data_in_code_entry), ); for (object.data_in_code_entries.items) |dice| { const new_dice: macho.data_in_code_entry = .{ - .offset = text_sect.offset + target_mapping.offset + dice.offset, + .offset = text_sect.offset + target_map.offset + dice.offset, .length = dice.length, .kind = dice.kind, }; |
