| ... | @@ -1245,6 +1245,9 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node | ... | @@ -1245,6 +1245,9 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1245 | // Generate and emit non-incremental sections. | 1245 | // Generate and emit non-incremental sections. |
| 1246 | try self.initSections(); | 1246 | try self.initSections(); |
| 1247 | try self.sortSections(); | 1247 | try self.sortSections(); |
| | 1248 | for (self.objects.items) |index| { |
| | 1249 | try self.file(index).?.object.addAtomsToOutputSections(self); |
| | 1250 | } |
| 1248 | try self.updateSectionSizes(); | 1251 | try self.updateSectionSizes(); |
| 1249 | | 1252 | |
| 1250 | try self.allocateSections(); | 1253 | try self.allocateSections(); |
| ... | @@ -1424,7 +1427,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node | ... | @@ -1424,7 +1427,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1424 | phdr_table_load.p_filesz = 0; | 1427 | phdr_table_load.p_filesz = 0; |
| 1425 | | 1428 | |
| 1426 | self.phdr_table_dirty = false; | 1429 | self.phdr_table_dirty = false; |
| 1427 | } | 1430 | } else try self.writePhdrs(); |
| 1428 | | 1431 | |
| 1429 | if (self.shdr_table_dirty) { | 1432 | if (self.shdr_table_dirty) { |
| 1430 | const shsize: u64 = switch (self.ptr_width) { | 1433 | const shsize: u64 = switch (self.ptr_width) { |
| ... | @@ -1476,8 +1479,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node | ... | @@ -1476,8 +1479,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1476 | self.shdr_table_dirty = false; | 1479 | self.shdr_table_dirty = false; |
| 1477 | } | 1480 | } |
| 1478 | | 1481 | |
| | 1482 | try self.writeAtoms(); |
| 1479 | try self.writeSyntheticSections(); | 1483 | try self.writeSyntheticSections(); |
| 1480 | try self.writeObjects(); | | |
| 1481 | | 1484 | |
| 1482 | if (self.entry_addr == null and self.base.options.effectiveOutputMode() == .Exe) { | 1485 | if (self.entry_addr == null and self.base.options.effectiveOutputMode() == .Exe) { |
| 1483 | log.debug("flushing. no_entry_point_found = true", .{}); | 1486 | log.debug("flushing. no_entry_point_found = true", .{}); |
| ... | @@ -1485,7 +1488,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node | ... | @@ -1485,7 +1488,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1485 | } else { | 1488 | } else { |
| 1486 | log.debug("flushing. no_entry_point_found = false", .{}); | 1489 | log.debug("flushing. no_entry_point_found = false", .{}); |
| 1487 | self.error_flags.no_entry_point_found = false; | 1490 | self.error_flags.no_entry_point_found = false; |
| 1488 | try self.writeElfHeader(); | 1491 | try self.writeHeader(); |
| 1489 | } | 1492 | } |
| 1490 | | 1493 | |
| 1491 | // Dump the state for easy debugging. | 1494 | // Dump the state for easy debugging. |
| ... | @@ -1756,30 +1759,6 @@ fn scanRelocs(self: *Elf) !void { | ... | @@ -1756,30 +1759,6 @@ fn scanRelocs(self: *Elf) !void { |
| 1756 | } | 1759 | } |
| 1757 | } | 1760 | } |
| 1758 | | 1761 | |
| 1759 | fn writeObjects(self: *Elf) !void { | | |
| 1760 | const gpa = self.base.allocator; | | |
| 1761 | | | |
| 1762 | for (self.objects.items) |index| { | | |
| 1763 | const object = self.file(index).?.object; | | |
| 1764 | for (object.atoms.items) |atom_index| { | | |
| 1765 | const atom_ptr = self.atom(atom_index) orelse continue; | | |
| 1766 | if (!atom_ptr.flags.alive) continue; | | |
| 1767 | | | |
| 1768 | const shdr = &self.shdrs.items[atom_ptr.outputShndx().?]; | | |
| 1769 | if (shdr.sh_type == elf.SHT_NOBITS) continue; | | |
| 1770 | if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; // TODO we don't yet know how to handle non-alloc sections | | |
| 1771 | | | |
| 1772 | const file_offset = shdr.sh_offset + atom_ptr.value - shdr.sh_addr; | | |
| 1773 | log.debug("writing atom({d}) at 0x{x}", .{ atom_ptr.atom_index, file_offset }); | | |
| 1774 | const code = try object.codeDecompressAlloc(self, atom_ptr.atom_index); | | |
| 1775 | defer gpa.free(code); | | |
| 1776 | | | |
| 1777 | try atom_ptr.resolveRelocs(self, code); | | |
| 1778 | try self.base.file.?.pwriteAll(code, file_offset); | | |
| 1779 | } | | |
| 1780 | } | | |
| 1781 | } | | |
| 1782 | | | |
| 1783 | fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !void { | 1762 | fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !void { |
| 1784 | const tracy = trace(@src()); | 1763 | const tracy = trace(@src()); |
| 1785 | defer tracy.end(); | 1764 | defer tracy.end(); |
| ... | @@ -2480,7 +2459,14 @@ fn writeDwarfAddrAssumeCapacity(self: *Elf, buf: *std.ArrayList(u8), addr: u64) | ... | @@ -2480,7 +2459,14 @@ fn writeDwarfAddrAssumeCapacity(self: *Elf, buf: *std.ArrayList(u8), addr: u64) |
| 2480 | } | 2459 | } |
| 2481 | } | 2460 | } |
| 2482 | | 2461 | |
| 2483 | fn writeElfHeader(self: *Elf) !void { | 2462 | fn writePhdrs(self: *Elf) !void { |
| | 2463 | const phoff = @sizeOf(elf.Elf64_Ehdr); |
| | 2464 | const phdrs_size = self.phdrs.items.len * @sizeOf(elf.Elf64_Phdr); |
| | 2465 | log.debug("writing program headers from 0x{x} to 0x{x}", .{ phoff, phoff + phdrs_size }); |
| | 2466 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.phdrs.items), phoff); |
| | 2467 | } |
| | 2468 | |
| | 2469 | fn writeHeader(self: *Elf) !void { |
| 2484 | var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 = undefined; | 2470 | var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 = undefined; |
| 2485 | | 2471 | |
| 2486 | var index: usize = 0; | 2472 | var index: usize = 0; |
| ... | @@ -2532,7 +2518,11 @@ fn writeElfHeader(self: *Elf) !void { | ... | @@ -2532,7 +2518,11 @@ fn writeElfHeader(self: *Elf) !void { |
| 2532 | | 2518 | |
| 2533 | const e_entry = if (elf_type == .REL) 0 else self.entry_addr.?; | 2519 | const e_entry = if (elf_type == .REL) 0 else self.entry_addr.?; |
| 2534 | | 2520 | |
| 2535 | const phdr_table_offset = self.phdrs.items[self.phdr_table_index.?].p_offset; | 2521 | // TODO |
| | 2522 | const phdr_table_offset = if (self.phdr_table_index) |ind| |
| | 2523 | self.phdrs.items[ind].p_offset |
| | 2524 | else |
| | 2525 | @sizeOf(elf.Elf64_Ehdr); |
| 2536 | switch (self.ptr_width) { | 2526 | switch (self.ptr_width) { |
| 2537 | .p32 => { | 2527 | .p32 => { |
| 2538 | mem.writeInt(u32, hdr_buf[index..][0..4], @as(u32, @intCast(e_entry)), endian); | 2528 | mem.writeInt(u32, hdr_buf[index..][0..4], @as(u32, @intCast(e_entry)), endian); |
| ... | @@ -3401,13 +3391,7 @@ fn initSections(self: *Elf) !void { | ... | @@ -3401,13 +3391,7 @@ fn initSections(self: *Elf) !void { |
| 3401 | }; | 3391 | }; |
| 3402 | | 3392 | |
| 3403 | for (self.objects.items) |index| { | 3393 | for (self.objects.items) |index| { |
| 3404 | const object = self.file(index).?.object; | 3394 | try self.file(index).?.object.initOutputSections(self); |
| 3405 | for (object.atoms.items) |atom_index| { | | |
| 3406 | const atom_ptr = self.atom(atom_index) orelse continue; | | |
| 3407 | if (!atom_ptr.flags.alive) continue; | | |
| 3408 | const shdr = atom_ptr.inputShdr(self); | | |
| 3409 | atom_ptr.output_section_index = try object.initOutputSection(self, shdr); | | |
| 3410 | } | | |
| 3411 | } | 3395 | } |
| 3412 | | 3396 | |
| 3413 | if (self.got.entries.items.len > 0 and self.got_section_index == null) { | 3397 | if (self.got.entries.items.len > 0 and self.got_section_index == null) { |
| ... | @@ -3525,14 +3509,6 @@ fn sortSections(self: *Elf) !void { | ... | @@ -3525,14 +3509,6 @@ fn sortSections(self: *Elf) !void { |
| 3525 | self.shdrs.appendAssumeCapacity(slice[sorted.shndx]); | 3509 | self.shdrs.appendAssumeCapacity(slice[sorted.shndx]); |
| 3526 | } | 3510 | } |
| 3527 | | 3511 | |
| 3528 | for (self.objects.items) |index| { | | |
| 3529 | for (self.file(index).?.atoms()) |atom_index| { | | |
| 3530 | const atom_ptr = self.atom(atom_index) orelse continue; | | |
| 3531 | if (!atom_ptr.flags.alive) continue; | | |
| 3532 | atom_ptr.output_section_index = backlinks[atom_ptr.output_section_index]; | | |
| 3533 | } | | |
| 3534 | } | | |
| 3535 | | | |
| 3536 | for (&[_]*?u16{ | 3512 | for (&[_]*?u16{ |
| 3537 | &self.eh_frame_section_index, | 3513 | &self.eh_frame_section_index, |
| 3538 | &self.eh_frame_hdr_section_index, | 3514 | &self.eh_frame_hdr_section_index, |
| ... | @@ -3891,6 +3867,31 @@ fn allocateAtoms(self: *Elf) void { | ... | @@ -3891,6 +3867,31 @@ fn allocateAtoms(self: *Elf) void { |
| 3891 | } | 3867 | } |
| 3892 | } | 3868 | } |
| 3893 | | 3869 | |
| | 3870 | fn writeAtoms(self: *Elf) !void { |
| | 3871 | const gpa = self.base.allocator; |
| | 3872 | for (self.shdrs.items, 0..) |shdr, shndx| { |
| | 3873 | if (shdr.sh_type == elf.SHT_NULL) continue; |
| | 3874 | if (shdr.sh_type == elf.SHT_NOBITS) continue; |
| | 3875 | |
| | 3876 | log.debug("writing atoms in '{s}' section", .{self.shstrtab.getAssumeExists(shdr.sh_name)}); |
| | 3877 | |
| | 3878 | const buffer = try gpa.alloc(u8, shdr.sh_size); |
| | 3879 | defer gpa.free(buffer); |
| | 3880 | const padding_byte: u8 = if (shdr.sh_type == elf.SHT_PROGBITS and |
| | 3881 | shdr.sh_flags & elf.SHF_EXECINSTR != 0) |
| | 3882 | 0xcc // int3 |
| | 3883 | else |
| | 3884 | 0; |
| | 3885 | @memset(buffer, padding_byte); |
| | 3886 | |
| | 3887 | for (self.objects.items) |index| { |
| | 3888 | try self.file(index).?.object.writeAtoms(self, @intCast(shndx), buffer); |
| | 3889 | } |
| | 3890 | |
| | 3891 | try self.base.file.?.pwriteAll(buffer, shdr.sh_offset); |
| | 3892 | } |
| | 3893 | } |
| | 3894 | |
| 3894 | fn updateSymtabSize(self: *Elf) !void { | 3895 | fn updateSymtabSize(self: *Elf) !void { |
| 3895 | var sizes = SymtabSize{}; | 3896 | var sizes = SymtabSize{}; |
| 3896 | | 3897 | |