| ... | @@ -186,6 +186,12 @@ comdat_groups_table: std.AutoHashMapUnmanaged(u32, ComdatGroupOwner.Index) = .{} | ... | @@ -186,6 +186,12 @@ comdat_groups_table: std.AutoHashMapUnmanaged(u32, ComdatGroupOwner.Index) = .{} |
| 186 | /// such as `resolver` and `comdat_groups_table`. | 186 | /// such as `resolver` and `comdat_groups_table`. |
| 187 | strings: StringTable = .{}, | 187 | strings: StringTable = .{}, |
| 188 | | 188 | |
| | 189 | /// Static archive state. |
| | 190 | /// TODO it may be wise to move it somewhere else, but for the time being, it |
| | 191 | /// is far easier to pollute global state. |
| | 192 | ar_symtab: std.ArrayListUnmanaged(struct { u32, File.Index }) = .{}, |
| | 193 | ar_strtab: StringTable = .{}, |
| | 194 | |
| 189 | /// When allocating, the ideal_capacity is calculated by | 195 | /// When allocating, the ideal_capacity is calculated by |
| 190 | /// actual_capacity + (actual_capacity / ideal_factor) | 196 | /// actual_capacity + (actual_capacity / ideal_factor) |
| 191 | const ideal_factor = 3; | 197 | const ideal_factor = 3; |
| ... | @@ -392,6 +398,9 @@ pub fn deinit(self: *Elf) void { | ... | @@ -392,6 +398,9 @@ pub fn deinit(self: *Elf) void { |
| 392 | self.copy_rel.deinit(gpa); | 398 | self.copy_rel.deinit(gpa); |
| 393 | self.rela_dyn.deinit(gpa); | 399 | self.rela_dyn.deinit(gpa); |
| 394 | self.rela_plt.deinit(gpa); | 400 | self.rela_plt.deinit(gpa); |
| | 401 | |
| | 402 | self.ar_symtab.deinit(gpa); |
| | 403 | self.ar_strtab.deinit(gpa); |
| 395 | } | 404 | } |
| 396 | | 405 | |
| 397 | pub fn getDeclVAddr(self: *Elf, decl_index: Module.Decl.Index, reloc_info: link.File.RelocInfo) !u64 { | 406 | pub fn getDeclVAddr(self: *Elf, decl_index: Module.Decl.Index, reloc_info: link.File.RelocInfo) !u64 { |
| ... | @@ -1383,15 +1392,15 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node | ... | @@ -1383,15 +1392,15 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1383 | if (csu.crtend) |v| try positionals.append(.{ .path = v }); | 1392 | if (csu.crtend) |v| try positionals.append(.{ .path = v }); |
| 1384 | if (csu.crtn) |v| try positionals.append(.{ .path = v }); | 1393 | if (csu.crtn) |v| try positionals.append(.{ .path = v }); |
| 1385 | | 1394 | |
| | 1395 | if (self.zigObjectPtr()) |zig_object| try zig_object.flushModule(self); |
| | 1396 | if (self.isStaticLib()) return self.flushStaticLib(comp); |
| | 1397 | |
| 1386 | for (positionals.items) |obj| { | 1398 | for (positionals.items) |obj| { |
| 1387 | var parse_ctx: ParseErrorCtx = .{ .detected_cpu_arch = undefined }; | 1399 | var parse_ctx: ParseErrorCtx = .{ .detected_cpu_arch = undefined }; |
| 1388 | self.parsePositional(obj.path, obj.must_link, &parse_ctx) catch |err| | 1400 | self.parsePositional(obj.path, obj.must_link, &parse_ctx) catch |err| |
| 1389 | try self.handleAndReportParseError(obj.path, err, &parse_ctx); | 1401 | try self.handleAndReportParseError(obj.path, err, &parse_ctx); |
| 1390 | } | 1402 | } |
| 1391 | | 1403 | |
| 1392 | if (self.zigObjectPtr()) |zig_object| try zig_object.flushModule(self); | | |
| 1393 | if (self.isStaticLib()) return self.flushStaticLib(comp); | | |
| 1394 | | | |
| 1395 | // Dedup shared objects | 1404 | // Dedup shared objects |
| 1396 | { | 1405 | { |
| 1397 | var seen_dsos = std.StringHashMap(void).init(gpa); | 1406 | var seen_dsos = std.StringHashMap(void).init(gpa); |
| ... | @@ -1412,7 +1421,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node | ... | @@ -1412,7 +1421,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1412 | | 1421 | |
| 1413 | // If we haven't already, create a linker-generated input file comprising of | 1422 | // If we haven't already, create a linker-generated input file comprising of |
| 1414 | // linker-defined synthetic symbols only such as `_DYNAMIC`, etc. | 1423 | // linker-defined synthetic symbols only such as `_DYNAMIC`, etc. |
| 1415 | if (self.linker_defined_index == null and !self.isObject()) { | 1424 | if (self.linker_defined_index == null and !self.isRelocatable()) { |
| 1416 | const index = @as(File.Index, @intCast(try self.files.addOne(gpa))); | 1425 | const index = @as(File.Index, @intCast(try self.files.addOne(gpa))); |
| 1417 | self.files.set(index, .{ .linker_defined = .{ .index = index } }); | 1426 | self.files.set(index, .{ .linker_defined = .{ .index = index } }); |
| 1418 | self.linker_defined_index = index; | 1427 | self.linker_defined_index = index; |
| ... | @@ -1517,14 +1526,55 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node | ... | @@ -1517,14 +1526,55 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1517 | } else { | 1526 | } else { |
| 1518 | log.debug("flushing. no_entry_point_found = false", .{}); | 1527 | log.debug("flushing. no_entry_point_found = false", .{}); |
| 1519 | self.error_flags.no_entry_point_found = false; | 1528 | self.error_flags.no_entry_point_found = false; |
| 1520 | try self.writeHeader(); | 1529 | try self.writeElfHeader(); |
| 1521 | } | 1530 | } |
| 1522 | } | 1531 | } |
| 1523 | | 1532 | |
| 1524 | pub fn flushStaticLib(self: *Elf, comp: *Compilation) link.File.FlushError!void { | 1533 | pub fn flushStaticLib(self: *Elf, comp: *Compilation) link.File.FlushError!void { |
| 1525 | _ = comp; | 1534 | _ = comp; |
| 1526 | var err = try self.addErrorWithNotes(0); | 1535 | |
| 1527 | try err.addMsg(self, "fatal linker error: emitting static libs unimplemented", .{}); | 1536 | // First, we flush relocatable object file generated with our backends. |
| | 1537 | if (self.zigObjectPtr()) |zig_object| { |
| | 1538 | zig_object.resolveSymbols(self); |
| | 1539 | zig_object.claimUnresolvedObject(self); |
| | 1540 | |
| | 1541 | try self.initSymtab(); |
| | 1542 | try self.initShStrtab(); |
| | 1543 | try self.sortShdrs(); |
| | 1544 | zig_object.updateRelaSectionSizes(self); |
| | 1545 | try self.updateSymtabSize(); |
| | 1546 | self.updateShStrtabSize(); |
| | 1547 | |
| | 1548 | try self.allocateNonAllocSections(); |
| | 1549 | |
| | 1550 | try self.writeShdrTable(); |
| | 1551 | try zig_object.writeRelaSections(self); |
| | 1552 | try self.writeSymtab(); |
| | 1553 | try self.writeShStrtab(); |
| | 1554 | try self.writeElfHeader(); |
| | 1555 | |
| | 1556 | // Update ar symbol and string tables. |
| | 1557 | try zig_object.asFile().updateArSymtab(self); |
| | 1558 | |
| | 1559 | for (self.ar_symtab.items, 0..) |entry, i| { |
| | 1560 | std.debug.print("{d}: {s} in {}\n", .{ |
| | 1561 | i, |
| | 1562 | self.ar_strtab.getAssumeExists(entry[0]), |
| | 1563 | self.file(entry[1]).?.fmtPath(), |
| | 1564 | }); |
| | 1565 | } |
| | 1566 | } |
| | 1567 | |
| | 1568 | // TODO parse positionals that we want to make part of the archive |
| | 1569 | |
| | 1570 | if (build_options.enable_logging) { |
| | 1571 | state_log.debug("{}", .{self.dumpState()}); |
| | 1572 | } |
| | 1573 | |
| | 1574 | // try self.writeArHdr(); |
| | 1575 | // TODO beyond this point I expect writing out objects parsed from the cmdline |
| | 1576 | |
| | 1577 | try self.writeArMagic(); |
| 1528 | } | 1578 | } |
| 1529 | | 1579 | |
| 1530 | pub fn flushObject(self: *Elf, comp: *Compilation) link.File.FlushError!void { | 1580 | pub fn flushObject(self: *Elf, comp: *Compilation) link.File.FlushError!void { |
| ... | @@ -1543,7 +1593,7 @@ pub fn flushObject(self: *Elf, comp: *Compilation) link.File.FlushError!void { | ... | @@ -1543,7 +1593,7 @@ pub fn flushObject(self: *Elf, comp: *Compilation) link.File.FlushError!void { |
| 1543 | | 1593 | |
| 1544 | try self.writeShdrTable(); | 1594 | try self.writeShdrTable(); |
| 1545 | try self.writeSyntheticSections(); | 1595 | try self.writeSyntheticSections(); |
| 1546 | try self.writeHeader(); | 1596 | try self.writeElfHeader(); |
| 1547 | } | 1597 | } |
| 1548 | | 1598 | |
| 1549 | const ParseError = error{ | 1599 | const ParseError = error{ |
| ... | @@ -2797,7 +2847,7 @@ fn writePhdrTable(self: *Elf) !void { | ... | @@ -2797,7 +2847,7 @@ fn writePhdrTable(self: *Elf) !void { |
| 2797 | } | 2847 | } |
| 2798 | } | 2848 | } |
| 2799 | | 2849 | |
| 2800 | fn writeHeader(self: *Elf) !void { | 2850 | fn writeElfHeader(self: *Elf) !void { |
| 2801 | var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 = undefined; | 2851 | var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 = undefined; |
| 2802 | | 2852 | |
| 2803 | var index: usize = 0; | 2853 | var index: usize = 0; |
| ... | @@ -2918,6 +2968,15 @@ fn writeHeader(self: *Elf) !void { | ... | @@ -2918,6 +2968,15 @@ fn writeHeader(self: *Elf) !void { |
| 2918 | try self.base.file.?.pwriteAll(hdr_buf[0..index], 0); | 2968 | try self.base.file.?.pwriteAll(hdr_buf[0..index], 0); |
| 2919 | } | 2969 | } |
| 2920 | | 2970 | |
| | 2971 | fn writeArMagic(self: *Elf) !void { |
| | 2972 | // Magic bytes. |
| | 2973 | var buffer: [@as(usize, Archive.SARMAG) + 1]u8 = undefined; |
| | 2974 | var stream = std.io.fixedBufferStream(&buffer); |
| | 2975 | const writer = stream.writer(); |
| | 2976 | try writer.print("{s}\x00", .{Archive.ARMAG}); |
| | 2977 | try self.base.file.?.pwriteAll(&buffer, 0); |
| | 2978 | } |
| | 2979 | |
| 2921 | pub fn freeDecl(self: *Elf, decl_index: Module.Decl.Index) void { | 2980 | pub fn freeDecl(self: *Elf, decl_index: Module.Decl.Index) void { |
| 2922 | if (self.llvm_object) |llvm_object| return llvm_object.freeDecl(decl_index); | 2981 | if (self.llvm_object) |llvm_object| return llvm_object.freeDecl(decl_index); |
| 2923 | return self.zigObjectPtr().?.freeDecl(self, decl_index); | 2982 | return self.zigObjectPtr().?.freeDecl(self, decl_index); |
| ... | @@ -3147,17 +3206,13 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { | ... | @@ -3147,17 +3206,13 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { |
| 3147 | } | 3206 | } |
| 3148 | | 3207 | |
| 3149 | fn initSections(self: *Elf) !void { | 3208 | fn initSections(self: *Elf) !void { |
| 3150 | const small_ptr = switch (self.ptr_width) { | | |
| 3151 | .p32 => true, | | |
| 3152 | .p64 => false, | | |
| 3153 | }; | | |
| 3154 | const ptr_size = self.ptrWidthBytes(); | 3209 | const ptr_size = self.ptrWidthBytes(); |
| 3155 | | 3210 | |
| 3156 | if (!self.isStaticLib()) for (self.objects.items) |index| { | 3211 | for (self.objects.items) |index| { |
| 3157 | try self.file(index).?.object.initOutputSections(self); | 3212 | try self.file(index).?.object.initOutputSections(self); |
| 3158 | }; | 3213 | } |
| 3159 | | 3214 | |
| 3160 | const needs_eh_frame = if (self.isStaticLib()) false else for (self.objects.items) |index| { | 3215 | const needs_eh_frame = for (self.objects.items) |index| { |
| 3161 | if (self.file(index).?.object.cies.items.len > 0) break true; | 3216 | if (self.file(index).?.object.cies.items.len > 0) break true; |
| 3162 | } else false; | 3217 | } else false; |
| 3163 | if (needs_eh_frame) { | 3218 | if (needs_eh_frame) { |
| ... | @@ -3340,6 +3395,15 @@ fn initSections(self: *Elf) !void { | ... | @@ -3340,6 +3395,15 @@ fn initSections(self: *Elf) !void { |
| 3340 | } | 3395 | } |
| 3341 | } | 3396 | } |
| 3342 | | 3397 | |
| | 3398 | try self.initSymtab(); |
| | 3399 | try self.initShStrtab(); |
| | 3400 | } |
| | 3401 | |
| | 3402 | fn initSymtab(self: *Elf) !void { |
| | 3403 | const small_ptr = switch (self.ptr_width) { |
| | 3404 | .p32 => true, |
| | 3405 | .p64 => false, |
| | 3406 | }; |
| 3343 | if (self.symtab_section_index == null) { | 3407 | if (self.symtab_section_index == null) { |
| 3344 | self.symtab_section_index = try self.addSection(.{ | 3408 | self.symtab_section_index = try self.addSection(.{ |
| 3345 | .name = ".symtab", | 3409 | .name = ".symtab", |
| ... | @@ -3358,6 +3422,9 @@ fn initSections(self: *Elf) !void { | ... | @@ -3358,6 +3422,9 @@ fn initSections(self: *Elf) !void { |
| 3358 | .offset = std.math.maxInt(u64), | 3422 | .offset = std.math.maxInt(u64), |
| 3359 | }); | 3423 | }); |
| 3360 | } | 3424 | } |
| | 3425 | } |
| | 3426 | |
| | 3427 | fn initShStrtab(self: *Elf) !void { |
| 3361 | if (self.shstrtab_section_index == null) { | 3428 | if (self.shstrtab_section_index == null) { |
| 3362 | self.shstrtab_section_index = try self.addSection(.{ | 3429 | self.shstrtab_section_index = try self.addSection(.{ |
| 3363 | .name = ".shstrtab", | 3430 | .name = ".shstrtab", |
| ... | @@ -3933,10 +4000,11 @@ fn updateSectionSizes(self: *Elf) !void { | ... | @@ -3933,10 +4000,11 @@ fn updateSectionSizes(self: *Elf) !void { |
| 3933 | self.shdrs.items[index].sh_size = self.verneed.size(); | 4000 | self.shdrs.items[index].sh_size = self.verneed.size(); |
| 3934 | } | 4001 | } |
| 3935 | | 4002 | |
| 3936 | if (self.symtab_section_index != null) { | 4003 | try self.updateSymtabSize(); |
| 3937 | try self.updateSymtabSize(); | 4004 | self.updateShStrtabSize(); |
| 3938 | } | 4005 | } |
| 3939 | | 4006 | |
| | 4007 | fn updateShStrtabSize(self: *Elf) void { |
| 3940 | if (self.shstrtab_section_index) |index| { | 4008 | if (self.shstrtab_section_index) |index| { |
| 3941 | self.shdrs.items[index].sh_size = self.shstrtab.items.len; | 4009 | self.shdrs.items[index].sh_size = self.shstrtab.items.len; |
| 3942 | } | 4010 | } |
| ... | @@ -4546,14 +4614,15 @@ fn writeSyntheticSections(self: *Elf) !void { | ... | @@ -4546,14 +4614,15 @@ fn writeSyntheticSections(self: *Elf) !void { |
| 4546 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.rela_plt.items), shdr.sh_offset); | 4614 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.rela_plt.items), shdr.sh_offset); |
| 4547 | } | 4615 | } |
| 4548 | | 4616 | |
| | 4617 | try self.writeSymtab(); |
| | 4618 | try self.writeShStrtab(); |
| | 4619 | } |
| | 4620 | |
| | 4621 | fn writeShStrtab(self: *Elf) !void { |
| 4549 | if (self.shstrtab_section_index) |index| { | 4622 | if (self.shstrtab_section_index) |index| { |
| 4550 | const shdr = self.shdrs.items[index]; | 4623 | const shdr = self.shdrs.items[index]; |
| 4551 | try self.base.file.?.pwriteAll(self.shstrtab.items, shdr.sh_offset); | 4624 | try self.base.file.?.pwriteAll(self.shstrtab.items, shdr.sh_offset); |
| 4552 | } | 4625 | } |
| 4553 | | | |
| 4554 | if (self.symtab_section_index) |_| { | | |
| 4555 | try self.writeSymtab(); | | |
| 4556 | } | | |
| 4557 | } | 4626 | } |
| 4558 | | 4627 | |
| 4559 | fn writeSymtab(self: *Elf) !void { | 4628 | fn writeSymtab(self: *Elf) !void { |