| ... | @@ -107,11 +107,6 @@ locals: std.ArrayListUnmanaged(*Symbol) = .{}, | ... | @@ -107,11 +107,6 @@ locals: std.ArrayListUnmanaged(*Symbol) = .{}, |
| 107 | imports: std.ArrayListUnmanaged(*Symbol) = .{}, | 107 | imports: std.ArrayListUnmanaged(*Symbol) = .{}, |
| 108 | globals: std.StringArrayHashMapUnmanaged(*Symbol) = .{}, | 108 | globals: std.StringArrayHashMapUnmanaged(*Symbol) = .{}, |
| 109 | | 109 | |
| 110 | /// Offset into __DATA,__common section. | | |
| 111 | /// Set if the linker found tentative definitions in any of the objects. | | |
| 112 | tentative_defs_offset: u64 = 0, | | |
| 113 | has_tentative_defs: bool = false, | | |
| 114 | | | |
| 115 | threadlocal_offsets: std.ArrayListUnmanaged(TlvOffset) = .{}, // TODO merge with Symbol abstraction | 110 | threadlocal_offsets: std.ArrayListUnmanaged(TlvOffset) = .{}, // TODO merge with Symbol abstraction |
| 116 | local_rebases: std.ArrayListUnmanaged(Pointer) = .{}, | 111 | local_rebases: std.ArrayListUnmanaged(Pointer) = .{}, |
| 117 | stubs: std.ArrayListUnmanaged(*Symbol) = .{}, | 112 | stubs: std.ArrayListUnmanaged(*Symbol) = .{}, |
| ... | @@ -145,8 +140,6 @@ pub const TextBlock = struct { | ... | @@ -145,8 +140,6 @@ pub const TextBlock = struct { |
| 145 | relocs: ?[]*Relocation = null, | 140 | relocs: ?[]*Relocation = null, |
| 146 | size: u64, | 141 | size: u64, |
| 147 | alignment: u32, | 142 | alignment: u32, |
| 148 | segment_id: u16 = 0, | | |
| 149 | section_id: u16 = 0, | | |
| 150 | next: ?*TextBlock = null, | 143 | next: ?*TextBlock = null, |
| 151 | prev: ?*TextBlock = null, | 144 | prev: ?*TextBlock = null, |
| 152 | | 145 | |
| ... | @@ -168,23 +161,21 @@ pub const TextBlock = struct { | ... | @@ -168,23 +161,21 @@ pub const TextBlock = struct { |
| 168 | | 161 | |
| 169 | pub fn print_this(self: *const TextBlock, zld: *Zld) void { | 162 | pub fn print_this(self: *const TextBlock, zld: *Zld) void { |
| 170 | log.warn("TextBlock", .{}); | 163 | log.warn("TextBlock", .{}); |
| 171 | log.warn(" | {}: '{s}'", .{ self.local_sym_index, zld.locals.items[self.local_sym_index].name }); | 164 | log.warn(" | {}: {}", .{ self.local_sym_index, zld.locals.items[self.local_sym_index] }); |
| 172 | if (self.aliases) |aliases| { | 165 | if (self.aliases) |aliases| { |
| 173 | log.warn(" | Aliases:", .{}); | 166 | log.warn(" | Aliases:", .{}); |
| 174 | for (aliases) |index| { | 167 | for (aliases) |index| { |
| 175 | log.warn(" | {}: '{s}'", .{ index, zld.locals.items[index].name }); | 168 | log.warn(" | {}: {}", .{ index, zld.locals.items[index] }); |
| 176 | } | 169 | } |
| 177 | } | 170 | } |
| 178 | if (self.references) |references| { | 171 | if (self.references) |references| { |
| 179 | log.warn(" | References:", .{}); | 172 | log.warn(" | References:", .{}); |
| 180 | for (references) |index| { | 173 | for (references) |index| { |
| 181 | log.warn(" | {}: '{s}'", .{ index, zld.locals.items[index].name }); | 174 | log.warn(" | {}: {}", .{ index, zld.locals.items[index] }); |
| 182 | } | 175 | } |
| 183 | } | 176 | } |
| 184 | log.warn(" | size = {}", .{self.size}); | 177 | log.warn(" | size = {}", .{self.size}); |
| 185 | log.warn(" | align = {}", .{self.alignment}); | 178 | log.warn(" | align = {}", .{self.alignment}); |
| 186 | log.warn(" | segment_id = {}", .{self.segment_id}); | | |
| 187 | log.warn(" | section_id = {}", .{self.section_id}); | | |
| 188 | } | 179 | } |
| 189 | | 180 | |
| 190 | pub fn print(self: *const TextBlock, zld: *Zld) void { | 181 | pub fn print(self: *const TextBlock, zld: *Zld) void { |
| ... | @@ -300,7 +291,6 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg | ... | @@ -300,7 +291,6 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg |
| 300 | // try self.allocateDataSegment(); | 291 | // try self.allocateDataSegment(); |
| 301 | // self.allocateLinkeditSegment(); | 292 | // self.allocateLinkeditSegment(); |
| 302 | // try self.allocateSymbols(); | 293 | // try self.allocateSymbols(); |
| 303 | // try self.allocateTentativeSymbols(); | | |
| 304 | // try self.allocateProxyBindAddresses(); | 294 | // try self.allocateProxyBindAddresses(); |
| 305 | // try self.flush(); | 295 | // try self.flush(); |
| 306 | } | 296 | } |
| ... | @@ -415,37 +405,6 @@ fn updateMetadata(self: *Zld) !void { | ... | @@ -415,37 +405,6 @@ fn updateMetadata(self: *Zld) !void { |
| 415 | } | 405 | } |
| 416 | } | 406 | } |
| 417 | | 407 | |
| 418 | // Ensure we have __DATA,__common section if we have tentative definitions. | | |
| 419 | // Update size and alignment of __DATA,__common section. | | |
| 420 | if (self.has_tentative_defs) { | | |
| 421 | const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; | | |
| 422 | const common_section_index = self.common_section_index orelse ind: { | | |
| 423 | self.common_section_index = @intCast(u16, data_seg.sections.items.len); | | |
| 424 | try data_seg.addSection(self.allocator, "__common", .{ | | |
| 425 | .flags = macho.S_ZEROFILL, | | |
| 426 | }); | | |
| 427 | break :ind self.common_section_index.?; | | |
| 428 | }; | | |
| 429 | const common_sect = &data_seg.sections.items[common_section_index]; | | |
| 430 | | | |
| 431 | var max_align: u16 = 0; | | |
| 432 | var added_size: u64 = 0; | | |
| 433 | for (self.globals.values()) |sym| { | | |
| 434 | if (sym.payload != .tentative) continue; | | |
| 435 | max_align = math.max(max_align, sym.payload.tentative.alignment); | | |
| 436 | added_size += sym.payload.tentative.size; | | |
| 437 | } | | |
| 438 | | | |
| 439 | common_sect.@"align" = math.max(common_sect.@"align", max_align); | | |
| 440 | | | |
| 441 | const alignment = try math.powi(u32, 2, common_sect.@"align"); | | |
| 442 | const offset = mem.alignForwardGeneric(u64, common_sect.size, alignment); | | |
| 443 | const size = mem.alignForwardGeneric(u64, added_size, alignment); | | |
| 444 | | | |
| 445 | common_sect.size = offset + size; | | |
| 446 | self.tentative_defs_offset = offset; | | |
| 447 | } | | |
| 448 | | | |
| 449 | tlv_align: { | 408 | tlv_align: { |
| 450 | const has_tlv = | 409 | const has_tlv = |
| 451 | self.tlv_section_index != null or | 410 | self.tlv_section_index != null or |
| ... | @@ -1182,48 +1141,6 @@ fn allocateSymbols(self: *Zld) !void { | ... | @@ -1182,48 +1141,6 @@ fn allocateSymbols(self: *Zld) !void { |
| 1182 | } | 1141 | } |
| 1183 | } | 1142 | } |
| 1184 | | 1143 | |
| 1185 | fn allocateTentativeSymbols(self: *Zld) !void { | | |
| 1186 | if (!self.has_tentative_defs) return; | | |
| 1187 | | | |
| 1188 | const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; | | |
| 1189 | const common_sect = &data_seg.sections.items[self.common_section_index.?]; | | |
| 1190 | | | |
| 1191 | const alignment = try math.powi(u32, 2, common_sect.@"align"); | | |
| 1192 | var base_address: u64 = common_sect.addr + self.tentative_defs_offset; | | |
| 1193 | | | |
| 1194 | log.debug("base address for tentative definitions 0x{x}", .{base_address}); | | |
| 1195 | | | |
| 1196 | // TODO there might be a more generic way of doing this. | | |
| 1197 | var section: u8 = 0; | | |
| 1198 | for (self.load_commands.items) |cmd, cmd_id| { | | |
| 1199 | if (cmd != .Segment) break; | | |
| 1200 | if (cmd_id == self.data_segment_cmd_index.?) { | | |
| 1201 | section += @intCast(u8, self.common_section_index.?) + 1; | | |
| 1202 | break; | | |
| 1203 | } | | |
| 1204 | section += @intCast(u8, cmd.Segment.sections.items.len); | | |
| 1205 | } | | |
| 1206 | | | |
| 1207 | // Convert tentative definitions into regular symbols. | | |
| 1208 | for (self.globals.values()) |sym| { | | |
| 1209 | if (sym.payload != .tentative) continue; | | |
| 1210 | | | |
| 1211 | const address = mem.alignForwardGeneric(u64, base_address + sym.payload.tentative.size, alignment); | | |
| 1212 | | | |
| 1213 | log.debug("tentative definition '{s}' allocated from 0x{x} to 0x{x}", .{ sym.name, base_address, address }); | | |
| 1214 | | | |
| 1215 | sym.payload = .{ | | |
| 1216 | .regular = .{ | | |
| 1217 | .linkage = .global, | | |
| 1218 | .address = base_address, | | |
| 1219 | .section = section, | | |
| 1220 | .weak_ref = false, | | |
| 1221 | }, | | |
| 1222 | }; | | |
| 1223 | base_address = address; | | |
| 1224 | } | | |
| 1225 | } | | |
| 1226 | | | |
| 1227 | fn allocateProxyBindAddresses(self: *Zld) !void { | 1144 | fn allocateProxyBindAddresses(self: *Zld) !void { |
| 1228 | for (self.objects.items) |object| { | 1145 | for (self.objects.items) |object| { |
| 1229 | for (object.sections.items) |sect| { | 1146 | for (object.sections.items) |sect| { |
| ... | @@ -1648,15 +1565,56 @@ fn resolveSymbols(self: *Zld) !void { | ... | @@ -1648,15 +1565,56 @@ fn resolveSymbols(self: *Zld) !void { |
| 1648 | } | 1565 | } |
| 1649 | | 1566 | |
| 1650 | // Put any globally defined regular symbol as local. | 1567 | // Put any globally defined regular symbol as local. |
| 1651 | // Mark if we need to allocate zerofill section for tentative definitions | 1568 | // Convert any tentative definition into a regular symbol and allocate |
| | 1569 | // text blocks for each tentative defintion. |
| 1652 | for (self.globals.values()) |symbol| { | 1570 | for (self.globals.values()) |symbol| { |
| 1653 | switch (symbol.payload) { | 1571 | switch (symbol.payload) { |
| 1654 | .regular => |*reg| { | 1572 | .regular => |*reg| { |
| 1655 | reg.local_sym_index = @intCast(u32, self.locals.items.len); | 1573 | reg.local_sym_index = @intCast(u32, self.locals.items.len); |
| 1656 | try self.locals.append(self.allocator, symbol); | 1574 | try self.locals.append(self.allocator, symbol); |
| 1657 | }, | 1575 | }, |
| 1658 | .tentative => { | 1576 | .tentative => |tent| { |
| 1659 | self.has_tentative_defs = true; | 1577 | if (self.common_section_index == null) { |
| | 1578 | const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| | 1579 | self.common_section_index = @intCast(u16, data_seg.sections.items.len); |
| | 1580 | try data_seg.addSection(self.allocator, "__common", .{ |
| | 1581 | .flags = macho.S_ZEROFILL, |
| | 1582 | }); |
| | 1583 | } |
| | 1584 | |
| | 1585 | const size = tent.size; |
| | 1586 | const code = try self.allocator.alloc(u8, size); |
| | 1587 | mem.set(u8, code, 0); |
| | 1588 | const alignment = tent.alignment; |
| | 1589 | const local_sym_index = @intCast(u32, self.locals.items.len); |
| | 1590 | |
| | 1591 | symbol.payload = .{ |
| | 1592 | .regular = .{ |
| | 1593 | .linkage = .global, |
| | 1594 | .segment_id = self.data_segment_cmd_index.?, |
| | 1595 | .section_id = self.common_section_index.?, |
| | 1596 | .local_sym_index = local_sym_index, |
| | 1597 | }, |
| | 1598 | }; |
| | 1599 | try self.locals.append(self.allocator, symbol); |
| | 1600 | |
| | 1601 | const block = try self.allocator.create(TextBlock); |
| | 1602 | errdefer self.allocator.destroy(block); |
| | 1603 | |
| | 1604 | block.* = .{ |
| | 1605 | .local_sym_index = local_sym_index, |
| | 1606 | .code = code, |
| | 1607 | .size = size, |
| | 1608 | .alignment = alignment, |
| | 1609 | }; |
| | 1610 | |
| | 1611 | // TODO I'm not 100% sure about this yet, but I believe we should keep a separate list of |
| | 1612 | // TextBlocks per segment. |
| | 1613 | if (self.last_text_block) |last| { |
| | 1614 | last.next = block; |
| | 1615 | block.prev = last; |
| | 1616 | } |
| | 1617 | self.last_text_block = block; |
| 1660 | }, | 1618 | }, |
| 1661 | else => {}, | 1619 | else => {}, |
| 1662 | } | 1620 | } |
| ... | @@ -1733,13 +1691,7 @@ fn resolveSymbols(self: *Zld) !void { | ... | @@ -1733,13 +1691,7 @@ fn resolveSymbols(self: *Zld) !void { |
| 1733 | | 1691 | |
| 1734 | fn parseTextBlocks(self: *Zld) !void { | 1692 | fn parseTextBlocks(self: *Zld) !void { |
| 1735 | for (self.objects.items) |object| { | 1693 | for (self.objects.items) |object| { |
| 1736 | if (try object.parseTextBlocks(self)) |block| { | 1694 | try object.parseTextBlocks(self); |
| 1737 | if (self.last_text_block) |last| { | | |
| 1738 | last.next = block; | | |
| 1739 | block.prev = last; | | |
| 1740 | } | | |
| 1741 | self.last_text_block = block; | | |
| 1742 | } | | |
| 1743 | } | 1695 | } |
| 1744 | | 1696 | |
| 1745 | if (self.last_text_block) |block| { | 1697 | if (self.last_text_block) |block| { |