authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-03 14:54:53+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-15 18:49:47+02:00
log7c82079d2cfb2f8c299707aa4c79455a73601914
treea516d667a51fd3878fffb04c0d8557ed7515e575
parentceb431507d827f5ac53a18d8904886708325c0e7

zld: allocate symbols using the new scheme


1 files changed, 108 insertions(+), 105 deletions(-)

src/link/MachO/Zld.zig+108-105
...@@ -108,6 +108,7 @@ globals: std.StringArrayHashMapUnmanaged(*Symbol) = .{},...@@ -108,6 +108,7 @@ globals: std.StringArrayHashMapUnmanaged(*Symbol) = .{},
108/// Offset into __DATA,__common section.108/// Offset into __DATA,__common section.
109/// Set if the linker found tentative definitions in any of the objects.109/// Set if the linker found tentative definitions in any of the objects.
110tentative_defs_offset: u64 = 0,110tentative_defs_offset: u64 = 0,
111has_tentative_defs: bool = false,
111112
112threadlocal_offsets: std.ArrayListUnmanaged(TlvOffset) = .{}, // TODO merge with Symbol abstraction113threadlocal_offsets: std.ArrayListUnmanaged(TlvOffset) = .{}, // TODO merge with Symbol abstraction
113local_rebases: std.ArrayListUnmanaged(Pointer) = .{},114local_rebases: std.ArrayListUnmanaged(Pointer) = .{},
...@@ -222,20 +223,33 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg...@@ -222,20 +223,33 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg
222 try self.parseInputFiles(files, args.syslibroot);223 try self.parseInputFiles(files, args.syslibroot);
223 try self.parseLibs(args.libs, args.syslibroot);224 try self.parseLibs(args.libs, args.syslibroot);
224 try self.resolveSymbols();225 try self.resolveSymbols();
226 try self.resolveStubsAndGotEntries();
227 try self.updateMetadata();
228 try self.sortSections();
229 try self.addRpaths(args.rpaths);
230 try self.addDataInCodeLC();
231 try self.addCodeSignatureLC();
232 try self.allocateTextSegment();
233 try self.allocateDataConstSegment();
234 try self.allocateDataSegment();
235 self.allocateLinkeditSegment();
236 try self.allocateSymbols();
237 try self.allocateTentativeSymbols();
238 try self.allocateProxyBindAddresses();
239
240 log.warn("globals", .{});
241 for (self.globals.values()) |value| {
242 log.warn(" | {s}: {}", .{ value.name, value.payload });
243 }
244
245 for (self.objects.items) |object| {
246 log.warn("object {s}", .{object.name.?});
247 for (object.symbols.items) |sym| {
248 log.warn(" | {s}: {}", .{ sym.name, sym.payload });
249 }
250 }
251
225 return error.TODO;252 return error.TODO;
226 // try self.resolveStubsAndGotEntries();
227 // try self.updateMetadata();
228 // try self.sortSections();
229 // try self.addRpaths(args.rpaths);
230 // try self.addDataInCodeLC();
231 // try self.addCodeSignatureLC();
232 // try self.allocateTextSegment();
233 // try self.allocateDataConstSegment();
234 // try self.allocateDataSegment();
235 // self.allocateLinkeditSegment();
236 // try self.allocateSymbols();
237 // try self.allocateTentativeSymbols();
238 // try self.allocateProxyBindAddresses();
239 // try self.flush();253 // try self.flush();
240}254}
241255
...@@ -351,7 +365,7 @@ fn updateMetadata(self: *Zld) !void {...@@ -351,7 +365,7 @@ fn updateMetadata(self: *Zld) !void {
351365
352 // Ensure we have __DATA,__common section if we have tentative definitions.366 // Ensure we have __DATA,__common section if we have tentative definitions.
353 // Update size and alignment of __DATA,__common section.367 // Update size and alignment of __DATA,__common section.
354 if (self.tentatives.values().len > 0) {368 if (self.has_tentative_defs) {
355 const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;369 const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
356 const common_section_index = self.common_section_index orelse ind: {370 const common_section_index = self.common_section_index orelse ind: {
357 self.common_section_index = @intCast(u16, data_seg.sections.items.len);371 self.common_section_index = @intCast(u16, data_seg.sections.items.len);
...@@ -364,10 +378,10 @@ fn updateMetadata(self: *Zld) !void {...@@ -364,10 +378,10 @@ fn updateMetadata(self: *Zld) !void {
364378
365 var max_align: u16 = 0;379 var max_align: u16 = 0;
366 var added_size: u64 = 0;380 var added_size: u64 = 0;
367 for (self.tentatives.values()) |sym| {381 for (self.globals.values()) |sym| {
368 const tent = sym.cast(Symbol.Tentative) orelse unreachable;382 if (sym.payload != .tentative) continue;
369 max_align = math.max(max_align, tent.alignment);383 max_align = math.max(max_align, sym.payload.tentative.alignment);
370 added_size += tent.size;384 added_size += sym.payload.tentative.size;
371 }385 }
372386
373 common_sect.@"align" = math.max(common_sect.@"align", max_align);387 common_sect.@"align" = math.max(common_sect.@"align", max_align);
...@@ -1069,47 +1083,55 @@ fn allocateSegment(self: *Zld, index: u16, offset: u64) !void {...@@ -1069,47 +1083,55 @@ fn allocateSegment(self: *Zld, index: u16, offset: u64) !void {
1069 seg.inner.vmsize = seg_size_aligned;1083 seg.inner.vmsize = seg_size_aligned;
1070}1084}
10711085
1072fn allocateSymbols(self: *Zld) !void {1086fn allocateSymbol(self: *Zld, symbol: *Symbol) !void {
1073 for (self.objects.items) |object| {1087 const reg = &symbol.payload.regular;
1074 for (object.symbols.items) |sym| {1088 const object = reg.file orelse return;
1075 const reg = sym.cast(Symbol.Regular) orelse continue;1089 const source_sect = &object.sections.items[reg.section];
1090 const target_map = source_sect.target_map orelse {
1091 log.debug("section '{s},{s}' not mapped for symbol '{s}'", .{
1092 parseName(&source_sect.inner.segname),
1093 parseName(&source_sect.inner.sectname),
1094 symbol.name,
1095 });
1096 return;
1097 };
10761098
1077 const source_sect = &object.sections.items[reg.section];1099 const target_seg = self.load_commands.items[target_map.segment_id].Segment;
1078 const target_map = source_sect.target_map orelse {1100 const target_sect = target_seg.sections.items[target_map.section_id];
1079 log.debug("section '{s},{s}' not mapped for symbol '{s}'", .{1101 const target_addr = target_sect.addr + target_map.offset;
1080 parseName(&source_sect.inner.segname),1102 const address = reg.address - source_sect.inner.addr + target_addr;
1081 parseName(&source_sect.inner.sectname),
1082 sym.name,
1083 });
1084 continue;
1085 };
10861103
1087 const target_seg = self.load_commands.items[target_map.segment_id].Segment;1104 log.debug("resolving symbol '{s}' at 0x{x}", .{ symbol.name, address });
1088 const target_sect = target_seg.sections.items[target_map.section_id];
1089 const target_addr = target_sect.addr + target_map.offset;
1090 const address = reg.address - source_sect.inner.addr + target_addr;
1091
1092 log.debug("resolving symbol '{s}' at 0x{x}", .{ sym.name, address });
1093
1094 // TODO there might be a more generic way of doing this.
1095 var section: u8 = 0;
1096 for (self.load_commands.items) |cmd, cmd_id| {
1097 if (cmd != .Segment) break;
1098 if (cmd_id == target_map.segment_id) {
1099 section += @intCast(u8, target_map.section_id) + 1;
1100 break;
1101 }
1102 section += @intCast(u8, cmd.Segment.sections.items.len);
1103 }
11041105
1105 reg.address = address;1106 // TODO there might be a more generic way of doing this.
1106 reg.section = section;1107 var section: u8 = 0;
1108 for (self.load_commands.items) |cmd, cmd_id| {
1109 if (cmd != .Segment) break;
1110 if (cmd_id == target_map.segment_id) {
1111 section += @intCast(u8, target_map.section_id) + 1;
1112 break;
1107 }1113 }
1114 section += @intCast(u8, cmd.Segment.sections.items.len);
1115 }
1116
1117 reg.address = address;
1118 reg.section = section;
1119}
1120
1121fn allocateSymbols(self: *Zld) !void {
1122 for (self.locals.items) |symbol| {
1123 if (symbol.payload != .regular) continue;
1124 try self.allocateSymbol(symbol);
1125 }
1126
1127 for (self.globals.values()) |symbol| {
1128 if (symbol.payload != .regular) continue;
1129 try self.allocateSymbol(symbol);
1108 }1130 }
1109}1131}
11101132
1111fn allocateTentativeSymbols(self: *Zld) !void {1133fn allocateTentativeSymbols(self: *Zld) !void {
1112 if (self.tentatives.values().len == 0) return;1134 if (!self.has_tentative_defs) return;
11131135
1114 const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;1136 const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
1115 const common_sect = &data_seg.sections.items[self.common_section_index.?];1137 const common_sect = &data_seg.sections.items[self.common_section_index.?];
...@@ -1131,36 +1153,21 @@ fn allocateTentativeSymbols(self: *Zld) !void {...@@ -1131,36 +1153,21 @@ fn allocateTentativeSymbols(self: *Zld) !void {
1131 }1153 }
11321154
1133 // Convert tentative definitions into regular symbols.1155 // Convert tentative definitions into regular symbols.
1134 for (self.tentatives.values()) |sym| {1156 for (self.globals.values()) |sym| {
1135 const tent = sym.cast(Symbol.Tentative) orelse unreachable;1157 if (sym.payload != .tentative) continue;
1136 const reg = try Symbol.Regular.new(self.allocator, tent.base.name, .{
1137 .linkage = .global,
1138 .address = base_address,
1139 .section = section,
1140 .weak_ref = false,
1141 .file = tent.file,
1142 });
1143 reg.got_index = tent.base.got_index;
1144 reg.stubs_index = tent.base.stubs_index;
1145
1146 try self.globals.putNoClobber(self.allocator, reg.name, reg);
1147 tent.base.alias = reg;
1148
1149 if (tent.base.got_index) |idx| {
1150 self.got_entries.items[idx] = reg;
1151 }
1152 if (tent.base.stubs_index) |idx| {
1153 self.stubs.items[idx] = reg;
1154 }
11551158
1156 const address = mem.alignForwardGeneric(u64, base_address + tent.size, alignment);1159 const address = mem.alignForwardGeneric(u64, base_address + sym.payload.tentative.size, alignment);
11571160
1158 log.debug("tentative definition '{s}' allocated from 0x{x} to 0x{x}", .{1161 log.debug("tentative definition '{s}' allocated from 0x{x} to 0x{x}", .{ sym.name, base_address, address });
1159 tent.base.name,
1160 base_address,
1161 address,
1162 });
11631162
1163 sym.payload = .{
1164 .regular = .{
1165 .linkage = .global,
1166 .address = base_address,
1167 .section = section,
1168 .weak_ref = false,
1169 },
1170 };
1164 base_address = address;1171 base_address = address;
1165 }1172 }
1166}1173}
...@@ -1174,17 +1181,17 @@ fn allocateProxyBindAddresses(self: *Zld) !void {...@@ -1174,17 +1181,17 @@ fn allocateProxyBindAddresses(self: *Zld) !void {
1174 if (rel.@"type" != .unsigned) continue; // GOT is currently special-cased1181 if (rel.@"type" != .unsigned) continue; // GOT is currently special-cased
1175 if (rel.target != .symbol) continue;1182 if (rel.target != .symbol) continue;
11761183
1177 const sym = object.symbols.items[rel.target.symbol].getTopmostAlias();1184 const sym = object.symbols.items[rel.target.symbol];
1178 if (sym.cast(Symbol.Proxy)) |proxy| {1185 if (sym.payload != .proxy) continue;
1179 const target_map = sect.target_map orelse continue;
1180 const target_seg = self.load_commands.items[target_map.segment_id].Segment;
1181 const target_sect = target_seg.sections.items[target_map.section_id];
11821186
1183 try proxy.bind_info.append(self.allocator, .{1187 const target_map = sect.target_map orelse continue;
1184 .segment_id = target_map.segment_id,1188 const target_seg = self.load_commands.items[target_map.segment_id].Segment;
1185 .address = target_sect.addr + target_map.offset + rel.offset,1189 const target_sect = target_seg.sections.items[target_map.section_id];
1186 });1190
1187 }1191 try sym.payload.proxy.bind_info.append(self.allocator, .{
1192 .segment_id = target_map.segment_id,
1193 .address = target_sect.addr + target_map.offset + rel.offset,
1194 });
1188 }1195 }
1189 }1196 }
1190 }1197 }
...@@ -1586,6 +1593,14 @@ fn resolveSymbols(self: *Zld) !void {...@@ -1586,6 +1593,14 @@ fn resolveSymbols(self: *Zld) !void {
1586 }1593 }
1587 }1594 }
15881595
1596 // Mark if we need to allocate zerofill section for tentative definitions
1597 for (self.globals.values()) |symbol| {
1598 if (symbol.payload == .tentative) {
1599 self.has_tentative_defs = true;
1600 break;
1601 }
1602 }
1603
1589 // Third pass, resolve symbols in dynamic libraries.1604 // Third pass, resolve symbols in dynamic libraries.
1590 {1605 {
1591 // Put dyld_stub_binder as an undefined special symbol.1606 // Put dyld_stub_binder as an undefined special symbol.
...@@ -1651,18 +1666,6 @@ fn resolveSymbols(self: *Zld) !void {...@@ -1651,18 +1666,6 @@ fn resolveSymbols(self: *Zld) !void {
1651 }1666 }
16521667
1653 if (has_undefined) return error.UndefinedSymbolReference;1668 if (has_undefined) return error.UndefinedSymbolReference;
1654
1655 log.warn("globals", .{});
1656 for (self.globals.values()) |value| {
1657 log.warn(" | {s}: {}", .{ value.name, value.payload });
1658 }
1659
1660 for (self.objects.items) |object| {
1661 log.warn("object {s}", .{object.name.?});
1662 for (object.symbols.items) |sym| {
1663 log.warn(" | {s}: {}", .{ sym.name, sym.payload });
1664 }
1665 }
1666}1669}
16671670
1668fn resolveStubsAndGotEntries(self: *Zld) !void {1671fn resolveStubsAndGotEntries(self: *Zld) !void {
...@@ -1675,7 +1678,7 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {...@@ -1675,7 +1678,7 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {
1675 switch (rel.@"type") {1678 switch (rel.@"type") {
1676 .unsigned => continue,1679 .unsigned => continue,
1677 .got_page, .got_page_off, .got_load, .got, .pointer_to_got => {1680 .got_page, .got_page_off, .got_load, .got, .pointer_to_got => {
1678 const sym = object.symbols.items[rel.target.symbol].getTopmostAlias();1681 const sym = object.symbols.items[rel.target.symbol];
1679 if (sym.got_index != null) continue;1682 if (sym.got_index != null) continue;
16801683
1681 const index = @intCast(u32, self.got_entries.items.len);1684 const index = @intCast(u32, self.got_entries.items.len);
...@@ -1687,11 +1690,11 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {...@@ -1687,11 +1690,11 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {
1687 else => {1690 else => {
1688 if (rel.target != .symbol) continue;1691 if (rel.target != .symbol) continue;
16891692
1690 const sym = object.symbols.items[rel.target.symbol].getTopmostAlias();1693 const sym = object.symbols.items[rel.target.symbol];
1691 assert(sym.@"type" != .unresolved);1694 assert(sym.payload != .undef);
16921695
1693 if (sym.stubs_index != null) continue;1696 if (sym.stubs_index != null) continue;
1694 if (sym.@"type" != .proxy) continue;1697 if (sym.payload != .proxy) continue;
16951698
1696 const index = @intCast(u32, self.stubs.items.len);1699 const index = @intCast(u32, self.stubs.items.len);
1697 sym.stubs_index = index;1700 sym.stubs_index = index;
...@@ -1705,7 +1708,7 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {...@@ -1705,7 +1708,7 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {
1705 }1708 }
17061709
1707 // Finally, put dyld_stub_binder as the final GOT entry1710 // Finally, put dyld_stub_binder as the final GOT entry
1708 const sym = self.imports.get("dyld_stub_binder") orelse unreachable;1711 const sym = self.globals.get("dyld_stub_binder") orelse unreachable;
1709 const index = @intCast(u32, self.got_entries.items.len);1712 const index = @intCast(u32, self.got_entries.items.len);
1710 sym.got_index = index;1713 sym.got_index = index;
1711 try self.got_entries.append(self.allocator, sym);1714 try self.got_entries.append(self.allocator, sym);