| author | |
| committer | |
| log | 7e31804870cac14063b2468f544fc77a4cbb616f |
| tree | 87e84657c242c95177218185fe34bb5c6f69f035 |
| parent | f87dd43c1285d38d7a0f3092f6487bf1e1f4faa6 |
| parent | e1d5bb365b3b8d645fbdfc4ffb6a14ef3bb0e766 |
| signature |
elf: redo how we allocate atoms extracted from input relocatable object files10 files changed, 1145 insertions(+), 988 deletions(-)
CMakeLists.txt+1| ... | @@ -600,6 +600,7 @@ set(ZIG_STAGE2_SOURCES | ... | @@ -600,6 +600,7 @@ set(ZIG_STAGE2_SOURCES |
| 600 | src/link/Elf.zig | 600 | src/link/Elf.zig |
| 601 | src/link/Elf/Archive.zig | 601 | src/link/Elf/Archive.zig |
| 602 | src/link/Elf/Atom.zig | 602 | src/link/Elf/Atom.zig |
| 603 | src/link/Elf/AtomList.zig | ||
| 603 | src/link/Elf/LdScript.zig | 604 | src/link/Elf/LdScript.zig |
| 604 | src/link/Elf/LinkerDefined.zig | 605 | src/link/Elf/LinkerDefined.zig |
| 605 | src/link/Elf/Object.zig | 606 | src/link/Elf/Object.zig |
src/link/Dwarf.zig+81-63| ... | @@ -261,7 +261,6 @@ pub const Section = struct { | ... | @@ -261,7 +261,6 @@ pub const Section = struct { |
| 261 | index: u32, | 261 | index: u32, |
| 262 | first: Unit.Index.Optional, | 262 | first: Unit.Index.Optional, |
| 263 | last: Unit.Index.Optional, | 263 | last: Unit.Index.Optional, |
| 264 | off: u64, | ||
| 265 | len: u64, | 264 | len: u64, |
| 266 | units: std.ArrayListUnmanaged(Unit), | 265 | units: std.ArrayListUnmanaged(Unit), |
| 267 | 266 | ||
| ... | @@ -284,9 +283,8 @@ pub const Section = struct { | ... | @@ -284,9 +283,8 @@ pub const Section = struct { |
| 284 | .index = std.math.maxInt(u32), | 283 | .index = std.math.maxInt(u32), |
| 285 | .first = .none, | 284 | .first = .none, |
| 286 | .last = .none, | 285 | .last = .none, |
| 287 | .off = 0, | ||
| 288 | .len = 0, | ||
| 289 | .units = .{}, | 286 | .units = .{}, |
| 287 | .len = 0, | ||
| 290 | }; | 288 | }; |
| 291 | 289 | ||
| 292 | fn deinit(sec: *Section, gpa: std.mem.Allocator) void { | 290 | fn deinit(sec: *Section, gpa: std.mem.Allocator) void { |
| ... | @@ -295,6 +293,20 @@ pub const Section = struct { | ... | @@ -295,6 +293,20 @@ pub const Section = struct { |
| 295 | sec.* = undefined; | 293 | sec.* = undefined; |
| 296 | } | 294 | } |
| 297 | 295 | ||
| 296 | fn off(sec: Section, dwarf: *Dwarf) u64 { | ||
| 297 | if (dwarf.bin_file.cast(.elf)) |elf_file| { | ||
| 298 | const zo = elf_file.zigObjectPtr().?; | ||
| 299 | const atom = zo.symbol(sec.index).atom(elf_file).?; | ||
| 300 | return atom.offset(elf_file); | ||
| 301 | } else if (dwarf.bin_file.cast(.macho)) |macho_file| { | ||
| 302 | const header = if (macho_file.d_sym) |d_sym| | ||
| 303 | d_sym.sections.items[sec.index] | ||
| 304 | else | ||
| 305 | macho_file.sections.items(.header)[sec.index]; | ||
| 306 | return header.offset; | ||
| 307 | } else unreachable; | ||
| 308 | } | ||
| 309 | |||
| 298 | fn addUnit(sec: *Section, header_len: u32, trailer_len: u32, dwarf: *Dwarf) UpdateError!Unit.Index { | 310 | fn addUnit(sec: *Section, header_len: u32, trailer_len: u32, dwarf: *Dwarf) UpdateError!Unit.Index { |
| 299 | const unit: Unit.Index = @enumFromInt(sec.units.items.len); | 311 | const unit: Unit.Index = @enumFromInt(sec.units.items.len); |
| 300 | const unit_ptr = try sec.units.addOne(dwarf.gpa); | 312 | const unit_ptr = try sec.units.addOne(dwarf.gpa); |
| ... | @@ -306,9 +318,9 @@ pub const Section = struct { | ... | @@ -306,9 +318,9 @@ pub const Section = struct { |
| 306 | .next = .none, | 318 | .next = .none, |
| 307 | .first = .none, | 319 | .first = .none, |
| 308 | .last = .none, | 320 | .last = .none, |
| 309 | .off = 0, | ||
| 310 | .header_len = aligned_header_len, | 321 | .header_len = aligned_header_len, |
| 311 | .trailer_len = aligned_trailer_len, | 322 | .trailer_len = aligned_trailer_len, |
| 323 | .off = 0, | ||
| 312 | .len = aligned_header_len + aligned_trailer_len, | 324 | .len = aligned_header_len + aligned_trailer_len, |
| 313 | .entries = .{}, | 325 | .entries = .{}, |
| 314 | .cross_unit_relocs = .{}, | 326 | .cross_unit_relocs = .{}, |
| ... | @@ -375,12 +387,16 @@ pub const Section = struct { | ... | @@ -375,12 +387,16 @@ pub const Section = struct { |
| 375 | fn resize(sec: *Section, dwarf: *Dwarf, len: u64) UpdateError!void { | 387 | fn resize(sec: *Section, dwarf: *Dwarf, len: u64) UpdateError!void { |
| 376 | if (len <= sec.len) return; | 388 | if (len <= sec.len) return; |
| 377 | if (dwarf.bin_file.cast(.elf)) |elf_file| { | 389 | if (dwarf.bin_file.cast(.elf)) |elf_file| { |
| 390 | const zo = elf_file.zigObjectPtr().?; | ||
| 391 | const atom = zo.symbol(sec.index).atom(elf_file).?; | ||
| 392 | const shndx = atom.output_section_index; | ||
| 378 | if (sec == &dwarf.debug_frame.section) | 393 | if (sec == &dwarf.debug_frame.section) |
| 379 | try elf_file.growAllocSection(sec.index, len) | 394 | try elf_file.growAllocSection(shndx, len, sec.alignment.toByteUnits().?) |
| 380 | else | 395 | else |
| 381 | try elf_file.growNonAllocSection(sec.index, len, @intCast(sec.alignment.toByteUnits().?), true); | 396 | try elf_file.growNonAllocSection(shndx, len, sec.alignment.toByteUnits().?, true); |
| 382 | const shdr = &elf_file.sections.items(.shdr)[sec.index]; | 397 | const shdr = elf_file.sections.items(.shdr)[shndx]; |
| 383 | sec.off = shdr.sh_offset; | 398 | atom.size = shdr.sh_size; |
| 399 | atom.alignment = InternPool.Alignment.fromNonzeroByteUnits(shdr.sh_addralign); | ||
| 384 | sec.len = shdr.sh_size; | 400 | sec.len = shdr.sh_size; |
| 385 | } else if (dwarf.bin_file.cast(.macho)) |macho_file| { | 401 | } else if (dwarf.bin_file.cast(.macho)) |macho_file| { |
| 386 | const header = if (macho_file.d_sym) |*d_sym| header: { | 402 | const header = if (macho_file.d_sym) |*d_sym| header: { |
| ... | @@ -390,7 +406,6 @@ pub const Section = struct { | ... | @@ -390,7 +406,6 @@ pub const Section = struct { |
| 390 | try macho_file.growSection(@intCast(sec.index), len); | 406 | try macho_file.growSection(@intCast(sec.index), len); |
| 391 | break :header &macho_file.sections.items(.header)[sec.index]; | 407 | break :header &macho_file.sections.items(.header)[sec.index]; |
| 392 | }; | 408 | }; |
| 393 | sec.off = header.offset; | ||
| 394 | sec.len = header.size; | 409 | sec.len = header.size; |
| 395 | } | 410 | } |
| 396 | } | 411 | } |
| ... | @@ -399,18 +414,21 @@ pub const Section = struct { | ... | @@ -399,18 +414,21 @@ pub const Section = struct { |
| 399 | const len = sec.getUnit(sec.first.unwrap() orelse return).off; | 414 | const len = sec.getUnit(sec.first.unwrap() orelse return).off; |
| 400 | if (len == 0) return; | 415 | if (len == 0) return; |
| 401 | for (sec.units.items) |*unit| unit.off -= len; | 416 | for (sec.units.items) |*unit| unit.off -= len; |
| 402 | sec.off += len; | ||
| 403 | sec.len -= len; | 417 | sec.len -= len; |
| 404 | if (dwarf.bin_file.cast(.elf)) |elf_file| { | 418 | if (dwarf.bin_file.cast(.elf)) |elf_file| { |
| 405 | const shdr = &elf_file.sections.items(.shdr)[sec.index]; | 419 | const zo = elf_file.zigObjectPtr().?; |
| 406 | shdr.sh_offset = sec.off; | 420 | const atom = zo.symbol(sec.index).atom(elf_file).?; |
| 421 | const shndx = atom.output_section_index; | ||
| 422 | const shdr = &elf_file.sections.items(.shdr)[shndx]; | ||
| 423 | atom.size = sec.len; | ||
| 424 | shdr.sh_offset += len; | ||
| 407 | shdr.sh_size = sec.len; | 425 | shdr.sh_size = sec.len; |
| 408 | } else if (dwarf.bin_file.cast(.macho)) |macho_file| { | 426 | } else if (dwarf.bin_file.cast(.macho)) |macho_file| { |
| 409 | const header = if (macho_file.d_sym) |*d_sym| | 427 | const header = if (macho_file.d_sym) |*d_sym| |
| 410 | &d_sym.sections.items[sec.index] | 428 | &d_sym.sections.items[sec.index] |
| 411 | else | 429 | else |
| 412 | &macho_file.sections.items(.header)[sec.index]; | 430 | &macho_file.sections.items(.header)[sec.index]; |
| 413 | header.offset = @intCast(sec.off); | 431 | header.offset += @intCast(len); |
| 414 | header.size = sec.len; | 432 | header.size = sec.len; |
| 415 | } | 433 | } |
| 416 | } | 434 | } |
| ... | @@ -539,9 +557,9 @@ const Unit = struct { | ... | @@ -539,9 +557,9 @@ const Unit = struct { |
| 539 | fn move(unit: *Unit, sec: *Section, dwarf: *Dwarf, new_off: u32) UpdateError!void { | 557 | fn move(unit: *Unit, sec: *Section, dwarf: *Dwarf, new_off: u32) UpdateError!void { |
| 540 | if (unit.off == new_off) return; | 558 | if (unit.off == new_off) return; |
| 541 | if (try dwarf.getFile().?.copyRangeAll( | 559 | if (try dwarf.getFile().?.copyRangeAll( |
| 542 | sec.off + unit.off, | 560 | sec.off(dwarf) + unit.off, |
| 543 | dwarf.getFile().?, | 561 | dwarf.getFile().?, |
| 544 | sec.off + new_off, | 562 | sec.off(dwarf) + new_off, |
| 545 | unit.len, | 563 | unit.len, |
| 546 | ) != unit.len) return error.InputOutput; | 564 | ) != unit.len) return error.InputOutput; |
| 547 | unit.off = new_off; | 565 | unit.off = new_off; |
| ... | @@ -573,7 +591,7 @@ const Unit = struct { | ... | @@ -573,7 +591,7 @@ const Unit = struct { |
| 573 | 591 | ||
| 574 | fn replaceHeader(unit: *Unit, sec: *Section, dwarf: *Dwarf, contents: []const u8) UpdateError!void { | 592 | fn replaceHeader(unit: *Unit, sec: *Section, dwarf: *Dwarf, contents: []const u8) UpdateError!void { |
| 575 | assert(contents.len == unit.header_len); | 593 | assert(contents.len == unit.header_len); |
| 576 | try dwarf.getFile().?.pwriteAll(contents, sec.off + unit.off); | 594 | try dwarf.getFile().?.pwriteAll(contents, sec.off(dwarf) + unit.off); |
| 577 | } | 595 | } |
| 578 | 596 | ||
| 579 | fn writeTrailer(unit: *Unit, sec: *Section, dwarf: *Dwarf) UpdateError!void { | 597 | fn writeTrailer(unit: *Unit, sec: *Section, dwarf: *Dwarf) UpdateError!void { |
| ... | @@ -605,7 +623,7 @@ const Unit = struct { | ... | @@ -605,7 +623,7 @@ const Unit = struct { |
| 605 | assert(fbs.pos == extended_op_bytes + op_len_bytes); | 623 | assert(fbs.pos == extended_op_bytes + op_len_bytes); |
| 606 | writer.writeByte(DW.LNE.padding) catch unreachable; | 624 | writer.writeByte(DW.LNE.padding) catch unreachable; |
| 607 | assert(fbs.pos >= unit.trailer_len and fbs.pos <= len); | 625 | assert(fbs.pos >= unit.trailer_len and fbs.pos <= len); |
| 608 | return dwarf.getFile().?.pwriteAll(fbs.getWritten(), sec.off + start); | 626 | return dwarf.getFile().?.pwriteAll(fbs.getWritten(), sec.off(dwarf) + start); |
| 609 | } | 627 | } |
| 610 | var trailer = try std.ArrayList(u8).initCapacity(dwarf.gpa, len); | 628 | var trailer = try std.ArrayList(u8).initCapacity(dwarf.gpa, len); |
| 611 | defer trailer.deinit(); | 629 | defer trailer.deinit(); |
| ... | @@ -664,11 +682,11 @@ const Unit = struct { | ... | @@ -664,11 +682,11 @@ const Unit = struct { |
| 664 | assert(trailer.items.len == unit.trailer_len); | 682 | assert(trailer.items.len == unit.trailer_len); |
| 665 | trailer.appendNTimesAssumeCapacity(fill_byte, len - unit.trailer_len); | 683 | trailer.appendNTimesAssumeCapacity(fill_byte, len - unit.trailer_len); |
| 666 | assert(trailer.items.len == len); | 684 | assert(trailer.items.len == len); |
| 667 | try dwarf.getFile().?.pwriteAll(trailer.items, sec.off + start); | 685 | try dwarf.getFile().?.pwriteAll(trailer.items, sec.off(dwarf) + start); |
| 668 | } | 686 | } |
| 669 | 687 | ||
| 670 | fn resolveRelocs(unit: *Unit, sec: *Section, dwarf: *Dwarf) RelocError!void { | 688 | fn resolveRelocs(unit: *Unit, sec: *Section, dwarf: *Dwarf) RelocError!void { |
| 671 | const unit_off = sec.off + unit.off; | 689 | const unit_off = sec.off(dwarf) + unit.off; |
| 672 | for (unit.cross_unit_relocs.items) |reloc| { | 690 | for (unit.cross_unit_relocs.items) |reloc| { |
| 673 | const target_unit = sec.getUnit(reloc.target_unit); | 691 | const target_unit = sec.getUnit(reloc.target_unit); |
| 674 | try dwarf.resolveReloc( | 692 | try dwarf.resolveReloc( |
| ... | @@ -755,12 +773,12 @@ const Entry = struct { | ... | @@ -755,12 +773,12 @@ const Entry = struct { |
| 755 | dwarf.writeInt(unit_len[0..dwarf.sectionOffsetBytes()], len - dwarf.unitLengthBytes()); | 773 | dwarf.writeInt(unit_len[0..dwarf.sectionOffsetBytes()], len - dwarf.unitLengthBytes()); |
| 756 | try dwarf.getFile().?.pwriteAll( | 774 | try dwarf.getFile().?.pwriteAll( |
| 757 | unit_len[0..dwarf.sectionOffsetBytes()], | 775 | unit_len[0..dwarf.sectionOffsetBytes()], |
| 758 | sec.off + unit.off + unit.header_len + entry.off, | 776 | sec.off(dwarf) + unit.off + unit.header_len + entry.off, |
| 759 | ); | 777 | ); |
| 760 | const buf = try dwarf.gpa.alloc(u8, len - entry.len); | 778 | const buf = try dwarf.gpa.alloc(u8, len - entry.len); |
| 761 | defer dwarf.gpa.free(buf); | 779 | defer dwarf.gpa.free(buf); |
| 762 | @memset(buf, DW.CFA.nop); | 780 | @memset(buf, DW.CFA.nop); |
| 763 | try dwarf.getFile().?.pwriteAll(buf, sec.off + unit.off + unit.header_len + start); | 781 | try dwarf.getFile().?.pwriteAll(buf, sec.off(dwarf) + unit.off + unit.header_len + start); |
| 764 | return; | 782 | return; |
| 765 | } | 783 | } |
| 766 | const len = unit.getEntry(entry.next.unwrap() orelse return).off - start; | 784 | const len = unit.getEntry(entry.next.unwrap() orelse return).off - start; |
| ... | @@ -816,7 +834,7 @@ const Entry = struct { | ... | @@ -816,7 +834,7 @@ const Entry = struct { |
| 816 | }, | 834 | }, |
| 817 | } else assert(!sec.pad_to_ideal and len == 0); | 835 | } else assert(!sec.pad_to_ideal and len == 0); |
| 818 | assert(fbs.pos <= len); | 836 | assert(fbs.pos <= len); |
| 819 | try dwarf.getFile().?.pwriteAll(fbs.getWritten(), sec.off + unit.off + unit.header_len + start); | 837 | try dwarf.getFile().?.pwriteAll(fbs.getWritten(), sec.off(dwarf) + unit.off + unit.header_len + start); |
| 820 | } | 838 | } |
| 821 | 839 | ||
| 822 | fn resize(entry_ptr: *Entry, unit: *Unit, sec: *Section, dwarf: *Dwarf, len: u32) UpdateError!void { | 840 | fn resize(entry_ptr: *Entry, unit: *Unit, sec: *Section, dwarf: *Dwarf, len: u32) UpdateError!void { |
| ... | @@ -851,15 +869,15 @@ const Entry = struct { | ... | @@ -851,15 +869,15 @@ const Entry = struct { |
| 851 | 869 | ||
| 852 | fn replace(entry_ptr: *Entry, unit: *Unit, sec: *Section, dwarf: *Dwarf, contents: []const u8) UpdateError!void { | 870 | fn replace(entry_ptr: *Entry, unit: *Unit, sec: *Section, dwarf: *Dwarf, contents: []const u8) UpdateError!void { |
| 853 | assert(contents.len == entry_ptr.len); | 871 | assert(contents.len == entry_ptr.len); |
| 854 | try dwarf.getFile().?.pwriteAll(contents, sec.off + unit.off + unit.header_len + entry_ptr.off); | 872 | try dwarf.getFile().?.pwriteAll(contents, sec.off(dwarf) + unit.off + unit.header_len + entry_ptr.off); |
| 855 | if (false) { | 873 | if (false) { |
| 856 | const buf = try dwarf.gpa.alloc(u8, sec.len); | 874 | const buf = try dwarf.gpa.alloc(u8, sec.len); |
| 857 | defer dwarf.gpa.free(buf); | 875 | defer dwarf.gpa.free(buf); |
| 858 | _ = try dwarf.getFile().?.preadAll(buf, sec.off); | 876 | _ = try dwarf.getFile().?.preadAll(buf, sec.off(dwarf)); |
| 859 | log.info("Section{{ .first = {}, .last = {}, .off = 0x{x}, .len = 0x{x} }}", .{ | 877 | log.info("Section{{ .first = {}, .last = {}, .off = 0x{x}, .len = 0x{x} }}", .{ |
| 860 | @intFromEnum(sec.first), | 878 | @intFromEnum(sec.first), |
| 861 | @intFromEnum(sec.last), | 879 | @intFromEnum(sec.last), |
| 862 | sec.off, | 880 | sec.off(dwarf), |
| 863 | sec.len, | 881 | sec.len, |
| 864 | }); | 882 | }); |
| 865 | for (sec.units.items) |*unit_ptr| { | 883 | for (sec.units.items) |*unit_ptr| { |
| ... | @@ -891,9 +909,11 @@ const Entry = struct { | ... | @@ -891,9 +909,11 @@ const Entry = struct { |
| 891 | if (std.debug.runtime_safety) { | 909 | if (std.debug.runtime_safety) { |
| 892 | log.err("missing {} from {s}", .{ | 910 | log.err("missing {} from {s}", .{ |
| 893 | @as(Entry.Index, @enumFromInt(entry - unit.entries.items.ptr)), | 911 | @as(Entry.Index, @enumFromInt(entry - unit.entries.items.ptr)), |
| 894 | std.mem.sliceTo(if (dwarf.bin_file.cast(.elf)) |elf_file| | 912 | std.mem.sliceTo(if (dwarf.bin_file.cast(.elf)) |elf_file| sh_name: { |
| 895 | elf_file.shstrtab.items[elf_file.sections.items(.shdr)[sec.index].sh_name..] | 913 | const zo = elf_file.zigObjectPtr().?; |
| 896 | else if (dwarf.bin_file.cast(.macho)) |macho_file| | 914 | const shndx = zo.symbol(sec.index).atom(elf_file).?.output_section_index; |
| 915 | break :sh_name elf_file.shstrtab.items[elf_file.sections.items(.shdr)[shndx].sh_name..]; | ||
| 916 | } else if (dwarf.bin_file.cast(.macho)) |macho_file| | ||
| 897 | if (macho_file.d_sym) |*d_sym| | 917 | if (macho_file.d_sym) |*d_sym| |
| 898 | &d_sym.sections.items[sec.index].segname | 918 | &d_sym.sections.items[sec.index].segname |
| 899 | else | 919 | else |
| ... | @@ -924,7 +944,7 @@ const Entry = struct { | ... | @@ -924,7 +944,7 @@ const Entry = struct { |
| 924 | } | 944 | } |
| 925 | 945 | ||
| 926 | fn resolveRelocs(entry: *Entry, unit: *Unit, sec: *Section, dwarf: *Dwarf) RelocError!void { | 946 | fn resolveRelocs(entry: *Entry, unit: *Unit, sec: *Section, dwarf: *Dwarf) RelocError!void { |
| 927 | const entry_off = sec.off + unit.off + unit.header_len + entry.off; | 947 | const entry_off = sec.off(dwarf) + unit.off + unit.header_len + entry.off; |
| 928 | for (entry.cross_entry_relocs.items) |reloc| { | 948 | for (entry.cross_entry_relocs.items) |reloc| { |
| 929 | try dwarf.resolveReloc( | 949 | try dwarf.resolveReloc( |
| 930 | entry_off + reloc.source_off, | 950 | entry_off + reloc.source_off, |
| ... | @@ -961,7 +981,8 @@ const Entry = struct { | ... | @@ -961,7 +981,8 @@ const Entry = struct { |
| 961 | .none, .debug_frame => {}, | 981 | .none, .debug_frame => {}, |
| 962 | .eh_frame => return if (dwarf.bin_file.cast(.elf)) |elf_file| { | 982 | .eh_frame => return if (dwarf.bin_file.cast(.elf)) |elf_file| { |
| 963 | const zo = elf_file.zigObjectPtr().?; | 983 | const zo = elf_file.zigObjectPtr().?; |
| 964 | const entry_addr: i64 = @intCast(entry_off - sec.off + elf_file.shdrs.items[sec.index].sh_addr); | 984 | const shndx = zo.symbol(sec.index).atom(elf_file).?.output_section_index; |
| 985 | const entry_addr: i64 = @intCast(entry_off - sec.off(dwarf) + elf_file.shdrs.items[shndx].sh_addr); | ||
| 965 | for (entry.external_relocs.items) |reloc| { | 986 | for (entry.external_relocs.items) |reloc| { |
| 966 | const symbol = zo.symbol(reloc.target_sym); | 987 | const symbol = zo.symbol(reloc.target_sym); |
| 967 | try dwarf.resolveReloc( | 988 | try dwarf.resolveReloc( |
| ... | @@ -1877,34 +1898,7 @@ pub fn init(lf: *link.File, format: DW.Format) Dwarf { | ... | @@ -1877,34 +1898,7 @@ pub fn init(lf: *link.File, format: DW.Format) Dwarf { |
| 1877 | } | 1898 | } |
| 1878 | 1899 | ||
| 1879 | pub fn reloadSectionMetadata(dwarf: *Dwarf) void { | 1900 | pub fn reloadSectionMetadata(dwarf: *Dwarf) void { |
| 1880 | if (dwarf.bin_file.cast(.elf)) |elf_file| { | 1901 | if (dwarf.bin_file.cast(.macho)) |macho_file| { |
| 1881 | for ([_]*Section{ | ||
| 1882 | &dwarf.debug_abbrev.section, | ||
| 1883 | &dwarf.debug_aranges.section, | ||
| 1884 | &dwarf.debug_frame.section, | ||
| 1885 | &dwarf.debug_info.section, | ||
| 1886 | &dwarf.debug_line.section, | ||
| 1887 | &dwarf.debug_line_str.section, | ||
| 1888 | &dwarf.debug_loclists.section, | ||
| 1889 | &dwarf.debug_rnglists.section, | ||
| 1890 | &dwarf.debug_str.section, | ||
| 1891 | }, [_]u32{ | ||
| 1892 | elf_file.debug_abbrev_section_index.?, | ||
| 1893 | elf_file.debug_aranges_section_index.?, | ||
| 1894 | elf_file.eh_frame_section_index.?, | ||
| 1895 | elf_file.debug_info_section_index.?, | ||
| 1896 | elf_file.debug_line_section_index.?, | ||
| 1897 | elf_file.debug_line_str_section_index.?, | ||
| 1898 | elf_file.debug_loclists_section_index.?, | ||
| 1899 | elf_file.debug_rnglists_section_index.?, | ||
| 1900 | elf_file.debug_str_section_index.?, | ||
| 1901 | }) |sec, section_index| { | ||
| 1902 | const shdr = &elf_file.sections.items(.shdr)[section_index]; | ||
| 1903 | sec.index = section_index; | ||
| 1904 | sec.off = shdr.sh_offset; | ||
| 1905 | sec.len = shdr.sh_size; | ||
| 1906 | } | ||
| 1907 | } else if (dwarf.bin_file.cast(.macho)) |macho_file| { | ||
| 1908 | if (macho_file.d_sym) |*d_sym| { | 1902 | if (macho_file.d_sym) |*d_sym| { |
| 1909 | for ([_]*Section{ | 1903 | for ([_]*Section{ |
| 1910 | &dwarf.debug_abbrev.section, | 1904 | &dwarf.debug_abbrev.section, |
| ... | @@ -1927,7 +1921,6 @@ pub fn reloadSectionMetadata(dwarf: *Dwarf) void { | ... | @@ -1927,7 +1921,6 @@ pub fn reloadSectionMetadata(dwarf: *Dwarf) void { |
| 1927 | }) |sec, sect_index| { | 1921 | }) |sec, sect_index| { |
| 1928 | const header = &d_sym.sections.items[sect_index]; | 1922 | const header = &d_sym.sections.items[sect_index]; |
| 1929 | sec.index = sect_index; | 1923 | sec.index = sect_index; |
| 1930 | sec.off = header.offset; | ||
| 1931 | sec.len = header.size; | 1924 | sec.len = header.size; |
| 1932 | } | 1925 | } |
| 1933 | } else { | 1926 | } else { |
| ... | @@ -1952,7 +1945,6 @@ pub fn reloadSectionMetadata(dwarf: *Dwarf) void { | ... | @@ -1952,7 +1945,6 @@ pub fn reloadSectionMetadata(dwarf: *Dwarf) void { |
| 1952 | }) |sec, sect_index| { | 1945 | }) |sec, sect_index| { |
| 1953 | const header = &macho_file.sections.items(.header)[sect_index]; | 1946 | const header = &macho_file.sections.items(.header)[sect_index]; |
| 1954 | sec.index = sect_index; | 1947 | sec.index = sect_index; |
| 1955 | sec.off = header.offset; | ||
| 1956 | sec.len = header.size; | 1948 | sec.len = header.size; |
| 1957 | } | 1949 | } |
| 1958 | } | 1950 | } |
| ... | @@ -1960,6 +1952,32 @@ pub fn reloadSectionMetadata(dwarf: *Dwarf) void { | ... | @@ -1960,6 +1952,32 @@ pub fn reloadSectionMetadata(dwarf: *Dwarf) void { |
| 1960 | } | 1952 | } |
| 1961 | 1953 | ||
| 1962 | pub fn initMetadata(dwarf: *Dwarf) UpdateError!void { | 1954 | pub fn initMetadata(dwarf: *Dwarf) UpdateError!void { |
| 1955 | if (dwarf.bin_file.cast(.elf)) |elf_file| { | ||
| 1956 | const zo = elf_file.zigObjectPtr().?; | ||
| 1957 | for ([_]*Section{ | ||
| 1958 | &dwarf.debug_abbrev.section, | ||
| 1959 | &dwarf.debug_aranges.section, | ||
| 1960 | &dwarf.debug_frame.section, | ||
| 1961 | &dwarf.debug_info.section, | ||
| 1962 | &dwarf.debug_line.section, | ||
| 1963 | &dwarf.debug_line_str.section, | ||
| 1964 | &dwarf.debug_loclists.section, | ||
| 1965 | &dwarf.debug_rnglists.section, | ||
| 1966 | &dwarf.debug_str.section, | ||
| 1967 | }, [_]u32{ | ||
| 1968 | zo.debug_abbrev_index.?, | ||
| 1969 | zo.debug_aranges_index.?, | ||
| 1970 | zo.eh_frame_index.?, | ||
| 1971 | zo.debug_info_index.?, | ||
| 1972 | zo.debug_line_index.?, | ||
| 1973 | zo.debug_line_str_index.?, | ||
| 1974 | zo.debug_loclists_index.?, | ||
| 1975 | zo.debug_rnglists_index.?, | ||
| 1976 | zo.debug_str_index.?, | ||
| 1977 | }) |sec, sym_index| { | ||
| 1978 | sec.index = sym_index; | ||
| 1979 | } | ||
| 1980 | } | ||
| 1963 | dwarf.reloadSectionMetadata(); | 1981 | dwarf.reloadSectionMetadata(); |
| 1964 | 1982 | ||
| 1965 | dwarf.debug_abbrev.section.pad_to_ideal = false; | 1983 | dwarf.debug_abbrev.section.pad_to_ideal = false; |
| ... | @@ -2523,7 +2541,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool | ... | @@ -2523,7 +2541,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool |
| 2523 | var abbrev_code_buf: [AbbrevCode.decl_bytes]u8 = undefined; | 2541 | var abbrev_code_buf: [AbbrevCode.decl_bytes]u8 = undefined; |
| 2524 | if (try dwarf.getFile().?.preadAll( | 2542 | if (try dwarf.getFile().?.preadAll( |
| 2525 | &abbrev_code_buf, | 2543 | &abbrev_code_buf, |
| 2526 | dwarf.debug_info.section.off + unit_ptr.off + unit_ptr.header_len + entry_ptr.off, | 2544 | dwarf.debug_info.section.off(dwarf) + unit_ptr.off + unit_ptr.header_len + entry_ptr.off, |
| 2527 | ) != abbrev_code_buf.len) return error.InputOutput; | 2545 | ) != abbrev_code_buf.len) return error.InputOutput; |
| 2528 | var abbrev_code_fbs = std.io.fixedBufferStream(&abbrev_code_buf); | 2546 | var abbrev_code_fbs = std.io.fixedBufferStream(&abbrev_code_buf); |
| 2529 | const abbrev_code: AbbrevCode = @enumFromInt( | 2547 | const abbrev_code: AbbrevCode = @enumFromInt( |
| ... | @@ -3934,7 +3952,7 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { | ... | @@ -3934,7 +3952,7 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { |
| 3934 | if (dwarf.debug_str.section.dirty) { | 3952 | if (dwarf.debug_str.section.dirty) { |
| 3935 | const contents = dwarf.debug_str.contents.items; | 3953 | const contents = dwarf.debug_str.contents.items; |
| 3936 | try dwarf.debug_str.section.resize(dwarf, contents.len); | 3954 | try dwarf.debug_str.section.resize(dwarf, contents.len); |
| 3937 | try dwarf.getFile().?.pwriteAll(contents, dwarf.debug_str.section.off); | 3955 | try dwarf.getFile().?.pwriteAll(contents, dwarf.debug_str.section.off(dwarf)); |
| 3938 | dwarf.debug_str.section.dirty = false; | 3956 | dwarf.debug_str.section.dirty = false; |
| 3939 | } | 3957 | } |
| 3940 | if (dwarf.debug_line.section.dirty) { | 3958 | if (dwarf.debug_line.section.dirty) { |
| ... | @@ -4040,7 +4058,7 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { | ... | @@ -4040,7 +4058,7 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { |
| 4040 | if (dwarf.debug_line_str.section.dirty) { | 4058 | if (dwarf.debug_line_str.section.dirty) { |
| 4041 | const contents = dwarf.debug_line_str.contents.items; | 4059 | const contents = dwarf.debug_line_str.contents.items; |
| 4042 | try dwarf.debug_line_str.section.resize(dwarf, contents.len); | 4060 | try dwarf.debug_line_str.section.resize(dwarf, contents.len); |
| 4043 | try dwarf.getFile().?.pwriteAll(contents, dwarf.debug_line_str.section.off); | 4061 | try dwarf.getFile().?.pwriteAll(contents, dwarf.debug_line_str.section.off(dwarf)); |
| 4044 | dwarf.debug_line_str.section.dirty = false; | 4062 | dwarf.debug_line_str.section.dirty = false; |
| 4045 | } | 4063 | } |
| 4046 | if (dwarf.debug_loclists.section.dirty) { | 4064 | if (dwarf.debug_loclists.section.dirty) { |
src/link/Elf.zig+328-293| ... | @@ -54,16 +54,6 @@ shdr_table_offset: ?u64 = null, | ... | @@ -54,16 +54,6 @@ shdr_table_offset: ?u64 = null, |
| 54 | /// Same order as in the file. | 54 | /// Same order as in the file. |
| 55 | phdrs: std.ArrayListUnmanaged(elf.Elf64_Phdr) = .{}, | 55 | phdrs: std.ArrayListUnmanaged(elf.Elf64_Phdr) = .{}, |
| 56 | 56 | ||
| 57 | /// Tracked loadable segments during incremental linking. | ||
| 58 | /// The index into the program headers of a PT_LOAD program header with Read and Execute flags | ||
| 59 | phdr_zig_load_re_index: ?u16 = null, | ||
| 60 | /// The index into the program headers of a PT_LOAD program header with Read flag | ||
| 61 | phdr_zig_load_ro_index: ?u16 = null, | ||
| 62 | /// The index into the program headers of a PT_LOAD program header with Write flag | ||
| 63 | phdr_zig_load_rw_index: ?u16 = null, | ||
| 64 | /// The index into the program headers of a PT_LOAD program header with zerofill data. | ||
| 65 | phdr_zig_load_zerofill_index: ?u16 = null, | ||
| 66 | |||
| 67 | /// Special program headers | 57 | /// Special program headers |
| 68 | /// PT_PHDR | 58 | /// PT_PHDR |
| 69 | phdr_table_index: ?u16 = null, | 59 | phdr_table_index: ?u16 = null, |
| ... | @@ -124,22 +114,6 @@ rela_plt: std.ArrayListUnmanaged(elf.Elf64_Rela) = .{}, | ... | @@ -124,22 +114,6 @@ rela_plt: std.ArrayListUnmanaged(elf.Elf64_Rela) = .{}, |
| 124 | /// Applies only to a relocatable. | 114 | /// Applies only to a relocatable. |
| 125 | comdat_group_sections: std.ArrayListUnmanaged(ComdatGroupSection) = .{}, | 115 | comdat_group_sections: std.ArrayListUnmanaged(ComdatGroupSection) = .{}, |
| 126 | 116 | ||
| 127 | /// Tracked section headers with incremental updates to Zig object. | ||
| 128 | /// .rela.* sections are only used when emitting a relocatable object file. | ||
| 129 | zig_text_section_index: ?u32 = null, | ||
| 130 | zig_data_rel_ro_section_index: ?u32 = null, | ||
| 131 | zig_data_section_index: ?u32 = null, | ||
| 132 | zig_bss_section_index: ?u32 = null, | ||
| 133 | |||
| 134 | debug_info_section_index: ?u32 = null, | ||
| 135 | debug_abbrev_section_index: ?u32 = null, | ||
| 136 | debug_str_section_index: ?u32 = null, | ||
| 137 | debug_aranges_section_index: ?u32 = null, | ||
| 138 | debug_line_section_index: ?u32 = null, | ||
| 139 | debug_line_str_section_index: ?u32 = null, | ||
| 140 | debug_loclists_section_index: ?u32 = null, | ||
| 141 | debug_rnglists_section_index: ?u32 = null, | ||
| 142 | |||
| 143 | copy_rel_section_index: ?u32 = null, | 117 | copy_rel_section_index: ?u32 = null, |
| 144 | dynamic_section_index: ?u32 = null, | 118 | dynamic_section_index: ?u32 = null, |
| 145 | dynstrtab_section_index: ?u32 = null, | 119 | dynstrtab_section_index: ?u32 = null, |
| ... | @@ -419,7 +393,8 @@ pub fn deinit(self: *Elf) void { | ... | @@ -419,7 +393,8 @@ pub fn deinit(self: *Elf) void { |
| 419 | self.objects.deinit(gpa); | 393 | self.objects.deinit(gpa); |
| 420 | self.shared_objects.deinit(gpa); | 394 | self.shared_objects.deinit(gpa); |
| 421 | 395 | ||
| 422 | for (self.sections.items(.atom_list), self.sections.items(.free_list)) |*atoms, *free_list| { | 396 | for (self.sections.items(.atom_list_2), self.sections.items(.atom_list), self.sections.items(.free_list)) |*atom_list, *atoms, *free_list| { |
| 397 | atom_list.deinit(gpa); | ||
| 423 | atoms.deinit(gpa); | 398 | atoms.deinit(gpa); |
| 424 | free_list.deinit(gpa); | 399 | free_list.deinit(gpa); |
| 425 | } | 400 | } |
| ... | @@ -554,7 +529,7 @@ pub fn findFreeSpace(self: *Elf, object_size: u64, min_alignment: u64) !u64 { | ... | @@ -554,7 +529,7 @@ pub fn findFreeSpace(self: *Elf, object_size: u64, min_alignment: u64) !u64 { |
| 554 | return start; | 529 | return start; |
| 555 | } | 530 | } |
| 556 | 531 | ||
| 557 | pub fn growAllocSection(self: *Elf, shdr_index: u32, needed_size: u64) !void { | 532 | pub fn growAllocSection(self: *Elf, shdr_index: u32, needed_size: u64, min_alignment: u64) !void { |
| 558 | const slice = self.sections.slice(); | 533 | const slice = self.sections.slice(); |
| 559 | const shdr = &slice.items(.shdr)[shdr_index]; | 534 | const shdr = &slice.items(.shdr)[shdr_index]; |
| 560 | assert(shdr.sh_flags & elf.SHF_ALLOC != 0); | 535 | assert(shdr.sh_flags & elf.SHF_ALLOC != 0); |
| ... | @@ -573,8 +548,7 @@ pub fn growAllocSection(self: *Elf, shdr_index: u32, needed_size: u64) !void { | ... | @@ -573,8 +548,7 @@ pub fn growAllocSection(self: *Elf, shdr_index: u32, needed_size: u64) !void { |
| 573 | const existing_size = shdr.sh_size; | 548 | const existing_size = shdr.sh_size; |
| 574 | shdr.sh_size = 0; | 549 | shdr.sh_size = 0; |
| 575 | // Must move the entire section. | 550 | // Must move the entire section. |
| 576 | const alignment = if (maybe_phdr) |phdr| phdr.p_align else shdr.sh_addralign; | 551 | const new_offset = try self.findFreeSpace(needed_size, min_alignment); |
| 577 | const new_offset = try self.findFreeSpace(needed_size, alignment); | ||
| 578 | 552 | ||
| 579 | log.debug("new '{s}' file offset 0x{x} to 0x{x}", .{ | 553 | log.debug("new '{s}' file offset 0x{x} to 0x{x}", .{ |
| 580 | self.getShString(shdr.sh_name), | 554 | self.getShString(shdr.sh_name), |
| ... | @@ -614,7 +588,7 @@ pub fn growNonAllocSection( | ... | @@ -614,7 +588,7 @@ pub fn growNonAllocSection( |
| 614 | self: *Elf, | 588 | self: *Elf, |
| 615 | shdr_index: u32, | 589 | shdr_index: u32, |
| 616 | needed_size: u64, | 590 | needed_size: u64, |
| 617 | min_alignment: u32, | 591 | min_alignment: u64, |
| 618 | requires_file_copy: bool, | 592 | requires_file_copy: bool, |
| 619 | ) !void { | 593 | ) !void { |
| 620 | const shdr = &self.sections.items(.shdr)[shdr_index]; | 594 | const shdr = &self.sections.items(.shdr)[shdr_index]; |
| ... | @@ -648,33 +622,124 @@ pub fn growNonAllocSection( | ... | @@ -648,33 +622,124 @@ pub fn growNonAllocSection( |
| 648 | try self.base.file.?.setEndPos(shdr.sh_offset + needed_size); | 622 | try self.base.file.?.setEndPos(shdr.sh_offset + needed_size); |
| 649 | } | 623 | } |
| 650 | shdr.sh_size = needed_size; | 624 | shdr.sh_size = needed_size; |
| 651 | |||
| 652 | self.markDirty(shdr_index); | 625 | self.markDirty(shdr_index); |
| 653 | } | 626 | } |
| 654 | 627 | ||
| 655 | pub fn markDirty(self: *Elf, shdr_index: u32) void { | 628 | pub fn markDirty(self: *Elf, shdr_index: u32) void { |
| 656 | const zig_object = self.zigObjectPtr().?; | 629 | if (self.zigObjectPtr()) |zo| { |
| 657 | if (zig_object.dwarf) |_| { | 630 | for ([_]?Symbol.Index{ |
| 658 | if (self.debug_info_section_index.? == shdr_index) { | 631 | zo.debug_info_index, |
| 659 | zig_object.debug_info_section_dirty = true; | 632 | zo.debug_abbrev_index, |
| 660 | } else if (self.debug_abbrev_section_index.? == shdr_index) { | 633 | zo.debug_aranges_index, |
| 661 | zig_object.debug_abbrev_section_dirty = true; | 634 | zo.debug_str_index, |
| 662 | } else if (self.debug_str_section_index.? == shdr_index) { | 635 | zo.debug_line_index, |
| 663 | zig_object.debug_str_section_dirty = true; | 636 | zo.debug_line_str_index, |
| 664 | } else if (self.debug_aranges_section_index.? == shdr_index) { | 637 | zo.debug_loclists_index, |
| 665 | zig_object.debug_aranges_section_dirty = true; | 638 | zo.debug_rnglists_index, |
| 666 | } else if (self.debug_line_section_index.? == shdr_index) { | 639 | }, [_]*bool{ |
| 667 | zig_object.debug_line_section_dirty = true; | 640 | &zo.debug_info_section_dirty, |
| 668 | } else if (self.debug_line_str_section_index.? == shdr_index) { | 641 | &zo.debug_abbrev_section_dirty, |
| 669 | zig_object.debug_line_str_section_dirty = true; | 642 | &zo.debug_aranges_section_dirty, |
| 670 | } else if (self.debug_loclists_section_index.? == shdr_index) { | 643 | &zo.debug_str_section_dirty, |
| 671 | zig_object.debug_loclists_section_dirty = true; | 644 | &zo.debug_line_section_dirty, |
| 672 | } else if (self.debug_rnglists_section_index.? == shdr_index) { | 645 | &zo.debug_line_str_section_dirty, |
| 673 | zig_object.debug_rnglists_section_dirty = true; | 646 | &zo.debug_loclists_section_dirty, |
| 647 | &zo.debug_rnglists_section_dirty, | ||
| 648 | }) |maybe_sym_index, dirty| { | ||
| 649 | const sym_index = maybe_sym_index orelse continue; | ||
| 650 | if (zo.symbol(sym_index).atom(self).?.output_section_index == shdr_index) { | ||
| 651 | dirty.* = true; | ||
| 652 | break; | ||
| 653 | } | ||
| 674 | } | 654 | } |
| 675 | } | 655 | } |
| 676 | } | 656 | } |
| 677 | 657 | ||
| 658 | const AllocateChunkResult = struct { | ||
| 659 | value: u64, | ||
| 660 | placement: Ref, | ||
| 661 | }; | ||
| 662 | |||
| 663 | pub fn allocateChunk(self: *Elf, args: struct { | ||
| 664 | size: u64, | ||
| 665 | shndx: u32, | ||
| 666 | alignment: Atom.Alignment, | ||
| 667 | requires_padding: bool = true, | ||
| 668 | }) !AllocateChunkResult { | ||
| 669 | const slice = self.sections.slice(); | ||
| 670 | const shdr = &slice.items(.shdr)[args.shndx]; | ||
| 671 | const free_list = &slice.items(.free_list)[args.shndx]; | ||
| 672 | const last_atom_ref = &slice.items(.last_atom)[args.shndx]; | ||
| 673 | const new_atom_ideal_capacity = if (args.requires_padding) padToIdeal(args.size) else args.size; | ||
| 674 | |||
| 675 | // First we look for an appropriately sized free list node. | ||
| 676 | // The list is unordered. We'll just take the first thing that works. | ||
| 677 | const res: AllocateChunkResult = blk: { | ||
| 678 | var i: usize = if (self.base.child_pid == null) 0 else free_list.items.len; | ||
| 679 | while (i < free_list.items.len) { | ||
| 680 | const big_atom_ref = free_list.items[i]; | ||
| 681 | const big_atom = self.atom(big_atom_ref).?; | ||
| 682 | // We now have a pointer to a live atom that has too much capacity. | ||
| 683 | // Is it enough that we could fit this new atom? | ||
| 684 | const cap = big_atom.capacity(self); | ||
| 685 | const ideal_capacity = if (args.requires_padding) padToIdeal(cap) else cap; | ||
| 686 | const ideal_capacity_end_vaddr = std.math.add(u64, @intCast(big_atom.value), ideal_capacity) catch ideal_capacity; | ||
| 687 | const capacity_end_vaddr = @as(u64, @intCast(big_atom.value)) + cap; | ||
| 688 | const new_start_vaddr_unaligned = capacity_end_vaddr - new_atom_ideal_capacity; | ||
| 689 | const new_start_vaddr = args.alignment.backward(new_start_vaddr_unaligned); | ||
| 690 | if (new_start_vaddr < ideal_capacity_end_vaddr) { | ||
| 691 | // Additional bookkeeping here to notice if this free list node | ||
| 692 | // should be deleted because the block that it points to has grown to take up | ||
| 693 | // more of the extra capacity. | ||
| 694 | if (!big_atom.freeListEligible(self)) { | ||
| 695 | _ = free_list.swapRemove(i); | ||
| 696 | } else { | ||
| 697 | i += 1; | ||
| 698 | } | ||
| 699 | continue; | ||
| 700 | } | ||
| 701 | // At this point we know that we will place the new block here. But the | ||
| 702 | // remaining question is whether there is still yet enough capacity left | ||
| 703 | // over for there to still be a free list node. | ||
| 704 | const remaining_capacity = new_start_vaddr - ideal_capacity_end_vaddr; | ||
| 705 | const keep_free_list_node = remaining_capacity >= min_text_capacity; | ||
| 706 | |||
| 707 | if (!keep_free_list_node) { | ||
| 708 | _ = free_list.swapRemove(i); | ||
| 709 | } | ||
| 710 | break :blk .{ .value = new_start_vaddr, .placement = big_atom_ref }; | ||
| 711 | } else if (self.atom(last_atom_ref.*)) |last_atom| { | ||
| 712 | const ideal_capacity = if (args.requires_padding) padToIdeal(last_atom.size) else last_atom.size; | ||
| 713 | const ideal_capacity_end_vaddr = @as(u64, @intCast(last_atom.value)) + ideal_capacity; | ||
| 714 | const new_start_vaddr = args.alignment.forward(ideal_capacity_end_vaddr); | ||
| 715 | break :blk .{ .value = new_start_vaddr, .placement = last_atom.ref() }; | ||
| 716 | } else { | ||
| 717 | break :blk .{ .value = 0, .placement = .{} }; | ||
| 718 | } | ||
| 719 | }; | ||
| 720 | |||
| 721 | log.debug("allocated chunk (size({x}),align({x})) at 0x{x} (file(0x{x}))", .{ | ||
| 722 | args.size, | ||
| 723 | args.alignment.toByteUnits().?, | ||
| 724 | shdr.sh_addr + res.value, | ||
| 725 | shdr.sh_offset + res.value, | ||
| 726 | }); | ||
| 727 | |||
| 728 | const expand_section = if (self.atom(res.placement)) |placement_atom| | ||
| 729 | placement_atom.nextAtom(self) == null | ||
| 730 | else | ||
| 731 | true; | ||
| 732 | if (expand_section) { | ||
| 733 | const needed_size = res.value + args.size; | ||
| 734 | if (shdr.sh_flags & elf.SHF_ALLOC != 0) | ||
| 735 | try self.growAllocSection(args.shndx, needed_size, args.alignment.toByteUnits().?) | ||
| 736 | else | ||
| 737 | try self.growNonAllocSection(args.shndx, needed_size, args.alignment.toByteUnits().?, true); | ||
| 738 | } | ||
| 739 | |||
| 740 | return res; | ||
| 741 | } | ||
| 742 | |||
| 678 | pub fn flush(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void { | 743 | pub fn flush(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void { |
| 679 | const use_lld = build_options.have_llvm and self.base.comp.config.use_lld; | 744 | const use_lld = build_options.have_llvm and self.base.comp.config.use_lld; |
| 680 | if (use_lld) { | 745 | if (use_lld) { |
| ... | @@ -972,14 +1037,13 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod | ... | @@ -972,14 +1037,13 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod |
| 972 | try self.initSyntheticSections(); | 1037 | try self.initSyntheticSections(); |
| 973 | try self.initSpecialPhdrs(); | 1038 | try self.initSpecialPhdrs(); |
| 974 | try self.sortShdrs(); | 1039 | try self.sortShdrs(); |
| 975 | for (self.objects.items) |index| { | 1040 | |
| 976 | try self.file(index).?.object.addAtomsToOutputSections(self); | ||
| 977 | } | ||
| 978 | try self.sortInitFini(); | ||
| 979 | try self.setDynamicSection(rpath_table.keys()); | 1041 | try self.setDynamicSection(rpath_table.keys()); |
| 980 | self.sortDynamicSymtab(); | 1042 | self.sortDynamicSymtab(); |
| 981 | try self.setHashSections(); | 1043 | try self.setHashSections(); |
| 982 | try self.setVersionSymtab(); | 1044 | try self.setVersionSymtab(); |
| 1045 | |||
| 1046 | try self.sortInitFini(); | ||
| 983 | try self.updateMergeSectionSizes(); | 1047 | try self.updateMergeSectionSizes(); |
| 984 | try self.updateSectionSizes(); | 1048 | try self.updateSectionSizes(); |
| 985 | 1049 | ||
| ... | @@ -1010,7 +1074,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod | ... | @@ -1010,7 +1074,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod |
| 1010 | if (shdr.sh_type == elf.SHT_NOBITS) continue; | 1074 | if (shdr.sh_type == elf.SHT_NOBITS) continue; |
| 1011 | const code = try zo.codeAlloc(self, atom_index); | 1075 | const code = try zo.codeAlloc(self, atom_index); |
| 1012 | defer gpa.free(code); | 1076 | defer gpa.free(code); |
| 1013 | const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value)); | 1077 | const file_offset = atom_ptr.offset(self); |
| 1014 | atom_ptr.resolveRelocsAlloc(self, code) catch |err| switch (err) { | 1078 | atom_ptr.resolveRelocsAlloc(self, code) catch |err| switch (err) { |
| 1015 | error.RelocFailure, error.RelaxFailure => has_reloc_errors = true, | 1079 | error.RelocFailure, error.RelaxFailure => has_reloc_errors = true, |
| 1016 | error.UnsupportedCpuArch => { | 1080 | error.UnsupportedCpuArch => { |
| ... | @@ -1750,6 +1814,59 @@ fn scanRelocs(self: *Elf) !void { | ... | @@ -1750,6 +1814,59 @@ fn scanRelocs(self: *Elf) !void { |
| 1750 | } | 1814 | } |
| 1751 | } | 1815 | } |
| 1752 | 1816 | ||
| 1817 | pub fn initOutputSection(self: *Elf, args: struct { | ||
| 1818 | name: [:0]const u8, | ||
| 1819 | flags: u64, | ||
| 1820 | type: u32, | ||
| 1821 | }) error{OutOfMemory}!u32 { | ||
| 1822 | const name = blk: { | ||
| 1823 | if (self.base.isRelocatable()) break :blk args.name; | ||
| 1824 | if (args.flags & elf.SHF_MERGE != 0) break :blk args.name; | ||
| 1825 | const name_prefixes: []const [:0]const u8 = &.{ | ||
| 1826 | ".text", ".data.rel.ro", ".data", ".rodata", ".bss.rel.ro", ".bss", | ||
| 1827 | ".init_array", ".fini_array", ".tbss", ".tdata", ".gcc_except_table", ".ctors", | ||
| 1828 | ".dtors", ".gnu.warning", | ||
| 1829 | }; | ||
| 1830 | inline for (name_prefixes) |prefix| { | ||
| 1831 | if (std.mem.eql(u8, args.name, prefix) or std.mem.startsWith(u8, args.name, prefix ++ ".")) { | ||
| 1832 | break :blk prefix; | ||
| 1833 | } | ||
| 1834 | } | ||
| 1835 | break :blk args.name; | ||
| 1836 | }; | ||
| 1837 | const @"type" = tt: { | ||
| 1838 | if (self.getTarget().cpu.arch == .x86_64 and args.type == elf.SHT_X86_64_UNWIND) | ||
| 1839 | break :tt elf.SHT_PROGBITS; | ||
| 1840 | switch (args.type) { | ||
| 1841 | elf.SHT_NULL => unreachable, | ||
| 1842 | elf.SHT_PROGBITS => { | ||
| 1843 | if (std.mem.eql(u8, args.name, ".init_array") or std.mem.startsWith(u8, args.name, ".init_array.")) | ||
| 1844 | break :tt elf.SHT_INIT_ARRAY; | ||
| 1845 | if (std.mem.eql(u8, args.name, ".fini_array") or std.mem.startsWith(u8, args.name, ".fini_array.")) | ||
| 1846 | break :tt elf.SHT_FINI_ARRAY; | ||
| 1847 | break :tt args.type; | ||
| 1848 | }, | ||
| 1849 | else => break :tt args.type, | ||
| 1850 | } | ||
| 1851 | }; | ||
| 1852 | const flags = blk: { | ||
| 1853 | var flags = args.flags; | ||
| 1854 | if (!self.base.isRelocatable()) { | ||
| 1855 | flags &= ~@as(u64, elf.SHF_COMPRESSED | elf.SHF_GROUP | elf.SHF_GNU_RETAIN); | ||
| 1856 | } | ||
| 1857 | break :blk switch (@"type") { | ||
| 1858 | elf.SHT_INIT_ARRAY, elf.SHT_FINI_ARRAY => flags | elf.SHF_WRITE, | ||
| 1859 | else => flags, | ||
| 1860 | }; | ||
| 1861 | }; | ||
| 1862 | const out_shndx = self.sectionByName(name) orelse try self.addSection(.{ | ||
| 1863 | .type = @"type", | ||
| 1864 | .flags = flags, | ||
| 1865 | .name = try self.insertShString(name), | ||
| 1866 | }); | ||
| 1867 | return out_shndx; | ||
| 1868 | } | ||
| 1869 | |||
| 1753 | fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) !void { | 1870 | fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) !void { |
| 1754 | dev.check(.lld_linker); | 1871 | dev.check(.lld_linker); |
| 1755 | 1872 | ||
| ... | @@ -2783,12 +2900,16 @@ fn initSyntheticSections(self: *Elf) !void { | ... | @@ -2783,12 +2900,16 @@ fn initSyntheticSections(self: *Elf) !void { |
| 2783 | const target = self.getTarget(); | 2900 | const target = self.getTarget(); |
| 2784 | const ptr_size = self.ptrWidthBytes(); | 2901 | const ptr_size = self.ptrWidthBytes(); |
| 2785 | 2902 | ||
| 2786 | const needs_eh_frame = for (self.objects.items) |index| { | 2903 | const needs_eh_frame = blk: { |
| 2787 | if (self.file(index).?.object.cies.items.len > 0) break true; | 2904 | if (self.zigObjectPtr()) |zo| |
| 2788 | } else false; | 2905 | if (zo.eh_frame_index != null) break :blk true; |
| 2906 | break :blk for (self.objects.items) |index| { | ||
| 2907 | if (self.file(index).?.object.cies.items.len > 0) break true; | ||
| 2908 | } else false; | ||
| 2909 | }; | ||
| 2789 | if (needs_eh_frame) { | 2910 | if (needs_eh_frame) { |
| 2790 | if (self.eh_frame_section_index == null) { | 2911 | if (self.eh_frame_section_index == null) { |
| 2791 | self.eh_frame_section_index = try self.addSection(.{ | 2912 | self.eh_frame_section_index = self.sectionByName(".eh_frame") orelse try self.addSection(.{ |
| 2792 | .name = try self.insertShString(".eh_frame"), | 2913 | .name = try self.insertShString(".eh_frame"), |
| 2793 | .type = if (target.cpu.arch == .x86_64) | 2914 | .type = if (target.cpu.arch == .x86_64) |
| 2794 | elf.SHT_X86_64_UNWIND | 2915 | elf.SHT_X86_64_UNWIND |
| ... | @@ -3084,8 +3205,9 @@ fn sortInitFini(self: *Elf) !void { | ... | @@ -3084,8 +3205,9 @@ fn sortInitFini(self: *Elf) !void { |
| 3084 | } | 3205 | } |
| 3085 | }; | 3206 | }; |
| 3086 | 3207 | ||
| 3087 | for (slice.items(.shdr), slice.items(.atom_list)) |shdr, *atom_list| { | 3208 | for (slice.items(.shdr), slice.items(.atom_list_2)) |shdr, *atom_list| { |
| 3088 | if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; | 3209 | if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; |
| 3210 | if (atom_list.atoms.items.len == 0) continue; | ||
| 3089 | 3211 | ||
| 3090 | var is_init_fini = false; | 3212 | var is_init_fini = false; |
| 3091 | var is_ctor_dtor = false; | 3213 | var is_ctor_dtor = false; |
| ... | @@ -3099,15 +3221,13 @@ fn sortInitFini(self: *Elf) !void { | ... | @@ -3099,15 +3221,13 @@ fn sortInitFini(self: *Elf) !void { |
| 3099 | is_ctor_dtor = mem.indexOf(u8, name, ".ctors") != null or mem.indexOf(u8, name, ".dtors") != null; | 3221 | is_ctor_dtor = mem.indexOf(u8, name, ".ctors") != null or mem.indexOf(u8, name, ".dtors") != null; |
| 3100 | }, | 3222 | }, |
| 3101 | } | 3223 | } |
| 3102 | |||
| 3103 | if (!is_init_fini and !is_ctor_dtor) continue; | 3224 | if (!is_init_fini and !is_ctor_dtor) continue; |
| 3104 | if (atom_list.items.len == 0) continue; | ||
| 3105 | 3225 | ||
| 3106 | var entries = std.ArrayList(Entry).init(gpa); | 3226 | var entries = std.ArrayList(Entry).init(gpa); |
| 3107 | try entries.ensureTotalCapacityPrecise(atom_list.items.len); | 3227 | try entries.ensureTotalCapacityPrecise(atom_list.atoms.items.len); |
| 3108 | defer entries.deinit(); | 3228 | defer entries.deinit(); |
| 3109 | 3229 | ||
| 3110 | for (atom_list.items) |ref| { | 3230 | for (atom_list.atoms.items) |ref| { |
| 3111 | const atom_ptr = self.atom(ref).?; | 3231 | const atom_ptr = self.atom(ref).?; |
| 3112 | const object = atom_ptr.file(self).?.object; | 3232 | const object = atom_ptr.file(self).?.object; |
| 3113 | const priority = blk: { | 3233 | const priority = blk: { |
| ... | @@ -3126,9 +3246,9 @@ fn sortInitFini(self: *Elf) !void { | ... | @@ -3126,9 +3246,9 @@ fn sortInitFini(self: *Elf) !void { |
| 3126 | 3246 | ||
| 3127 | mem.sort(Entry, entries.items, self, Entry.lessThan); | 3247 | mem.sort(Entry, entries.items, self, Entry.lessThan); |
| 3128 | 3248 | ||
| 3129 | atom_list.clearRetainingCapacity(); | 3249 | atom_list.atoms.clearRetainingCapacity(); |
| 3130 | for (entries.items) |entry| { | 3250 | for (entries.items) |entry| { |
| 3131 | atom_list.appendAssumeCapacity(entry.atom_ref); | 3251 | atom_list.atoms.appendAssumeCapacity(entry.atom_ref); |
| 3132 | } | 3252 | } |
| 3133 | } | 3253 | } |
| 3134 | } | 3254 | } |
| ... | @@ -3233,9 +3353,6 @@ fn sortPhdrs(self: *Elf) error{OutOfMemory}!void { | ... | @@ -3233,9 +3353,6 @@ fn sortPhdrs(self: *Elf) error{OutOfMemory}!void { |
| 3233 | } | 3353 | } |
| 3234 | 3354 | ||
| 3235 | for (&[_]*?u16{ | 3355 | for (&[_]*?u16{ |
| 3236 | &self.phdr_zig_load_re_index, | ||
| 3237 | &self.phdr_zig_load_ro_index, | ||
| 3238 | &self.phdr_zig_load_zerofill_index, | ||
| 3239 | &self.phdr_table_index, | 3356 | &self.phdr_table_index, |
| 3240 | &self.phdr_table_load_index, | 3357 | &self.phdr_table_load_index, |
| 3241 | &self.phdr_interp_index, | 3358 | &self.phdr_interp_index, |
| ... | @@ -3272,33 +3389,36 @@ fn shdrRank(self: *Elf, shndx: u32) u8 { | ... | @@ -3272,33 +3389,36 @@ fn shdrRank(self: *Elf, shndx: u32) u8 { |
| 3272 | elf.SHT_PREINIT_ARRAY, | 3389 | elf.SHT_PREINIT_ARRAY, |
| 3273 | elf.SHT_INIT_ARRAY, | 3390 | elf.SHT_INIT_ARRAY, |
| 3274 | elf.SHT_FINI_ARRAY, | 3391 | elf.SHT_FINI_ARRAY, |
| 3275 | => return 0xf2, | 3392 | => return 0xf1, |
| 3276 | 3393 | ||
| 3277 | elf.SHT_DYNAMIC => return 0xf3, | 3394 | elf.SHT_DYNAMIC => return 0xf2, |
| 3278 | 3395 | ||
| 3279 | elf.SHT_RELA, elf.SHT_GROUP => return 0xf, | 3396 | elf.SHT_RELA, elf.SHT_GROUP => return 0xf, |
| 3280 | 3397 | ||
| 3281 | elf.SHT_PROGBITS => if (flags & elf.SHF_ALLOC != 0) { | 3398 | elf.SHT_PROGBITS => if (flags & elf.SHF_ALLOC != 0) { |
| 3282 | if (flags & elf.SHF_EXECINSTR != 0) { | 3399 | if (flags & elf.SHF_EXECINSTR != 0) { |
| 3283 | return 0xf1; | 3400 | return 0xf0; |
| 3284 | } else if (flags & elf.SHF_WRITE != 0) { | 3401 | } else if (flags & elf.SHF_WRITE != 0) { |
| 3285 | return if (flags & elf.SHF_TLS != 0) 0xf4 else 0xf6; | 3402 | return if (flags & elf.SHF_TLS != 0) 0xf3 else 0xf5; |
| 3286 | } else if (mem.eql(u8, name, ".interp")) { | 3403 | } else if (mem.eql(u8, name, ".interp")) { |
| 3287 | return 1; | 3404 | return 1; |
| 3405 | } else if (mem.startsWith(u8, name, ".eh_frame")) { | ||
| 3406 | return 0xe1; | ||
| 3288 | } else { | 3407 | } else { |
| 3289 | return 0xf0; | 3408 | return 0xe0; |
| 3290 | } | 3409 | } |
| 3291 | } else { | 3410 | } else { |
| 3292 | if (mem.startsWith(u8, name, ".debug")) { | 3411 | if (mem.startsWith(u8, name, ".debug")) { |
| 3293 | return 0xf8; | 3412 | return 0xf7; |
| 3294 | } else { | 3413 | } else { |
| 3295 | return 0xf9; | 3414 | return 0xf8; |
| 3296 | } | 3415 | } |
| 3297 | }, | 3416 | }, |
| 3417 | elf.SHT_X86_64_UNWIND => return 0xe1, | ||
| 3298 | 3418 | ||
| 3299 | elf.SHT_NOBITS => return if (flags & elf.SHF_TLS != 0) 0xf5 else 0xf7, | 3419 | elf.SHT_NOBITS => return if (flags & elf.SHF_TLS != 0) 0xf4 else 0xf6, |
| 3300 | elf.SHT_SYMTAB => return 0xfa, | 3420 | elf.SHT_SYMTAB => return 0xf9, |
| 3301 | elf.SHT_STRTAB => return if (mem.eql(u8, name, ".dynstr")) 0x4 else 0xfb, | 3421 | elf.SHT_STRTAB => return if (mem.eql(u8, name, ".dynstr")) 0x4 else 0xfa, |
| 3302 | else => return 0xff, | 3422 | else => return 0xff, |
| 3303 | } | 3423 | } |
| 3304 | } | 3424 | } |
| ... | @@ -3361,18 +3481,6 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void { | ... | @@ -3361,18 +3481,6 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void { |
| 3361 | &self.copy_rel_section_index, | 3481 | &self.copy_rel_section_index, |
| 3362 | &self.versym_section_index, | 3482 | &self.versym_section_index, |
| 3363 | &self.verneed_section_index, | 3483 | &self.verneed_section_index, |
| 3364 | &self.zig_text_section_index, | ||
| 3365 | &self.zig_data_rel_ro_section_index, | ||
| 3366 | &self.zig_data_section_index, | ||
| 3367 | &self.zig_bss_section_index, | ||
| 3368 | &self.debug_info_section_index, | ||
| 3369 | &self.debug_abbrev_section_index, | ||
| 3370 | &self.debug_str_section_index, | ||
| 3371 | &self.debug_aranges_section_index, | ||
| 3372 | &self.debug_line_section_index, | ||
| 3373 | &self.debug_line_str_section_index, | ||
| 3374 | &self.debug_loclists_section_index, | ||
| 3375 | &self.debug_rnglists_section_index, | ||
| 3376 | }) |maybe_index| { | 3484 | }) |maybe_index| { |
| 3377 | if (maybe_index.*) |*index| { | 3485 | if (maybe_index.*) |*index| { |
| 3378 | index.* = backlinks[index.*]; | 3486 | index.* = backlinks[index.*]; |
| ... | @@ -3383,13 +3491,19 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void { | ... | @@ -3383,13 +3491,19 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void { |
| 3383 | msec.output_section_index = backlinks[msec.output_section_index]; | 3491 | msec.output_section_index = backlinks[msec.output_section_index]; |
| 3384 | } | 3492 | } |
| 3385 | 3493 | ||
| 3386 | for (self.sections.items(.shdr)) |*shdr| { | 3494 | const slice = self.sections.slice(); |
| 3387 | if (shdr.sh_type != elf.SHT_RELA) continue; | 3495 | for (slice.items(.shdr), slice.items(.atom_list_2)) |*shdr, *atom_list| { |
| 3388 | // FIXME:JK we should spin up .symtab potentially earlier, or set all non-dynamic RELA sections | 3496 | atom_list.output_section_index = backlinks[atom_list.output_section_index]; |
| 3389 | // to point at symtab | 3497 | for (atom_list.atoms.items) |ref| { |
| 3390 | // shdr.sh_link = backlinks[shdr.sh_link]; | 3498 | self.atom(ref).?.output_section_index = atom_list.output_section_index; |
| 3391 | shdr.sh_link = self.symtab_section_index.?; | 3499 | } |
| 3392 | shdr.sh_info = backlinks[shdr.sh_info]; | 3500 | if (shdr.sh_type == elf.SHT_RELA) { |
| 3501 | // FIXME:JK we should spin up .symtab potentially earlier, or set all non-dynamic RELA sections | ||
| 3502 | // to point at symtab | ||
| 3503 | // shdr.sh_link = backlinks[shdr.sh_link]; | ||
| 3504 | shdr.sh_link = self.symtab_section_index.?; | ||
| 3505 | shdr.sh_info = backlinks[shdr.sh_info]; | ||
| 3506 | } | ||
| 3393 | } | 3507 | } |
| 3394 | 3508 | ||
| 3395 | if (self.zigObjectPtr()) |zo| { | 3509 | if (self.zigObjectPtr()) |zo| { |
| ... | @@ -3397,7 +3511,6 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void { | ... | @@ -3397,7 +3511,6 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void { |
| 3397 | const atom_ptr = zo.atom(atom_index) orelse continue; | 3511 | const atom_ptr = zo.atom(atom_index) orelse continue; |
| 3398 | atom_ptr.output_section_index = backlinks[atom_ptr.output_section_index]; | 3512 | atom_ptr.output_section_index = backlinks[atom_ptr.output_section_index]; |
| 3399 | } | 3513 | } |
| 3400 | if (zo.dwarf) |*dwarf| dwarf.reloadSectionMetadata(); | ||
| 3401 | } | 3514 | } |
| 3402 | 3515 | ||
| 3403 | for (self.comdat_group_sections.items) |*cg| { | 3516 | for (self.comdat_group_sections.items) |*cg| { |
| ... | @@ -3405,53 +3518,53 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void { | ... | @@ -3405,53 +3518,53 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void { |
| 3405 | } | 3518 | } |
| 3406 | 3519 | ||
| 3407 | if (self.symtab_section_index) |index| { | 3520 | if (self.symtab_section_index) |index| { |
| 3408 | const shdr = &self.sections.items(.shdr)[index]; | 3521 | const shdr = &slice.items(.shdr)[index]; |
| 3409 | shdr.sh_link = self.strtab_section_index.?; | 3522 | shdr.sh_link = self.strtab_section_index.?; |
| 3410 | } | 3523 | } |
| 3411 | 3524 | ||
| 3412 | if (self.dynamic_section_index) |index| { | 3525 | if (self.dynamic_section_index) |index| { |
| 3413 | const shdr = &self.sections.items(.shdr)[index]; | 3526 | const shdr = &slice.items(.shdr)[index]; |
| 3414 | shdr.sh_link = self.dynstrtab_section_index.?; | 3527 | shdr.sh_link = self.dynstrtab_section_index.?; |
| 3415 | } | 3528 | } |
| 3416 | 3529 | ||
| 3417 | if (self.dynsymtab_section_index) |index| { | 3530 | if (self.dynsymtab_section_index) |index| { |
| 3418 | const shdr = &self.sections.items(.shdr)[index]; | 3531 | const shdr = &slice.items(.shdr)[index]; |
| 3419 | shdr.sh_link = self.dynstrtab_section_index.?; | 3532 | shdr.sh_link = self.dynstrtab_section_index.?; |
| 3420 | } | 3533 | } |
| 3421 | 3534 | ||
| 3422 | if (self.hash_section_index) |index| { | 3535 | if (self.hash_section_index) |index| { |
| 3423 | const shdr = &self.sections.items(.shdr)[index]; | 3536 | const shdr = &slice.items(.shdr)[index]; |
| 3424 | shdr.sh_link = self.dynsymtab_section_index.?; | 3537 | shdr.sh_link = self.dynsymtab_section_index.?; |
| 3425 | } | 3538 | } |
| 3426 | 3539 | ||
| 3427 | if (self.gnu_hash_section_index) |index| { | 3540 | if (self.gnu_hash_section_index) |index| { |
| 3428 | const shdr = &self.sections.items(.shdr)[index]; | 3541 | const shdr = &slice.items(.shdr)[index]; |
| 3429 | shdr.sh_link = self.dynsymtab_section_index.?; | 3542 | shdr.sh_link = self.dynsymtab_section_index.?; |
| 3430 | } | 3543 | } |
| 3431 | 3544 | ||
| 3432 | if (self.versym_section_index) |index| { | 3545 | if (self.versym_section_index) |index| { |
| 3433 | const shdr = &self.sections.items(.shdr)[index]; | 3546 | const shdr = &slice.items(.shdr)[index]; |
| 3434 | shdr.sh_link = self.dynsymtab_section_index.?; | 3547 | shdr.sh_link = self.dynsymtab_section_index.?; |
| 3435 | } | 3548 | } |
| 3436 | 3549 | ||
| 3437 | if (self.verneed_section_index) |index| { | 3550 | if (self.verneed_section_index) |index| { |
| 3438 | const shdr = &self.sections.items(.shdr)[index]; | 3551 | const shdr = &slice.items(.shdr)[index]; |
| 3439 | shdr.sh_link = self.dynstrtab_section_index.?; | 3552 | shdr.sh_link = self.dynstrtab_section_index.?; |
| 3440 | } | 3553 | } |
| 3441 | 3554 | ||
| 3442 | if (self.rela_dyn_section_index) |index| { | 3555 | if (self.rela_dyn_section_index) |index| { |
| 3443 | const shdr = &self.sections.items(.shdr)[index]; | 3556 | const shdr = &slice.items(.shdr)[index]; |
| 3444 | shdr.sh_link = self.dynsymtab_section_index orelse 0; | 3557 | shdr.sh_link = self.dynsymtab_section_index orelse 0; |
| 3445 | } | 3558 | } |
| 3446 | 3559 | ||
| 3447 | if (self.rela_plt_section_index) |index| { | 3560 | if (self.rela_plt_section_index) |index| { |
| 3448 | const shdr = &self.sections.items(.shdr)[index]; | 3561 | const shdr = &slice.items(.shdr)[index]; |
| 3449 | shdr.sh_link = self.dynsymtab_section_index.?; | 3562 | shdr.sh_link = self.dynsymtab_section_index.?; |
| 3450 | shdr.sh_info = self.plt_section_index.?; | 3563 | shdr.sh_info = self.plt_section_index.?; |
| 3451 | } | 3564 | } |
| 3452 | 3565 | ||
| 3453 | if (self.eh_frame_rela_section_index) |index| { | 3566 | if (self.eh_frame_rela_section_index) |index| { |
| 3454 | const shdr = &self.sections.items(.shdr)[index]; | 3567 | const shdr = &slice.items(.shdr)[index]; |
| 3455 | shdr.sh_link = self.symtab_section_index.?; | 3568 | shdr.sh_link = self.symtab_section_index.?; |
| 3456 | shdr.sh_info = self.eh_frame_section_index.?; | 3569 | shdr.sh_info = self.eh_frame_section_index.?; |
| 3457 | } | 3570 | } |
| ... | @@ -3459,37 +3572,32 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void { | ... | @@ -3459,37 +3572,32 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void { |
| 3459 | 3572 | ||
| 3460 | fn updateSectionSizes(self: *Elf) !void { | 3573 | fn updateSectionSizes(self: *Elf) !void { |
| 3461 | const slice = self.sections.slice(); | 3574 | const slice = self.sections.slice(); |
| 3462 | for (slice.items(.shdr), slice.items(.atom_list)) |*shdr, atom_list| { | 3575 | for (slice.items(.shdr), slice.items(.atom_list_2)) |shdr, *atom_list| { |
| 3463 | if (atom_list.items.len == 0) continue; | 3576 | if (atom_list.atoms.items.len == 0) continue; |
| 3464 | if (self.requiresThunks() and shdr.sh_flags & elf.SHF_EXECINSTR != 0) continue; | 3577 | if (self.requiresThunks() and shdr.sh_flags & elf.SHF_EXECINSTR != 0) continue; |
| 3465 | for (atom_list.items) |ref| { | 3578 | atom_list.updateSize(self); |
| 3466 | const atom_ptr = self.atom(ref) orelse continue; | 3579 | try atom_list.allocate(self); |
| 3467 | if (!atom_ptr.alive) continue; | ||
| 3468 | const offset = atom_ptr.alignment.forward(shdr.sh_size); | ||
| 3469 | const padding = offset - shdr.sh_size; | ||
| 3470 | atom_ptr.value = @intCast(offset); | ||
| 3471 | shdr.sh_size += padding + atom_ptr.size; | ||
| 3472 | shdr.sh_addralign = @max(shdr.sh_addralign, atom_ptr.alignment.toByteUnits() orelse 1); | ||
| 3473 | } | ||
| 3474 | } | 3580 | } |
| 3475 | 3581 | ||
| 3476 | if (self.requiresThunks()) { | 3582 | if (self.requiresThunks()) { |
| 3477 | for (slice.items(.shdr), slice.items(.atom_list), 0..) |*shdr, atom_list, shndx| { | 3583 | for (slice.items(.shdr), slice.items(.atom_list_2)) |shdr, *atom_list| { |
| 3478 | if (shdr.sh_flags & elf.SHF_EXECINSTR == 0) continue; | 3584 | if (shdr.sh_flags & elf.SHF_EXECINSTR == 0) continue; |
| 3479 | if (atom_list.items.len == 0) continue; | 3585 | if (atom_list.atoms.items.len == 0) continue; |
| 3480 | 3586 | ||
| 3481 | // Create jump/branch range extenders if needed. | 3587 | // Create jump/branch range extenders if needed. |
| 3482 | try self.createThunks(shdr, @intCast(shndx)); | 3588 | try self.createThunks(atom_list); |
| 3589 | try atom_list.allocate(self); | ||
| 3590 | } | ||
| 3591 | |||
| 3592 | // FIXME:JK this will hopefully not be needed once we create a link from Atom/Thunk to AtomList. | ||
| 3593 | for (self.thunks.items) |*th| { | ||
| 3594 | th.value += slice.items(.atom_list_2)[th.output_section_index].value; | ||
| 3483 | } | 3595 | } |
| 3484 | } | 3596 | } |
| 3485 | 3597 | ||
| 3486 | const shdrs = slice.items(.shdr); | 3598 | const shdrs = slice.items(.shdr); |
| 3487 | if (self.eh_frame_section_index) |index| { | 3599 | if (self.eh_frame_section_index) |index| { |
| 3488 | shdrs[index].sh_size = existing_size: { | 3600 | shdrs[index].sh_size = try eh_frame.calcEhFrameSize(self); |
| 3489 | const zo = self.zigObjectPtr() orelse break :existing_size 0; | ||
| 3490 | const sym = zo.symbol(zo.eh_frame_index orelse break :existing_size 0); | ||
| 3491 | break :existing_size sym.atom(self).?.size; | ||
| 3492 | } + try eh_frame.calcEhFrameSize(self); | ||
| 3493 | } | 3601 | } |
| 3494 | 3602 | ||
| 3495 | if (self.eh_frame_hdr_section_index) |index| { | 3603 | if (self.eh_frame_hdr_section_index) |index| { |
| ... | @@ -3587,13 +3695,11 @@ fn shdrToPhdrFlags(sh_flags: u64) u32 { | ... | @@ -3587,13 +3695,11 @@ fn shdrToPhdrFlags(sh_flags: u64) u32 { |
| 3587 | /// (This is an upper bound so that we can reserve enough space for the header and progam header | 3695 | /// (This is an upper bound so that we can reserve enough space for the header and progam header |
| 3588 | /// table without running out of space and being forced to move things around.) | 3696 | /// table without running out of space and being forced to move things around.) |
| 3589 | fn getMaxNumberOfPhdrs() u64 { | 3697 | fn getMaxNumberOfPhdrs() u64 { |
| 3590 | // First, assume we compile Zig's source incrementally, this gives us: | 3698 | // The estimated maximum number of segments the linker can emit for input sections are: |
| 3591 | var num: u64 = number_of_zig_segments; | 3699 | var num: u64 = max_number_of_object_segments; |
| 3592 | // Next, the estimated maximum number of segments the linker can emit for input sections are: | 3700 | // Any other non-loadable program headers, including TLS, DYNAMIC, GNU_STACK, GNU_EH_FRAME, INTERP: |
| 3593 | num += max_number_of_object_segments; | ||
| 3594 | // Next, any other non-loadable program headers, including TLS, DYNAMIC, GNU_STACK, GNU_EH_FRAME, INTERP: | ||
| 3595 | num += max_number_of_special_phdrs; | 3701 | num += max_number_of_special_phdrs; |
| 3596 | // Finally, PHDR program header and corresponding read-only load segment: | 3702 | // PHDR program header and corresponding read-only load segment: |
| 3597 | num += 2; | 3703 | num += 2; |
| 3598 | return num; | 3704 | return num; |
| 3599 | } | 3705 | } |
| ... | @@ -3603,10 +3709,9 @@ fn getMaxNumberOfPhdrs() u64 { | ... | @@ -3603,10 +3709,9 @@ fn getMaxNumberOfPhdrs() u64 { |
| 3603 | /// We permit a maximum of 3**2 number of segments. | 3709 | /// We permit a maximum of 3**2 number of segments. |
| 3604 | fn calcNumberOfSegments(self: *Elf) usize { | 3710 | fn calcNumberOfSegments(self: *Elf) usize { |
| 3605 | var covers: [9]bool = [_]bool{false} ** 9; | 3711 | var covers: [9]bool = [_]bool{false} ** 9; |
| 3606 | for (self.sections.items(.shdr), 0..) |shdr, shndx| { | 3712 | for (self.sections.items(.shdr)) |shdr| { |
| 3607 | if (shdr.sh_type == elf.SHT_NULL) continue; | 3713 | if (shdr.sh_type == elf.SHT_NULL) continue; |
| 3608 | if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; | 3714 | if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; |
| 3609 | if (self.isZigSection(@intCast(shndx))) continue; | ||
| 3610 | const flags = shdrToPhdrFlags(shdr.sh_flags); | 3715 | const flags = shdrToPhdrFlags(shdr.sh_flags); |
| 3611 | covers[flags - 1] = true; | 3716 | covers[flags - 1] = true; |
| 3612 | } | 3717 | } |
| ... | @@ -3704,7 +3809,6 @@ pub fn allocateAllocSections(self: *Elf) !void { | ... | @@ -3704,7 +3809,6 @@ pub fn allocateAllocSections(self: *Elf) !void { |
| 3704 | for (slice.items(.shdr), 0..) |shdr, shndx| { | 3809 | for (slice.items(.shdr), 0..) |shdr, shndx| { |
| 3705 | if (shdr.sh_type == elf.SHT_NULL) continue; | 3810 | if (shdr.sh_type == elf.SHT_NULL) continue; |
| 3706 | if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; | 3811 | if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; |
| 3707 | if (self.isZigSection(@intCast(shndx))) continue; | ||
| 3708 | const flags = shdrToPhdrFlags(shdr.sh_flags); | 3812 | const flags = shdrToPhdrFlags(shdr.sh_flags); |
| 3709 | try covers[flags - 1].append(@intCast(shndx)); | 3813 | try covers[flags - 1].append(@intCast(shndx)); |
| 3710 | } | 3814 | } |
| ... | @@ -3794,10 +3898,20 @@ pub fn allocateAllocSections(self: *Elf) !void { | ... | @@ -3794,10 +3898,20 @@ pub fn allocateAllocSections(self: *Elf) !void { |
| 3794 | } | 3898 | } |
| 3795 | new_offset = alignment.@"align"(shndx, shdr.sh_addralign, new_offset); | 3899 | new_offset = alignment.@"align"(shndx, shdr.sh_addralign, new_offset); |
| 3796 | 3900 | ||
| 3797 | if (shndx == self.eh_frame_section_index) eh_frame: { | 3901 | if (self.zigObjectPtr()) |zo| blk: { |
| 3798 | const zo = self.zigObjectPtr() orelse break :eh_frame; | 3902 | const existing_size = for ([_]?Symbol.Index{ |
| 3799 | const sym = zo.symbol(zo.eh_frame_index orelse break :eh_frame); | 3903 | zo.text_index, |
| 3800 | const existing_size = sym.atom(self).?.size; | 3904 | zo.rodata_index, |
| 3905 | zo.data_relro_index, | ||
| 3906 | zo.data_index, | ||
| 3907 | zo.tdata_index, | ||
| 3908 | zo.eh_frame_index, | ||
| 3909 | }) |maybe_sym_index| { | ||
| 3910 | const sect_sym_index = maybe_sym_index orelse continue; | ||
| 3911 | const sect_atom_ptr = zo.symbol(sect_sym_index).atom(self).?; | ||
| 3912 | if (sect_atom_ptr.output_section_index != shndx) continue; | ||
| 3913 | break sect_atom_ptr.size; | ||
| 3914 | } else break :blk; | ||
| 3801 | log.debug("moving {s} from 0x{x} to 0x{x}", .{ | 3915 | log.debug("moving {s} from 0x{x} to 0x{x}", .{ |
| 3802 | self.getShString(shdr.sh_name), | 3916 | self.getShString(shdr.sh_name), |
| 3803 | shdr.sh_offset, | 3917 | shdr.sh_offset, |
| ... | @@ -3830,27 +3944,27 @@ pub fn allocateNonAllocSections(self: *Elf) !void { | ... | @@ -3830,27 +3944,27 @@ pub fn allocateNonAllocSections(self: *Elf) !void { |
| 3830 | shdr.sh_size = 0; | 3944 | shdr.sh_size = 0; |
| 3831 | const new_offset = try self.findFreeSpace(needed_size, shdr.sh_addralign); | 3945 | const new_offset = try self.findFreeSpace(needed_size, shdr.sh_addralign); |
| 3832 | 3946 | ||
| 3833 | if (self.isDebugSection(@intCast(shndx))) { | 3947 | if (self.zigObjectPtr()) |zo| blk: { |
| 3948 | const existing_size = for ([_]?Symbol.Index{ | ||
| 3949 | zo.debug_info_index, | ||
| 3950 | zo.debug_abbrev_index, | ||
| 3951 | zo.debug_aranges_index, | ||
| 3952 | zo.debug_str_index, | ||
| 3953 | zo.debug_line_index, | ||
| 3954 | zo.debug_line_str_index, | ||
| 3955 | zo.debug_loclists_index, | ||
| 3956 | zo.debug_rnglists_index, | ||
| 3957 | }) |maybe_sym_index| { | ||
| 3958 | const sym_index = maybe_sym_index orelse continue; | ||
| 3959 | const sym = zo.symbol(sym_index); | ||
| 3960 | const atom_ptr = sym.atom(self).?; | ||
| 3961 | if (atom_ptr.output_section_index == shndx) break atom_ptr.size; | ||
| 3962 | } else break :blk; | ||
| 3834 | log.debug("moving {s} from 0x{x} to 0x{x}", .{ | 3963 | log.debug("moving {s} from 0x{x} to 0x{x}", .{ |
| 3835 | self.getShString(shdr.sh_name), | 3964 | self.getShString(shdr.sh_name), |
| 3836 | shdr.sh_offset, | 3965 | shdr.sh_offset, |
| 3837 | new_offset, | 3966 | new_offset, |
| 3838 | }); | 3967 | }); |
| 3839 | const zo = self.zigObjectPtr().?; | ||
| 3840 | const existing_size = for ([_]Symbol.Index{ | ||
| 3841 | zo.debug_info_index.?, | ||
| 3842 | zo.debug_abbrev_index.?, | ||
| 3843 | zo.debug_aranges_index.?, | ||
| 3844 | zo.debug_str_index.?, | ||
| 3845 | zo.debug_line_index.?, | ||
| 3846 | zo.debug_line_str_index.?, | ||
| 3847 | zo.debug_loclists_index.?, | ||
| 3848 | zo.debug_rnglists_index.?, | ||
| 3849 | }) |sym_index| { | ||
| 3850 | const sym = zo.symbol(sym_index); | ||
| 3851 | const atom_ptr = sym.atom(self).?; | ||
| 3852 | if (atom_ptr.output_section_index == shndx) break atom_ptr.size; | ||
| 3853 | } else 0; | ||
| 3854 | const amt = try self.base.file.?.copyRangeAll( | 3968 | const amt = try self.base.file.?.copyRangeAll( |
| 3855 | shdr.sh_offset, | 3969 | shdr.sh_offset, |
| 3856 | self.base.file.?, | 3970 | self.base.file.?, |
| ... | @@ -3934,91 +4048,28 @@ fn writeAtoms(self: *Elf) !void { | ... | @@ -3934,91 +4048,28 @@ fn writeAtoms(self: *Elf) !void { |
| 3934 | undefs.deinit(); | 4048 | undefs.deinit(); |
| 3935 | } | 4049 | } |
| 3936 | 4050 | ||
| 3937 | var has_reloc_errors = false; | 4051 | var buffer = std.ArrayList(u8).init(gpa); |
| 4052 | defer buffer.deinit(); | ||
| 4053 | |||
| 3938 | const slice = self.sections.slice(); | 4054 | const slice = self.sections.slice(); |
| 3939 | for (slice.items(.shdr), slice.items(.atom_list), 0..) |shdr, atom_list, shndx| { | 4055 | var has_reloc_errors = false; |
| 3940 | if (shdr.sh_type == elf.SHT_NULL) continue; | 4056 | for (slice.items(.shdr), slice.items(.atom_list_2)) |shdr, atom_list| { |
| 3941 | if (shdr.sh_type == elf.SHT_NOBITS) continue; | 4057 | if (shdr.sh_type == elf.SHT_NOBITS) continue; |
| 3942 | if (atom_list.items.len == 0) continue; | 4058 | if (atom_list.atoms.items.len == 0) continue; |
| 3943 | 4059 | atom_list.write(&buffer, &undefs, self) catch |err| switch (err) { | |
| 3944 | log.debug("writing atoms in '{s}' section", .{self.getShString(shdr.sh_name)}); | 4060 | error.UnsupportedCpuArch => { |
| 3945 | 4061 | try self.reportUnsupportedCpuArch(); | |
| 3946 | // TODO really, really handle debug section separately | 4062 | return error.FlushFailure; |
| 3947 | const base_offset = if (self.isDebugSection(@intCast(shndx))) base_offset: { | 4063 | }, |
| 3948 | const zo = self.zigObjectPtr().?; | 4064 | error.RelocFailure, error.RelaxFailure => has_reloc_errors = true, |
| 3949 | for ([_]Symbol.Index{ | 4065 | else => |e| return e, |
| 3950 | zo.debug_info_index.?, | 4066 | }; |
| 3951 | zo.debug_abbrev_index.?, | ||
| 3952 | zo.debug_aranges_index.?, | ||
| 3953 | zo.debug_str_index.?, | ||
| 3954 | zo.debug_line_index.?, | ||
| 3955 | zo.debug_line_str_index.?, | ||
| 3956 | zo.debug_loclists_index.?, | ||
| 3957 | zo.debug_rnglists_index.?, | ||
| 3958 | }) |sym_index| { | ||
| 3959 | const sym = zo.symbol(sym_index); | ||
| 3960 | const atom_ptr = sym.atom(self).?; | ||
| 3961 | if (atom_ptr.output_section_index == shndx) break :base_offset atom_ptr.size; | ||
| 3962 | } | ||
| 3963 | break :base_offset 0; | ||
| 3964 | } else if (@as(u32, @intCast(shndx)) == self.eh_frame_section_index) base_offset: { | ||
| 3965 | const zo = self.zigObjectPtr() orelse break :base_offset 0; | ||
| 3966 | const sym = zo.symbol(zo.eh_frame_index orelse break :base_offset 0); | ||
| 3967 | break :base_offset sym.atom(self).?.size; | ||
| 3968 | } else 0; | ||
| 3969 | const sh_offset = shdr.sh_offset + base_offset; | ||
| 3970 | const sh_size = math.cast(usize, shdr.sh_size - base_offset) orelse return error.Overflow; | ||
| 3971 | |||
| 3972 | const buffer = try gpa.alloc(u8, sh_size); | ||
| 3973 | defer gpa.free(buffer); | ||
| 3974 | const padding_byte: u8 = if (shdr.sh_type == elf.SHT_PROGBITS and | ||
| 3975 | shdr.sh_flags & elf.SHF_EXECINSTR != 0 and self.getTarget().cpu.arch == .x86_64) | ||
| 3976 | 0xcc // int3 | ||
| 3977 | else | ||
| 3978 | 0; | ||
| 3979 | @memset(buffer, padding_byte); | ||
| 3980 | |||
| 3981 | for (atom_list.items) |ref| { | ||
| 3982 | const atom_ptr = self.atom(ref).?; | ||
| 3983 | assert(atom_ptr.alive); | ||
| 3984 | |||
| 3985 | const offset = math.cast(usize, atom_ptr.value - @as(i64, @intCast(base_offset))) orelse | ||
| 3986 | return error.Overflow; | ||
| 3987 | const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow; | ||
| 3988 | |||
| 3989 | log.debug("writing atom({}) at 0x{x}", .{ ref, sh_offset + offset }); | ||
| 3990 | |||
| 3991 | // TODO decompress directly into provided buffer | ||
| 3992 | const out_code = buffer[offset..][0..size]; | ||
| 3993 | const in_code = switch (atom_ptr.file(self).?) { | ||
| 3994 | .object => |x| try x.codeDecompressAlloc(self, ref.index), | ||
| 3995 | .zig_object => |x| try x.codeAlloc(self, ref.index), | ||
| 3996 | else => unreachable, | ||
| 3997 | }; | ||
| 3998 | defer gpa.free(in_code); | ||
| 3999 | @memcpy(out_code, in_code); | ||
| 4000 | |||
| 4001 | const res = if (shdr.sh_flags & elf.SHF_ALLOC == 0) | ||
| 4002 | atom_ptr.resolveRelocsNonAlloc(self, out_code, &undefs) | ||
| 4003 | else | ||
| 4004 | atom_ptr.resolveRelocsAlloc(self, out_code); | ||
| 4005 | _ = res catch |err| switch (err) { | ||
| 4006 | error.UnsupportedCpuArch => { | ||
| 4007 | try self.reportUnsupportedCpuArch(); | ||
| 4008 | return error.FlushFailure; | ||
| 4009 | }, | ||
| 4010 | error.RelocFailure, error.RelaxFailure => has_reloc_errors = true, | ||
| 4011 | else => |e| return e, | ||
| 4012 | }; | ||
| 4013 | } | ||
| 4014 | |||
| 4015 | try self.base.file.?.pwriteAll(buffer, sh_offset); | ||
| 4016 | } | 4067 | } |
| 4017 | 4068 | ||
| 4018 | if (self.requiresThunks()) { | 4069 | try self.reportUndefinedSymbols(&undefs); |
| 4019 | var buffer = std.ArrayList(u8).init(gpa); | 4070 | if (has_reloc_errors) return error.FlushFailure; |
| 4020 | defer buffer.deinit(); | ||
| 4021 | 4071 | ||
| 4072 | if (self.requiresThunks()) { | ||
| 4022 | for (self.thunks.items) |th| { | 4073 | for (self.thunks.items) |th| { |
| 4023 | const thunk_size = th.size(self); | 4074 | const thunk_size = th.size(self); |
| 4024 | try buffer.ensureUnusedCapacity(thunk_size); | 4075 | try buffer.ensureUnusedCapacity(thunk_size); |
| ... | @@ -4030,10 +4081,6 @@ fn writeAtoms(self: *Elf) !void { | ... | @@ -4030,10 +4081,6 @@ fn writeAtoms(self: *Elf) !void { |
| 4030 | buffer.clearRetainingCapacity(); | 4081 | buffer.clearRetainingCapacity(); |
| 4031 | } | 4082 | } |
| 4032 | } | 4083 | } |
| 4033 | |||
| 4034 | try self.reportUndefinedSymbols(&undefs); | ||
| 4035 | |||
| 4036 | if (has_reloc_errors) return error.FlushFailure; | ||
| 4037 | } | 4084 | } |
| 4038 | 4085 | ||
| 4039 | pub fn updateSymtabSize(self: *Elf) !void { | 4086 | pub fn updateSymtabSize(self: *Elf) !void { |
| ... | @@ -4667,34 +4714,6 @@ pub fn isEffectivelyDynLib(self: Elf) bool { | ... | @@ -4667,34 +4714,6 @@ pub fn isEffectivelyDynLib(self: Elf) bool { |
| 4667 | }; | 4714 | }; |
| 4668 | } | 4715 | } |
| 4669 | 4716 | ||
| 4670 | pub fn isZigSection(self: Elf, shndx: u32) bool { | ||
| 4671 | inline for (&[_]?u32{ | ||
| 4672 | self.zig_text_section_index, | ||
| 4673 | self.zig_data_rel_ro_section_index, | ||
| 4674 | self.zig_data_section_index, | ||
| 4675 | self.zig_bss_section_index, | ||
| 4676 | }) |index| { | ||
| 4677 | if (index == shndx) return true; | ||
| 4678 | } | ||
| 4679 | return false; | ||
| 4680 | } | ||
| 4681 | |||
| 4682 | pub fn isDebugSection(self: Elf, shndx: u32) bool { | ||
| 4683 | inline for (&[_]?u32{ | ||
| 4684 | self.debug_info_section_index, | ||
| 4685 | self.debug_abbrev_section_index, | ||
| 4686 | self.debug_str_section_index, | ||
| 4687 | self.debug_aranges_section_index, | ||
| 4688 | self.debug_line_section_index, | ||
| 4689 | self.debug_line_str_section_index, | ||
| 4690 | self.debug_loclists_section_index, | ||
| 4691 | self.debug_rnglists_section_index, | ||
| 4692 | }) |index| { | ||
| 4693 | if (index == shndx) return true; | ||
| 4694 | } | ||
| 4695 | return false; | ||
| 4696 | } | ||
| 4697 | |||
| 4698 | pub fn addPhdr(self: *Elf, opts: struct { | 4717 | pub fn addPhdr(self: *Elf, opts: struct { |
| 4699 | type: u32 = 0, | 4718 | type: u32 = 0, |
| 4700 | flags: u32 = 0, | 4719 | flags: u32 = 0, |
| ... | @@ -5070,7 +5089,7 @@ fn reportMissingLibraryError( | ... | @@ -5070,7 +5089,7 @@ fn reportMissingLibraryError( |
| 5070 | } | 5089 | } |
| 5071 | } | 5090 | } |
| 5072 | 5091 | ||
| 5073 | pub fn reportUnsupportedCpuArch(self: *Elf) error{OutOfMemory}!void { | 5092 | fn reportUnsupportedCpuArch(self: *Elf) error{OutOfMemory}!void { |
| 5074 | var err = try self.base.addErrorWithNotes(0); | 5093 | var err = try self.base.addErrorWithNotes(0); |
| 5075 | try err.addMsg("fatal linker error: unsupported CPU architecture {s}", .{ | 5094 | try err.addMsg("fatal linker error: unsupported CPU architecture {s}", .{ |
| 5076 | @tagName(self.getTarget().cpu.arch), | 5095 | @tagName(self.getTarget().cpu.arch), |
| ... | @@ -5282,6 +5301,14 @@ fn fmtDumpState( | ... | @@ -5282,6 +5301,14 @@ fn fmtDumpState( |
| 5282 | try writer.print("{}\n", .{linker_defined.fmtSymtab(self)}); | 5301 | try writer.print("{}\n", .{linker_defined.fmtSymtab(self)}); |
| 5283 | } | 5302 | } |
| 5284 | 5303 | ||
| 5304 | const slice = self.sections.slice(); | ||
| 5305 | { | ||
| 5306 | try writer.writeAll("atom lists\n"); | ||
| 5307 | for (slice.items(.shdr), slice.items(.atom_list_2), 0..) |shdr, atom_list, shndx| { | ||
| 5308 | try writer.print("shdr({d}) : {s} : {}", .{ shndx, self.getShString(shdr.sh_name), atom_list.fmt(self) }); | ||
| 5309 | } | ||
| 5310 | } | ||
| 5311 | |||
| 5285 | if (self.requiresThunks()) { | 5312 | if (self.requiresThunks()) { |
| 5286 | try writer.writeAll("thunks\n"); | 5313 | try writer.writeAll("thunks\n"); |
| 5287 | for (self.thunks.items, 0..) |th, index| { | 5314 | for (self.thunks.items, 0..) |th, index| { |
| ... | @@ -5303,7 +5330,7 @@ fn fmtDumpState( | ... | @@ -5303,7 +5330,7 @@ fn fmtDumpState( |
| 5303 | } | 5330 | } |
| 5304 | 5331 | ||
| 5305 | try writer.writeAll("\nOutput shdrs\n"); | 5332 | try writer.writeAll("\nOutput shdrs\n"); |
| 5306 | for (self.sections.items(.shdr), self.sections.items(.phndx), 0..) |shdr, phndx, shndx| { | 5333 | for (slice.items(.shdr), slice.items(.phndx), 0..) |shdr, phndx, shndx| { |
| 5307 | try writer.print(" shdr({d}) : phdr({?d}) : {}\n", .{ | 5334 | try writer.print(" shdr({d}) : phdr({?d}) : {}\n", .{ |
| 5308 | shndx, | 5335 | shndx, |
| 5309 | phndx, | 5336 | phndx, |
| ... | @@ -5373,7 +5400,6 @@ fn requiresThunks(self: Elf) bool { | ... | @@ -5373,7 +5400,6 @@ fn requiresThunks(self: Elf) bool { |
| 5373 | /// so that we reserve enough space for the program header table up-front. | 5400 | /// so that we reserve enough space for the program header table up-front. |
| 5374 | /// Bump these numbers when adding or deleting a Zig specific pre-allocated segment, or adding | 5401 | /// Bump these numbers when adding or deleting a Zig specific pre-allocated segment, or adding |
| 5375 | /// more special-purpose program headers. | 5402 | /// more special-purpose program headers. |
| 5376 | pub const number_of_zig_segments = 4; | ||
| 5377 | const max_number_of_object_segments = 9; | 5403 | const max_number_of_object_segments = 9; |
| 5378 | const max_number_of_special_phdrs = 5; | 5404 | const max_number_of_special_phdrs = 5; |
| 5379 | 5405 | ||
| ... | @@ -5558,8 +5584,14 @@ const Section = struct { | ... | @@ -5558,8 +5584,14 @@ const Section = struct { |
| 5558 | phndx: ?u32 = null, | 5584 | phndx: ?u32 = null, |
| 5559 | 5585 | ||
| 5560 | /// List of atoms contributing to this section. | 5586 | /// List of atoms contributing to this section. |
| 5587 | /// TODO currently this is only used for relocations tracking in relocatable mode | ||
| 5588 | /// but will be merged with atom_list_2. | ||
| 5561 | atom_list: std.ArrayListUnmanaged(Ref) = .{}, | 5589 | atom_list: std.ArrayListUnmanaged(Ref) = .{}, |
| 5562 | 5590 | ||
| 5591 | /// List of atoms contributing to this section. | ||
| 5592 | /// This can be used by sections that require special handling such as init/fini array, etc. | ||
| 5593 | atom_list_2: AtomList = .{}, | ||
| 5594 | |||
| 5563 | /// Index of the last allocated atom in this section. | 5595 | /// Index of the last allocated atom in this section. |
| 5564 | last_atom: Ref = .{ .index = 0, .file = 0 }, | 5596 | last_atom: Ref = .{ .index = 0, .file = 0 }, |
| 5565 | 5597 | ||
| ... | @@ -5588,9 +5620,10 @@ fn defaultEntrySymbolName(cpu_arch: std.Target.Cpu.Arch) []const u8 { | ... | @@ -5588,9 +5620,10 @@ fn defaultEntrySymbolName(cpu_arch: std.Target.Cpu.Arch) []const u8 { |
| 5588 | }; | 5620 | }; |
| 5589 | } | 5621 | } |
| 5590 | 5622 | ||
| 5591 | fn createThunks(elf_file: *Elf, shdr: *elf.Elf64_Shdr, shndx: u32) !void { | 5623 | fn createThunks(elf_file: *Elf, atom_list: *AtomList) !void { |
| 5592 | const gpa = elf_file.base.comp.gpa; | 5624 | const gpa = elf_file.base.comp.gpa; |
| 5593 | const cpu_arch = elf_file.getTarget().cpu.arch; | 5625 | const cpu_arch = elf_file.getTarget().cpu.arch; |
| 5626 | |||
| 5594 | // A branch will need an extender if its target is larger than | 5627 | // A branch will need an extender if its target is larger than |
| 5595 | // `2^(jump_bits - 1) - margin` where margin is some arbitrary number. | 5628 | // `2^(jump_bits - 1) - margin` where margin is some arbitrary number. |
| 5596 | const max_distance = switch (cpu_arch) { | 5629 | const max_distance = switch (cpu_arch) { |
| ... | @@ -5598,36 +5631,44 @@ fn createThunks(elf_file: *Elf, shdr: *elf.Elf64_Shdr, shndx: u32) !void { | ... | @@ -5598,36 +5631,44 @@ fn createThunks(elf_file: *Elf, shdr: *elf.Elf64_Shdr, shndx: u32) !void { |
| 5598 | .x86_64, .riscv64 => unreachable, | 5631 | .x86_64, .riscv64 => unreachable, |
| 5599 | else => @panic("unhandled arch"), | 5632 | else => @panic("unhandled arch"), |
| 5600 | }; | 5633 | }; |
| 5601 | const atoms = elf_file.sections.items(.atom_list)[shndx].items; | ||
| 5602 | assert(atoms.len > 0); | ||
| 5603 | 5634 | ||
| 5604 | for (atoms) |ref| { | 5635 | const advance = struct { |
| 5636 | fn advance(list: *AtomList, size: u64, alignment: Atom.Alignment) !i64 { | ||
| 5637 | const offset = alignment.forward(list.size); | ||
| 5638 | const padding = offset - list.size; | ||
| 5639 | list.size += padding + size; | ||
| 5640 | list.alignment = list.alignment.max(alignment); | ||
| 5641 | return @intCast(offset); | ||
| 5642 | } | ||
| 5643 | }.advance; | ||
| 5644 | |||
| 5645 | for (atom_list.atoms.items) |ref| { | ||
| 5605 | elf_file.atom(ref).?.value = -1; | 5646 | elf_file.atom(ref).?.value = -1; |
| 5606 | } | 5647 | } |
| 5607 | 5648 | ||
| 5608 | var i: usize = 0; | 5649 | var i: usize = 0; |
| 5609 | while (i < atoms.len) { | 5650 | while (i < atom_list.atoms.items.len) { |
| 5610 | const start = i; | 5651 | const start = i; |
| 5611 | const start_atom = elf_file.atom(atoms[start]).?; | 5652 | const start_atom = elf_file.atom(atom_list.atoms.items[start]).?; |
| 5612 | assert(start_atom.alive); | 5653 | assert(start_atom.alive); |
| 5613 | start_atom.value = try advanceSection(shdr, start_atom.size, start_atom.alignment); | 5654 | start_atom.value = try advance(atom_list, start_atom.size, start_atom.alignment); |
| 5614 | i += 1; | 5655 | i += 1; |
| 5615 | 5656 | ||
| 5616 | while (i < atoms.len) : (i += 1) { | 5657 | while (i < atom_list.atoms.items.len) : (i += 1) { |
| 5617 | const atom_ptr = elf_file.atom(atoms[i]).?; | 5658 | const atom_ptr = elf_file.atom(atom_list.atoms.items[i]).?; |
| 5618 | assert(atom_ptr.alive); | 5659 | assert(atom_ptr.alive); |
| 5619 | if (@as(i64, @intCast(atom_ptr.alignment.forward(shdr.sh_size))) - start_atom.value >= max_distance) | 5660 | if (@as(i64, @intCast(atom_ptr.alignment.forward(atom_list.size))) - start_atom.value >= max_distance) |
| 5620 | break; | 5661 | break; |
| 5621 | atom_ptr.value = try advanceSection(shdr, atom_ptr.size, atom_ptr.alignment); | 5662 | atom_ptr.value = try advance(atom_list, atom_ptr.size, atom_ptr.alignment); |
| 5622 | } | 5663 | } |
| 5623 | 5664 | ||
| 5624 | // Insert a thunk at the group end | 5665 | // Insert a thunk at the group end |
| 5625 | const thunk_index = try elf_file.addThunk(); | 5666 | const thunk_index = try elf_file.addThunk(); |
| 5626 | const thunk_ptr = elf_file.thunk(thunk_index); | 5667 | const thunk_ptr = elf_file.thunk(thunk_index); |
| 5627 | thunk_ptr.output_section_index = shndx; | 5668 | thunk_ptr.output_section_index = atom_list.output_section_index; |
| 5628 | 5669 | ||
| 5629 | // Scan relocs in the group and create trampolines for any unreachable callsite | 5670 | // Scan relocs in the group and create trampolines for any unreachable callsite |
| 5630 | for (atoms[start..i]) |ref| { | 5671 | for (atom_list.atoms.items[start..i]) |ref| { |
| 5631 | const atom_ptr = elf_file.atom(ref).?; | 5672 | const atom_ptr = elf_file.atom(ref).?; |
| 5632 | const file_ptr = atom_ptr.file(elf_file).?; | 5673 | const file_ptr = atom_ptr.file(elf_file).?; |
| 5633 | log.debug("atom({}) {s}", .{ ref, atom_ptr.name(elf_file) }); | 5674 | log.debug("atom({}) {s}", .{ ref, atom_ptr.name(elf_file) }); |
| ... | @@ -5657,18 +5698,11 @@ fn createThunks(elf_file: *Elf, shdr: *elf.Elf64_Shdr, shndx: u32) !void { | ... | @@ -5657,18 +5698,11 @@ fn createThunks(elf_file: *Elf, shdr: *elf.Elf64_Shdr, shndx: u32) !void { |
| 5657 | atom_ptr.addExtra(.{ .thunk = thunk_index }, elf_file); | 5698 | atom_ptr.addExtra(.{ .thunk = thunk_index }, elf_file); |
| 5658 | } | 5699 | } |
| 5659 | 5700 | ||
| 5660 | thunk_ptr.value = try advanceSection(shdr, thunk_ptr.size(elf_file), Atom.Alignment.fromNonzeroByteUnits(2)); | 5701 | thunk_ptr.value = try advance(atom_list, thunk_ptr.size(elf_file), Atom.Alignment.fromNonzeroByteUnits(2)); |
| 5661 | 5702 | ||
| 5662 | log.debug("thunk({d}) : {}", .{ thunk_index, thunk_ptr.fmt(elf_file) }); | 5703 | log.debug("thunk({d}) : {}", .{ thunk_index, thunk_ptr.fmt(elf_file) }); |
| 5663 | } | 5704 | } |
| 5664 | } | 5705 | } |
| 5665 | fn advanceSection(shdr: *elf.Elf64_Shdr, adv_size: u64, alignment: Atom.Alignment) !i64 { | ||
| 5666 | const offset = alignment.forward(shdr.sh_size); | ||
| 5667 | const padding = offset - shdr.sh_size; | ||
| 5668 | shdr.sh_size += padding + adv_size; | ||
| 5669 | shdr.sh_addralign = @max(shdr.sh_addralign, alignment.toByteUnits() orelse 1); | ||
| 5670 | return @intCast(offset); | ||
| 5671 | } | ||
| 5672 | 5706 | ||
| 5673 | const std = @import("std"); | 5707 | const std = @import("std"); |
| 5674 | const build_options = @import("build_options"); | 5708 | const build_options = @import("build_options"); |
| ... | @@ -5699,6 +5733,7 @@ const Air = @import("../Air.zig"); | ... | @@ -5699,6 +5733,7 @@ const Air = @import("../Air.zig"); |
| 5699 | const Allocator = std.mem.Allocator; | 5733 | const Allocator = std.mem.Allocator; |
| 5700 | const Archive = @import("Elf/Archive.zig"); | 5734 | const Archive = @import("Elf/Archive.zig"); |
| 5701 | pub const Atom = @import("Elf/Atom.zig"); | 5735 | pub const Atom = @import("Elf/Atom.zig"); |
| 5736 | const AtomList = @import("Elf/AtomList.zig"); | ||
| 5702 | const Cache = std.Build.Cache; | 5737 | const Cache = std.Build.Cache; |
| 5703 | const Path = Cache.Path; | 5738 | const Path = Cache.Path; |
| 5704 | const Compilation = @import("../Compilation.zig"); | 5739 | const Compilation = @import("../Compilation.zig"); |
src/link/Elf/Atom.zig+15-144| ... | @@ -51,6 +51,11 @@ pub fn address(self: Atom, elf_file: *Elf) i64 { | ... | @@ -51,6 +51,11 @@ pub fn address(self: Atom, elf_file: *Elf) i64 { |
| 51 | return @as(i64, @intCast(shdr.sh_addr)) + self.value; | 51 | return @as(i64, @intCast(shdr.sh_addr)) + self.value; |
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | pub fn offset(self: Atom, elf_file: *Elf) u64 { | ||
| 55 | const shdr = elf_file.sections.items(.shdr)[self.output_section_index]; | ||
| 56 | return shdr.sh_offset + @as(u64, @intCast(self.value)); | ||
| 57 | } | ||
| 58 | |||
| 54 | pub fn ref(self: Atom) Elf.Ref { | 59 | pub fn ref(self: Atom) Elf.Ref { |
| 55 | return .{ .index = self.atom_index, .file = self.file_index }; | 60 | return .{ .index = self.atom_index, .file = self.file_index }; |
| 56 | } | 61 | } |
| ... | @@ -123,140 +128,6 @@ pub fn freeListEligible(self: Atom, elf_file: *Elf) bool { | ... | @@ -123,140 +128,6 @@ pub fn freeListEligible(self: Atom, elf_file: *Elf) bool { |
| 123 | return surplus >= Elf.min_text_capacity; | 128 | return surplus >= Elf.min_text_capacity; |
| 124 | } | 129 | } |
| 125 | 130 | ||
| 126 | pub fn allocate(self: *Atom, elf_file: *Elf) !void { | ||
| 127 | const slice = elf_file.sections.slice(); | ||
| 128 | const shdr = &slice.items(.shdr)[self.output_section_index]; | ||
| 129 | const free_list = &slice.items(.free_list)[self.output_section_index]; | ||
| 130 | const last_atom_ref = &slice.items(.last_atom)[self.output_section_index]; | ||
| 131 | const new_atom_ideal_capacity = Elf.padToIdeal(self.size); | ||
| 132 | |||
| 133 | // We use these to indicate our intention to update metadata, placing the new atom, | ||
| 134 | // and possibly removing a free list node. | ||
| 135 | // It would be simpler to do it inside the for loop below, but that would cause a | ||
| 136 | // problem if an error was returned later in the function. So this action | ||
| 137 | // is actually carried out at the end of the function, when errors are no longer possible. | ||
| 138 | var atom_placement: ?Elf.Ref = null; | ||
| 139 | var free_list_removal: ?usize = null; | ||
| 140 | |||
| 141 | // First we look for an appropriately sized free list node. | ||
| 142 | // The list is unordered. We'll just take the first thing that works. | ||
| 143 | self.value = blk: { | ||
| 144 | var i: usize = if (elf_file.base.child_pid == null) 0 else free_list.items.len; | ||
| 145 | while (i < free_list.items.len) { | ||
| 146 | const big_atom_ref = free_list.items[i]; | ||
| 147 | const big_atom = elf_file.atom(big_atom_ref).?; | ||
| 148 | // We now have a pointer to a live atom that has too much capacity. | ||
| 149 | // Is it enough that we could fit this new atom? | ||
| 150 | const cap = big_atom.capacity(elf_file); | ||
| 151 | const ideal_capacity = Elf.padToIdeal(cap); | ||
| 152 | const ideal_capacity_end_vaddr = std.math.add(u64, @intCast(big_atom.value), ideal_capacity) catch ideal_capacity; | ||
| 153 | const capacity_end_vaddr = @as(u64, @intCast(big_atom.value)) + cap; | ||
| 154 | const new_start_vaddr_unaligned = capacity_end_vaddr - new_atom_ideal_capacity; | ||
| 155 | const new_start_vaddr = self.alignment.backward(new_start_vaddr_unaligned); | ||
| 156 | if (new_start_vaddr < ideal_capacity_end_vaddr) { | ||
| 157 | // Additional bookkeeping here to notice if this free list node | ||
| 158 | // should be deleted because the block that it points to has grown to take up | ||
| 159 | // more of the extra capacity. | ||
| 160 | if (!big_atom.freeListEligible(elf_file)) { | ||
| 161 | _ = free_list.swapRemove(i); | ||
| 162 | } else { | ||
| 163 | i += 1; | ||
| 164 | } | ||
| 165 | continue; | ||
| 166 | } | ||
| 167 | // At this point we know that we will place the new block here. But the | ||
| 168 | // remaining question is whether there is still yet enough capacity left | ||
| 169 | // over for there to still be a free list node. | ||
| 170 | const remaining_capacity = new_start_vaddr - ideal_capacity_end_vaddr; | ||
| 171 | const keep_free_list_node = remaining_capacity >= Elf.min_text_capacity; | ||
| 172 | |||
| 173 | // Set up the metadata to be updated, after errors are no longer possible. | ||
| 174 | atom_placement = big_atom_ref; | ||
| 175 | if (!keep_free_list_node) { | ||
| 176 | free_list_removal = i; | ||
| 177 | } | ||
| 178 | break :blk @intCast(new_start_vaddr); | ||
| 179 | } else if (elf_file.atom(last_atom_ref.*)) |last_atom| { | ||
| 180 | const ideal_capacity = Elf.padToIdeal(last_atom.size); | ||
| 181 | const ideal_capacity_end_vaddr = @as(u64, @intCast(last_atom.value)) + ideal_capacity; | ||
| 182 | const new_start_vaddr = self.alignment.forward(ideal_capacity_end_vaddr); | ||
| 183 | // Set up the metadata to be updated, after errors are no longer possible. | ||
| 184 | atom_placement = last_atom.ref(); | ||
| 185 | break :blk @intCast(new_start_vaddr); | ||
| 186 | } else { | ||
| 187 | break :blk 0; | ||
| 188 | } | ||
| 189 | }; | ||
| 190 | |||
| 191 | log.debug("allocated atom({}) : '{s}' at 0x{x} to 0x{x}", .{ | ||
| 192 | self.ref(), | ||
| 193 | self.name(elf_file), | ||
| 194 | self.address(elf_file), | ||
| 195 | self.address(elf_file) + @as(i64, @intCast(self.size)), | ||
| 196 | }); | ||
| 197 | |||
| 198 | const expand_section = if (atom_placement) |placement_ref| | ||
| 199 | elf_file.atom(placement_ref).?.nextAtom(elf_file) == null | ||
| 200 | else | ||
| 201 | true; | ||
| 202 | if (expand_section) { | ||
| 203 | const needed_size: u64 = @intCast(self.value + @as(i64, @intCast(self.size))); | ||
| 204 | try elf_file.growAllocSection(self.output_section_index, needed_size); | ||
| 205 | last_atom_ref.* = self.ref(); | ||
| 206 | |||
| 207 | switch (self.file(elf_file).?) { | ||
| 208 | .zig_object => |zo| if (zo.dwarf) |_| { | ||
| 209 | // The .debug_info section has `low_pc` and `high_pc` values which is the virtual address | ||
| 210 | // range of the compilation unit. When we expand the text section, this range changes, | ||
| 211 | // so the DW_TAG.compile_unit tag of the .debug_info section becomes dirty. | ||
| 212 | zo.debug_info_section_dirty = true; | ||
| 213 | // This becomes dirty for the same reason. We could potentially make this more | ||
| 214 | // fine-grained with the addition of support for more compilation units. It is planned to | ||
| 215 | // model each package as a different compilation unit. | ||
| 216 | zo.debug_aranges_section_dirty = true; | ||
| 217 | zo.debug_rnglists_section_dirty = true; | ||
| 218 | }, | ||
| 219 | else => {}, | ||
| 220 | } | ||
| 221 | } | ||
| 222 | shdr.sh_addralign = @max(shdr.sh_addralign, self.alignment.toByteUnits().?); | ||
| 223 | |||
| 224 | // This function can also reallocate an atom. | ||
| 225 | // In this case we need to "unplug" it from its previous location before | ||
| 226 | // plugging it in to its new location. | ||
| 227 | if (self.prevAtom(elf_file)) |prev| { | ||
| 228 | prev.next_atom_ref = self.next_atom_ref; | ||
| 229 | } | ||
| 230 | if (self.nextAtom(elf_file)) |next| { | ||
| 231 | next.prev_atom_ref = self.prev_atom_ref; | ||
| 232 | } | ||
| 233 | |||
| 234 | if (atom_placement) |big_atom_ref| { | ||
| 235 | const big_atom = elf_file.atom(big_atom_ref).?; | ||
| 236 | self.prev_atom_ref = big_atom_ref; | ||
| 237 | self.next_atom_ref = big_atom.next_atom_ref; | ||
| 238 | big_atom.next_atom_ref = self.ref(); | ||
| 239 | } else { | ||
| 240 | self.prev_atom_ref = .{ .index = 0, .file = 0 }; | ||
| 241 | self.next_atom_ref = .{ .index = 0, .file = 0 }; | ||
| 242 | } | ||
| 243 | if (free_list_removal) |i| { | ||
| 244 | _ = free_list.swapRemove(i); | ||
| 245 | } | ||
| 246 | |||
| 247 | self.alive = true; | ||
| 248 | } | ||
| 249 | |||
| 250 | pub fn shrink(self: *Atom, elf_file: *Elf) void { | ||
| 251 | _ = self; | ||
| 252 | _ = elf_file; | ||
| 253 | } | ||
| 254 | |||
| 255 | pub fn grow(self: *Atom, elf_file: *Elf) !void { | ||
| 256 | if (!self.alignment.check(@intCast(self.value)) or self.size > self.capacity(elf_file)) | ||
| 257 | try self.allocate(elf_file); | ||
| 258 | } | ||
| 259 | |||
| 260 | pub fn free(self: *Atom, elf_file: *Elf) void { | 131 | pub fn free(self: *Atom, elf_file: *Elf) void { |
| 261 | log.debug("freeAtom atom({}) ({s})", .{ self.ref(), self.name(elf_file) }); | 132 | log.debug("freeAtom atom({}) ({s})", .{ self.ref(), self.name(elf_file) }); |
| 262 | 133 | ||
| ... | @@ -1807,7 +1678,7 @@ const aarch64 = struct { | ... | @@ -1807,7 +1678,7 @@ const aarch64 = struct { |
| 1807 | => { | 1678 | => { |
| 1808 | // TODO: NC means no overflow check | 1679 | // TODO: NC means no overflow check |
| 1809 | const taddr = @as(u64, @intCast(S + A)); | 1680 | const taddr = @as(u64, @intCast(S + A)); |
| 1810 | const offset: u12 = switch (r_type) { | 1681 | const off: u12 = switch (r_type) { |
| 1811 | .LDST8_ABS_LO12_NC => @truncate(taddr), | 1682 | .LDST8_ABS_LO12_NC => @truncate(taddr), |
| 1812 | .LDST16_ABS_LO12_NC => @divExact(@as(u12, @truncate(taddr)), 2), | 1683 | .LDST16_ABS_LO12_NC => @divExact(@as(u12, @truncate(taddr)), 2), |
| 1813 | .LDST32_ABS_LO12_NC => @divExact(@as(u12, @truncate(taddr)), 4), | 1684 | .LDST32_ABS_LO12_NC => @divExact(@as(u12, @truncate(taddr)), 4), |
| ... | @@ -1815,7 +1686,7 @@ const aarch64 = struct { | ... | @@ -1815,7 +1686,7 @@ const aarch64 = struct { |
| 1815 | .LDST128_ABS_LO12_NC => @divExact(@as(u12, @truncate(taddr)), 16), | 1686 | .LDST128_ABS_LO12_NC => @divExact(@as(u12, @truncate(taddr)), 16), |
| 1816 | else => unreachable, | 1687 | else => unreachable, |
| 1817 | }; | 1688 | }; |
| 1818 | aarch64_util.writeLoadStoreRegInst(offset, code); | 1689 | aarch64_util.writeLoadStoreRegInst(off, code); |
| 1819 | }, | 1690 | }, |
| 1820 | 1691 | ||
| 1821 | .TLSLE_ADD_TPREL_HI12 => { | 1692 | .TLSLE_ADD_TPREL_HI12 => { |
| ... | @@ -1839,8 +1710,8 @@ const aarch64 = struct { | ... | @@ -1839,8 +1710,8 @@ const aarch64 = struct { |
| 1839 | .TLSIE_LD64_GOTTPREL_LO12_NC => { | 1710 | .TLSIE_LD64_GOTTPREL_LO12_NC => { |
| 1840 | const S_ = target.gotTpAddress(elf_file); | 1711 | const S_ = target.gotTpAddress(elf_file); |
| 1841 | relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A }); | 1712 | relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A }); |
| 1842 | const offset: u12 = try math.divExact(u12, @truncate(@as(u64, @bitCast(S_ + A))), 8); | 1713 | const off: u12 = try math.divExact(u12, @truncate(@as(u64, @bitCast(S_ + A))), 8); |
| 1843 | aarch64_util.writeLoadStoreRegInst(offset, code); | 1714 | aarch64_util.writeLoadStoreRegInst(off, code); |
| 1844 | }, | 1715 | }, |
| 1845 | 1716 | ||
| 1846 | .TLSGD_ADR_PAGE21 => { | 1717 | .TLSGD_ADR_PAGE21 => { |
| ... | @@ -1853,8 +1724,8 @@ const aarch64 = struct { | ... | @@ -1853,8 +1724,8 @@ const aarch64 = struct { |
| 1853 | .TLSGD_ADD_LO12_NC => { | 1724 | .TLSGD_ADD_LO12_NC => { |
| 1854 | const S_ = target.tlsGdAddress(elf_file); | 1725 | const S_ = target.tlsGdAddress(elf_file); |
| 1855 | relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A }); | 1726 | relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A }); |
| 1856 | const offset: u12 = @truncate(@as(u64, @bitCast(S_ + A))); | 1727 | const off: u12 = @truncate(@as(u64, @bitCast(S_ + A))); |
| 1857 | aarch64_util.writeAddImmInst(offset, code); | 1728 | aarch64_util.writeAddImmInst(off, code); |
| 1858 | }, | 1729 | }, |
| 1859 | 1730 | ||
| 1860 | .TLSDESC_ADR_PAGE21 => { | 1731 | .TLSDESC_ADR_PAGE21 => { |
| ... | @@ -1873,8 +1744,8 @@ const aarch64 = struct { | ... | @@ -1873,8 +1744,8 @@ const aarch64 = struct { |
| 1873 | if (target.flags.has_tlsdesc) { | 1744 | if (target.flags.has_tlsdesc) { |
| 1874 | const S_ = target.tlsDescAddress(elf_file); | 1745 | const S_ = target.tlsDescAddress(elf_file); |
| 1875 | relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A }); | 1746 | relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A }); |
| 1876 | const offset: u12 = try math.divExact(u12, @truncate(@as(u64, @bitCast(S_ + A))), 8); | 1747 | const off: u12 = try math.divExact(u12, @truncate(@as(u64, @bitCast(S_ + A))), 8); |
| 1877 | aarch64_util.writeLoadStoreRegInst(offset, code); | 1748 | aarch64_util.writeLoadStoreRegInst(off, code); |
| 1878 | } else { | 1749 | } else { |
| 1879 | relocs_log.debug(" relaxing ldr => nop", .{}); | 1750 | relocs_log.debug(" relaxing ldr => nop", .{}); |
| 1880 | mem.writeInt(u32, code, Instruction.nop().toU32(), .little); | 1751 | mem.writeInt(u32, code, Instruction.nop().toU32(), .little); |
| ... | @@ -1885,8 +1756,8 @@ const aarch64 = struct { | ... | @@ -1885,8 +1756,8 @@ const aarch64 = struct { |
| 1885 | if (target.flags.has_tlsdesc) { | 1756 | if (target.flags.has_tlsdesc) { |
| 1886 | const S_ = target.tlsDescAddress(elf_file); | 1757 | const S_ = target.tlsDescAddress(elf_file); |
| 1887 | relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A }); | 1758 | relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A }); |
| 1888 | const offset: u12 = @truncate(@as(u64, @bitCast(S_ + A))); | 1759 | const off: u12 = @truncate(@as(u64, @bitCast(S_ + A))); |
| 1889 | aarch64_util.writeAddImmInst(offset, code); | 1760 | aarch64_util.writeAddImmInst(off, code); |
| 1890 | } else { | 1761 | } else { |
| 1891 | const old_inst = Instruction{ | 1762 | const old_inst = Instruction{ |
| 1892 | .add_subtract_immediate = mem.bytesToValue(std.meta.TagPayload( | 1763 | .add_subtract_immediate = mem.bytesToValue(std.meta.TagPayload( |
src/link/Elf/AtomList.zig created+208| ... | @@ -0,0 +1,208 @@ | ||
| 1 | value: i64 = 0, | ||
| 2 | size: u64 = 0, | ||
| 3 | alignment: Atom.Alignment = .@"1", | ||
| 4 | output_section_index: u32 = 0, | ||
| 5 | atoms: std.ArrayListUnmanaged(Elf.Ref) = .{}, | ||
| 6 | |||
| 7 | pub fn deinit(list: *AtomList, allocator: Allocator) void { | ||
| 8 | list.atoms.deinit(allocator); | ||
| 9 | } | ||
| 10 | |||
| 11 | pub fn address(list: AtomList, elf_file: *Elf) i64 { | ||
| 12 | const shdr = elf_file.sections.items(.shdr)[list.output_section_index]; | ||
| 13 | return @as(i64, @intCast(shdr.sh_addr)) + list.value; | ||
| 14 | } | ||
| 15 | |||
| 16 | pub fn offset(list: AtomList, elf_file: *Elf) u64 { | ||
| 17 | const shdr = elf_file.sections.items(.shdr)[list.output_section_index]; | ||
| 18 | return shdr.sh_offset + @as(u64, @intCast(list.value)); | ||
| 19 | } | ||
| 20 | |||
| 21 | pub fn updateSize(list: *AtomList, elf_file: *Elf) void { | ||
| 22 | for (list.atoms.items) |ref| { | ||
| 23 | const atom_ptr = elf_file.atom(ref).?; | ||
| 24 | assert(atom_ptr.alive); | ||
| 25 | const off = atom_ptr.alignment.forward(list.size); | ||
| 26 | const padding = off - list.size; | ||
| 27 | atom_ptr.value = @intCast(off); | ||
| 28 | list.size += padding + atom_ptr.size; | ||
| 29 | list.alignment = list.alignment.max(atom_ptr.alignment); | ||
| 30 | } | ||
| 31 | } | ||
| 32 | |||
| 33 | pub fn allocate(list: *AtomList, elf_file: *Elf) !void { | ||
| 34 | const alloc_res = try elf_file.allocateChunk(.{ | ||
| 35 | .shndx = list.output_section_index, | ||
| 36 | .size = list.size, | ||
| 37 | .alignment = list.alignment, | ||
| 38 | .requires_padding = false, | ||
| 39 | }); | ||
| 40 | list.value = @intCast(alloc_res.value); | ||
| 41 | |||
| 42 | const slice = elf_file.sections.slice(); | ||
| 43 | const shdr = &slice.items(.shdr)[list.output_section_index]; | ||
| 44 | const last_atom_ref = &slice.items(.last_atom)[list.output_section_index]; | ||
| 45 | |||
| 46 | const expand_section = if (elf_file.atom(alloc_res.placement)) |placement_atom| | ||
| 47 | placement_atom.nextAtom(elf_file) == null | ||
| 48 | else | ||
| 49 | true; | ||
| 50 | if (expand_section) last_atom_ref.* = list.lastAtom(elf_file).ref(); | ||
| 51 | shdr.sh_addralign = @max(shdr.sh_addralign, list.alignment.toByteUnits().?); | ||
| 52 | |||
| 53 | // FIXME:JK this currently ignores Thunks as valid chunks. | ||
| 54 | { | ||
| 55 | var idx: usize = 0; | ||
| 56 | while (idx < list.atoms.items.len) : (idx += 1) { | ||
| 57 | const curr_atom_ptr = elf_file.atom(list.atoms.items[idx]).?; | ||
| 58 | if (idx > 0) { | ||
| 59 | curr_atom_ptr.prev_atom_ref = list.atoms.items[idx - 1]; | ||
| 60 | } | ||
| 61 | if (idx + 1 < list.atoms.items.len) { | ||
| 62 | curr_atom_ptr.next_atom_ref = list.atoms.items[idx + 1]; | ||
| 63 | } | ||
| 64 | } | ||
| 65 | } | ||
| 66 | |||
| 67 | if (elf_file.atom(alloc_res.placement)) |placement_atom| { | ||
| 68 | list.firstAtom(elf_file).prev_atom_ref = placement_atom.ref(); | ||
| 69 | list.lastAtom(elf_file).next_atom_ref = placement_atom.next_atom_ref; | ||
| 70 | placement_atom.next_atom_ref = list.firstAtom(elf_file).ref(); | ||
| 71 | } | ||
| 72 | |||
| 73 | // FIXME:JK if we had a link from Atom to parent AtomList we would not need to update Atom's value or osec index | ||
| 74 | for (list.atoms.items) |ref| { | ||
| 75 | const atom_ptr = elf_file.atom(ref).?; | ||
| 76 | atom_ptr.output_section_index = list.output_section_index; | ||
| 77 | atom_ptr.value += list.value; | ||
| 78 | } | ||
| 79 | } | ||
| 80 | |||
| 81 | pub fn write(list: AtomList, buffer: *std.ArrayList(u8), undefs: anytype, elf_file: *Elf) !void { | ||
| 82 | const gpa = elf_file.base.comp.gpa; | ||
| 83 | const osec = elf_file.sections.items(.shdr)[list.output_section_index]; | ||
| 84 | assert(osec.sh_type != elf.SHT_NOBITS); | ||
| 85 | |||
| 86 | log.debug("writing atoms in section '{s}'", .{elf_file.getShString(osec.sh_name)}); | ||
| 87 | |||
| 88 | const list_size = math.cast(usize, list.size) orelse return error.Overflow; | ||
| 89 | try buffer.ensureUnusedCapacity(list_size); | ||
| 90 | buffer.appendNTimesAssumeCapacity(0, list_size); | ||
| 91 | |||
| 92 | for (list.atoms.items) |ref| { | ||
| 93 | const atom_ptr = elf_file.atom(ref).?; | ||
| 94 | assert(atom_ptr.alive); | ||
| 95 | |||
| 96 | const off = math.cast(usize, atom_ptr.value - list.value) orelse return error.Overflow; | ||
| 97 | const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow; | ||
| 98 | |||
| 99 | log.debug(" atom({}) at 0x{x}", .{ ref, list.offset(elf_file) + off }); | ||
| 100 | |||
| 101 | const object = atom_ptr.file(elf_file).?.object; | ||
| 102 | const code = try object.codeDecompressAlloc(elf_file, ref.index); | ||
| 103 | defer gpa.free(code); | ||
| 104 | const out_code = buffer.items[off..][0..size]; | ||
| 105 | @memcpy(out_code, code); | ||
| 106 | |||
| 107 | if (osec.sh_flags & elf.SHF_ALLOC == 0) | ||
| 108 | try atom_ptr.resolveRelocsNonAlloc(elf_file, out_code, undefs) | ||
| 109 | else | ||
| 110 | try atom_ptr.resolveRelocsAlloc(elf_file, out_code); | ||
| 111 | } | ||
| 112 | |||
| 113 | try elf_file.base.file.?.pwriteAll(buffer.items, list.offset(elf_file)); | ||
| 114 | buffer.clearRetainingCapacity(); | ||
| 115 | } | ||
| 116 | |||
| 117 | pub fn writeRelocatable(list: AtomList, buffer: *std.ArrayList(u8), elf_file: *Elf) !void { | ||
| 118 | const gpa = elf_file.base.comp.gpa; | ||
| 119 | const osec = elf_file.sections.items(.shdr)[list.output_section_index]; | ||
| 120 | assert(osec.sh_type != elf.SHT_NOBITS); | ||
| 121 | |||
| 122 | log.debug("writing atoms in section '{s}'", .{elf_file.getShString(osec.sh_name)}); | ||
| 123 | |||
| 124 | const list_size = math.cast(usize, list.size) orelse return error.Overflow; | ||
| 125 | try buffer.ensureUnusedCapacity(list_size); | ||
| 126 | buffer.appendNTimesAssumeCapacity(0, list_size); | ||
| 127 | |||
| 128 | for (list.atoms.items) |ref| { | ||
| 129 | const atom_ptr = elf_file.atom(ref).?; | ||
| 130 | assert(atom_ptr.alive); | ||
| 131 | |||
| 132 | const off = math.cast(usize, atom_ptr.value - list.value) orelse return error.Overflow; | ||
| 133 | const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow; | ||
| 134 | |||
| 135 | log.debug(" atom({}) at 0x{x}", .{ ref, list.offset(elf_file) + off }); | ||
| 136 | |||
| 137 | const object = atom_ptr.file(elf_file).?.object; | ||
| 138 | const code = try object.codeDecompressAlloc(elf_file, ref.index); | ||
| 139 | defer gpa.free(code); | ||
| 140 | const out_code = buffer.items[off..][0..size]; | ||
| 141 | @memcpy(out_code, code); | ||
| 142 | } | ||
| 143 | |||
| 144 | try elf_file.base.file.?.pwriteAll(buffer.items, list.offset(elf_file)); | ||
| 145 | buffer.clearRetainingCapacity(); | ||
| 146 | } | ||
| 147 | |||
| 148 | pub fn firstAtom(list: AtomList, elf_file: *Elf) *Atom { | ||
| 149 | assert(list.atoms.items.len > 0); | ||
| 150 | return elf_file.atom(list.atoms.items[0]).?; | ||
| 151 | } | ||
| 152 | |||
| 153 | pub fn lastAtom(list: AtomList, elf_file: *Elf) *Atom { | ||
| 154 | assert(list.atoms.items.len > 0); | ||
| 155 | return elf_file.atom(list.atoms.items[list.atoms.items.len - 1]).?; | ||
| 156 | } | ||
| 157 | |||
| 158 | pub fn format( | ||
| 159 | list: AtomList, | ||
| 160 | comptime unused_fmt_string: []const u8, | ||
| 161 | options: std.fmt.FormatOptions, | ||
| 162 | writer: anytype, | ||
| 163 | ) !void { | ||
| 164 | _ = list; | ||
| 165 | _ = unused_fmt_string; | ||
| 166 | _ = options; | ||
| 167 | _ = writer; | ||
| 168 | @compileError("do not format AtomList directly"); | ||
| 169 | } | ||
| 170 | |||
| 171 | const FormatCtx = struct { AtomList, *Elf }; | ||
| 172 | |||
| 173 | pub fn fmt(list: AtomList, elf_file: *Elf) std.fmt.Formatter(format2) { | ||
| 174 | return .{ .data = .{ list, elf_file } }; | ||
| 175 | } | ||
| 176 | |||
| 177 | fn format2( | ||
| 178 | ctx: FormatCtx, | ||
| 179 | comptime unused_fmt_string: []const u8, | ||
| 180 | options: std.fmt.FormatOptions, | ||
| 181 | writer: anytype, | ||
| 182 | ) !void { | ||
| 183 | _ = unused_fmt_string; | ||
| 184 | _ = options; | ||
| 185 | const list, const elf_file = ctx; | ||
| 186 | try writer.print("list : @{x} : shdr({d}) : align({x}) : size({x})", .{ | ||
| 187 | list.address(elf_file), list.output_section_index, | ||
| 188 | list.alignment.toByteUnits() orelse 0, list.size, | ||
| 189 | }); | ||
| 190 | try writer.writeAll(" : atoms{ "); | ||
| 191 | for (list.atoms.items, 0..) |ref, i| { | ||
| 192 | try writer.print("{}", .{ref}); | ||
| 193 | if (i < list.atoms.items.len - 1) try writer.writeAll(", "); | ||
| 194 | } | ||
| 195 | try writer.writeAll(" }"); | ||
| 196 | } | ||
| 197 | |||
| 198 | const assert = std.debug.assert; | ||
| 199 | const elf = std.elf; | ||
| 200 | const log = std.log.scoped(.link); | ||
| 201 | const math = std.math; | ||
| 202 | const std = @import("std"); | ||
| 203 | |||
| 204 | const Allocator = std.mem.Allocator; | ||
| 205 | const Atom = @import("Atom.zig"); | ||
| 206 | const AtomList = @This(); | ||
| 207 | const Elf = @import("../Elf.zig"); | ||
| 208 | const Object = @import("Object.zig"); | ||
src/link/Elf/Object.zig+42-81| ... | @@ -311,58 +311,6 @@ fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file: | ... | @@ -311,58 +311,6 @@ fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file: |
| 311 | }; | 311 | }; |
| 312 | } | 312 | } |
| 313 | 313 | ||
| 314 | fn initOutputSection(self: Object, elf_file: *Elf, shdr: elf.Elf64_Shdr) error{OutOfMemory}!u32 { | ||
| 315 | const name = blk: { | ||
| 316 | const name = self.getString(shdr.sh_name); | ||
| 317 | if (elf_file.base.isRelocatable()) break :blk name; | ||
| 318 | if (shdr.sh_flags & elf.SHF_MERGE != 0) break :blk name; | ||
| 319 | const sh_name_prefixes: []const [:0]const u8 = &.{ | ||
| 320 | ".text", ".data.rel.ro", ".data", ".rodata", ".bss.rel.ro", ".bss", | ||
| 321 | ".init_array", ".fini_array", ".tbss", ".tdata", ".gcc_except_table", ".ctors", | ||
| 322 | ".dtors", ".gnu.warning", | ||
| 323 | }; | ||
| 324 | inline for (sh_name_prefixes) |prefix| { | ||
| 325 | if (std.mem.eql(u8, name, prefix) or std.mem.startsWith(u8, name, prefix ++ ".")) { | ||
| 326 | break :blk prefix; | ||
| 327 | } | ||
| 328 | } | ||
| 329 | break :blk name; | ||
| 330 | }; | ||
| 331 | const @"type" = tt: { | ||
| 332 | if (elf_file.getTarget().cpu.arch == .x86_64 and | ||
| 333 | shdr.sh_type == elf.SHT_X86_64_UNWIND) break :tt elf.SHT_PROGBITS; | ||
| 334 | |||
| 335 | const @"type" = switch (shdr.sh_type) { | ||
| 336 | elf.SHT_NULL => unreachable, | ||
| 337 | elf.SHT_PROGBITS => blk: { | ||
| 338 | if (std.mem.eql(u8, name, ".init_array") or std.mem.startsWith(u8, name, ".init_array.")) | ||
| 339 | break :blk elf.SHT_INIT_ARRAY; | ||
| 340 | if (std.mem.eql(u8, name, ".fini_array") or std.mem.startsWith(u8, name, ".fini_array.")) | ||
| 341 | break :blk elf.SHT_FINI_ARRAY; | ||
| 342 | break :blk shdr.sh_type; | ||
| 343 | }, | ||
| 344 | else => shdr.sh_type, | ||
| 345 | }; | ||
| 346 | break :tt @"type"; | ||
| 347 | }; | ||
| 348 | const flags = blk: { | ||
| 349 | var flags = shdr.sh_flags; | ||
| 350 | if (!elf_file.base.isRelocatable()) { | ||
| 351 | flags &= ~@as(u64, elf.SHF_COMPRESSED | elf.SHF_GROUP | elf.SHF_GNU_RETAIN); | ||
| 352 | } | ||
| 353 | break :blk switch (@"type") { | ||
| 354 | elf.SHT_INIT_ARRAY, elf.SHT_FINI_ARRAY => flags | elf.SHF_WRITE, | ||
| 355 | else => flags, | ||
| 356 | }; | ||
| 357 | }; | ||
| 358 | const out_shndx = elf_file.sectionByName(name) orelse try elf_file.addSection(.{ | ||
| 359 | .type = @"type", | ||
| 360 | .flags = flags, | ||
| 361 | .name = try elf_file.insertShString(name), | ||
| 362 | }); | ||
| 363 | return out_shndx; | ||
| 364 | } | ||
| 365 | |||
| 366 | fn skipShdr(self: *Object, index: u32, elf_file: *Elf) bool { | 314 | fn skipShdr(self: *Object, index: u32, elf_file: *Elf) bool { |
| 367 | const comp = elf_file.base.comp; | 315 | const comp = elf_file.base.comp; |
| 368 | const shdr = self.shdrs.items[index]; | 316 | const shdr = self.shdrs.items[index]; |
| ... | @@ -438,15 +386,24 @@ fn parseEhFrame(self: *Object, allocator: Allocator, handle: std.fs.File, shndx: | ... | @@ -438,15 +386,24 @@ fn parseEhFrame(self: *Object, allocator: Allocator, handle: std.fs.File, shndx: |
| 438 | .input_section_index = shndx, | 386 | .input_section_index = shndx, |
| 439 | .file_index = self.index, | 387 | .file_index = self.index, |
| 440 | }), | 388 | }), |
| 441 | .fde => try self.fdes.append(allocator, .{ | 389 | .fde => { |
| 442 | .offset = data_start + rec.offset, | 390 | if (rel_range.len == 0) { |
| 443 | .size = rec.size, | 391 | // No relocs for an FDE means we cannot associate this FDE to an Atom |
| 444 | .cie_index = undefined, | 392 | // so we skip it. According to mold source code |
| 445 | .rel_index = rel_start + @as(u32, @intCast(rel_range.start)), | 393 | // (https://github.com/rui314/mold/blob/a3e69502b0eaf1126d6093e8ea5e6fdb95219811/src/input-files.cc#L525-L528) |
| 446 | .rel_num = @as(u32, @intCast(rel_range.len)), | 394 | // this can happen for object files built with -r flag by the linker. |
| 447 | .input_section_index = shndx, | 395 | continue; |
| 448 | .file_index = self.index, | 396 | } |
| 449 | }), | 397 | try self.fdes.append(allocator, .{ |
| 398 | .offset = data_start + rec.offset, | ||
| 399 | .size = rec.size, | ||
| 400 | .cie_index = undefined, | ||
| 401 | .rel_index = rel_start + @as(u32, @intCast(rel_range.start)), | ||
| 402 | .rel_num = @as(u32, @intCast(rel_range.len)), | ||
| 403 | .input_section_index = shndx, | ||
| 404 | .file_index = self.index, | ||
| 405 | }); | ||
| 406 | }, | ||
| 450 | } | 407 | } |
| 451 | } | 408 | } |
| 452 | 409 | ||
| ... | @@ -622,7 +579,7 @@ pub fn claimUnresolved(self: *Object, elf_file: *Elf) void { | ... | @@ -622,7 +579,7 @@ pub fn claimUnresolved(self: *Object, elf_file: *Elf) void { |
| 622 | } | 579 | } |
| 623 | } | 580 | } |
| 624 | 581 | ||
| 625 | pub fn claimUnresolvedObject(self: *Object, elf_file: *Elf) void { | 582 | pub fn claimUnresolvedRelocatable(self: *Object, elf_file: *Elf) void { |
| 626 | const first_global = self.first_global orelse return; | 583 | const first_global = self.first_global orelse return; |
| 627 | for (self.globals(), 0..) |*sym, i| { | 584 | for (self.globals(), 0..) |*sym, i| { |
| 628 | const esym_index = @as(u32, @intCast(first_global + i)); | 585 | const esym_index = @as(u32, @intCast(first_global + i)); |
| ... | @@ -985,21 +942,14 @@ pub fn initOutputSections(self: *Object, elf_file: *Elf) !void { | ... | @@ -985,21 +942,14 @@ pub fn initOutputSections(self: *Object, elf_file: *Elf) !void { |
| 985 | const atom_ptr = self.atom(atom_index) orelse continue; | 942 | const atom_ptr = self.atom(atom_index) orelse continue; |
| 986 | if (!atom_ptr.alive) continue; | 943 | if (!atom_ptr.alive) continue; |
| 987 | const shdr = atom_ptr.inputShdr(elf_file); | 944 | const shdr = atom_ptr.inputShdr(elf_file); |
| 988 | _ = try self.initOutputSection(elf_file, shdr); | 945 | const osec = try elf_file.initOutputSection(.{ |
| 989 | } | 946 | .name = self.getString(shdr.sh_name), |
| 990 | } | 947 | .flags = shdr.sh_flags, |
| 991 | 948 | .type = shdr.sh_type, | |
| 992 | pub fn addAtomsToOutputSections(self: *Object, elf_file: *Elf) !void { | 949 | }); |
| 993 | for (self.atoms_indexes.items) |atom_index| { | 950 | const atom_list = &elf_file.sections.items(.atom_list_2)[osec]; |
| 994 | const atom_ptr = self.atom(atom_index) orelse continue; | 951 | atom_list.output_section_index = osec; |
| 995 | if (!atom_ptr.alive) continue; | 952 | try atom_list.atoms.append(elf_file.base.comp.gpa, atom_ptr.ref()); |
| 996 | const shdr = atom_ptr.inputShdr(elf_file); | ||
| 997 | atom_ptr.output_section_index = self.initOutputSection(elf_file, shdr) catch unreachable; | ||
| 998 | |||
| 999 | const comp = elf_file.base.comp; | ||
| 1000 | const gpa = comp.gpa; | ||
| 1001 | const atom_list = &elf_file.sections.items(.atom_list)[atom_ptr.output_section_index]; | ||
| 1002 | try atom_list.append(gpa, .{ .index = atom_index, .file = self.index }); | ||
| 1003 | } | 953 | } |
| 1004 | } | 954 | } |
| 1005 | 955 | ||
| ... | @@ -1007,9 +957,14 @@ pub fn initRelaSections(self: *Object, elf_file: *Elf) !void { | ... | @@ -1007,9 +957,14 @@ pub fn initRelaSections(self: *Object, elf_file: *Elf) !void { |
| 1007 | for (self.atoms_indexes.items) |atom_index| { | 957 | for (self.atoms_indexes.items) |atom_index| { |
| 1008 | const atom_ptr = self.atom(atom_index) orelse continue; | 958 | const atom_ptr = self.atom(atom_index) orelse continue; |
| 1009 | if (!atom_ptr.alive) continue; | 959 | if (!atom_ptr.alive) continue; |
| 960 | if (atom_ptr.output_section_index == elf_file.eh_frame_section_index) continue; | ||
| 1010 | const shndx = atom_ptr.relocsShndx() orelse continue; | 961 | const shndx = atom_ptr.relocsShndx() orelse continue; |
| 1011 | const shdr = self.shdrs.items[shndx]; | 962 | const shdr = self.shdrs.items[shndx]; |
| 1012 | const out_shndx = try self.initOutputSection(elf_file, shdr); | 963 | const out_shndx = try elf_file.initOutputSection(.{ |
| 964 | .name = self.getString(shdr.sh_name), | ||
| 965 | .flags = shdr.sh_flags, | ||
| 966 | .type = shdr.sh_type, | ||
| 967 | }); | ||
| 1013 | const out_shdr = &elf_file.sections.items(.shdr)[out_shndx]; | 968 | const out_shdr = &elf_file.sections.items(.shdr)[out_shndx]; |
| 1014 | out_shdr.sh_type = elf.SHT_RELA; | 969 | out_shdr.sh_type = elf.SHT_RELA; |
| 1015 | out_shdr.sh_addralign = @alignOf(elf.Elf64_Rela); | 970 | out_shdr.sh_addralign = @alignOf(elf.Elf64_Rela); |
| ... | @@ -1022,10 +977,15 @@ pub fn addAtomsToRelaSections(self: *Object, elf_file: *Elf) !void { | ... | @@ -1022,10 +977,15 @@ pub fn addAtomsToRelaSections(self: *Object, elf_file: *Elf) !void { |
| 1022 | for (self.atoms_indexes.items) |atom_index| { | 977 | for (self.atoms_indexes.items) |atom_index| { |
| 1023 | const atom_ptr = self.atom(atom_index) orelse continue; | 978 | const atom_ptr = self.atom(atom_index) orelse continue; |
| 1024 | if (!atom_ptr.alive) continue; | 979 | if (!atom_ptr.alive) continue; |
| 980 | if (atom_ptr.output_section_index == elf_file.eh_frame_section_index) continue; | ||
| 1025 | const shndx = blk: { | 981 | const shndx = blk: { |
| 1026 | const shndx = atom_ptr.relocsShndx() orelse continue; | 982 | const shndx = atom_ptr.relocsShndx() orelse continue; |
| 1027 | const shdr = self.shdrs.items[shndx]; | 983 | const shdr = self.shdrs.items[shndx]; |
| 1028 | break :blk self.initOutputSection(elf_file, shdr) catch unreachable; | 984 | break :blk elf_file.initOutputSection(.{ |
| 985 | .name = self.getString(shdr.sh_name), | ||
| 986 | .flags = shdr.sh_flags, | ||
| 987 | .type = shdr.sh_type, | ||
| 988 | }) catch unreachable; | ||
| 1029 | }; | 989 | }; |
| 1030 | const slice = elf_file.sections.slice(); | 990 | const slice = elf_file.sections.slice(); |
| 1031 | const shdr = &slice.items(.shdr)[shndx]; | 991 | const shdr = &slice.items(.shdr)[shndx]; |
| ... | @@ -1538,12 +1498,12 @@ fn formatComdatGroups( | ... | @@ -1538,12 +1498,12 @@ fn formatComdatGroups( |
| 1538 | } | 1498 | } |
| 1539 | } | 1499 | } |
| 1540 | 1500 | ||
| 1541 | pub fn fmtPath(self: *Object) std.fmt.Formatter(formatPath) { | 1501 | pub fn fmtPath(self: Object) std.fmt.Formatter(formatPath) { |
| 1542 | return .{ .data = self }; | 1502 | return .{ .data = self }; |
| 1543 | } | 1503 | } |
| 1544 | 1504 | ||
| 1545 | fn formatPath( | 1505 | fn formatPath( |
| 1546 | object: *Object, | 1506 | object: Object, |
| 1547 | comptime unused_fmt_string: []const u8, | 1507 | comptime unused_fmt_string: []const u8, |
| 1548 | options: std.fmt.FormatOptions, | 1508 | options: std.fmt.FormatOptions, |
| 1549 | writer: anytype, | 1509 | writer: anytype, |
| ... | @@ -1578,6 +1538,7 @@ const mem = std.mem; | ... | @@ -1578,6 +1538,7 @@ const mem = std.mem; |
| 1578 | const Allocator = mem.Allocator; | 1538 | const Allocator = mem.Allocator; |
| 1579 | const Archive = @import("Archive.zig"); | 1539 | const Archive = @import("Archive.zig"); |
| 1580 | const Atom = @import("Atom.zig"); | 1540 | const Atom = @import("Atom.zig"); |
| 1541 | const AtomList = @import("AtomList.zig"); | ||
| 1581 | const Cie = eh_frame.Cie; | 1542 | const Cie = eh_frame.Cie; |
| 1582 | const Elf = @import("../Elf.zig"); | 1543 | const Elf = @import("../Elf.zig"); |
| 1583 | const Fde = eh_frame.Fde; | 1544 | const Fde = eh_frame.Fde; |
src/link/Elf/ZigObject.zig+358-287| ... | @@ -51,6 +51,14 @@ debug_loclists_section_dirty: bool = false, | ... | @@ -51,6 +51,14 @@ debug_loclists_section_dirty: bool = false, |
| 51 | debug_rnglists_section_dirty: bool = false, | 51 | debug_rnglists_section_dirty: bool = false, |
| 52 | eh_frame_section_dirty: bool = false, | 52 | eh_frame_section_dirty: bool = false, |
| 53 | 53 | ||
| 54 | text_index: ?Symbol.Index = null, | ||
| 55 | rodata_index: ?Symbol.Index = null, | ||
| 56 | data_relro_index: ?Symbol.Index = null, | ||
| 57 | data_index: ?Symbol.Index = null, | ||
| 58 | bss_index: ?Symbol.Index = null, | ||
| 59 | tdata_index: ?Symbol.Index = null, | ||
| 60 | tbss_index: ?Symbol.Index = null, | ||
| 61 | eh_frame_index: ?Symbol.Index = null, | ||
| 54 | debug_info_index: ?Symbol.Index = null, | 62 | debug_info_index: ?Symbol.Index = null, |
| 55 | debug_abbrev_index: ?Symbol.Index = null, | 63 | debug_abbrev_index: ?Symbol.Index = null, |
| 56 | debug_aranges_index: ?Symbol.Index = null, | 64 | debug_aranges_index: ?Symbol.Index = null, |
| ... | @@ -59,7 +67,6 @@ debug_line_index: ?Symbol.Index = null, | ... | @@ -59,7 +67,6 @@ debug_line_index: ?Symbol.Index = null, |
| 59 | debug_line_str_index: ?Symbol.Index = null, | 67 | debug_line_str_index: ?Symbol.Index = null, |
| 60 | debug_loclists_index: ?Symbol.Index = null, | 68 | debug_loclists_index: ?Symbol.Index = null, |
| 61 | debug_rnglists_index: ?Symbol.Index = null, | 69 | debug_rnglists_index: ?Symbol.Index = null, |
| 62 | eh_frame_index: ?Symbol.Index = null, | ||
| 63 | 70 | ||
| 64 | pub const global_symbol_bit: u32 = 0x80000000; | 71 | pub const global_symbol_bit: u32 = 0x80000000; |
| 65 | pub const symbol_mask: u32 = 0x7fffffff; | 72 | pub const symbol_mask: u32 = 0x7fffffff; |
| ... | @@ -71,6 +78,7 @@ const InitOptions = struct { | ... | @@ -71,6 +78,7 @@ const InitOptions = struct { |
| 71 | }; | 78 | }; |
| 72 | 79 | ||
| 73 | pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { | 80 | pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { |
| 81 | _ = options; | ||
| 74 | const comp = elf_file.base.comp; | 82 | const comp = elf_file.base.comp; |
| 75 | const gpa = comp.gpa; | 83 | const gpa = comp.gpa; |
| 76 | const ptr_size = elf_file.ptrWidthBytes(); | 84 | const ptr_size = elf_file.ptrWidthBytes(); |
| ... | @@ -88,190 +96,13 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { | ... | @@ -88,190 +96,13 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { |
| 88 | esym.st_shndx = elf.SHN_ABS; | 96 | esym.st_shndx = elf.SHN_ABS; |
| 89 | } | 97 | } |
| 90 | 98 | ||
| 91 | const fillSection = struct { | ||
| 92 | fn fillSection(ef: *Elf, shdr: *elf.Elf64_Shdr, size: u64, phndx: ?u16) !void { | ||
| 93 | if (ef.base.isRelocatable()) { | ||
| 94 | const off = try ef.findFreeSpace(size, shdr.sh_addralign); | ||
| 95 | shdr.sh_offset = off; | ||
| 96 | shdr.sh_size = size; | ||
| 97 | } else { | ||
| 98 | const phdr = ef.phdrs.items[phndx.?]; | ||
| 99 | shdr.sh_addr = phdr.p_vaddr; | ||
| 100 | shdr.sh_offset = phdr.p_offset; | ||
| 101 | shdr.sh_size = phdr.p_memsz; | ||
| 102 | } | ||
| 103 | } | ||
| 104 | }.fillSection; | ||
| 105 | |||
| 106 | comptime assert(Elf.number_of_zig_segments == 4); | ||
| 107 | |||
| 108 | if (!elf_file.base.isRelocatable()) { | ||
| 109 | if (elf_file.phdr_zig_load_re_index == null) { | ||
| 110 | const filesz = options.program_code_size_hint; | ||
| 111 | const off = try elf_file.findFreeSpace(filesz, elf_file.page_size); | ||
| 112 | elf_file.phdr_zig_load_re_index = try elf_file.addPhdr(.{ | ||
| 113 | .type = elf.PT_LOAD, | ||
| 114 | .offset = off, | ||
| 115 | .filesz = filesz, | ||
| 116 | .addr = if (ptr_size >= 4) 0x4000000 else 0x4000, | ||
| 117 | .memsz = filesz, | ||
| 118 | .@"align" = elf_file.page_size, | ||
| 119 | .flags = elf.PF_X | elf.PF_R | elf.PF_W, | ||
| 120 | }); | ||
| 121 | } | ||
| 122 | |||
| 123 | if (elf_file.phdr_zig_load_ro_index == null) { | ||
| 124 | const alignment = elf_file.page_size; | ||
| 125 | const filesz: u64 = 1024; | ||
| 126 | const off = try elf_file.findFreeSpace(filesz, alignment); | ||
| 127 | elf_file.phdr_zig_load_ro_index = try elf_file.addPhdr(.{ | ||
| 128 | .type = elf.PT_LOAD, | ||
| 129 | .offset = off, | ||
| 130 | .filesz = filesz, | ||
| 131 | .addr = if (ptr_size >= 4) 0xc000000 else 0xa000, | ||
| 132 | .memsz = filesz, | ||
| 133 | .@"align" = alignment, | ||
| 134 | .flags = elf.PF_R | elf.PF_W, | ||
| 135 | }); | ||
| 136 | } | ||
| 137 | |||
| 138 | if (elf_file.phdr_zig_load_rw_index == null) { | ||
| 139 | const alignment = elf_file.page_size; | ||
| 140 | const filesz: u64 = 1024; | ||
| 141 | const off = try elf_file.findFreeSpace(filesz, alignment); | ||
| 142 | elf_file.phdr_zig_load_rw_index = try elf_file.addPhdr(.{ | ||
| 143 | .type = elf.PT_LOAD, | ||
| 144 | .offset = off, | ||
| 145 | .filesz = filesz, | ||
| 146 | .addr = if (ptr_size >= 4) 0x10000000 else 0xc000, | ||
| 147 | .memsz = filesz, | ||
| 148 | .@"align" = alignment, | ||
| 149 | .flags = elf.PF_R | elf.PF_W, | ||
| 150 | }); | ||
| 151 | } | ||
| 152 | |||
| 153 | if (elf_file.phdr_zig_load_zerofill_index == null) { | ||
| 154 | const alignment = elf_file.page_size; | ||
| 155 | elf_file.phdr_zig_load_zerofill_index = try elf_file.addPhdr(.{ | ||
| 156 | .type = elf.PT_LOAD, | ||
| 157 | .addr = if (ptr_size >= 4) 0x14000000 else 0xf000, | ||
| 158 | .memsz = 1024, | ||
| 159 | .@"align" = alignment, | ||
| 160 | .flags = elf.PF_R | elf.PF_W, | ||
| 161 | }); | ||
| 162 | } | ||
| 163 | } | ||
| 164 | |||
| 165 | if (elf_file.zig_text_section_index == null) { | ||
| 166 | elf_file.zig_text_section_index = try elf_file.addSection(.{ | ||
| 167 | .name = try elf_file.insertShString(".text.zig"), | ||
| 168 | .type = elf.SHT_PROGBITS, | ||
| 169 | .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR, | ||
| 170 | .addralign = 1, | ||
| 171 | .offset = std.math.maxInt(u64), | ||
| 172 | }); | ||
| 173 | const shdr = &elf_file.sections.items(.shdr)[elf_file.zig_text_section_index.?]; | ||
| 174 | const phndx = &elf_file.sections.items(.phndx)[elf_file.zig_text_section_index.?]; | ||
| 175 | try fillSection(elf_file, shdr, options.program_code_size_hint, elf_file.phdr_zig_load_re_index); | ||
| 176 | if (elf_file.base.isRelocatable()) { | ||
| 177 | _ = try elf_file.addRelaShdr( | ||
| 178 | try elf_file.insertShString(".rela.text.zig"), | ||
| 179 | elf_file.zig_text_section_index.?, | ||
| 180 | ); | ||
| 181 | } else { | ||
| 182 | phndx.* = elf_file.phdr_zig_load_re_index.?; | ||
| 183 | } | ||
| 184 | } | ||
| 185 | |||
| 186 | if (elf_file.zig_data_rel_ro_section_index == null) { | ||
| 187 | elf_file.zig_data_rel_ro_section_index = try elf_file.addSection(.{ | ||
| 188 | .name = try elf_file.insertShString(".data.rel.ro.zig"), | ||
| 189 | .type = elf.SHT_PROGBITS, | ||
| 190 | .addralign = 1, | ||
| 191 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, | ||
| 192 | .offset = std.math.maxInt(u64), | ||
| 193 | }); | ||
| 194 | const shdr = &elf_file.sections.items(.shdr)[elf_file.zig_data_rel_ro_section_index.?]; | ||
| 195 | const phndx = &elf_file.sections.items(.phndx)[elf_file.zig_data_rel_ro_section_index.?]; | ||
| 196 | try fillSection(elf_file, shdr, 1024, elf_file.phdr_zig_load_ro_index); | ||
| 197 | if (elf_file.base.isRelocatable()) { | ||
| 198 | _ = try elf_file.addRelaShdr( | ||
| 199 | try elf_file.insertShString(".rela.data.rel.ro.zig"), | ||
| 200 | elf_file.zig_data_rel_ro_section_index.?, | ||
| 201 | ); | ||
| 202 | } else { | ||
| 203 | phndx.* = elf_file.phdr_zig_load_ro_index.?; | ||
| 204 | } | ||
| 205 | } | ||
| 206 | |||
| 207 | if (elf_file.zig_data_section_index == null) { | ||
| 208 | elf_file.zig_data_section_index = try elf_file.addSection(.{ | ||
| 209 | .name = try elf_file.insertShString(".data.zig"), | ||
| 210 | .type = elf.SHT_PROGBITS, | ||
| 211 | .addralign = ptr_size, | ||
| 212 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, | ||
| 213 | .offset = std.math.maxInt(u64), | ||
| 214 | }); | ||
| 215 | const shdr = &elf_file.sections.items(.shdr)[elf_file.zig_data_section_index.?]; | ||
| 216 | const phndx = &elf_file.sections.items(.phndx)[elf_file.zig_data_section_index.?]; | ||
| 217 | try fillSection(elf_file, shdr, 1024, elf_file.phdr_zig_load_rw_index); | ||
| 218 | if (elf_file.base.isRelocatable()) { | ||
| 219 | _ = try elf_file.addRelaShdr( | ||
| 220 | try elf_file.insertShString(".rela.data.zig"), | ||
| 221 | elf_file.zig_data_section_index.?, | ||
| 222 | ); | ||
| 223 | } else { | ||
| 224 | phndx.* = elf_file.phdr_zig_load_rw_index.?; | ||
| 225 | } | ||
| 226 | } | ||
| 227 | |||
| 228 | if (elf_file.zig_bss_section_index == null) { | ||
| 229 | elf_file.zig_bss_section_index = try elf_file.addSection(.{ | ||
| 230 | .name = try elf_file.insertShString(".bss.zig"), | ||
| 231 | .type = elf.SHT_NOBITS, | ||
| 232 | .addralign = ptr_size, | ||
| 233 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, | ||
| 234 | .offset = 0, | ||
| 235 | }); | ||
| 236 | const shdr = &elf_file.sections.items(.shdr)[elf_file.zig_bss_section_index.?]; | ||
| 237 | const phndx = &elf_file.sections.items(.phndx)[elf_file.zig_bss_section_index.?]; | ||
| 238 | if (elf_file.base.isRelocatable()) { | ||
| 239 | shdr.sh_size = 1024; | ||
| 240 | } else { | ||
| 241 | phndx.* = elf_file.phdr_zig_load_zerofill_index.?; | ||
| 242 | const phdr = elf_file.phdrs.items[phndx.*.?]; | ||
| 243 | shdr.sh_addr = phdr.p_vaddr; | ||
| 244 | shdr.sh_size = phdr.p_memsz; | ||
| 245 | } | ||
| 246 | } | ||
| 247 | |||
| 248 | switch (comp.config.debug_format) { | 99 | switch (comp.config.debug_format) { |
| 249 | .strip => {}, | 100 | .strip => {}, |
| 250 | .dwarf => |v| { | 101 | .dwarf => |v| { |
| 251 | var dwarf = Dwarf.init(&elf_file.base, v); | 102 | var dwarf = Dwarf.init(&elf_file.base, v); |
| 252 | 103 | ||
| 253 | const addSectionSymbol = struct { | 104 | if (self.debug_str_index == null) { |
| 254 | fn addSectionSymbol( | 105 | const osec = try elf_file.addSection(.{ |
| 255 | zig_object: *ZigObject, | ||
| 256 | alloc: Allocator, | ||
| 257 | name: [:0]const u8, | ||
| 258 | alignment: Atom.Alignment, | ||
| 259 | shndx: u32, | ||
| 260 | ) !Symbol.Index { | ||
| 261 | const name_off = try zig_object.addString(alloc, name); | ||
| 262 | const index = try zig_object.newSymbolWithAtom(alloc, name_off); | ||
| 263 | const sym = zig_object.symbol(index); | ||
| 264 | const esym = &zig_object.symtab.items(.elf_sym)[sym.esym_index]; | ||
| 265 | esym.st_info |= elf.STT_SECTION; | ||
| 266 | const atom_ptr = zig_object.atom(sym.ref.index).?; | ||
| 267 | atom_ptr.alignment = alignment; | ||
| 268 | atom_ptr.output_section_index = shndx; | ||
| 269 | return index; | ||
| 270 | } | ||
| 271 | }.addSectionSymbol; | ||
| 272 | |||
| 273 | if (elf_file.debug_str_section_index == null) { | ||
| 274 | elf_file.debug_str_section_index = try elf_file.addSection(.{ | ||
| 275 | .name = try elf_file.insertShString(".debug_str"), | 106 | .name = try elf_file.insertShString(".debug_str"), |
| 276 | .flags = elf.SHF_MERGE | elf.SHF_STRINGS, | 107 | .flags = elf.SHF_MERGE | elf.SHF_STRINGS, |
| 277 | .entsize = 1, | 108 | .entsize = 1, |
| ... | @@ -279,51 +110,56 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { | ... | @@ -279,51 +110,56 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { |
| 279 | .addralign = 1, | 110 | .addralign = 1, |
| 280 | }); | 111 | }); |
| 281 | self.debug_str_section_dirty = true; | 112 | self.debug_str_section_dirty = true; |
| 282 | self.debug_str_index = try addSectionSymbol(self, gpa, ".debug_str", .@"1", elf_file.debug_str_section_index.?); | 113 | self.debug_str_index = try self.addSectionSymbol(gpa, ".debug_str", .@"1", osec); |
| 114 | elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_str_index.?).ref; | ||
| 283 | } | 115 | } |
| 284 | 116 | ||
| 285 | if (elf_file.debug_info_section_index == null) { | 117 | if (self.debug_info_index == null) { |
| 286 | elf_file.debug_info_section_index = try elf_file.addSection(.{ | 118 | const osec = try elf_file.addSection(.{ |
| 287 | .name = try elf_file.insertShString(".debug_info"), | 119 | .name = try elf_file.insertShString(".debug_info"), |
| 288 | .type = elf.SHT_PROGBITS, | 120 | .type = elf.SHT_PROGBITS, |
| 289 | .addralign = 1, | 121 | .addralign = 1, |
| 290 | }); | 122 | }); |
| 291 | self.debug_info_section_dirty = true; | 123 | self.debug_info_section_dirty = true; |
| 292 | self.debug_info_index = try addSectionSymbol(self, gpa, ".debug_info", .@"1", elf_file.debug_info_section_index.?); | 124 | self.debug_info_index = try self.addSectionSymbol(gpa, ".debug_info", .@"1", osec); |
| 125 | elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_info_index.?).ref; | ||
| 293 | } | 126 | } |
| 294 | 127 | ||
| 295 | if (elf_file.debug_abbrev_section_index == null) { | 128 | if (self.debug_abbrev_index == null) { |
| 296 | elf_file.debug_abbrev_section_index = try elf_file.addSection(.{ | 129 | const osec = try elf_file.addSection(.{ |
| 297 | .name = try elf_file.insertShString(".debug_abbrev"), | 130 | .name = try elf_file.insertShString(".debug_abbrev"), |
| 298 | .type = elf.SHT_PROGBITS, | 131 | .type = elf.SHT_PROGBITS, |
| 299 | .addralign = 1, | 132 | .addralign = 1, |
| 300 | }); | 133 | }); |
| 301 | self.debug_abbrev_section_dirty = true; | 134 | self.debug_abbrev_section_dirty = true; |
| 302 | self.debug_abbrev_index = try addSectionSymbol(self, gpa, ".debug_abbrev", .@"1", elf_file.debug_abbrev_section_index.?); | 135 | self.debug_abbrev_index = try self.addSectionSymbol(gpa, ".debug_abbrev", .@"1", osec); |
| 136 | elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_abbrev_index.?).ref; | ||
| 303 | } | 137 | } |
| 304 | 138 | ||
| 305 | if (elf_file.debug_aranges_section_index == null) { | 139 | if (self.debug_aranges_index == null) { |
| 306 | elf_file.debug_aranges_section_index = try elf_file.addSection(.{ | 140 | const osec = try elf_file.addSection(.{ |
| 307 | .name = try elf_file.insertShString(".debug_aranges"), | 141 | .name = try elf_file.insertShString(".debug_aranges"), |
| 308 | .type = elf.SHT_PROGBITS, | 142 | .type = elf.SHT_PROGBITS, |
| 309 | .addralign = 16, | 143 | .addralign = 16, |
| 310 | }); | 144 | }); |
| 311 | self.debug_aranges_section_dirty = true; | 145 | self.debug_aranges_section_dirty = true; |
| 312 | self.debug_aranges_index = try addSectionSymbol(self, gpa, ".debug_aranges", .@"16", elf_file.debug_aranges_section_index.?); | 146 | self.debug_aranges_index = try self.addSectionSymbol(gpa, ".debug_aranges", .@"16", osec); |
| 147 | elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_aranges_index.?).ref; | ||
| 313 | } | 148 | } |
| 314 | 149 | ||
| 315 | if (elf_file.debug_line_section_index == null) { | 150 | if (self.debug_line_index == null) { |
| 316 | elf_file.debug_line_section_index = try elf_file.addSection(.{ | 151 | const osec = try elf_file.addSection(.{ |
| 317 | .name = try elf_file.insertShString(".debug_line"), | 152 | .name = try elf_file.insertShString(".debug_line"), |
| 318 | .type = elf.SHT_PROGBITS, | 153 | .type = elf.SHT_PROGBITS, |
| 319 | .addralign = 1, | 154 | .addralign = 1, |
| 320 | }); | 155 | }); |
| 321 | self.debug_line_section_dirty = true; | 156 | self.debug_line_section_dirty = true; |
| 322 | self.debug_line_index = try addSectionSymbol(self, gpa, ".debug_line", .@"1", elf_file.debug_line_section_index.?); | 157 | self.debug_line_index = try self.addSectionSymbol(gpa, ".debug_line", .@"1", osec); |
| 158 | elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_line_index.?).ref; | ||
| 323 | } | 159 | } |
| 324 | 160 | ||
| 325 | if (elf_file.debug_line_str_section_index == null) { | 161 | if (self.debug_line_str_index == null) { |
| 326 | elf_file.debug_line_str_section_index = try elf_file.addSection(.{ | 162 | const osec = try elf_file.addSection(.{ |
| 327 | .name = try elf_file.insertShString(".debug_line_str"), | 163 | .name = try elf_file.insertShString(".debug_line_str"), |
| 328 | .flags = elf.SHF_MERGE | elf.SHF_STRINGS, | 164 | .flags = elf.SHF_MERGE | elf.SHF_STRINGS, |
| 329 | .entsize = 1, | 165 | .entsize = 1, |
| ... | @@ -331,31 +167,34 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { | ... | @@ -331,31 +167,34 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { |
| 331 | .addralign = 1, | 167 | .addralign = 1, |
| 332 | }); | 168 | }); |
| 333 | self.debug_line_str_section_dirty = true; | 169 | self.debug_line_str_section_dirty = true; |
| 334 | self.debug_line_str_index = try addSectionSymbol(self, gpa, ".debug_line_str", .@"1", elf_file.debug_line_str_section_index.?); | 170 | self.debug_line_str_index = try self.addSectionSymbol(gpa, ".debug_line_str", .@"1", osec); |
| 171 | elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_line_str_index.?).ref; | ||
| 335 | } | 172 | } |
| 336 | 173 | ||
| 337 | if (elf_file.debug_loclists_section_index == null) { | 174 | if (self.debug_loclists_index == null) { |
| 338 | elf_file.debug_loclists_section_index = try elf_file.addSection(.{ | 175 | const osec = try elf_file.addSection(.{ |
| 339 | .name = try elf_file.insertShString(".debug_loclists"), | 176 | .name = try elf_file.insertShString(".debug_loclists"), |
| 340 | .type = elf.SHT_PROGBITS, | 177 | .type = elf.SHT_PROGBITS, |
| 341 | .addralign = 1, | 178 | .addralign = 1, |
| 342 | }); | 179 | }); |
| 343 | self.debug_loclists_section_dirty = true; | 180 | self.debug_loclists_section_dirty = true; |
| 344 | self.debug_loclists_index = try addSectionSymbol(self, gpa, ".debug_loclists", .@"1", elf_file.debug_loclists_section_index.?); | 181 | self.debug_loclists_index = try self.addSectionSymbol(gpa, ".debug_loclists", .@"1", osec); |
| 182 | elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_loclists_index.?).ref; | ||
| 345 | } | 183 | } |
| 346 | 184 | ||
| 347 | if (elf_file.debug_rnglists_section_index == null) { | 185 | if (self.debug_rnglists_index == null) { |
| 348 | elf_file.debug_rnglists_section_index = try elf_file.addSection(.{ | 186 | const osec = try elf_file.addSection(.{ |
| 349 | .name = try elf_file.insertShString(".debug_rnglists"), | 187 | .name = try elf_file.insertShString(".debug_rnglists"), |
| 350 | .type = elf.SHT_PROGBITS, | 188 | .type = elf.SHT_PROGBITS, |
| 351 | .addralign = 1, | 189 | .addralign = 1, |
| 352 | }); | 190 | }); |
| 353 | self.debug_rnglists_section_dirty = true; | 191 | self.debug_rnglists_section_dirty = true; |
| 354 | self.debug_rnglists_index = try addSectionSymbol(self, gpa, ".debug_rnglists", .@"1", elf_file.debug_rnglists_section_index.?); | 192 | self.debug_rnglists_index = try self.addSectionSymbol(gpa, ".debug_rnglists", .@"1", osec); |
| 193 | elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_rnglists_index.?).ref; | ||
| 355 | } | 194 | } |
| 356 | 195 | ||
| 357 | if (elf_file.eh_frame_section_index == null) { | 196 | if (self.eh_frame_index == null) { |
| 358 | elf_file.eh_frame_section_index = try elf_file.addSection(.{ | 197 | const osec = try elf_file.addSection(.{ |
| 359 | .name = try elf_file.insertShString(".eh_frame"), | 198 | .name = try elf_file.insertShString(".eh_frame"), |
| 360 | .type = if (elf_file.getTarget().cpu.arch == .x86_64) | 199 | .type = if (elf_file.getTarget().cpu.arch == .x86_64) |
| 361 | elf.SHT_X86_64_UNWIND | 200 | elf.SHT_X86_64_UNWIND |
| ... | @@ -365,7 +204,8 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { | ... | @@ -365,7 +204,8 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { |
| 365 | .addralign = ptr_size, | 204 | .addralign = ptr_size, |
| 366 | }); | 205 | }); |
| 367 | self.eh_frame_section_dirty = true; | 206 | self.eh_frame_section_dirty = true; |
| 368 | self.eh_frame_index = try addSectionSymbol(self, gpa, ".eh_frame", Atom.Alignment.fromNonzeroByteUnits(ptr_size), elf_file.eh_frame_section_index.?); | 207 | self.eh_frame_index = try self.addSectionSymbol(gpa, ".eh_frame", Atom.Alignment.fromNonzeroByteUnits(ptr_size), osec); |
| 208 | elf_file.sections.items(.last_atom)[osec] = self.symbol(self.eh_frame_index.?).ref; | ||
| 369 | } | 209 | } |
| 370 | 210 | ||
| 371 | try dwarf.initMetadata(); | 211 | try dwarf.initMetadata(); |
| ... | @@ -404,10 +244,6 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void { | ... | @@ -404,10 +244,6 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void { |
| 404 | meta.exports.deinit(allocator); | 244 | meta.exports.deinit(allocator); |
| 405 | } | 245 | } |
| 406 | self.uavs.deinit(allocator); | 246 | self.uavs.deinit(allocator); |
| 407 | |||
| 408 | for (self.tls_variables.values()) |*tlv| { | ||
| 409 | tlv.deinit(allocator); | ||
| 410 | } | ||
| 411 | self.tls_variables.deinit(allocator); | 247 | self.tls_variables.deinit(allocator); |
| 412 | 248 | ||
| 413 | if (self.dwarf) |*dwarf| { | 249 | if (self.dwarf) |*dwarf| { |
| ... | @@ -499,12 +335,6 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi | ... | @@ -499,12 +335,6 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi |
| 499 | const sym = self.symbol(sym_index); | 335 | const sym = self.symbol(sym_index); |
| 500 | const atom_ptr = self.atom(sym.ref.index).?; | 336 | const atom_ptr = self.atom(sym.ref.index).?; |
| 501 | if (!atom_ptr.alive) continue; | 337 | if (!atom_ptr.alive) continue; |
| 502 | const shndx = sym.outputShndx(elf_file).?; | ||
| 503 | const shdr = elf_file.sections.items(.shdr)[shndx]; | ||
| 504 | const esym = &self.symtab.items(.elf_sym)[sym.esym_index]; | ||
| 505 | esym.st_size = shdr.sh_size; | ||
| 506 | atom_ptr.size = shdr.sh_size; | ||
| 507 | atom_ptr.alignment = Atom.Alignment.fromNonzeroByteUnits(shdr.sh_addralign); | ||
| 508 | 338 | ||
| 509 | log.debug("parsing relocs in {s}", .{sym.name(elf_file)}); | 339 | log.debug("parsing relocs in {s}", .{sym.name(elf_file)}); |
| 510 | 340 | ||
| ... | @@ -665,14 +495,6 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi | ... | @@ -665,14 +495,6 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi |
| 665 | } | 495 | } |
| 666 | } | 496 | } |
| 667 | } | 497 | } |
| 668 | |||
| 669 | if (elf_file.base.isRelocatable() and relocs.items.len > 0) { | ||
| 670 | const rela_sect_name = try std.fmt.allocPrintZ(gpa, ".rela{s}", .{elf_file.getShString(shdr.sh_name)}); | ||
| 671 | defer gpa.free(rela_sect_name); | ||
| 672 | if (elf_file.sectionByName(rela_sect_name) == null) { | ||
| 673 | _ = try elf_file.addRelaShdr(try elf_file.insertShString(rela_sect_name), shndx); | ||
| 674 | } | ||
| 675 | } | ||
| 676 | } | 498 | } |
| 677 | 499 | ||
| 678 | self.debug_abbrev_section_dirty = false; | 500 | self.debug_abbrev_section_dirty = false; |
| ... | @@ -835,7 +657,7 @@ pub fn claimUnresolved(self: *ZigObject, elf_file: *Elf) void { | ... | @@ -835,7 +657,7 @@ pub fn claimUnresolved(self: *ZigObject, elf_file: *Elf) void { |
| 835 | } | 657 | } |
| 836 | } | 658 | } |
| 837 | 659 | ||
| 838 | pub fn claimUnresolvedObject(self: ZigObject, elf_file: *Elf) void { | 660 | pub fn claimUnresolvedRelocatable(self: ZigObject, elf_file: *Elf) void { |
| 839 | for (self.global_symbols.items, 0..) |index, i| { | 661 | for (self.global_symbols.items, 0..) |index, i| { |
| 840 | const global = &self.symbols.items[index]; | 662 | const global = &self.symbols.items[index]; |
| 841 | const esym = self.symtab.items(.elf_sym)[index]; | 663 | const esym = self.symtab.items(.elf_sym)[index]; |
| ... | @@ -990,21 +812,48 @@ pub fn writeAr(self: ZigObject, writer: anytype) !void { | ... | @@ -990,21 +812,48 @@ pub fn writeAr(self: ZigObject, writer: anytype) !void { |
| 990 | try writer.writeAll(self.data.items); | 812 | try writer.writeAll(self.data.items); |
| 991 | } | 813 | } |
| 992 | 814 | ||
| 815 | pub fn initRelaSections(self: *ZigObject, elf_file: *Elf) !void { | ||
| 816 | const gpa = elf_file.base.comp.gpa; | ||
| 817 | for (self.atoms_indexes.items) |atom_index| { | ||
| 818 | const atom_ptr = self.atom(atom_index) orelse continue; | ||
| 819 | if (!atom_ptr.alive) continue; | ||
| 820 | if (atom_ptr.output_section_index == elf_file.eh_frame_section_index) continue; | ||
| 821 | const rela_shndx = atom_ptr.relocsShndx() orelse continue; | ||
| 822 | // TODO this check will become obsolete when we rework our relocs mechanism at the ZigObject level | ||
| 823 | if (self.relocs.items[rela_shndx].items.len == 0) continue; | ||
| 824 | const out_shndx = atom_ptr.output_section_index; | ||
| 825 | const out_shdr = elf_file.sections.items(.shdr)[out_shndx]; | ||
| 826 | if (out_shdr.sh_type == elf.SHT_NOBITS) continue; | ||
| 827 | const rela_sect_name = try std.fmt.allocPrintZ(gpa, ".rela{s}", .{ | ||
| 828 | elf_file.getShString(out_shdr.sh_name), | ||
| 829 | }); | ||
| 830 | defer gpa.free(rela_sect_name); | ||
| 831 | _ = elf_file.sectionByName(rela_sect_name) orelse | ||
| 832 | try elf_file.addRelaShdr(try elf_file.insertShString(rela_sect_name), out_shndx); | ||
| 833 | } | ||
| 834 | } | ||
| 835 | |||
| 993 | pub fn addAtomsToRelaSections(self: *ZigObject, elf_file: *Elf) !void { | 836 | pub fn addAtomsToRelaSections(self: *ZigObject, elf_file: *Elf) !void { |
| 837 | const gpa = elf_file.base.comp.gpa; | ||
| 994 | for (self.atoms_indexes.items) |atom_index| { | 838 | for (self.atoms_indexes.items) |atom_index| { |
| 995 | const atom_ptr = self.atom(atom_index) orelse continue; | 839 | const atom_ptr = self.atom(atom_index) orelse continue; |
| 996 | if (!atom_ptr.alive) continue; | 840 | if (!atom_ptr.alive) continue; |
| 841 | if (atom_ptr.output_section_index == elf_file.eh_frame_section_index) continue; | ||
| 997 | const rela_shndx = atom_ptr.relocsShndx() orelse continue; | 842 | const rela_shndx = atom_ptr.relocsShndx() orelse continue; |
| 998 | // TODO this check will become obsolete when we rework our relocs mechanism at the ZigObject level | 843 | // TODO this check will become obsolete when we rework our relocs mechanism at the ZigObject level |
| 999 | if (self.relocs.items[rela_shndx].items.len == 0) continue; | 844 | if (self.relocs.items[rela_shndx].items.len == 0) continue; |
| 1000 | const out_shndx = atom_ptr.output_section_index; | 845 | const out_shndx = atom_ptr.output_section_index; |
| 1001 | const out_shdr = elf_file.sections.items(.shdr)[out_shndx]; | 846 | const out_shdr = elf_file.sections.items(.shdr)[out_shndx]; |
| 1002 | if (out_shdr.sh_type == elf.SHT_NOBITS) continue; | 847 | if (out_shdr.sh_type == elf.SHT_NOBITS) continue; |
| 1003 | const out_rela_shndx = for (elf_file.sections.items(.shdr), 0..) |out_rela_shdr, out_rela_shndx| { | 848 | const rela_sect_name = try std.fmt.allocPrintZ(gpa, ".rela{s}", .{ |
| 1004 | if (out_rela_shdr.sh_type == elf.SHT_RELA and out_rela_shdr.sh_info == out_shndx) break out_rela_shndx; | 849 | elf_file.getShString(out_shdr.sh_name), |
| 1005 | } else unreachable; | 850 | }); |
| 851 | defer gpa.free(rela_sect_name); | ||
| 852 | const out_rela_shndx = elf_file.sectionByName(rela_sect_name).?; | ||
| 853 | const out_rela_shdr = &elf_file.sections.items(.shdr)[out_rela_shndx]; | ||
| 854 | out_rela_shdr.sh_info = out_shndx; | ||
| 855 | out_rela_shdr.sh_link = elf_file.symtab_section_index.?; | ||
| 1006 | const atom_list = &elf_file.sections.items(.atom_list)[out_rela_shndx]; | 856 | const atom_list = &elf_file.sections.items(.atom_list)[out_rela_shndx]; |
| 1007 | const gpa = elf_file.base.comp.gpa; | ||
| 1008 | try atom_list.append(gpa, .{ .index = atom_index, .file = self.index }); | 857 | try atom_list.append(gpa, .{ .index = atom_index, .file = self.index }); |
| 1009 | } | 858 | } |
| 1010 | } | 859 | } |
| ... | @@ -1075,15 +924,7 @@ pub fn writeSymtab(self: ZigObject, elf_file: *Elf) void { | ... | @@ -1075,15 +924,7 @@ pub fn writeSymtab(self: ZigObject, elf_file: *Elf) void { |
| 1075 | pub fn codeAlloc(self: *ZigObject, elf_file: *Elf, atom_index: Atom.Index) ![]u8 { | 924 | pub fn codeAlloc(self: *ZigObject, elf_file: *Elf, atom_index: Atom.Index) ![]u8 { |
| 1076 | const gpa = elf_file.base.comp.gpa; | 925 | const gpa = elf_file.base.comp.gpa; |
| 1077 | const atom_ptr = self.atom(atom_index).?; | 926 | const atom_ptr = self.atom(atom_index).?; |
| 1078 | const shdr = &elf_file.sections.items(.shdr)[atom_ptr.output_section_index]; | 927 | const file_offset = atom_ptr.offset(elf_file); |
| 1079 | |||
| 1080 | if (shdr.sh_flags & elf.SHF_TLS != 0) { | ||
| 1081 | const tlv = self.tls_variables.get(atom_index).?; | ||
| 1082 | const code = try gpa.dupe(u8, tlv.code); | ||
| 1083 | return code; | ||
| 1084 | } | ||
| 1085 | |||
| 1086 | const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value)); | ||
| 1087 | const size = std.math.cast(usize, atom_ptr.size) orelse return error.Overflow; | 928 | const size = std.math.cast(usize, atom_ptr.size) orelse return error.Overflow; |
| 1088 | const code = try gpa.alloc(u8, size); | 929 | const code = try gpa.alloc(u8, size); |
| 1089 | errdefer gpa.free(code); | 930 | errdefer gpa.free(code); |
| ... | @@ -1168,6 +1009,20 @@ pub fn lowerUav( | ... | @@ -1168,6 +1009,20 @@ pub fn lowerUav( |
| 1168 | return .{ .mcv = .{ .load_symbol = metadata.symbol_index } }; | 1009 | return .{ .mcv = .{ .load_symbol = metadata.symbol_index } }; |
| 1169 | } | 1010 | } |
| 1170 | 1011 | ||
| 1012 | const osec = if (self.data_relro_index) |sym_index| | ||
| 1013 | self.symbol(sym_index).atom(elf_file).?.output_section_index | ||
| 1014 | else osec: { | ||
| 1015 | const osec = try elf_file.addSection(.{ | ||
| 1016 | .name = try elf_file.insertShString(".data.rel.ro"), | ||
| 1017 | .type = elf.SHT_PROGBITS, | ||
| 1018 | .addralign = 1, | ||
| 1019 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, | ||
| 1020 | .offset = std.math.maxInt(u64), | ||
| 1021 | }); | ||
| 1022 | self.data_relro_index = try self.addSectionSymbol(gpa, ".data.rel.ro", .@"1", osec); | ||
| 1023 | break :osec osec; | ||
| 1024 | }; | ||
| 1025 | |||
| 1171 | var name_buf: [32]u8 = undefined; | 1026 | var name_buf: [32]u8 = undefined; |
| 1172 | const name = std.fmt.bufPrint(&name_buf, "__anon_{d}", .{ | 1027 | const name = std.fmt.bufPrint(&name_buf, "__anon_{d}", .{ |
| 1173 | @intFromEnum(uav), | 1028 | @intFromEnum(uav), |
| ... | @@ -1178,7 +1033,7 @@ pub fn lowerUav( | ... | @@ -1178,7 +1033,7 @@ pub fn lowerUav( |
| 1178 | name, | 1033 | name, |
| 1179 | val, | 1034 | val, |
| 1180 | uav_alignment, | 1035 | uav_alignment, |
| 1181 | elf_file.zig_data_rel_ro_section_index.?, | 1036 | osec, |
| 1182 | src_loc, | 1037 | src_loc, |
| 1183 | ) catch |err| switch (err) { | 1038 | ) catch |err| switch (err) { |
| 1184 | error.OutOfMemory => return error.OutOfMemory, | 1039 | error.OutOfMemory => return error.OutOfMemory, |
| ... | @@ -1270,6 +1125,27 @@ pub fn getOrCreateMetadataForNav( | ... | @@ -1270,6 +1125,27 @@ pub fn getOrCreateMetadataForNav( |
| 1270 | return gop.value_ptr.symbol_index; | 1125 | return gop.value_ptr.symbol_index; |
| 1271 | } | 1126 | } |
| 1272 | 1127 | ||
| 1128 | // FIXME: we always create an atom to basically store size and alignment, however, this is only true for | ||
| 1129 | // sections that have a single atom like the debug sections. It would be a better solution to decouple this | ||
| 1130 | // concept from the atom, maybe. | ||
| 1131 | fn addSectionSymbol( | ||
| 1132 | self: *ZigObject, | ||
| 1133 | allocator: Allocator, | ||
| 1134 | name: [:0]const u8, | ||
| 1135 | alignment: Atom.Alignment, | ||
| 1136 | shndx: u32, | ||
| 1137 | ) !Symbol.Index { | ||
| 1138 | const name_off = try self.addString(allocator, name); | ||
| 1139 | const index = try self.newSymbolWithAtom(allocator, name_off); | ||
| 1140 | const sym = self.symbol(index); | ||
| 1141 | const esym = &self.symtab.items(.elf_sym)[sym.esym_index]; | ||
| 1142 | esym.st_info |= elf.STT_SECTION; | ||
| 1143 | const atom_ptr = self.atom(sym.ref.index).?; | ||
| 1144 | atom_ptr.alignment = alignment; | ||
| 1145 | atom_ptr.output_section_index = shndx; | ||
| 1146 | return index; | ||
| 1147 | } | ||
| 1148 | |||
| 1273 | fn getNavShdrIndex( | 1149 | fn getNavShdrIndex( |
| 1274 | self: *ZigObject, | 1150 | self: *ZigObject, |
| 1275 | elf_file: *Elf, | 1151 | elf_file: *Elf, |
| ... | @@ -1278,10 +1154,24 @@ fn getNavShdrIndex( | ... | @@ -1278,10 +1154,24 @@ fn getNavShdrIndex( |
| 1278 | sym_index: Symbol.Index, | 1154 | sym_index: Symbol.Index, |
| 1279 | code: []const u8, | 1155 | code: []const u8, |
| 1280 | ) error{OutOfMemory}!u32 { | 1156 | ) error{OutOfMemory}!u32 { |
| 1157 | const gpa = elf_file.base.comp.gpa; | ||
| 1158 | const ptr_size = elf_file.ptrWidthBytes(); | ||
| 1281 | const ip = &zcu.intern_pool; | 1159 | const ip = &zcu.intern_pool; |
| 1282 | const any_non_single_threaded = elf_file.base.comp.config.any_non_single_threaded; | 1160 | const any_non_single_threaded = elf_file.base.comp.config.any_non_single_threaded; |
| 1283 | const nav_val = zcu.navValue(nav_index); | 1161 | const nav_val = zcu.navValue(nav_index); |
| 1284 | if (ip.isFunctionType(nav_val.typeOf(zcu).toIntern())) return elf_file.zig_text_section_index.?; | 1162 | if (ip.isFunctionType(nav_val.typeOf(zcu).toIntern())) { |
| 1163 | if (self.text_index) |symbol_index| | ||
| 1164 | return self.symbol(symbol_index).atom(elf_file).?.output_section_index; | ||
| 1165 | const osec = try elf_file.addSection(.{ | ||
| 1166 | .type = elf.SHT_PROGBITS, | ||
| 1167 | .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR, | ||
| 1168 | .name = try elf_file.insertShString(".text"), | ||
| 1169 | .addralign = 1, | ||
| 1170 | .offset = std.math.maxInt(u64), | ||
| 1171 | }); | ||
| 1172 | self.text_index = try self.addSectionSymbol(gpa, ".text", .@"1", osec); | ||
| 1173 | return osec; | ||
| 1174 | } | ||
| 1285 | const is_const, const is_threadlocal, const nav_init = switch (ip.indexToKey(nav_val.toIntern())) { | 1175 | const is_const, const is_threadlocal, const nav_init = switch (ip.indexToKey(nav_val.toIntern())) { |
| 1286 | .variable => |variable| .{ false, variable.is_threadlocal, variable.init }, | 1176 | .variable => |variable| .{ false, variable.is_threadlocal, variable.init }, |
| 1287 | .@"extern" => |@"extern"| .{ @"extern".is_const, @"extern".is_threadlocal, .none }, | 1177 | .@"extern" => |@"extern"| .{ @"extern".is_const, @"extern".is_threadlocal, .none }, |
| ... | @@ -1292,30 +1182,107 @@ fn getNavShdrIndex( | ... | @@ -1292,30 +1182,107 @@ fn getNavShdrIndex( |
| 1292 | const is_bss = !has_relocs and for (code) |byte| { | 1182 | const is_bss = !has_relocs and for (code) |byte| { |
| 1293 | if (byte != 0) break false; | 1183 | if (byte != 0) break false; |
| 1294 | } else true; | 1184 | } else true; |
| 1295 | if (is_bss) return elf_file.sectionByName(".tbss") orelse try elf_file.addSection(.{ | 1185 | if (is_bss) { |
| 1296 | .type = elf.SHT_NOBITS, | 1186 | if (self.tbss_index) |symbol_index| |
| 1187 | return self.symbol(symbol_index).atom(elf_file).?.output_section_index; | ||
| 1188 | const osec = try elf_file.addSection(.{ | ||
| 1189 | .name = try elf_file.insertShString(".tbss"), | ||
| 1190 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE | elf.SHF_TLS, | ||
| 1191 | .type = elf.SHT_NOBITS, | ||
| 1192 | .addralign = 1, | ||
| 1193 | }); | ||
| 1194 | self.tbss_index = try self.addSectionSymbol(gpa, ".tbss", .@"1", osec); | ||
| 1195 | return osec; | ||
| 1196 | } | ||
| 1197 | if (self.tdata_index) |symbol_index| | ||
| 1198 | return self.symbol(symbol_index).atom(elf_file).?.output_section_index; | ||
| 1199 | const osec = try elf_file.addSection(.{ | ||
| 1200 | .type = elf.SHT_PROGBITS, | ||
| 1297 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE | elf.SHF_TLS, | 1201 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE | elf.SHF_TLS, |
| 1298 | .name = try elf_file.insertShString(".tbss"), | 1202 | .name = try elf_file.insertShString(".tdata"), |
| 1203 | .addralign = 1, | ||
| 1299 | .offset = std.math.maxInt(u64), | 1204 | .offset = std.math.maxInt(u64), |
| 1300 | }); | 1205 | }); |
| 1301 | return elf_file.sectionByName(".tdata") orelse try elf_file.addSection(.{ | 1206 | self.tdata_index = try self.addSectionSymbol(gpa, ".tdata", .@"1", osec); |
| 1207 | return osec; | ||
| 1208 | } | ||
| 1209 | if (is_const) { | ||
| 1210 | if (self.data_relro_index) |symbol_index| | ||
| 1211 | return self.symbol(symbol_index).atom(elf_file).?.output_section_index; | ||
| 1212 | const osec = try elf_file.addSection(.{ | ||
| 1213 | .name = try elf_file.insertShString(".data.rel.ro"), | ||
| 1302 | .type = elf.SHT_PROGBITS, | 1214 | .type = elf.SHT_PROGBITS, |
| 1303 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE | elf.SHF_TLS, | 1215 | .addralign = 1, |
| 1304 | .name = try elf_file.insertShString(".tdata"), | 1216 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, |
| 1305 | .offset = std.math.maxInt(u64), | 1217 | .offset = std.math.maxInt(u64), |
| 1306 | }); | 1218 | }); |
| 1219 | self.data_relro_index = try self.addSectionSymbol(gpa, ".data.rel.ro", .@"1", osec); | ||
| 1220 | return osec; | ||
| 1307 | } | 1221 | } |
| 1308 | if (is_const) return elf_file.zig_data_rel_ro_section_index.?; | ||
| 1309 | if (nav_init != .none and Value.fromInterned(nav_init).isUndefDeep(zcu)) | 1222 | if (nav_init != .none and Value.fromInterned(nav_init).isUndefDeep(zcu)) |
| 1310 | return switch (zcu.navFileScope(nav_index).mod.optimize_mode) { | 1223 | return switch (zcu.navFileScope(nav_index).mod.optimize_mode) { |
| 1311 | .Debug, .ReleaseSafe => elf_file.zig_data_section_index.?, | 1224 | .Debug, .ReleaseSafe => { |
| 1312 | .ReleaseFast, .ReleaseSmall => elf_file.zig_bss_section_index.?, | 1225 | if (self.data_index) |symbol_index| |
| 1226 | return self.symbol(symbol_index).atom(elf_file).?.output_section_index; | ||
| 1227 | const osec = try elf_file.addSection(.{ | ||
| 1228 | .name = try elf_file.insertShString(".data"), | ||
| 1229 | .type = elf.SHT_PROGBITS, | ||
| 1230 | .addralign = ptr_size, | ||
| 1231 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, | ||
| 1232 | .offset = std.math.maxInt(u64), | ||
| 1233 | }); | ||
| 1234 | self.data_index = try self.addSectionSymbol( | ||
| 1235 | gpa, | ||
| 1236 | ".data", | ||
| 1237 | Atom.Alignment.fromNonzeroByteUnits(ptr_size), | ||
| 1238 | osec, | ||
| 1239 | ); | ||
| 1240 | return osec; | ||
| 1241 | }, | ||
| 1242 | .ReleaseFast, .ReleaseSmall => { | ||
| 1243 | if (self.bss_index) |symbol_index| | ||
| 1244 | return self.symbol(symbol_index).atom(elf_file).?.output_section_index; | ||
| 1245 | const osec = try elf_file.addSection(.{ | ||
| 1246 | .type = elf.SHT_NOBITS, | ||
| 1247 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, | ||
| 1248 | .name = try elf_file.insertShString(".bss"), | ||
| 1249 | .addralign = 1, | ||
| 1250 | }); | ||
| 1251 | self.bss_index = try self.addSectionSymbol(gpa, ".bss", .@"1", osec); | ||
| 1252 | return osec; | ||
| 1253 | }, | ||
| 1313 | }; | 1254 | }; |
| 1314 | const is_bss = !has_relocs and for (code) |byte| { | 1255 | const is_bss = !has_relocs and for (code) |byte| { |
| 1315 | if (byte != 0) break false; | 1256 | if (byte != 0) break false; |
| 1316 | } else true; | 1257 | } else true; |
| 1317 | if (is_bss) return elf_file.zig_bss_section_index.?; | 1258 | if (is_bss) { |
| 1318 | return elf_file.zig_data_section_index.?; | 1259 | if (self.bss_index) |symbol_index| |
| 1260 | return self.symbol(symbol_index).atom(elf_file).?.output_section_index; | ||
| 1261 | const osec = try elf_file.addSection(.{ | ||
| 1262 | .type = elf.SHT_NOBITS, | ||
| 1263 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, | ||
| 1264 | .name = try elf_file.insertShString(".bss"), | ||
| 1265 | .addralign = 1, | ||
| 1266 | }); | ||
| 1267 | self.bss_index = try self.addSectionSymbol(gpa, ".bss", .@"1", osec); | ||
| 1268 | return osec; | ||
| 1269 | } | ||
| 1270 | if (self.data_index) |symbol_index| | ||
| 1271 | return self.symbol(symbol_index).atom(elf_file).?.output_section_index; | ||
| 1272 | const osec = try elf_file.addSection(.{ | ||
| 1273 | .name = try elf_file.insertShString(".data"), | ||
| 1274 | .type = elf.SHT_PROGBITS, | ||
| 1275 | .addralign = ptr_size, | ||
| 1276 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, | ||
| 1277 | .offset = std.math.maxInt(u64), | ||
| 1278 | }); | ||
| 1279 | self.data_index = try self.addSectionSymbol( | ||
| 1280 | gpa, | ||
| 1281 | ".data", | ||
| 1282 | Atom.Alignment.fromNonzeroByteUnits(ptr_size), | ||
| 1283 | osec, | ||
| 1284 | ); | ||
| 1285 | return osec; | ||
| 1319 | } | 1286 | } |
| 1320 | 1287 | ||
| 1321 | fn updateNavCode( | 1288 | fn updateNavCode( |
| ... | @@ -1362,19 +1329,18 @@ fn updateNavCode( | ... | @@ -1362,19 +1329,18 @@ fn updateNavCode( |
| 1362 | const capacity = atom_ptr.capacity(elf_file); | 1329 | const capacity = atom_ptr.capacity(elf_file); |
| 1363 | const need_realloc = code.len > capacity or !required_alignment.check(@intCast(atom_ptr.value)); | 1330 | const need_realloc = code.len > capacity or !required_alignment.check(@intCast(atom_ptr.value)); |
| 1364 | if (need_realloc) { | 1331 | if (need_realloc) { |
| 1365 | try atom_ptr.grow(elf_file); | 1332 | try self.growAtom(atom_ptr, elf_file); |
| 1366 | log.debug("growing {} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), old_vaddr, atom_ptr.value }); | 1333 | log.debug("growing {} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), old_vaddr, atom_ptr.value }); |
| 1367 | if (old_vaddr != atom_ptr.value) { | 1334 | if (old_vaddr != atom_ptr.value) { |
| 1368 | sym.value = 0; | 1335 | sym.value = 0; |
| 1369 | esym.st_value = 0; | 1336 | esym.st_value = 0; |
| 1370 | } | 1337 | } |
| 1371 | } else if (code.len < old_size) { | 1338 | } else if (code.len < old_size) { |
| 1372 | atom_ptr.shrink(elf_file); | 1339 | // TODO shrink section size |
| 1373 | } | 1340 | } |
| 1374 | } else { | 1341 | } else { |
| 1375 | try atom_ptr.allocate(elf_file); | 1342 | try self.allocateAtom(atom_ptr, elf_file); |
| 1376 | errdefer self.freeNavMetadata(elf_file, sym_index); | 1343 | errdefer self.freeNavMetadata(elf_file, sym_index); |
| 1377 | |||
| 1378 | sym.value = 0; | 1344 | sym.value = 0; |
| 1379 | esym.st_value = 0; | 1345 | esym.st_value = 0; |
| 1380 | } | 1346 | } |
| ... | @@ -1404,7 +1370,7 @@ fn updateNavCode( | ... | @@ -1404,7 +1370,7 @@ fn updateNavCode( |
| 1404 | 1370 | ||
| 1405 | const shdr = elf_file.sections.items(.shdr)[shdr_index]; | 1371 | const shdr = elf_file.sections.items(.shdr)[shdr_index]; |
| 1406 | if (shdr.sh_type != elf.SHT_NOBITS) { | 1372 | if (shdr.sh_type != elf.SHT_NOBITS) { |
| 1407 | const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value)); | 1373 | const file_offset = atom_ptr.offset(elf_file); |
| 1408 | try elf_file.base.file.?.pwriteAll(code, file_offset); | 1374 | try elf_file.base.file.?.pwriteAll(code, file_offset); |
| 1409 | log.debug("writing {} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), file_offset, file_offset + code.len }); | 1375 | log.debug("writing {} from 0x{x} to 0x{x}", .{ nav.fqn.fmt(ip), file_offset, file_offset + code.len }); |
| 1410 | } | 1376 | } |
| ... | @@ -1433,15 +1399,11 @@ fn updateTlv( | ... | @@ -1433,15 +1399,11 @@ fn updateTlv( |
| 1433 | const atom_ptr = sym.atom(elf_file).?; | 1399 | const atom_ptr = sym.atom(elf_file).?; |
| 1434 | const name_offset = try self.strtab.insert(gpa, nav.fqn.toSlice(ip)); | 1400 | const name_offset = try self.strtab.insert(gpa, nav.fqn.toSlice(ip)); |
| 1435 | 1401 | ||
| 1436 | sym.value = 0; | ||
| 1437 | sym.name_offset = name_offset; | ||
| 1438 | |||
| 1439 | atom_ptr.output_section_index = shndx; | ||
| 1440 | atom_ptr.alive = true; | 1402 | atom_ptr.alive = true; |
| 1441 | atom_ptr.name_offset = name_offset; | 1403 | atom_ptr.name_offset = name_offset; |
| 1404 | atom_ptr.output_section_index = shndx; | ||
| 1442 | 1405 | ||
| 1443 | sym.name_offset = name_offset; | 1406 | sym.name_offset = name_offset; |
| 1444 | esym.st_value = 0; | ||
| 1445 | esym.st_name = name_offset; | 1407 | esym.st_name = name_offset; |
| 1446 | esym.st_info = elf.STT_TLS; | 1408 | esym.st_info = elf.STT_TLS; |
| 1447 | esym.st_size = code.len; | 1409 | esym.st_size = code.len; |
| ... | @@ -1449,21 +1411,25 @@ fn updateTlv( | ... | @@ -1449,21 +1411,25 @@ fn updateTlv( |
| 1449 | atom_ptr.alignment = required_alignment; | 1411 | atom_ptr.alignment = required_alignment; |
| 1450 | atom_ptr.size = code.len; | 1412 | atom_ptr.size = code.len; |
| 1451 | 1413 | ||
| 1452 | self.navs.getPtr(nav_index).?.allocated = true; | 1414 | const gop = try self.tls_variables.getOrPut(gpa, atom_ptr.atom_index); |
| 1415 | assert(!gop.found_existing); // TODO incremental updates | ||
| 1453 | 1416 | ||
| 1454 | { | 1417 | try self.allocateAtom(atom_ptr, elf_file); |
| 1455 | const gop = try self.tls_variables.getOrPut(gpa, atom_ptr.atom_index); | 1418 | sym.value = 0; |
| 1456 | assert(!gop.found_existing); // TODO incremental updates | 1419 | esym.st_value = 0; |
| 1457 | gop.value_ptr.* = .{ .symbol_index = sym_index }; | ||
| 1458 | 1420 | ||
| 1459 | // We only store the data for the TLV if it's non-zerofill. | 1421 | self.navs.getPtr(nav_index).?.allocated = true; |
| 1460 | if (elf_file.sections.items(.shdr)[shndx].sh_type != elf.SHT_NOBITS) { | ||
| 1461 | gop.value_ptr.code = try gpa.dupe(u8, code); | ||
| 1462 | } | ||
| 1463 | } | ||
| 1464 | 1422 | ||
| 1465 | const atom_list = &elf_file.sections.items(.atom_list)[atom_ptr.output_section_index]; | 1423 | const shdr = elf_file.sections.items(.shdr)[shndx]; |
| 1466 | try atom_list.append(gpa, .{ .index = atom_ptr.atom_index, .file = self.index }); | 1424 | if (shdr.sh_type != elf.SHT_NOBITS) { |
| 1425 | const file_offset = atom_ptr.offset(elf_file); | ||
| 1426 | try elf_file.base.file.?.pwriteAll(code, file_offset); | ||
| 1427 | log.debug("writing TLV {s} from 0x{x} to 0x{x}", .{ | ||
| 1428 | atom_ptr.name(elf_file), | ||
| 1429 | file_offset, | ||
| 1430 | file_offset + code.len, | ||
| 1431 | }); | ||
| 1432 | } | ||
| 1467 | } | 1433 | } |
| 1468 | 1434 | ||
| 1469 | pub fn updateFunc( | 1435 | pub fn updateFunc( |
| ... | @@ -1558,6 +1524,19 @@ pub fn updateFunc( | ... | @@ -1558,6 +1524,19 @@ pub fn updateFunc( |
| 1558 | self.symbol(sym_index).name(elf_file), | 1524 | self.symbol(sym_index).name(elf_file), |
| 1559 | }); | 1525 | }); |
| 1560 | defer gpa.free(name); | 1526 | defer gpa.free(name); |
| 1527 | const osec = if (self.text_index) |sect_sym_index| | ||
| 1528 | self.symbol(sect_sym_index).atom(elf_file).?.output_section_index | ||
| 1529 | else osec: { | ||
| 1530 | const osec = try elf_file.addSection(.{ | ||
| 1531 | .name = try elf_file.insertShString(".text"), | ||
| 1532 | .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR, | ||
| 1533 | .type = elf.SHT_PROGBITS, | ||
| 1534 | .addralign = 1, | ||
| 1535 | .offset = std.math.maxInt(u64), | ||
| 1536 | }); | ||
| 1537 | self.text_index = try self.addSectionSymbol(gpa, ".text", .@"1", osec); | ||
| 1538 | break :osec osec; | ||
| 1539 | }; | ||
| 1561 | const name_off = try self.addString(gpa, name); | 1540 | const name_off = try self.addString(gpa, name); |
| 1562 | const tr_size = trampolineSize(elf_file.getTarget().cpu.arch); | 1541 | const tr_size = trampolineSize(elf_file.getTarget().cpu.arch); |
| 1563 | const tr_sym_index = try self.newSymbolWithAtom(gpa, name_off); | 1542 | const tr_sym_index = try self.newSymbolWithAtom(gpa, name_off); |
| ... | @@ -1569,7 +1548,7 @@ pub fn updateFunc( | ... | @@ -1569,7 +1548,7 @@ pub fn updateFunc( |
| 1569 | tr_atom_ptr.value = old_rva; | 1548 | tr_atom_ptr.value = old_rva; |
| 1570 | tr_atom_ptr.alive = true; | 1549 | tr_atom_ptr.alive = true; |
| 1571 | tr_atom_ptr.alignment = old_alignment; | 1550 | tr_atom_ptr.alignment = old_alignment; |
| 1572 | tr_atom_ptr.output_section_index = elf_file.zig_text_section_index.?; | 1551 | tr_atom_ptr.output_section_index = osec; |
| 1573 | tr_atom_ptr.size = tr_size; | 1552 | tr_atom_ptr.size = tr_size; |
| 1574 | const target_sym = self.symbol(sym_index); | 1553 | const target_sym = self.symbol(sym_index); |
| 1575 | target_sym.addExtra(.{ .trampoline = tr_sym_index }, elf_file); | 1554 | target_sym.addExtra(.{ .trampoline = tr_sym_index }, elf_file); |
| ... | @@ -1723,8 +1702,32 @@ fn updateLazySymbol( | ... | @@ -1723,8 +1702,32 @@ fn updateLazySymbol( |
| 1723 | }; | 1702 | }; |
| 1724 | 1703 | ||
| 1725 | const output_section_index = switch (sym.kind) { | 1704 | const output_section_index = switch (sym.kind) { |
| 1726 | .code => elf_file.zig_text_section_index.?, | 1705 | .code => if (self.text_index) |sym_index| |
| 1727 | .const_data => elf_file.zig_data_rel_ro_section_index.?, | 1706 | self.symbol(sym_index).atom(elf_file).?.output_section_index |
| 1707 | else osec: { | ||
| 1708 | const osec = try elf_file.addSection(.{ | ||
| 1709 | .name = try elf_file.insertShString(".text"), | ||
| 1710 | .type = elf.SHT_PROGBITS, | ||
| 1711 | .addralign = 1, | ||
| 1712 | .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR, | ||
| 1713 | .offset = std.math.maxInt(u64), | ||
| 1714 | }); | ||
| 1715 | self.text_index = try self.addSectionSymbol(gpa, ".text", .@"1", osec); | ||
| 1716 | break :osec osec; | ||
| 1717 | }, | ||
| 1718 | .const_data => if (self.rodata_index) |sym_index| | ||
| 1719 | self.symbol(sym_index).atom(elf_file).?.output_section_index | ||
| 1720 | else osec: { | ||
| 1721 | const osec = try elf_file.addSection(.{ | ||
| 1722 | .name = try elf_file.insertShString(".rodata"), | ||
| 1723 | .type = elf.SHT_PROGBITS, | ||
| 1724 | .addralign = 1, | ||
| 1725 | .flags = elf.SHF_ALLOC, | ||
| 1726 | .offset = std.math.maxInt(u64), | ||
| 1727 | }); | ||
| 1728 | self.rodata_index = try self.addSectionSymbol(gpa, ".rodata", .@"1", osec); | ||
| 1729 | break :osec osec; | ||
| 1730 | }, | ||
| 1728 | }; | 1731 | }; |
| 1729 | const local_sym = self.symbol(symbol_index); | 1732 | const local_sym = self.symbol(symbol_index); |
| 1730 | local_sym.name_offset = name_str_index; | 1733 | local_sym.name_offset = name_str_index; |
| ... | @@ -1739,15 +1742,13 @@ fn updateLazySymbol( | ... | @@ -1739,15 +1742,13 @@ fn updateLazySymbol( |
| 1739 | atom_ptr.size = code.len; | 1742 | atom_ptr.size = code.len; |
| 1740 | atom_ptr.output_section_index = output_section_index; | 1743 | atom_ptr.output_section_index = output_section_index; |
| 1741 | 1744 | ||
| 1742 | try atom_ptr.allocate(elf_file); | 1745 | try self.allocateAtom(atom_ptr, elf_file); |
| 1743 | errdefer self.freeNavMetadata(elf_file, symbol_index); | 1746 | errdefer self.freeNavMetadata(elf_file, symbol_index); |
| 1744 | 1747 | ||
| 1745 | local_sym.value = 0; | 1748 | local_sym.value = 0; |
| 1746 | local_esym.st_value = 0; | 1749 | local_esym.st_value = 0; |
| 1747 | 1750 | ||
| 1748 | const shdr = elf_file.sections.items(.shdr)[output_section_index]; | 1751 | try elf_file.base.file.?.pwriteAll(code, atom_ptr.offset(elf_file)); |
| 1749 | const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value)); | ||
| 1750 | try elf_file.base.file.?.pwriteAll(code, file_offset); | ||
| 1751 | } | 1752 | } |
| 1752 | 1753 | ||
| 1753 | const LowerConstResult = union(enum) { | 1754 | const LowerConstResult = union(enum) { |
| ... | @@ -1797,13 +1798,10 @@ fn lowerConst( | ... | @@ -1797,13 +1798,10 @@ fn lowerConst( |
| 1797 | atom_ptr.size = code.len; | 1798 | atom_ptr.size = code.len; |
| 1798 | atom_ptr.output_section_index = output_section_index; | 1799 | atom_ptr.output_section_index = output_section_index; |
| 1799 | 1800 | ||
| 1800 | try atom_ptr.allocate(elf_file); | 1801 | try self.allocateAtom(atom_ptr, elf_file); |
| 1801 | // TODO rename and re-audit this method | ||
| 1802 | errdefer self.freeNavMetadata(elf_file, sym_index); | 1802 | errdefer self.freeNavMetadata(elf_file, sym_index); |
| 1803 | 1803 | ||
| 1804 | const shdr = elf_file.sections.items(.shdr)[output_section_index]; | 1804 | try elf_file.base.file.?.pwriteAll(code, atom_ptr.offset(elf_file)); |
| 1805 | const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value)); | ||
| 1806 | try elf_file.base.file.?.pwriteAll(code, file_offset); | ||
| 1807 | 1805 | ||
| 1808 | return .{ .ok = sym_index }; | 1806 | return .{ .ok = sym_index }; |
| 1809 | } | 1807 | } |
| ... | @@ -1965,8 +1963,7 @@ fn trampolineSize(cpu_arch: std.Target.Cpu.Arch) u64 { | ... | @@ -1965,8 +1963,7 @@ fn trampolineSize(cpu_arch: std.Target.Cpu.Arch) u64 { |
| 1965 | 1963 | ||
| 1966 | fn writeTrampoline(tr_sym: Symbol, target: Symbol, elf_file: *Elf) !void { | 1964 | fn writeTrampoline(tr_sym: Symbol, target: Symbol, elf_file: *Elf) !void { |
| 1967 | const atom_ptr = tr_sym.atom(elf_file).?; | 1965 | const atom_ptr = tr_sym.atom(elf_file).?; |
| 1968 | const shdr = elf_file.sections.items(.shdr)[atom_ptr.output_section_index]; | 1966 | const fileoff = atom_ptr.offset(elf_file); |
| 1969 | const fileoff = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value)); | ||
| 1970 | const source_addr = tr_sym.address(.{}, elf_file); | 1967 | const source_addr = tr_sym.address(.{}, elf_file); |
| 1971 | const target_addr = target.address(.{ .trampoline = false }, elf_file); | 1968 | const target_addr = target.address(.{ .trampoline = false }, elf_file); |
| 1972 | var buf: [max_trampoline_len]u8 = undefined; | 1969 | var buf: [max_trampoline_len]u8 = undefined; |
| ... | @@ -1998,6 +1995,80 @@ fn writeTrampoline(tr_sym: Symbol, target: Symbol, elf_file: *Elf) !void { | ... | @@ -1998,6 +1995,80 @@ fn writeTrampoline(tr_sym: Symbol, target: Symbol, elf_file: *Elf) !void { |
| 1998 | } | 1995 | } |
| 1999 | } | 1996 | } |
| 2000 | 1997 | ||
| 1998 | fn allocateAtom(self: *ZigObject, atom_ptr: *Atom, elf_file: *Elf) !void { | ||
| 1999 | const alloc_res = try elf_file.allocateChunk(.{ | ||
| 2000 | .shndx = atom_ptr.output_section_index, | ||
| 2001 | .size = atom_ptr.size, | ||
| 2002 | .alignment = atom_ptr.alignment, | ||
| 2003 | }); | ||
| 2004 | atom_ptr.value = @intCast(alloc_res.value); | ||
| 2005 | |||
| 2006 | const slice = elf_file.sections.slice(); | ||
| 2007 | const shdr = &slice.items(.shdr)[atom_ptr.output_section_index]; | ||
| 2008 | const last_atom_ref = &slice.items(.last_atom)[atom_ptr.output_section_index]; | ||
| 2009 | |||
| 2010 | const expand_section = if (elf_file.atom(alloc_res.placement)) |placement_atom| | ||
| 2011 | placement_atom.nextAtom(elf_file) == null | ||
| 2012 | else | ||
| 2013 | true; | ||
| 2014 | if (expand_section) { | ||
| 2015 | last_atom_ref.* = atom_ptr.ref(); | ||
| 2016 | if (self.dwarf) |_| { | ||
| 2017 | // The .debug_info section has `low_pc` and `high_pc` values which is the virtual address | ||
| 2018 | // range of the compilation unit. When we expand the text section, this range changes, | ||
| 2019 | // so the DW_TAG.compile_unit tag of the .debug_info section becomes dirty. | ||
| 2020 | self.debug_info_section_dirty = true; | ||
| 2021 | // This becomes dirty for the same reason. We could potentially make this more | ||
| 2022 | // fine-grained with the addition of support for more compilation units. It is planned to | ||
| 2023 | // model each package as a different compilation unit. | ||
| 2024 | self.debug_aranges_section_dirty = true; | ||
| 2025 | self.debug_rnglists_section_dirty = true; | ||
| 2026 | } | ||
| 2027 | } | ||
| 2028 | shdr.sh_addralign = @max(shdr.sh_addralign, atom_ptr.alignment.toByteUnits().?); | ||
| 2029 | |||
| 2030 | const sect_atom_ptr = for ([_]?Symbol.Index{ | ||
| 2031 | self.text_index, | ||
| 2032 | self.rodata_index, | ||
| 2033 | self.data_relro_index, | ||
| 2034 | self.data_index, | ||
| 2035 | self.tdata_index, | ||
| 2036 | }) |maybe_sym_index| { | ||
| 2037 | const sect_sym_index = maybe_sym_index orelse continue; | ||
| 2038 | const sect_atom_ptr = self.symbol(sect_sym_index).atom(elf_file).?; | ||
| 2039 | if (sect_atom_ptr.output_section_index == atom_ptr.output_section_index) break sect_atom_ptr; | ||
| 2040 | } else null; | ||
| 2041 | if (sect_atom_ptr) |sap| { | ||
| 2042 | sap.size = shdr.sh_size; | ||
| 2043 | sap.alignment = Atom.Alignment.fromNonzeroByteUnits(shdr.sh_addralign); | ||
| 2044 | } | ||
| 2045 | |||
| 2046 | // This function can also reallocate an atom. | ||
| 2047 | // In this case we need to "unplug" it from its previous location before | ||
| 2048 | // plugging it in to its new location. | ||
| 2049 | if (atom_ptr.prevAtom(elf_file)) |prev| { | ||
| 2050 | prev.next_atom_ref = atom_ptr.next_atom_ref; | ||
| 2051 | } | ||
| 2052 | if (atom_ptr.nextAtom(elf_file)) |next| { | ||
| 2053 | next.prev_atom_ref = atom_ptr.prev_atom_ref; | ||
| 2054 | } | ||
| 2055 | |||
| 2056 | if (elf_file.atom(alloc_res.placement)) |big_atom| { | ||
| 2057 | atom_ptr.prev_atom_ref = alloc_res.placement; | ||
| 2058 | atom_ptr.next_atom_ref = big_atom.next_atom_ref; | ||
| 2059 | big_atom.next_atom_ref = atom_ptr.ref(); | ||
| 2060 | } else { | ||
| 2061 | atom_ptr.prev_atom_ref = .{ .index = 0, .file = 0 }; | ||
| 2062 | atom_ptr.next_atom_ref = .{ .index = 0, .file = 0 }; | ||
| 2063 | } | ||
| 2064 | } | ||
| 2065 | |||
| 2066 | fn growAtom(self: *ZigObject, atom_ptr: *Atom, elf_file: *Elf) !void { | ||
| 2067 | if (!atom_ptr.alignment.check(@intCast(atom_ptr.value)) or atom_ptr.size > atom_ptr.capacity(elf_file)) { | ||
| 2068 | try self.allocateAtom(atom_ptr, elf_file); | ||
| 2069 | } | ||
| 2070 | } | ||
| 2071 | |||
| 2001 | pub fn asFile(self: *ZigObject) File { | 2072 | pub fn asFile(self: *ZigObject) File { |
| 2002 | return .{ .zig_object = self }; | 2073 | return .{ .zig_object = self }; |
| 2003 | } | 2074 | } |
| ... | @@ -2271,7 +2342,7 @@ const AtomList = std.ArrayListUnmanaged(Atom.Index); | ... | @@ -2271,7 +2342,7 @@ const AtomList = std.ArrayListUnmanaged(Atom.Index); |
| 2271 | const NavTable = std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, AvMetadata); | 2342 | const NavTable = std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, AvMetadata); |
| 2272 | const UavTable = std.AutoArrayHashMapUnmanaged(InternPool.Index, AvMetadata); | 2343 | const UavTable = std.AutoArrayHashMapUnmanaged(InternPool.Index, AvMetadata); |
| 2273 | const LazySymbolTable = std.AutoArrayHashMapUnmanaged(InternPool.Index, LazySymbolMetadata); | 2344 | const LazySymbolTable = std.AutoArrayHashMapUnmanaged(InternPool.Index, LazySymbolMetadata); |
| 2274 | const TlsTable = std.AutoArrayHashMapUnmanaged(Atom.Index, TlsVariable); | 2345 | const TlsTable = std.AutoArrayHashMapUnmanaged(Atom.Index, void); |
| 2275 | 2346 | ||
| 2276 | const x86_64 = struct { | 2347 | const x86_64 = struct { |
| 2277 | fn writeTrampolineCode(source_addr: i64, target_addr: i64, buf: *[max_trampoline_len]u8) ![]u8 { | 2348 | fn writeTrampolineCode(source_addr: i64, target_addr: i64, buf: *[max_trampoline_len]u8) ![]u8 { |
src/link/Elf/eh_frame.zig+30-6| ... | @@ -233,7 +233,10 @@ pub fn calcEhFrameSize(elf_file: *Elf) !usize { | ... | @@ -233,7 +233,10 @@ pub fn calcEhFrameSize(elf_file: *Elf) !usize { |
| 233 | const comp = elf_file.base.comp; | 233 | const comp = elf_file.base.comp; |
| 234 | const gpa = comp.gpa; | 234 | const gpa = comp.gpa; |
| 235 | 235 | ||
| 236 | var offset: usize = 0; | 236 | var offset: usize = if (elf_file.zigObjectPtr()) |zo| blk: { |
| 237 | const sym = zo.symbol(zo.eh_frame_index orelse break :blk 0); | ||
| 238 | break :blk math.cast(usize, sym.atom(elf_file).?.size) orelse return error.Overflow; | ||
| 239 | } else 0; | ||
| 237 | 240 | ||
| 238 | var cies = std.ArrayList(Cie).init(gpa); | 241 | var cies = std.ArrayList(Cie).init(gpa); |
| 239 | defer cies.deinit(); | 242 | defer cies.deinit(); |
| ... | @@ -288,6 +291,13 @@ pub fn calcEhFrameHdrSize(elf_file: *Elf) usize { | ... | @@ -288,6 +291,13 @@ pub fn calcEhFrameHdrSize(elf_file: *Elf) usize { |
| 288 | 291 | ||
| 289 | pub fn calcEhFrameRelocs(elf_file: *Elf) usize { | 292 | pub fn calcEhFrameRelocs(elf_file: *Elf) usize { |
| 290 | var count: usize = 0; | 293 | var count: usize = 0; |
| 294 | if (elf_file.zigObjectPtr()) |zo| zo: { | ||
| 295 | const sym_index = zo.eh_frame_index orelse break :zo; | ||
| 296 | const sym = zo.symbol(sym_index); | ||
| 297 | const atom_ptr = zo.atom(sym.ref.index).?; | ||
| 298 | if (!atom_ptr.alive) break :zo; | ||
| 299 | count += atom_ptr.relocs(elf_file).len; | ||
| 300 | } | ||
| 291 | for (elf_file.objects.items) |index| { | 301 | for (elf_file.objects.items) |index| { |
| 292 | const object = elf_file.file(index).?.object; | 302 | const object = elf_file.file(index).?.object; |
| 293 | for (object.cies.items) |cie| { | 303 | for (object.cies.items) |cie| { |
| ... | @@ -386,7 +396,7 @@ pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void { | ... | @@ -386,7 +396,7 @@ pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void { |
| 386 | if (has_reloc_errors) return error.RelocFailure; | 396 | if (has_reloc_errors) return error.RelocFailure; |
| 387 | } | 397 | } |
| 388 | 398 | ||
| 389 | pub fn writeEhFrameObject(elf_file: *Elf, writer: anytype) !void { | 399 | pub fn writeEhFrameRelocatable(elf_file: *Elf, writer: anytype) !void { |
| 390 | for (elf_file.objects.items) |index| { | 400 | for (elf_file.objects.items) |index| { |
| 391 | const object = elf_file.file(index).?.object; | 401 | const object = elf_file.file(index).?.object; |
| 392 | 402 | ||
| ... | @@ -416,9 +426,8 @@ pub fn writeEhFrameObject(elf_file: *Elf, writer: anytype) !void { | ... | @@ -416,9 +426,8 @@ pub fn writeEhFrameObject(elf_file: *Elf, writer: anytype) !void { |
| 416 | } | 426 | } |
| 417 | } | 427 | } |
| 418 | 428 | ||
| 419 | fn emitReloc(elf_file: *Elf, rec: anytype, sym: *const Symbol, rel: elf.Elf64_Rela) elf.Elf64_Rela { | 429 | fn emitReloc(elf_file: *Elf, r_offset: u64, sym: *const Symbol, rel: elf.Elf64_Rela) elf.Elf64_Rela { |
| 420 | const cpu_arch = elf_file.getTarget().cpu.arch; | 430 | const cpu_arch = elf_file.getTarget().cpu.arch; |
| 421 | const r_offset = rec.address(elf_file) + rel.r_offset - rec.offset; | ||
| 422 | const r_type = rel.r_type(); | 431 | const r_type = rel.r_type(); |
| 423 | var r_addend = rel.r_addend; | 432 | var r_addend = rel.r_addend; |
| 424 | var r_sym: u32 = 0; | 433 | var r_sym: u32 = 0; |
| ... | @@ -452,6 +461,19 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void { | ... | @@ -452,6 +461,19 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void { |
| 452 | elf_file.sections.items(.shdr)[elf_file.eh_frame_section_index.?].sh_addr, | 461 | elf_file.sections.items(.shdr)[elf_file.eh_frame_section_index.?].sh_addr, |
| 453 | }); | 462 | }); |
| 454 | 463 | ||
| 464 | if (elf_file.zigObjectPtr()) |zo| zo: { | ||
| 465 | const sym_index = zo.eh_frame_index orelse break :zo; | ||
| 466 | const sym = zo.symbol(sym_index); | ||
| 467 | const atom_ptr = zo.atom(sym.ref.index).?; | ||
| 468 | if (!atom_ptr.alive) break :zo; | ||
| 469 | for (atom_ptr.relocs(elf_file)) |rel| { | ||
| 470 | const ref = zo.resolveSymbol(rel.r_sym(), elf_file); | ||
| 471 | const target = elf_file.symbol(ref).?; | ||
| 472 | const out_rel = emitReloc(elf_file, rel.r_offset, target, rel); | ||
| 473 | try writer.writeStruct(out_rel); | ||
| 474 | } | ||
| 475 | } | ||
| 476 | |||
| 455 | for (elf_file.objects.items) |index| { | 477 | for (elf_file.objects.items) |index| { |
| 456 | const object = elf_file.file(index).?.object; | 478 | const object = elf_file.file(index).?.object; |
| 457 | 479 | ||
| ... | @@ -460,7 +482,8 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void { | ... | @@ -460,7 +482,8 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void { |
| 460 | for (cie.relocs(elf_file)) |rel| { | 482 | for (cie.relocs(elf_file)) |rel| { |
| 461 | const ref = object.resolveSymbol(rel.r_sym(), elf_file); | 483 | const ref = object.resolveSymbol(rel.r_sym(), elf_file); |
| 462 | const sym = elf_file.symbol(ref).?; | 484 | const sym = elf_file.symbol(ref).?; |
| 463 | const out_rel = emitReloc(elf_file, cie, sym, rel); | 485 | const r_offset = cie.address(elf_file) + rel.r_offset - cie.offset; |
| 486 | const out_rel = emitReloc(elf_file, r_offset, sym, rel); | ||
| 464 | try writer.writeStruct(out_rel); | 487 | try writer.writeStruct(out_rel); |
| 465 | } | 488 | } |
| 466 | } | 489 | } |
| ... | @@ -470,7 +493,8 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void { | ... | @@ -470,7 +493,8 @@ pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void { |
| 470 | for (fde.relocs(elf_file)) |rel| { | 493 | for (fde.relocs(elf_file)) |rel| { |
| 471 | const ref = object.resolveSymbol(rel.r_sym(), elf_file); | 494 | const ref = object.resolveSymbol(rel.r_sym(), elf_file); |
| 472 | const sym = elf_file.symbol(ref).?; | 495 | const sym = elf_file.symbol(ref).?; |
| 473 | const out_rel = emitReloc(elf_file, fde, sym, rel); | 496 | const r_offset = fde.address(elf_file) + rel.r_offset - fde.offset; |
| 497 | const out_rel = emitReloc(elf_file, r_offset, sym, rel); | ||
| 474 | try writer.writeStruct(out_rel); | 498 | try writer.writeStruct(out_rel); |
| 475 | } | 499 | } |
| 476 | } | 500 | } |
src/link/Elf/relocatable.zig+80-114| ... | @@ -18,7 +18,7 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]co | ... | @@ -18,7 +18,7 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]co |
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | for (positionals.items) |obj| { | 20 | for (positionals.items) |obj| { |
| 21 | parsePositional(elf_file, obj.path) catch |err| switch (err) { | 21 | parsePositionalStaticLib(elf_file, obj.path) catch |err| switch (err) { |
| 22 | error.MalformedObject, | 22 | error.MalformedObject, |
| 23 | error.MalformedArchive, | 23 | error.MalformedArchive, |
| 24 | error.InvalidMachineType, | 24 | error.InvalidMachineType, |
| ... | @@ -38,17 +38,12 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]co | ... | @@ -38,17 +38,12 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]co |
| 38 | // First, we flush relocatable object file generated with our backends. | 38 | // First, we flush relocatable object file generated with our backends. |
| 39 | if (elf_file.zigObjectPtr()) |zig_object| { | 39 | if (elf_file.zigObjectPtr()) |zig_object| { |
| 40 | try zig_object.resolveSymbols(elf_file); | 40 | try zig_object.resolveSymbols(elf_file); |
| 41 | elf_file.markEhFrameAtomsDead(); | ||
| 41 | try elf_file.addCommentString(); | 42 | try elf_file.addCommentString(); |
| 42 | try elf_file.finalizeMergeSections(); | 43 | try elf_file.finalizeMergeSections(); |
| 43 | zig_object.claimUnresolvedObject(elf_file); | 44 | zig_object.claimUnresolvedRelocatable(elf_file); |
| 44 | 45 | ||
| 45 | for (elf_file.merge_sections.items) |*msec| { | 46 | try initSections(elf_file); |
| 46 | if (msec.finalized_subsections.items.len == 0) continue; | ||
| 47 | try msec.initOutputSection(elf_file); | ||
| 48 | } | ||
| 49 | |||
| 50 | try elf_file.initSymtab(); | ||
| 51 | try elf_file.initShStrtab(); | ||
| 52 | try elf_file.sortShdrs(); | 47 | try elf_file.sortShdrs(); |
| 53 | try zig_object.addAtomsToRelaSections(elf_file); | 48 | try zig_object.addAtomsToRelaSections(elf_file); |
| 54 | try elf_file.updateMergeSectionSizes(); | 49 | try elf_file.updateMergeSectionSizes(); |
| ... | @@ -208,7 +203,6 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const | ... | @@ -208,7 +203,6 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const |
| 208 | } | 203 | } |
| 209 | for (elf_file.objects.items) |index| { | 204 | for (elf_file.objects.items) |index| { |
| 210 | const object = elf_file.file(index).?.object; | 205 | const object = elf_file.file(index).?.object; |
| 211 | try object.addAtomsToOutputSections(elf_file); | ||
| 212 | try object.addAtomsToRelaSections(elf_file); | 206 | try object.addAtomsToRelaSections(elf_file); |
| 213 | } | 207 | } |
| 214 | try elf_file.updateMergeSectionSizes(); | 208 | try elf_file.updateMergeSectionSizes(); |
| ... | @@ -230,17 +224,17 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const | ... | @@ -230,17 +224,17 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const |
| 230 | if (elf_file.base.hasErrors()) return error.FlushFailure; | 224 | if (elf_file.base.hasErrors()) return error.FlushFailure; |
| 231 | } | 225 | } |
| 232 | 226 | ||
| 233 | fn parsePositional(elf_file: *Elf, path: []const u8) Elf.ParseError!void { | 227 | fn parsePositionalStaticLib(elf_file: *Elf, path: []const u8) Elf.ParseError!void { |
| 234 | if (try Object.isObject(path)) { | 228 | if (try Object.isObject(path)) { |
| 235 | try parseObject(elf_file, path); | 229 | try parseObjectStaticLib(elf_file, path); |
| 236 | } else if (try Archive.isArchive(path)) { | 230 | } else if (try Archive.isArchive(path)) { |
| 237 | try parseArchive(elf_file, path); | 231 | try parseArchiveStaticLib(elf_file, path); |
| 238 | } else return error.UnknownFileType; | 232 | } else return error.UnknownFileType; |
| 239 | // TODO: should we check for LD script? | 233 | // TODO: should we check for LD script? |
| 240 | // Actually, should we even unpack an archive? | 234 | // Actually, should we even unpack an archive? |
| 241 | } | 235 | } |
| 242 | 236 | ||
| 243 | fn parseObject(elf_file: *Elf, path: []const u8) Elf.ParseError!void { | 237 | fn parseObjectStaticLib(elf_file: *Elf, path: []const u8) Elf.ParseError!void { |
| 244 | const gpa = elf_file.base.comp.gpa; | 238 | const gpa = elf_file.base.comp.gpa; |
| 245 | const handle = try std.fs.cwd().openFile(path, .{}); | 239 | const handle = try std.fs.cwd().openFile(path, .{}); |
| 246 | const fh = try elf_file.addFileHandle(handle); | 240 | const fh = try elf_file.addFileHandle(handle); |
| ... | @@ -257,7 +251,7 @@ fn parseObject(elf_file: *Elf, path: []const u8) Elf.ParseError!void { | ... | @@ -257,7 +251,7 @@ fn parseObject(elf_file: *Elf, path: []const u8) Elf.ParseError!void { |
| 257 | try object.parseAr(elf_file); | 251 | try object.parseAr(elf_file); |
| 258 | } | 252 | } |
| 259 | 253 | ||
| 260 | fn parseArchive(elf_file: *Elf, path: []const u8) Elf.ParseError!void { | 254 | fn parseArchiveStaticLib(elf_file: *Elf, path: []const u8) Elf.ParseError!void { |
| 261 | const gpa = elf_file.base.comp.gpa; | 255 | const gpa = elf_file.base.comp.gpa; |
| 262 | const handle = try std.fs.cwd().openFile(path, .{}); | 256 | const handle = try std.fs.cwd().openFile(path, .{}); |
| 263 | const fh = try elf_file.addFileHandle(handle); | 257 | const fh = try elf_file.addFileHandle(handle); |
| ... | @@ -281,14 +275,17 @@ fn parseArchive(elf_file: *Elf, path: []const u8) Elf.ParseError!void { | ... | @@ -281,14 +275,17 @@ fn parseArchive(elf_file: *Elf, path: []const u8) Elf.ParseError!void { |
| 281 | 275 | ||
| 282 | fn claimUnresolved(elf_file: *Elf) void { | 276 | fn claimUnresolved(elf_file: *Elf) void { |
| 283 | if (elf_file.zigObjectPtr()) |zig_object| { | 277 | if (elf_file.zigObjectPtr()) |zig_object| { |
| 284 | zig_object.claimUnresolvedObject(elf_file); | 278 | zig_object.claimUnresolvedRelocatable(elf_file); |
| 285 | } | 279 | } |
| 286 | for (elf_file.objects.items) |index| { | 280 | for (elf_file.objects.items) |index| { |
| 287 | elf_file.file(index).?.object.claimUnresolvedObject(elf_file); | 281 | elf_file.file(index).?.object.claimUnresolvedRelocatable(elf_file); |
| 288 | } | 282 | } |
| 289 | } | 283 | } |
| 290 | 284 | ||
| 291 | fn initSections(elf_file: *Elf) !void { | 285 | fn initSections(elf_file: *Elf) !void { |
| 286 | if (elf_file.zigObjectPtr()) |zo| { | ||
| 287 | try zo.initRelaSections(elf_file); | ||
| 288 | } | ||
| 292 | for (elf_file.objects.items) |index| { | 289 | for (elf_file.objects.items) |index| { |
| 293 | const object = elf_file.file(index).?.object; | 290 | const object = elf_file.file(index).?.object; |
| 294 | try object.initOutputSections(elf_file); | 291 | try object.initOutputSections(elf_file); |
| ... | @@ -300,12 +297,17 @@ fn initSections(elf_file: *Elf) !void { | ... | @@ -300,12 +297,17 @@ fn initSections(elf_file: *Elf) !void { |
| 300 | try msec.initOutputSection(elf_file); | 297 | try msec.initOutputSection(elf_file); |
| 301 | } | 298 | } |
| 302 | 299 | ||
| 303 | const needs_eh_frame = for (elf_file.objects.items) |index| { | 300 | const needs_eh_frame = blk: { |
| 304 | if (elf_file.file(index).?.object.cies.items.len > 0) break true; | 301 | if (elf_file.zigObjectPtr()) |zo| |
| 305 | } else false; | 302 | if (zo.eh_frame_index != null) break :blk true; |
| 303 | break :blk for (elf_file.objects.items) |index| { | ||
| 304 | if (elf_file.file(index).?.object.cies.items.len > 0) break true; | ||
| 305 | } else false; | ||
| 306 | }; | ||
| 306 | if (needs_eh_frame) { | 307 | if (needs_eh_frame) { |
| 307 | if (elf_file.eh_frame_section_index == null) { | 308 | if (elf_file.eh_frame_section_index == null) { |
| 308 | elf_file.eh_frame_section_index = try elf_file.addSection(.{ | 309 | elf_file.eh_frame_section_index = elf_file.sectionByName(".eh_frame") orelse |
| 310 | try elf_file.addSection(.{ | ||
| 309 | .name = try elf_file.insertShString(".eh_frame"), | 311 | .name = try elf_file.insertShString(".eh_frame"), |
| 310 | .type = if (elf_file.getTarget().cpu.arch == .x86_64) | 312 | .type = if (elf_file.getTarget().cpu.arch == .x86_64) |
| 311 | elf.SHT_X86_64_UNWIND | 313 | elf.SHT_X86_64_UNWIND |
| ... | @@ -316,7 +318,8 @@ fn initSections(elf_file: *Elf) !void { | ... | @@ -316,7 +318,8 @@ fn initSections(elf_file: *Elf) !void { |
| 316 | .offset = std.math.maxInt(u64), | 318 | .offset = std.math.maxInt(u64), |
| 317 | }); | 319 | }); |
| 318 | } | 320 | } |
| 319 | elf_file.eh_frame_rela_section_index = try elf_file.addRelaShdr( | 321 | elf_file.eh_frame_rela_section_index = elf_file.sectionByName(".rela.eh_frame") orelse |
| 322 | try elf_file.addRelaShdr( | ||
| 320 | try elf_file.insertShString(".rela.eh_frame"), | 323 | try elf_file.insertShString(".rela.eh_frame"), |
| 321 | elf_file.eh_frame_section_index.?, | 324 | elf_file.eh_frame_section_index.?, |
| 322 | ); | 325 | ); |
| ... | @@ -351,36 +354,28 @@ fn initComdatGroups(elf_file: *Elf) !void { | ... | @@ -351,36 +354,28 @@ fn initComdatGroups(elf_file: *Elf) !void { |
| 351 | 354 | ||
| 352 | fn updateSectionSizes(elf_file: *Elf) !void { | 355 | fn updateSectionSizes(elf_file: *Elf) !void { |
| 353 | const slice = elf_file.sections.slice(); | 356 | const slice = elf_file.sections.slice(); |
| 357 | for (slice.items(.atom_list_2)) |*atom_list| { | ||
| 358 | if (atom_list.atoms.items.len == 0) continue; | ||
| 359 | atom_list.updateSize(elf_file); | ||
| 360 | try atom_list.allocate(elf_file); | ||
| 361 | } | ||
| 362 | |||
| 354 | for (slice.items(.shdr), 0..) |*shdr, shndx| { | 363 | for (slice.items(.shdr), 0..) |*shdr, shndx| { |
| 355 | const atom_list = slice.items(.atom_list)[shndx]; | 364 | const atom_list = slice.items(.atom_list)[shndx]; |
| 356 | if (shdr.sh_type != elf.SHT_RELA) { | 365 | if (shdr.sh_type != elf.SHT_RELA) continue; |
| 357 | for (atom_list.items) |ref| { | 366 | if (@as(u32, @intCast(shndx)) == elf_file.eh_frame_section_index) continue; |
| 358 | const atom_ptr = elf_file.atom(ref) orelse continue; | 367 | for (atom_list.items) |ref| { |
| 359 | if (!atom_ptr.alive) continue; | 368 | const atom_ptr = elf_file.atom(ref) orelse continue; |
| 360 | const offset = atom_ptr.alignment.forward(shdr.sh_size); | 369 | if (!atom_ptr.alive) continue; |
| 361 | const padding = offset - shdr.sh_size; | 370 | const relocs = atom_ptr.relocs(elf_file); |
| 362 | atom_ptr.value = @intCast(offset); | 371 | shdr.sh_size += shdr.sh_entsize * relocs.len; |
| 363 | shdr.sh_size += padding + atom_ptr.size; | ||
| 364 | shdr.sh_addralign = @max(shdr.sh_addralign, atom_ptr.alignment.toByteUnits() orelse 1); | ||
| 365 | } | ||
| 366 | } else { | ||
| 367 | for (atom_list.items) |ref| { | ||
| 368 | const atom_ptr = elf_file.atom(ref) orelse continue; | ||
| 369 | if (!atom_ptr.alive) continue; | ||
| 370 | const relocs = atom_ptr.relocs(elf_file); | ||
| 371 | shdr.sh_size += shdr.sh_entsize * relocs.len; | ||
| 372 | } | ||
| 373 | |||
| 374 | if (shdr.sh_size == 0) shdr.sh_offset = 0; | ||
| 375 | } | 372 | } |
| 373 | |||
| 374 | if (shdr.sh_size == 0) shdr.sh_offset = 0; | ||
| 376 | } | 375 | } |
| 377 | 376 | ||
| 378 | if (elf_file.eh_frame_section_index) |index| { | 377 | if (elf_file.eh_frame_section_index) |index| { |
| 379 | slice.items(.shdr)[index].sh_size = existing_size: { | 378 | slice.items(.shdr)[index].sh_size = try eh_frame.calcEhFrameSize(elf_file); |
| 380 | const zo = elf_file.zigObjectPtr() orelse break :existing_size 0; | ||
| 381 | const sym = zo.symbol(zo.eh_frame_index orelse break :existing_size 0); | ||
| 382 | break :existing_size sym.atom(elf_file).?.size; | ||
| 383 | } + try eh_frame.calcEhFrameSize(elf_file); | ||
| 384 | } | 379 | } |
| 385 | if (elf_file.eh_frame_rela_section_index) |index| { | 380 | if (elf_file.eh_frame_rela_section_index) |index| { |
| 386 | const shdr = &slice.items(.shdr)[index]; | 381 | const shdr = &slice.items(.shdr)[index]; |
| ... | @@ -405,7 +400,7 @@ fn updateComdatGroupsSizes(elf_file: *Elf) void { | ... | @@ -405,7 +400,7 @@ fn updateComdatGroupsSizes(elf_file: *Elf) void { |
| 405 | 400 | ||
| 406 | /// Allocates alloc sections when merging relocatable objects files together. | 401 | /// Allocates alloc sections when merging relocatable objects files together. |
| 407 | fn allocateAllocSections(elf_file: *Elf) !void { | 402 | fn allocateAllocSections(elf_file: *Elf) !void { |
| 408 | for (elf_file.sections.items(.shdr)) |*shdr| { | 403 | for (elf_file.sections.items(.shdr), 0..) |*shdr, shndx| { |
| 409 | if (shdr.sh_type == elf.SHT_NULL) continue; | 404 | if (shdr.sh_type == elf.SHT_NULL) continue; |
| 410 | if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; | 405 | if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; |
| 411 | if (shdr.sh_type == elf.SHT_NOBITS) { | 406 | if (shdr.sh_type == elf.SHT_NOBITS) { |
| ... | @@ -416,6 +411,34 @@ fn allocateAllocSections(elf_file: *Elf) !void { | ... | @@ -416,6 +411,34 @@ fn allocateAllocSections(elf_file: *Elf) !void { |
| 416 | if (needed_size > elf_file.allocatedSize(shdr.sh_offset)) { | 411 | if (needed_size > elf_file.allocatedSize(shdr.sh_offset)) { |
| 417 | shdr.sh_size = 0; | 412 | shdr.sh_size = 0; |
| 418 | const new_offset = try elf_file.findFreeSpace(needed_size, shdr.sh_addralign); | 413 | const new_offset = try elf_file.findFreeSpace(needed_size, shdr.sh_addralign); |
| 414 | |||
| 415 | if (elf_file.zigObjectPtr()) |zo| blk: { | ||
| 416 | const existing_size = for ([_]?Symbol.Index{ | ||
| 417 | zo.text_index, | ||
| 418 | zo.rodata_index, | ||
| 419 | zo.data_relro_index, | ||
| 420 | zo.data_index, | ||
| 421 | zo.tdata_index, | ||
| 422 | zo.eh_frame_index, | ||
| 423 | }) |maybe_sym_index| { | ||
| 424 | const sect_sym_index = maybe_sym_index orelse continue; | ||
| 425 | const sect_atom_ptr = zo.symbol(sect_sym_index).atom(elf_file).?; | ||
| 426 | if (sect_atom_ptr.output_section_index == shndx) break sect_atom_ptr.size; | ||
| 427 | } else break :blk; | ||
| 428 | log.debug("moving {s} from 0x{x} to 0x{x}", .{ | ||
| 429 | elf_file.getShString(shdr.sh_name), | ||
| 430 | shdr.sh_offset, | ||
| 431 | new_offset, | ||
| 432 | }); | ||
| 433 | const amt = try elf_file.base.file.?.copyRangeAll( | ||
| 434 | shdr.sh_offset, | ||
| 435 | elf_file.base.file.?, | ||
| 436 | new_offset, | ||
| 437 | existing_size, | ||
| 438 | ); | ||
| 439 | if (amt != existing_size) return error.InputOutput; | ||
| 440 | } | ||
| 441 | |||
| 419 | shdr.sh_offset = new_offset; | 442 | shdr.sh_offset = new_offset; |
| 420 | shdr.sh_size = needed_size; | 443 | shdr.sh_size = needed_size; |
| 421 | } | 444 | } |
| ... | @@ -424,73 +447,15 @@ fn allocateAllocSections(elf_file: *Elf) !void { | ... | @@ -424,73 +447,15 @@ fn allocateAllocSections(elf_file: *Elf) !void { |
| 424 | 447 | ||
| 425 | fn writeAtoms(elf_file: *Elf) !void { | 448 | fn writeAtoms(elf_file: *Elf) !void { |
| 426 | const gpa = elf_file.base.comp.gpa; | 449 | const gpa = elf_file.base.comp.gpa; |
| 427 | const slice = elf_file.sections.slice(); | ||
| 428 | |||
| 429 | // TODO iterate over `output_sections` directly | ||
| 430 | for (slice.items(.shdr), slice.items(.atom_list), 0..) |shdr, atom_list, shndx| { | ||
| 431 | if (shdr.sh_type == elf.SHT_NULL) continue; | ||
| 432 | if (shdr.sh_type == elf.SHT_NOBITS) continue; | ||
| 433 | if (shdr.sh_type == elf.SHT_RELA) continue; | ||
| 434 | if (atom_list.items.len == 0) continue; | ||
| 435 | |||
| 436 | log.debug("writing atoms in '{s}' section", .{elf_file.getShString(shdr.sh_name)}); | ||
| 437 | |||
| 438 | // TODO really, really handle debug section separately | ||
| 439 | const base_offset = if (elf_file.isDebugSection(@intCast(shndx))) blk: { | ||
| 440 | const zo = elf_file.zigObjectPtr().?; | ||
| 441 | break :blk for ([_]Symbol.Index{ | ||
| 442 | zo.debug_info_index.?, | ||
| 443 | zo.debug_abbrev_index.?, | ||
| 444 | zo.debug_aranges_index.?, | ||
| 445 | zo.debug_str_index.?, | ||
| 446 | zo.debug_line_index.?, | ||
| 447 | zo.debug_line_str_index.?, | ||
| 448 | zo.debug_loclists_index.?, | ||
| 449 | zo.debug_rnglists_index.?, | ||
| 450 | }) |sym_index| { | ||
| 451 | const sym = zo.symbol(sym_index); | ||
| 452 | const atom_ptr = sym.atom(elf_file).?; | ||
| 453 | if (atom_ptr.output_section_index == shndx) break atom_ptr.size; | ||
| 454 | } else 0; | ||
| 455 | } else 0; | ||
| 456 | const sh_offset = shdr.sh_offset + base_offset; | ||
| 457 | const sh_size = math.cast(usize, shdr.sh_size - base_offset) orelse return error.Overflow; | ||
| 458 | |||
| 459 | const buffer = try gpa.alloc(u8, sh_size); | ||
| 460 | defer gpa.free(buffer); | ||
| 461 | const padding_byte: u8 = if (shdr.sh_type == elf.SHT_PROGBITS and | ||
| 462 | shdr.sh_flags & elf.SHF_EXECINSTR != 0) | ||
| 463 | 0xcc // int3 | ||
| 464 | else | ||
| 465 | 0; | ||
| 466 | @memset(buffer, padding_byte); | ||
| 467 | |||
| 468 | for (atom_list.items) |ref| { | ||
| 469 | const atom_ptr = elf_file.atom(ref).?; | ||
| 470 | assert(atom_ptr.alive); | ||
| 471 | |||
| 472 | const offset = math.cast(usize, atom_ptr.value - @as(i64, @intCast(shdr.sh_addr - base_offset))) orelse | ||
| 473 | return error.Overflow; | ||
| 474 | const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow; | ||
| 475 | 450 | ||
| 476 | log.debug("writing atom({}) from 0x{x} to 0x{x}", .{ | 451 | var buffer = std.ArrayList(u8).init(gpa); |
| 477 | ref, | 452 | defer buffer.deinit(); |
| 478 | sh_offset + offset, | ||
| 479 | sh_offset + offset + size, | ||
| 480 | }); | ||
| 481 | |||
| 482 | // TODO decompress directly into provided buffer | ||
| 483 | const out_code = buffer[offset..][0..size]; | ||
| 484 | const in_code = switch (atom_ptr.file(elf_file).?) { | ||
| 485 | .object => |x| try x.codeDecompressAlloc(elf_file, ref.index), | ||
| 486 | .zig_object => |x| try x.codeAlloc(elf_file, ref.index), | ||
| 487 | else => unreachable, | ||
| 488 | }; | ||
| 489 | defer gpa.free(in_code); | ||
| 490 | @memcpy(out_code, in_code); | ||
| 491 | } | ||
| 492 | 453 | ||
| 493 | try elf_file.base.file.?.pwriteAll(buffer, sh_offset); | 454 | const slice = elf_file.sections.slice(); |
| 455 | for (slice.items(.shdr), slice.items(.atom_list_2)) |shdr, atom_list| { | ||
| 456 | if (shdr.sh_type == elf.SHT_NOBITS) continue; | ||
| 457 | if (atom_list.atoms.items.len == 0) continue; | ||
| 458 | try atom_list.writeRelocatable(&buffer, elf_file); | ||
| 494 | } | 459 | } |
| 495 | } | 460 | } |
| 496 | 461 | ||
| ... | @@ -498,9 +463,10 @@ fn writeSyntheticSections(elf_file: *Elf) !void { | ... | @@ -498,9 +463,10 @@ fn writeSyntheticSections(elf_file: *Elf) !void { |
| 498 | const gpa = elf_file.base.comp.gpa; | 463 | const gpa = elf_file.base.comp.gpa; |
| 499 | const slice = elf_file.sections.slice(); | 464 | const slice = elf_file.sections.slice(); |
| 500 | 465 | ||
| 501 | for (slice.items(.shdr), slice.items(.atom_list)) |shdr, atom_list| { | 466 | for (slice.items(.shdr), slice.items(.atom_list), 0..) |shdr, atom_list, shndx| { |
| 502 | if (shdr.sh_type != elf.SHT_RELA) continue; | 467 | if (shdr.sh_type != elf.SHT_RELA) continue; |
| 503 | if (atom_list.items.len == 0) continue; | 468 | if (atom_list.items.len == 0) continue; |
| 469 | if (@as(u32, @intCast(shndx)) == elf_file.eh_frame_section_index) continue; | ||
| 504 | 470 | ||
| 505 | const num_relocs = math.cast(usize, @divExact(shdr.sh_size, shdr.sh_entsize)) orelse | 471 | const num_relocs = math.cast(usize, @divExact(shdr.sh_size, shdr.sh_entsize)) orelse |
| 506 | return error.Overflow; | 472 | return error.Overflow; |
| ... | @@ -542,7 +508,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void { | ... | @@ -542,7 +508,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void { |
| 542 | const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; | 508 | const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; |
| 543 | var buffer = try std.ArrayList(u8).initCapacity(gpa, @intCast(sh_size - existing_size)); | 509 | var buffer = try std.ArrayList(u8).initCapacity(gpa, @intCast(sh_size - existing_size)); |
| 544 | defer buffer.deinit(); | 510 | defer buffer.deinit(); |
| 545 | try eh_frame.writeEhFrameObject(elf_file, buffer.writer()); | 511 | try eh_frame.writeEhFrameRelocatable(elf_file, buffer.writer()); |
| 546 | log.debug("writing .eh_frame from 0x{x} to 0x{x}", .{ | 512 | log.debug("writing .eh_frame from 0x{x} to 0x{x}", .{ |
| 547 | shdr.sh_offset + existing_size, | 513 | shdr.sh_offset + existing_size, |
| 548 | shdr.sh_offset + sh_size, | 514 | shdr.sh_offset + sh_size, |
test/link/elf.zig+2| ... | @@ -55,6 +55,7 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step { | ... | @@ -55,6 +55,7 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step { |
| 55 | 55 | ||
| 56 | // Exercise linker in ar mode | 56 | // Exercise linker in ar mode |
| 57 | elf_step.dependOn(testEmitStaticLib(b, .{ .target = musl_target })); | 57 | elf_step.dependOn(testEmitStaticLib(b, .{ .target = musl_target })); |
| 58 | elf_step.dependOn(testEmitStaticLibZig(b, .{ .target = musl_target })); | ||
| 58 | 59 | ||
| 59 | // Exercise linker with LLVM backend | 60 | // Exercise linker with LLVM backend |
| 60 | // musl tests | 61 | // musl tests |
| ... | @@ -66,6 +67,7 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step { | ... | @@ -66,6 +67,7 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step { |
| 66 | elf_step.dependOn(testEmptyObject(b, .{ .target = musl_target })); | 67 | elf_step.dependOn(testEmptyObject(b, .{ .target = musl_target })); |
| 67 | elf_step.dependOn(testEntryPoint(b, .{ .target = musl_target })); | 68 | elf_step.dependOn(testEntryPoint(b, .{ .target = musl_target })); |
| 68 | elf_step.dependOn(testGcSections(b, .{ .target = musl_target })); | 69 | elf_step.dependOn(testGcSections(b, .{ .target = musl_target })); |
| 70 | elf_step.dependOn(testGcSectionsZig(b, .{ .target = musl_target })); | ||
| 69 | elf_step.dependOn(testImageBase(b, .{ .target = musl_target })); | 71 | elf_step.dependOn(testImageBase(b, .{ .target = musl_target })); |
| 70 | elf_step.dependOn(testInitArrayOrder(b, .{ .target = musl_target })); | 72 | elf_step.dependOn(testInitArrayOrder(b, .{ .target = musl_target })); |
| 71 | elf_step.dependOn(testLargeAlignmentExe(b, .{ .target = musl_target })); | 73 | elf_step.dependOn(testLargeAlignmentExe(b, .{ .target = musl_target })); |