| ... | ... | @@ -186,6 +186,12 @@ comdat_groups_table: std.AutoHashMapUnmanaged(u32, ComdatGroupOwner.Index) = .{} |
| 186 | 186 | /// such as `resolver` and `comdat_groups_table`. |
| 187 | 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 | 195 | /// When allocating, the ideal_capacity is calculated by |
| 190 | 196 | /// actual_capacity + (actual_capacity / ideal_factor) |
| 191 | 197 | const ideal_factor = 3; |
| ... | ... | @@ -392,6 +398,9 @@ pub fn deinit(self: *Elf) void { |
| 392 | 398 | self.copy_rel.deinit(gpa); |
| 393 | 399 | self.rela_dyn.deinit(gpa); |
| 394 | 400 | self.rela_plt.deinit(gpa); |
| 401 | |
| 402 | self.ar_symtab.deinit(gpa); |
| 403 | self.ar_strtab.deinit(gpa); |
| 395 | 404 | } |
| 396 | 405 | |
| 397 | 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 | 1392 | if (csu.crtend) |v| try positionals.append(.{ .path = v }); |
| 1384 | 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 | 1398 | for (positionals.items) |obj| { |
| 1387 | 1399 | var parse_ctx: ParseErrorCtx = .{ .detected_cpu_arch = undefined }; |
| 1388 | 1400 | self.parsePositional(obj.path, obj.must_link, &parse_ctx) catch |err| |
| 1389 | 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 | 1404 | // Dedup shared objects |
| 1396 | 1405 | { |
| 1397 | 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 | 1421 | |
| 1413 | 1422 | // If we haven't already, create a linker-generated input file comprising of |
| 1414 | 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 | 1425 | const index = @as(File.Index, @intCast(try self.files.addOne(gpa))); |
| 1417 | 1426 | self.files.set(index, .{ .linker_defined = .{ .index = index } }); |
| 1418 | 1427 | self.linker_defined_index = index; |
| ... | ... | @@ -1517,14 +1526,55 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1517 | 1526 | } else { |
| 1518 | 1527 | log.debug("flushing. no_entry_point_found = false", .{}); |
| 1519 | 1528 | self.error_flags.no_entry_point_found = false; |
| 1520 | | try self.writeHeader(); |
| 1529 | try self.writeElfHeader(); |
| 1521 | 1530 | } |
| 1522 | 1531 | } |
| 1523 | 1532 | |
| 1524 | 1533 | pub fn flushStaticLib(self: *Elf, comp: *Compilation) link.File.FlushError!void { |
| 1525 | 1534 | _ = comp; |
| 1526 | | var err = try self.addErrorWithNotes(0); |
| 1527 | | try err.addMsg(self, "fatal linker error: emitting static libs unimplemented", .{}); |
| 1535 | |
| 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 | 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 | 1593 | |
| 1544 | 1594 | try self.writeShdrTable(); |
| 1545 | 1595 | try self.writeSyntheticSections(); |
| 1546 | | try self.writeHeader(); |
| 1596 | try self.writeElfHeader(); |
| 1547 | 1597 | } |
| 1548 | 1598 | |
| 1549 | 1599 | const ParseError = error{ |
| ... | ... | @@ -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 | 2851 | var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 = undefined; |
| 2802 | 2852 | |
| 2803 | 2853 | var index: usize = 0; |
| ... | ... | @@ -2918,6 +2968,15 @@ fn writeHeader(self: *Elf) !void { |
| 2918 | 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 | 2980 | pub fn freeDecl(self: *Elf, decl_index: Module.Decl.Index) void { |
| 2922 | 2981 | if (self.llvm_object) |llvm_object| return llvm_object.freeDecl(decl_index); |
| 2923 | 2982 | return self.zigObjectPtr().?.freeDecl(self, decl_index); |
| ... | ... | @@ -3147,17 +3206,13 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { |
| 3147 | 3206 | } |
| 3148 | 3207 | |
| 3149 | 3208 | fn initSections(self: *Elf) !void { |
| 3150 | | const small_ptr = switch (self.ptr_width) { |
| 3151 | | .p32 => true, |
| 3152 | | .p64 => false, |
| 3153 | | }; |
| 3154 | 3209 | const ptr_size = self.ptrWidthBytes(); |
| 3155 | 3210 | |
| 3156 | | if (!self.isStaticLib()) for (self.objects.items) |index| { |
| 3211 | for (self.objects.items) |index| { |
| 3157 | 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 | 3216 | if (self.file(index).?.object.cies.items.len > 0) break true; |
| 3162 | 3217 | } else false; |
| 3163 | 3218 | if (needs_eh_frame) { |
| ... | ... | @@ -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 | 3407 | if (self.symtab_section_index == null) { |
| 3344 | 3408 | self.symtab_section_index = try self.addSection(.{ |
| 3345 | 3409 | .name = ".symtab", |
| ... | ... | @@ -3358,6 +3422,9 @@ fn initSections(self: *Elf) !void { |
| 3358 | 3422 | .offset = std.math.maxInt(u64), |
| 3359 | 3423 | }); |
| 3360 | 3424 | } |
| 3425 | } |
| 3426 | |
| 3427 | fn initShStrtab(self: *Elf) !void { |
| 3361 | 3428 | if (self.shstrtab_section_index == null) { |
| 3362 | 3429 | self.shstrtab_section_index = try self.addSection(.{ |
| 3363 | 3430 | .name = ".shstrtab", |
| ... | ... | @@ -3933,10 +4000,11 @@ fn updateSectionSizes(self: *Elf) !void { |
| 3933 | 4000 | self.shdrs.items[index].sh_size = self.verneed.size(); |
| 3934 | 4001 | } |
| 3935 | 4002 | |
| 3936 | | if (self.symtab_section_index != null) { |
| 3937 | | try self.updateSymtabSize(); |
| 3938 | | } |
| 4003 | try self.updateSymtabSize(); |
| 4004 | self.updateShStrtabSize(); |
| 4005 | } |
| 3939 | 4006 | |
| 4007 | fn updateShStrtabSize(self: *Elf) void { |
| 3940 | 4008 | if (self.shstrtab_section_index) |index| { |
| 3941 | 4009 | self.shdrs.items[index].sh_size = self.shstrtab.items.len; |
| 3942 | 4010 | } |
| ... | ... | @@ -4546,14 +4614,15 @@ fn writeSyntheticSections(self: *Elf) !void { |
| 4546 | 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 | 4622 | if (self.shstrtab_section_index) |index| { |
| 4550 | 4623 | const shdr = self.shdrs.items[index]; |
| 4551 | 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 | 4628 | fn writeSymtab(self: *Elf) !void { |