authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-05-03 14:56:45+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-05-04 13:09:32+02:00
log00c3d57a51d963e078e8f4dfc090bd2a0d0d6a30
tree184b56a205513b8c45c49c9789a933fd5a63cb25
parentfcd57f08574fd89cf68080f2de6a1300375c83e5

zld: rewrite symbol allocations


1 files changed, 24 insertions(+), 75 deletions(-)

src/link/MachO/Zld.zig+24-75
......@@ -202,16 +202,14 @@ pub fn link(self: *Zld, files: []const []const u8, out_path: []const u8) !void {
202202 try self.resolveSymbols();
203203 // self.printSymbols();
204204 try self.resolveStubsAndGotEntries();
205 try self.updateMetadata();
206 try self.sortSections();
207 try self.allocateTextSegment();
208 try self.allocateDataConstSegment();
209 try self.allocateDataSegment();
210 self.allocateLinkeditSegment();
211 try self.allocateSymbols();
205212 return error.Unfinished;
206 // try self.updateMetadata();
207 // try self.sortSections();
208 // try self.allocateTextSegment();
209 // try self.allocateDataConstSegment();
210 // try self.allocateDataSegment();
211 // self.allocateLinkeditSegment();
212 // try self.allocateSymbols();
213 // try self.allocateStubsAndGotEntries();
214 // try self.allocateCppStatics();
215213 // try self.writeStubHelperCommon();
216214 // try self.resolveRelocsAndWriteSections();
217215 // try self.flush();
......@@ -797,7 +795,7 @@ fn sortSections(self: *Zld) !void {
797795
798796fn allocateTextSegment(self: *Zld) !void {
799797 const seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
800 const nstubs = @intCast(u32, self.stubs.items().len);
798 const nstubs = @intCast(u32, self.stubs.items.len);
801799
802800 const base_vmaddr = self.load_commands.items[self.pagezero_segment_cmd_index.?].Segment.inner.vmsize;
803801 seg.inner.fileoff = 0;
......@@ -848,7 +846,7 @@ fn allocateTextSegment(self: *Zld) !void {
848846
849847fn allocateDataConstSegment(self: *Zld) !void {
850848 const seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
851 const nentries = @intCast(u32, self.got_entries.items().len);
849 const nentries = @intCast(u32, self.got_entries.items.len);
852850
853851 const text_seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
854852 seg.inner.fileoff = text_seg.inner.fileoff + text_seg.inner.filesize;
......@@ -863,7 +861,7 @@ fn allocateDataConstSegment(self: *Zld) !void {
863861
864862fn allocateDataSegment(self: *Zld) !void {
865863 const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
866 const nstubs = @intCast(u32, self.stubs.items().len);
864 const nstubs = @intCast(u32, self.stubs.items.len);
867865
868866 const data_const_seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
869867 seg.inner.fileoff = data_const_seg.inner.fileoff + data_const_seg.inner.filesize;
......@@ -906,95 +904,46 @@ fn allocateSegment(self: *Zld, index: u16, offset: u64) !void {
906904}
907905
908906fn allocateSymbols(self: *Zld) !void {
909 for (self.objects.items) |*object, object_id| {
910 for (object.locals.items()) |*entry| {
911 const source_sym = object.symtab.items[entry.value.index.?];
912 const source_sect_id = source_sym.n_sect - 1;
907 for (self.objects.items) |object, object_id| {
908 for (object.symbols.items) |sym| {
909 const reg = sym.cast(Symbol.Regular) orelse continue;
913910
914911 // TODO I am more and more convinced we should store the mapping as part of the Object struct.
915912 const target_mapping = self.mappings.get(.{
916913 .object_id = @intCast(u16, object_id),
917 .source_sect_id = source_sect_id,
914 .source_sect_id = reg.section,
918915 }) orelse {
919916 if (self.unhandled_sections.get(.{
920917 .object_id = @intCast(u16, object_id),
921 .source_sect_id = source_sect_id,
918 .source_sect_id = reg.section,
922919 }) != null) continue;
923920
924 log.err("section not mapped for symbol '{s}'", .{entry.value.name});
921 log.err("section not mapped for symbol '{s}'", .{sym.name});
925922 return error.SectionNotMappedForSymbol;
926923 };
927924
928925 const source_seg = object.load_commands.items[object.segment_cmd_index.?].Segment;
929 const source_sect = source_seg.sections.items[source_sect_id];
926 const source_sect = source_seg.sections.items[reg.section];
930927 const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment;
931928 const target_sect = target_seg.sections.items[target_mapping.target_sect_id];
932929 const target_addr = target_sect.addr + target_mapping.offset;
933 const n_value = source_sym.n_value - source_sect.addr + target_addr;
930 const address = reg.address - source_sect.addr + target_addr;
934931
935 log.debug("resolving local symbol '{s}' at 0x{x}", .{ entry.value.name, n_value });
932 log.warn("resolving symbol '{s}' at 0x{x}", .{ sym.name, address });
936933
937934 // TODO there might be a more generic way of doing this.
938 var n_sect: u8 = 0;
935 var section: u8 = 0;
939936 for (self.load_commands.items) |cmd, cmd_id| {
940937 if (cmd != .Segment) break;
941938 if (cmd_id == target_mapping.target_seg_id) {
942 n_sect += @intCast(u8, target_mapping.target_sect_id) + 1;
939 section += @intCast(u8, target_mapping.target_sect_id) + 1;
943940 break;
944941 }
945 n_sect += @intCast(u8, cmd.Segment.sections.items.len);
942 section += @intCast(u8, cmd.Segment.sections.items.len);
946943 }
947944
948 entry.value.address = n_value;
949 entry.value.section = n_sect;
950 }
951 }
952
953 for (self.symtab.items()) |*entry| {
954 if (entry.value.tag == .import) continue;
955
956 const object_id = entry.value.file orelse unreachable;
957 const object = self.objects.items[object_id];
958 const local = object.locals.get(entry.key) orelse unreachable;
959
960 log.debug("resolving {} symbol '{s}' at 0x{x}", .{ entry.value.tag, entry.key, local.address });
961
962 entry.value.address = local.address;
963 entry.value.section = local.section;
964 }
965}
966
967fn allocateStubsAndGotEntries(self: *Zld) !void {
968 for (self.got_entries.items()) |*entry| {
969 if (entry.value.tag == .import) continue;
970
971 const object = self.objects.items[entry.value.file];
972 entry.value.target_addr = target_addr: {
973 if (object.locals.get(entry.key)) |local| {
974 break :target_addr local.address;
975 }
976 const global = self.symtab.get(entry.key) orelse unreachable;
977 break :target_addr global.address;
978 };
979
980 log.debug("resolving GOT entry '{s}' at 0x{x}", .{
981 entry.key,
982 entry.value.target_addr,
983 });
984 }
985}
986
987fn allocateCppStatics(self: *Zld) !void {
988 for (self.objects.items) |*object| {
989 for (object.initializers.items) |*initializer| {
990 const sym = object.symtab.items[initializer.symbol];
991 const sym_name = object.getString(sym.n_strx);
992 initializer.target_addr = object.locals.get(sym_name).?.address;
993
994 log.debug("resolving C++ initializer '{s}' at 0x{x}", .{
995 sym_name,
996 initializer.target_addr,
997 });
945 reg.address = address;
946 reg.section = section;
998947 }
999948 }
1000949}