aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2021-06-10 08:30:25 +0200
committerJakub Konka <kubkon@jakubkonka.com>2021-06-10 09:13:35 +0200
commit96bb81b6ef0896d0b63c54bfd5d1ac0fa267d68a (patch)
tree8d751f4925f3c05ff04dca9db3560af21593ef5f /src
parent88aec4a1ee49088685b16d744f35c902c4900a09 (diff)
downloadzig-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.zig5
-rw-r--r--src/link/MachO/Zld.zig207
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(&sect.inner.segname),
+ parseName(&sect.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,
};