| ... | ... | @@ -129,10 +129,15 @@ pub const TextBlock = struct { |
| 129 | 129 | size: u64, |
| 130 | 130 | alignment: u32, |
| 131 | 131 | rebases: std.ArrayList(u64), |
| 132 | | tlv_offsets: std.ArrayList(u64), |
| 132 | tlv_offsets: std.ArrayList(TlvOffset), |
| 133 | 133 | next: ?*TextBlock = null, |
| 134 | 134 | prev: ?*TextBlock = null, |
| 135 | 135 | |
| 136 | pub const TlvOffset = struct { |
| 137 | local_sym_index: u32, |
| 138 | offset: u64, |
| 139 | }; |
| 140 | |
| 136 | 141 | pub fn deinit(block: *TextBlock, allocator: *Allocator) void { |
| 137 | 142 | if (block.aliases) |aliases| { |
| 138 | 143 | allocator.free(aliases); |
| ... | ... | @@ -281,10 +286,11 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg |
| 281 | 286 | try self.addRpaths(args.rpaths); |
| 282 | 287 | try self.addDataInCodeLC(); |
| 283 | 288 | try self.addCodeSignatureLC(); |
| 284 | | // try self.allocateTextSegment(); |
| 285 | | // try self.allocateDataConstSegment(); |
| 286 | | // try self.allocateDataSegment(); |
| 287 | | // self.allocateLinkeditSegment(); |
| 289 | try self.allocateTextSegment(); |
| 290 | try self.allocateDataConstSegment(); |
| 291 | try self.allocateDataSegment(); |
| 292 | self.allocateLinkeditSegment(); |
| 293 | try self.allocateTextBlocks(); |
| 288 | 294 | |
| 289 | 295 | var it = self.blocks.iterator(); |
| 290 | 296 | while (it.next()) |entry| { |
| ... | ... | @@ -292,6 +298,7 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg |
| 292 | 298 | const sect = seg.sections.items[entry.key_ptr.sect]; |
| 293 | 299 | |
| 294 | 300 | log.warn("\n\n{s},{s} contents:", .{ segmentName(sect), sectionName(sect) }); |
| 301 | log.warn("{}", .{sect}); |
| 295 | 302 | entry.value_ptr.*.print(self); |
| 296 | 303 | } |
| 297 | 304 | return error.TODO; |
| ... | ... | @@ -865,14 +872,14 @@ fn sortSections(self: *Zld) !void { |
| 865 | 872 | while (it.next()) |entry| { |
| 866 | 873 | const old = entry.key_ptr.*; |
| 867 | 874 | const sect = if (old.seg == self.text_segment_cmd_index.?) |
| 868 | | text_index_mapping.get(old.sect) |
| 875 | text_index_mapping.get(old.sect).? |
| 869 | 876 | else if (old.seg == self.data_const_segment_cmd_index.?) |
| 870 | | data_const_index_mapping.get(old.sect) |
| 877 | data_const_index_mapping.get(old.sect).? |
| 871 | 878 | else |
| 872 | | data_index_mapping.get(old.sect); |
| 879 | data_index_mapping.get(old.sect).?; |
| 873 | 880 | transient.putAssumeCapacityNoClobber(.{ |
| 874 | 881 | .seg = old.seg, |
| 875 | | .sect = old.sect, |
| 882 | .sect = sect, |
| 876 | 883 | }, entry.value_ptr.*); |
| 877 | 884 | } |
| 878 | 885 | |
| ... | ... | @@ -880,6 +887,18 @@ fn sortSections(self: *Zld) !void { |
| 880 | 887 | self.blocks.deinit(self.allocator); |
| 881 | 888 | self.blocks = transient; |
| 882 | 889 | } |
| 890 | |
| 891 | for (self.locals.items) |sym, i| { |
| 892 | if (i == 0) continue; // skip the null symbol |
| 893 | assert(sym.payload == .regular); |
| 894 | const reg = &sym.payload.regular; |
| 895 | reg.section_id = if (reg.segment_id == self.text_segment_cmd_index.?) |
| 896 | text_index_mapping.get(reg.section_id).? |
| 897 | else if (reg.segment_id == self.data_const_segment_cmd_index.?) |
| 898 | data_const_index_mapping.get(reg.section_id).? |
| 899 | else |
| 900 | data_index_mapping.get(reg.section_id).?; |
| 901 | } |
| 883 | 902 | } |
| 884 | 903 | |
| 885 | 904 | fn allocateTextSegment(self: *Zld) !void { |
| ... | ... | @@ -991,50 +1010,26 @@ fn allocateSegment(self: *Zld, index: u16, offset: u64) !void { |
| 991 | 1010 | seg.inner.vmsize = seg_size_aligned; |
| 992 | 1011 | } |
| 993 | 1012 | |
| 994 | | fn allocateSymbol(self: *Zld, symbol: *Symbol) !void { |
| 995 | | const reg = &symbol.payload.regular; |
| 996 | | const object = reg.file orelse return; |
| 997 | | const source_sect = &object.sections.items[reg.section]; |
| 998 | | const target_map = source_sect.target_map orelse { |
| 999 | | log.debug("section '{s},{s}' not mapped for symbol '{s}'", .{ |
| 1000 | | segmentName(source_sect.inner), |
| 1001 | | sectionName(source_sect.inner), |
| 1002 | | symbol.name, |
| 1003 | | }); |
| 1004 | | return; |
| 1005 | | }; |
| 1006 | | |
| 1007 | | const target_seg = self.load_commands.items[target_map.segment_id].Segment; |
| 1008 | | const target_sect = target_seg.sections.items[target_map.section_id]; |
| 1009 | | const target_addr = target_sect.addr + target_map.offset; |
| 1010 | | const address = reg.address - source_sect.inner.addr + target_addr; |
| 1011 | | |
| 1012 | | log.debug("resolving symbol '{s}' at 0x{x}", .{ symbol.name, address }); |
| 1013 | | |
| 1014 | | // TODO there might be a more generic way of doing this. |
| 1015 | | var section: u8 = 0; |
| 1016 | | for (self.load_commands.items) |cmd, cmd_id| { |
| 1017 | | if (cmd != .Segment) break; |
| 1018 | | if (cmd_id == target_map.segment_id) { |
| 1019 | | section += @intCast(u8, target_map.section_id) + 1; |
| 1020 | | break; |
| 1013 | fn allocateTextBlocks(self: *Zld) !void { |
| 1014 | var it = self.blocks.iterator(); |
| 1015 | while (it.next()) |entry| { |
| 1016 | const match = entry.key_ptr.*; |
| 1017 | var block: *TextBlock = entry.value_ptr.*; |
| 1018 | |
| 1019 | const seg = self.load_commands.items[match.seg].Segment; |
| 1020 | const sect = seg.sections.items[match.sect]; |
| 1021 | var base_addr: u64 = sect.addr + sect.size; |
| 1022 | |
| 1023 | while (true) { |
| 1024 | const sym = self.locals.items[block.local_sym_index]; |
| 1025 | assert(sym.payload == .regular); |
| 1026 | sym.payload.regular.address = base_addr - block.size; |
| 1027 | base_addr -= block.size; |
| 1028 | |
| 1029 | if (block.prev) |prev| { |
| 1030 | block = prev; |
| 1031 | } else break; |
| 1021 | 1032 | } |
| 1022 | | section += @intCast(u8, cmd.Segment.sections.items.len); |
| 1023 | | } |
| 1024 | | |
| 1025 | | reg.address = address; |
| 1026 | | reg.section = section; |
| 1027 | | } |
| 1028 | | |
| 1029 | | fn allocateSymbols(self: *Zld) !void { |
| 1030 | | for (self.locals.items) |symbol| { |
| 1031 | | if (symbol.payload != .regular) continue; |
| 1032 | | try self.allocateSymbol(symbol); |
| 1033 | | } |
| 1034 | | |
| 1035 | | for (self.globals.values()) |symbol| { |
| 1036 | | if (symbol.payload != .regular) continue; |
| 1037 | | try self.allocateSymbol(symbol); |
| 1038 | 1033 | } |
| 1039 | 1034 | } |
| 1040 | 1035 | |
| ... | ... | @@ -1487,7 +1482,7 @@ fn resolveSymbols(self: *Zld) !void { |
| 1487 | 1482 | .code = code, |
| 1488 | 1483 | .relocs = std.ArrayList(Relocation).init(self.allocator), |
| 1489 | 1484 | .rebases = std.ArrayList(u64).init(self.allocator), |
| 1490 | | .tlv_offsets = std.ArrayList(u64).init(self.allocator), |
| 1485 | .tlv_offsets = std.ArrayList(TextBlock.TlvOffset).init(self.allocator), |
| 1491 | 1486 | .size = size, |
| 1492 | 1487 | .alignment = alignment, |
| 1493 | 1488 | }; |