| ... | ... | @@ -1,11 +1,16 @@ |
| 1 | 1 | base: link.File, |
| 2 | options: link.File.OpenOptions, |
| 2 | 3 | mf: MappedFile, |
| 3 | | known: Node.Known, |
| 4 | ni: Node.Known, |
| 4 | 5 | nodes: std.MultiArrayList(Node), |
| 5 | 6 | phdrs: std.ArrayList(MappedFile.Node.Index), |
| 7 | si: Symbol.Known, |
| 6 | 8 | symtab: std.ArrayList(Symbol), |
| 7 | 9 | shstrtab: StringTable, |
| 8 | 10 | strtab: StringTable, |
| 11 | dynsym: std.ArrayList(Symbol.Index), |
| 12 | dynstr: StringTable, |
| 13 | needed: std.AutoArrayHashMapUnmanaged(u32, void), |
| 9 | 14 | inputs: std.ArrayList(struct { |
| 10 | 15 | path: std.Build.Cache.Path, |
| 11 | 16 | member: ?[]const u8, |
| ... | ... | @@ -143,13 +148,13 @@ pub const Node = union(enum) { |
| 143 | 148 | }; |
| 144 | 149 | |
| 145 | 150 | pub const Known = struct { |
| 146 | | pub const rodata: MappedFile.Node.Index = @enumFromInt(1); |
| 147 | | pub const ehdr: MappedFile.Node.Index = @enumFromInt(2); |
| 148 | | pub const phdr: MappedFile.Node.Index = @enumFromInt(3); |
| 149 | | pub const shdr: MappedFile.Node.Index = @enumFromInt(4); |
| 150 | | pub const text: MappedFile.Node.Index = @enumFromInt(5); |
| 151 | | pub const data: MappedFile.Node.Index = @enumFromInt(6); |
| 152 | | |
| 151 | comptime file: MappedFile.Node.Index = .root, |
| 152 | comptime ehdr: MappedFile.Node.Index = @enumFromInt(1), |
| 153 | comptime shdr: MappedFile.Node.Index = @enumFromInt(2), |
| 154 | comptime rodata: MappedFile.Node.Index = @enumFromInt(3), |
| 155 | comptime phdr: MappedFile.Node.Index = @enumFromInt(4), |
| 156 | comptime text: MappedFile.Node.Index = @enumFromInt(5), |
| 157 | comptime data: MappedFile.Node.Index = @enumFromInt(6), |
| 153 | 158 | tls: MappedFile.Node.Index, |
| 154 | 159 | }; |
| 155 | 160 | |
| ... | ... | @@ -231,7 +236,6 @@ pub const Symbol = struct { |
| 231 | 236 | rodata, |
| 232 | 237 | text, |
| 233 | 238 | data, |
| 234 | | tdata, |
| 235 | 239 | _, |
| 236 | 240 | |
| 237 | 241 | pub fn get(si: Symbol.Index, elf: *Elf) *Symbol { |
| ... | ... | @@ -250,6 +254,7 @@ pub const Symbol = struct { |
| 250 | 254 | |
| 251 | 255 | pub const InitOptions = struct { |
| 252 | 256 | name: []const u8 = "", |
| 257 | lib_name: ?[]const u8 = null, |
| 253 | 258 | value: u64 = 0, |
| 254 | 259 | size: u64 = 0, |
| 255 | 260 | type: std.elf.STT, |
| ... | ... | @@ -258,29 +263,45 @@ pub const Symbol = struct { |
| 258 | 263 | shndx: std.elf.Section = std.elf.SHN_UNDEF, |
| 259 | 264 | }; |
| 260 | 265 | pub fn init(si: Symbol.Index, elf: *Elf, opts: InitOptions) !void { |
| 261 | | const name_entry = try elf.string(.strtab, opts.name); |
| 262 | | try Symbol.Index.symtab.node(elf).resize( |
| 263 | | &elf.mf, |
| 264 | | elf.base.comp.gpa, |
| 265 | | @as(usize, switch (elf.identClass()) { |
| 266 | | .NONE, _ => unreachable, |
| 267 | | .@"32" => @sizeOf(std.elf.Elf32.Sym), |
| 268 | | .@"64" => @sizeOf(std.elf.Elf64.Sym), |
| 269 | | }) * elf.symtab.items.len, |
| 270 | | ); |
| 266 | const gpa = elf.base.comp.gpa; |
| 267 | const target_endian = elf.targetEndian(); |
| 268 | const sym_size: usize = switch (elf.identClass()) { |
| 269 | .NONE, _ => unreachable, |
| 270 | inline else => |class| @sizeOf(class.ElfN().Sym), |
| 271 | }; |
| 272 | const name_strtab_entry = try elf.string(.strtab, opts.name); |
| 273 | try elf.si.symtab.node(elf).resize(&elf.mf, gpa, sym_size * elf.symtab.items.len); |
| 271 | 274 | switch (elf.symPtr(si)) { |
| 272 | | inline else => |sym| sym.* = .{ |
| 273 | | .name = name_entry, |
| 274 | | .value = @intCast(opts.value), |
| 275 | | .size = @intCast(opts.size), |
| 276 | | .info = .{ |
| 277 | | .type = opts.type, |
| 278 | | .bind = opts.bind, |
| 279 | | }, |
| 280 | | .other = .{ |
| 281 | | .visibility = opts.visibility, |
| 282 | | }, |
| 283 | | .shndx = opts.shndx, |
| 275 | inline else => |sym, class| { |
| 276 | sym.* = .{ |
| 277 | .name = name_strtab_entry, |
| 278 | .value = @intCast(opts.value), |
| 279 | .size = @intCast(opts.size), |
| 280 | .info = .{ .type = opts.type, .bind = opts.bind }, |
| 281 | .other = .{ .visibility = opts.visibility }, |
| 282 | .shndx = opts.shndx, |
| 283 | }; |
| 284 | if (target_endian != native_endian) std.mem.byteSwapAllFields(class.ElfN().Sym, sym); |
| 285 | }, |
| 286 | } |
| 287 | if (opts.bind == .LOCAL or elf.si.dynsym == .null) return; |
| 288 | const dsi = elf.dynsym.items.len; |
| 289 | try elf.dynsym.append(gpa, si); |
| 290 | const dynsym_ni = elf.si.dynsym.node(elf); |
| 291 | const name_dynstr_entry = try elf.string(.dynstr, opts.name); |
| 292 | try dynsym_ni.resize(&elf.mf, gpa, sym_size * elf.dynsym.items.len); |
| 293 | switch (elf.dynsymSlice()) { |
| 294 | inline else => |dynsym, class| { |
| 295 | const dsym = &dynsym[dsi]; |
| 296 | dsym.* = .{ |
| 297 | .name = name_dynstr_entry, |
| 298 | .value = @intCast(opts.value), |
| 299 | .size = @intCast(opts.size), |
| 300 | .info = .{ .type = opts.type, .bind = opts.bind }, |
| 301 | .other = .{ .visibility = opts.visibility }, |
| 302 | .shndx = opts.shndx, |
| 303 | }; |
| 304 | if (target_endian != native_endian) std.mem.byteSwapAllFields(class.ElfN().Sym, dsym); |
| 284 | 305 | }, |
| 285 | 306 | } |
| 286 | 307 | } |
| ... | ... | @@ -329,6 +350,19 @@ pub const Symbol = struct { |
| 329 | 350 | } |
| 330 | 351 | }; |
| 331 | 352 | |
| 353 | pub const Known = struct { |
| 354 | comptime symtab: Symbol.Index = .symtab, |
| 355 | comptime shstrtab: Symbol.Index = .shstrtab, |
| 356 | comptime strtab: Symbol.Index = .strtab, |
| 357 | comptime rodata: Symbol.Index = .rodata, |
| 358 | comptime text: Symbol.Index = .text, |
| 359 | comptime data: Symbol.Index = .data, |
| 360 | dynsym: Symbol.Index, |
| 361 | dynstr: Symbol.Index, |
| 362 | dynamic: Symbol.Index, |
| 363 | tdata: Symbol.Index, |
| 364 | }; |
| 365 | |
| 332 | 366 | comptime { |
| 333 | 367 | if (!std.debug.runtime_safety) std.debug.assert(@sizeOf(Symbol) == 16); |
| 334 | 368 | } |
| ... | ... | @@ -349,6 +383,22 @@ pub const Reloc = extern struct { |
| 349 | 383 | AARCH64: std.elf.R_AARCH64, |
| 350 | 384 | RISCV: std.elf.R_RISCV, |
| 351 | 385 | PPC64: std.elf.R_PPC64, |
| 386 | |
| 387 | pub fn absAddr(elf: *Elf) Reloc.Type { |
| 388 | return switch (elf.ehdrField(.machine)) { |
| 389 | else => unreachable, |
| 390 | .AARCH64 => .{ .AARCH64 = .ABS64 }, |
| 391 | .PPC64 => .{ .PPC64 = .ADDR64 }, |
| 392 | .RISCV => .{ .RISCV = .@"64" }, |
| 393 | .X86_64 => .{ .X86_64 = .@"64" }, |
| 394 | }; |
| 395 | } |
| 396 | pub fn sizeAddr(elf: *Elf) Reloc.Type { |
| 397 | return switch (elf.ehdrField(.machine)) { |
| 398 | else => unreachable, |
| 399 | .X86_64 => .{ .X86_64 = .SIZE64 }, |
| 400 | }; |
| 401 | } |
| 352 | 402 | }; |
| 353 | 403 | |
| 354 | 404 | pub const Index = enum(u32) { |
| ... | ... | @@ -411,7 +461,7 @@ pub const Reloc = extern struct { |
| 411 | 461 | ), |
| 412 | 462 | .TPOFF32 => { |
| 413 | 463 | const phdr = @field(elf.phdrSlice(), @tagName(class)); |
| 414 | | const ph = &phdr[elf.getNode(elf.known.tls).segment]; |
| 464 | const ph = &phdr[elf.getNode(elf.ni.tls).segment]; |
| 415 | 465 | assert(elf.targetLoad(&ph.type) == std.elf.PT_TLS); |
| 416 | 466 | std.mem.writeInt( |
| 417 | 467 | i32, |
| ... | ... | @@ -420,6 +470,18 @@ pub const Reloc = extern struct { |
| 420 | 470 | target_endian, |
| 421 | 471 | ); |
| 422 | 472 | }, |
| 473 | .SIZE32 => std.mem.writeInt( |
| 474 | u32, |
| 475 | loc_slice[0..4], |
| 476 | @intCast(elf.targetLoad(&target_sym.size)), |
| 477 | target_endian, |
| 478 | ), |
| 479 | .SIZE64 => std.mem.writeInt( |
| 480 | u64, |
| 481 | loc_slice[0..8], |
| 482 | @intCast(elf.targetLoad(&target_sym.size)), |
| 483 | target_endian, |
| 484 | ), |
| 423 | 485 | }, |
| 424 | 486 | } |
| 425 | 487 | }, |
| ... | ... | @@ -469,7 +531,6 @@ fn create( |
| 469 | 531 | path: std.Build.Cache.Path, |
| 470 | 532 | options: link.File.OpenOptions, |
| 471 | 533 | ) !*Elf { |
| 472 | | _ = options; |
| 473 | 534 | const target = &comp.root_mod.resolved_target.result; |
| 474 | 535 | assert(target.ofmt == .elf); |
| 475 | 536 | const class: std.elf.CLASS = switch (target.ptrBitWidth()) { |
| ... | ... | @@ -502,12 +563,16 @@ fn create( |
| 502 | 563 | .Obj => .REL, |
| 503 | 564 | }; |
| 504 | 565 | const machine = target.toElfMachine(); |
| 505 | | const maybe_interp = switch (comp.config.output_mode) { |
| 506 | | .Exe, .Lib => switch (comp.config.link_mode) { |
| 507 | | .static => null, |
| 508 | | .dynamic => target.dynamic_linker.get(), |
| 566 | const maybe_interp = switch (comp.config.link_mode) { |
| 567 | .static => null, |
| 568 | .dynamic => switch (comp.config.output_mode) { |
| 569 | .Exe => target.dynamic_linker.get(), |
| 570 | .Lib => if (comp.root_mod.resolved_target.is_explicit_dynamic_linker) |
| 571 | target.dynamic_linker.get() |
| 572 | else |
| 573 | null, |
| 574 | .Obj => null, |
| 509 | 575 | }, |
| 510 | | .Obj => null, |
| 511 | 576 | }; |
| 512 | 577 | |
| 513 | 578 | const elf = try arena.create(Elf); |
| ... | ... | @@ -530,12 +595,19 @@ fn create( |
| 530 | 595 | .allow_shlib_undefined = false, |
| 531 | 596 | .stack_size = 0, |
| 532 | 597 | }, |
| 598 | .options = options, |
| 533 | 599 | .mf = try .init(file, comp.gpa), |
| 534 | | .known = .{ |
| 600 | .ni = .{ |
| 535 | 601 | .tls = .none, |
| 536 | 602 | }, |
| 537 | 603 | .nodes = .empty, |
| 538 | 604 | .phdrs = .empty, |
| 605 | .si = .{ |
| 606 | .dynsym = .null, |
| 607 | .dynstr = .null, |
| 608 | .dynamic = .null, |
| 609 | .tdata = .null, |
| 610 | }, |
| 539 | 611 | .symtab = .empty, |
| 540 | 612 | .shstrtab = .{ |
| 541 | 613 | .map = .empty, |
| ... | ... | @@ -545,6 +617,12 @@ fn create( |
| 545 | 617 | .map = .empty, |
| 546 | 618 | .size = 1, |
| 547 | 619 | }, |
| 620 | .dynsym = .empty, |
| 621 | .dynstr = .{ |
| 622 | .map = .empty, |
| 623 | .size = 1, |
| 624 | }, |
| 625 | .needed = .empty, |
| 548 | 626 | .inputs = .empty, |
| 549 | 627 | .input_sections = .empty, |
| 550 | 628 | .input_section_pending_index = 0, |
| ... | ... | @@ -576,6 +654,9 @@ pub fn deinit(elf: *Elf) void { |
| 576 | 654 | elf.symtab.deinit(gpa); |
| 577 | 655 | elf.shstrtab.map.deinit(gpa); |
| 578 | 656 | elf.strtab.map.deinit(gpa); |
| 657 | elf.dynsym.deinit(gpa); |
| 658 | elf.dynstr.map.deinit(gpa); |
| 659 | elf.needed.deinit(gpa); |
| 579 | 660 | for (elf.inputs.items) |input| if (input.member) |m| gpa.free(m); |
| 580 | 661 | elf.inputs.deinit(gpa); |
| 581 | 662 | elf.input_sections.deinit(gpa); |
| ... | ... | @@ -599,6 +680,13 @@ fn initHeaders( |
| 599 | 680 | ) !void { |
| 600 | 681 | const comp = elf.base.comp; |
| 601 | 682 | const gpa = comp.gpa; |
| 683 | const have_dynamic_section = switch (@"type") { |
| 684 | .NONE => unreachable, |
| 685 | .REL => false, |
| 686 | .EXEC => comp.config.link_mode == .dynamic, |
| 687 | .DYN => true, |
| 688 | .CORE, _ => unreachable, |
| 689 | }; |
| 602 | 690 | const addr_align: std.mem.Alignment = switch (class) { |
| 603 | 691 | .NONE, _ => unreachable, |
| 604 | 692 | .@"32" => .@"4", |
| ... | ... | @@ -618,37 +706,32 @@ fn initHeaders( |
| 618 | 706 | phnum += 1; |
| 619 | 707 | const data_phndx = phnum; |
| 620 | 708 | phnum += 1; |
| 709 | const dynamic_phndx = if (have_dynamic_section) phndx: { |
| 710 | defer phnum += 1; |
| 711 | break :phndx phnum; |
| 712 | } else undefined; |
| 621 | 713 | const tls_phndx = if (comp.config.any_non_single_threaded) phndx: { |
| 622 | 714 | defer phnum += 1; |
| 623 | 715 | break :phndx phnum; |
| 624 | 716 | } else undefined; |
| 625 | 717 | |
| 626 | | const expected_nodes_len = 5 + phnum * 2; |
| 718 | const expected_nodes_len = 5 + phnum * 2 + @as(usize, 2) * @intFromBool(have_dynamic_section); |
| 627 | 719 | try elf.nodes.ensureTotalCapacity(gpa, expected_nodes_len); |
| 628 | 720 | try elf.phdrs.resize(gpa, phnum); |
| 629 | 721 | elf.nodes.appendAssumeCapacity(.file); |
| 630 | 722 | |
| 631 | | assert(Node.Known.rodata == try elf.mf.addOnlyChildNode(gpa, .root, .{ |
| 632 | | .alignment = elf.mf.flags.block_size, |
| 633 | | .fixed = true, |
| 634 | | .moved = true, |
| 635 | | .bubbles_moved = false, |
| 636 | | })); |
| 637 | | elf.nodes.appendAssumeCapacity(.{ .segment = rodata_phndx }); |
| 638 | | elf.phdrs.items[rodata_phndx] = Node.Known.rodata; |
| 639 | | |
| 640 | 723 | switch (class) { |
| 641 | 724 | .NONE, _ => unreachable, |
| 642 | 725 | inline else => |ct_class| { |
| 643 | 726 | const ElfN = ct_class.ElfN(); |
| 644 | | assert(Node.Known.ehdr == try elf.mf.addOnlyChildNode(gpa, Node.Known.rodata, .{ |
| 727 | assert(elf.ni.ehdr == try elf.mf.addOnlyChildNode(gpa, elf.ni.file, .{ |
| 645 | 728 | .size = @sizeOf(ElfN.Ehdr), |
| 646 | 729 | .alignment = addr_align, |
| 647 | 730 | .fixed = true, |
| 648 | 731 | })); |
| 649 | 732 | elf.nodes.appendAssumeCapacity(.ehdr); |
| 650 | 733 | |
| 651 | | const ehdr: *ElfN.Ehdr = @ptrCast(@alignCast(Node.Known.ehdr.slice(&elf.mf))); |
| 734 | const ehdr: *ElfN.Ehdr = @ptrCast(@alignCast(elf.ni.ehdr.slice(&elf.mf))); |
| 652 | 735 | const EI = std.elf.EI; |
| 653 | 736 | @memcpy(ehdr.ident[0..std.elf.MAGIC.len], std.elf.MAGIC); |
| 654 | 737 | ehdr.ident[EI.CLASS] = @intFromEnum(class); |
| ... | ... | @@ -674,37 +757,47 @@ fn initHeaders( |
| 674 | 757 | }, |
| 675 | 758 | } |
| 676 | 759 | |
| 677 | | assert(Node.Known.phdr == try elf.mf.addLastChildNode(gpa, Node.Known.rodata, .{ |
| 678 | | .size = elf.ehdrField(.phentsize) * elf.ehdrField(.phnum), |
| 760 | assert(elf.ni.shdr == try elf.mf.addLastChildNode(gpa, elf.ni.file, .{ |
| 761 | .size = elf.ehdrField(.shentsize) * elf.ehdrField(.shnum), |
| 679 | 762 | .alignment = addr_align, |
| 680 | 763 | .moved = true, |
| 681 | 764 | .resized = true, |
| 765 | })); |
| 766 | elf.nodes.appendAssumeCapacity(.shdr); |
| 767 | |
| 768 | assert(elf.ni.rodata == try elf.mf.addLastChildNode(gpa, elf.ni.file, .{ |
| 769 | .alignment = elf.mf.flags.block_size, |
| 770 | .moved = true, |
| 682 | 771 | .bubbles_moved = false, |
| 683 | 772 | })); |
| 684 | | elf.nodes.appendAssumeCapacity(.{ .segment = phdr_phndx }); |
| 685 | | elf.phdrs.items[phdr_phndx] = Node.Known.phdr; |
| 773 | elf.nodes.appendAssumeCapacity(.{ .segment = rodata_phndx }); |
| 774 | elf.phdrs.items[rodata_phndx] = elf.ni.rodata; |
| 686 | 775 | |
| 687 | | assert(Node.Known.shdr == try elf.mf.addLastChildNode(gpa, Node.Known.rodata, .{ |
| 688 | | .size = elf.ehdrField(.shentsize) * elf.ehdrField(.shnum), |
| 776 | assert(elf.ni.phdr == try elf.mf.addOnlyChildNode(gpa, elf.ni.rodata, .{ |
| 777 | .size = elf.ehdrField(.phentsize) * elf.ehdrField(.phnum), |
| 689 | 778 | .alignment = addr_align, |
| 779 | .moved = true, |
| 780 | .resized = true, |
| 781 | .bubbles_moved = false, |
| 690 | 782 | })); |
| 691 | | elf.nodes.appendAssumeCapacity(.shdr); |
| 783 | elf.nodes.appendAssumeCapacity(.{ .segment = phdr_phndx }); |
| 784 | elf.phdrs.items[phdr_phndx] = elf.ni.phdr; |
| 692 | 785 | |
| 693 | | assert(Node.Known.text == try elf.mf.addLastChildNode(gpa, .root, .{ |
| 786 | assert(elf.ni.text == try elf.mf.addLastChildNode(gpa, elf.ni.file, .{ |
| 694 | 787 | .alignment = elf.mf.flags.block_size, |
| 695 | 788 | .moved = true, |
| 696 | 789 | .bubbles_moved = false, |
| 697 | 790 | })); |
| 698 | 791 | elf.nodes.appendAssumeCapacity(.{ .segment = text_phndx }); |
| 699 | | elf.phdrs.items[text_phndx] = Node.Known.text; |
| 792 | elf.phdrs.items[text_phndx] = elf.ni.text; |
| 700 | 793 | |
| 701 | | assert(Node.Known.data == try elf.mf.addLastChildNode(gpa, .root, .{ |
| 794 | assert(elf.ni.data == try elf.mf.addLastChildNode(gpa, elf.ni.file, .{ |
| 702 | 795 | .alignment = elf.mf.flags.block_size, |
| 703 | 796 | .moved = true, |
| 704 | 797 | .bubbles_moved = false, |
| 705 | 798 | })); |
| 706 | 799 | elf.nodes.appendAssumeCapacity(.{ .segment = data_phndx }); |
| 707 | | elf.phdrs.items[data_phndx] = Node.Known.data; |
| 800 | elf.phdrs.items[data_phndx] = elf.ni.data; |
| 708 | 801 | |
| 709 | 802 | var ph_vaddr: u32 = switch (elf.ehdrField(.type)) { |
| 710 | 803 | else => 0, |
| ... | ... | @@ -723,7 +816,7 @@ fn initHeaders( |
| 723 | 816 | const ElfN = ct_class.ElfN(); |
| 724 | 817 | const target_endian = elf.targetEndian(); |
| 725 | 818 | |
| 726 | | const phdr: []ElfN.Phdr = @ptrCast(@alignCast(Node.Known.phdr.slice(&elf.mf))); |
| 819 | const phdr: []ElfN.Phdr = @ptrCast(@alignCast(elf.ni.phdr.slice(&elf.mf))); |
| 727 | 820 | const ph_phdr = &phdr[phdr_phndx]; |
| 728 | 821 | ph_phdr.* = .{ |
| 729 | 822 | .type = std.elf.PT_PHDR, |
| ... | ... | @@ -733,7 +826,7 @@ fn initHeaders( |
| 733 | 826 | .filesz = 0, |
| 734 | 827 | .memsz = 0, |
| 735 | 828 | .flags = .{ .R = true }, |
| 736 | | .@"align" = @intCast(Node.Known.phdr.alignment(&elf.mf).toByteUnits()), |
| 829 | .@"align" = @intCast(elf.ni.phdr.alignment(&elf.mf).toByteUnits()), |
| 737 | 830 | }; |
| 738 | 831 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_phdr); |
| 739 | 832 | |
| ... | ... | @@ -752,7 +845,7 @@ fn initHeaders( |
| 752 | 845 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_interp); |
| 753 | 846 | } |
| 754 | 847 | |
| 755 | | _, const rodata_size = Node.Known.rodata.location(&elf.mf).resolve(&elf.mf); |
| 848 | _, const rodata_size = elf.ni.rodata.location(&elf.mf).resolve(&elf.mf); |
| 756 | 849 | const ph_rodata = &phdr[rodata_phndx]; |
| 757 | 850 | ph_rodata.* = .{ |
| 758 | 851 | .type = std.elf.PT_NULL, |
| ... | ... | @@ -762,12 +855,12 @@ fn initHeaders( |
| 762 | 855 | .filesz = @intCast(rodata_size), |
| 763 | 856 | .memsz = @intCast(rodata_size), |
| 764 | 857 | .flags = .{ .R = true }, |
| 765 | | .@"align" = @intCast(Node.Known.rodata.alignment(&elf.mf).toByteUnits()), |
| 858 | .@"align" = @intCast(elf.ni.rodata.alignment(&elf.mf).toByteUnits()), |
| 766 | 859 | }; |
| 767 | 860 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_rodata); |
| 768 | 861 | ph_vaddr += @intCast(rodata_size); |
| 769 | 862 | |
| 770 | | _, const text_size = Node.Known.text.location(&elf.mf).resolve(&elf.mf); |
| 863 | _, const text_size = elf.ni.text.location(&elf.mf).resolve(&elf.mf); |
| 771 | 864 | const ph_text = &phdr[text_phndx]; |
| 772 | 865 | ph_text.* = .{ |
| 773 | 866 | .type = std.elf.PT_NULL, |
| ... | ... | @@ -777,12 +870,12 @@ fn initHeaders( |
| 777 | 870 | .filesz = @intCast(text_size), |
| 778 | 871 | .memsz = @intCast(text_size), |
| 779 | 872 | .flags = .{ .R = true, .X = true }, |
| 780 | | .@"align" = @intCast(Node.Known.text.alignment(&elf.mf).toByteUnits()), |
| 873 | .@"align" = @intCast(elf.ni.text.alignment(&elf.mf).toByteUnits()), |
| 781 | 874 | }; |
| 782 | 875 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_text); |
| 783 | 876 | ph_vaddr += @intCast(text_size); |
| 784 | 877 | |
| 785 | | _, const data_size = Node.Known.data.location(&elf.mf).resolve(&elf.mf); |
| 878 | _, const data_size = elf.ni.data.location(&elf.mf).resolve(&elf.mf); |
| 786 | 879 | const ph_data = &phdr[data_phndx]; |
| 787 | 880 | ph_data.* = .{ |
| 788 | 881 | .type = std.elf.PT_NULL, |
| ... | ... | @@ -792,11 +885,26 @@ fn initHeaders( |
| 792 | 885 | .filesz = @intCast(data_size), |
| 793 | 886 | .memsz = @intCast(data_size), |
| 794 | 887 | .flags = .{ .R = true, .W = true }, |
| 795 | | .@"align" = @intCast(Node.Known.data.alignment(&elf.mf).toByteUnits()), |
| 888 | .@"align" = @intCast(elf.ni.data.alignment(&elf.mf).toByteUnits()), |
| 796 | 889 | }; |
| 797 | 890 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_data); |
| 798 | 891 | ph_vaddr += @intCast(data_size); |
| 799 | 892 | |
| 893 | if (have_dynamic_section) { |
| 894 | const ph_dynamic = &phdr[dynamic_phndx]; |
| 895 | ph_dynamic.* = .{ |
| 896 | .type = std.elf.PT_DYNAMIC, |
| 897 | .offset = 0, |
| 898 | .vaddr = 0, |
| 899 | .paddr = 0, |
| 900 | .filesz = 0, |
| 901 | .memsz = 0, |
| 902 | .flags = .{ .R = true, .W = true }, |
| 903 | .@"align" = @intCast(addr_align.toByteUnits()), |
| 904 | }; |
| 905 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_dynamic); |
| 906 | } |
| 907 | |
| 800 | 908 | if (comp.config.any_non_single_threaded) { |
| 801 | 909 | const ph_tls = &phdr[tls_phndx]; |
| 802 | 910 | ph_tls.* = .{ |
| ... | ... | @@ -812,7 +920,7 @@ fn initHeaders( |
| 812 | 920 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_tls); |
| 813 | 921 | } |
| 814 | 922 | |
| 815 | | const sh_null: *ElfN.Shdr = @ptrCast(@alignCast(Node.Known.shdr.slice(&elf.mf))); |
| 923 | const sh_null: *ElfN.Shdr = @ptrCast(@alignCast(elf.ni.shdr.slice(&elf.mf))); |
| 816 | 924 | sh_null.* = .{ |
| 817 | 925 | .name = try elf.string(.shstrtab, ""), |
| 818 | 926 | .type = std.elf.SHT_NULL, |
| ... | ... | @@ -834,99 +942,142 @@ fn initHeaders( |
| 834 | 942 | .target_relocs = .none, |
| 835 | 943 | .unused = 0, |
| 836 | 944 | }; |
| 837 | | assert(try elf.addSection(Node.Known.rodata, .{ |
| 945 | assert(elf.si.symtab == try elf.addSection(elf.ni.file, .{ |
| 838 | 946 | .type = std.elf.SHT_SYMTAB, |
| 947 | .size = @sizeOf(ElfN.Sym) * 1, |
| 839 | 948 | .addralign = addr_align, |
| 840 | 949 | .entsize = @sizeOf(ElfN.Sym), |
| 841 | | }) == .symtab); |
| 842 | | |
| 843 | | const symtab: *ElfN.Sym = @ptrCast(@alignCast(Symbol.Index.symtab.node(elf).slice(&elf.mf))); |
| 844 | | symtab.* = .{ |
| 950 | })); |
| 951 | const symtab_null = @field(elf.symPtr(.null), @tagName(ct_class)); |
| 952 | symtab_null.* = .{ |
| 845 | 953 | .name = try elf.string(.strtab, ""), |
| 846 | 954 | .value = 0, |
| 847 | 955 | .size = 0, |
| 848 | | .info = .{ |
| 849 | | .type = .NOTYPE, |
| 850 | | .bind = .LOCAL, |
| 851 | | }, |
| 852 | | .other = .{ |
| 853 | | .visibility = .DEFAULT, |
| 854 | | }, |
| 956 | .info = .{ .type = .NOTYPE, .bind = .LOCAL }, |
| 957 | .other = .{ .visibility = .DEFAULT }, |
| 855 | 958 | .shndx = std.elf.SHN_UNDEF, |
| 856 | 959 | }; |
| 960 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Sym, symtab_null); |
| 857 | 961 | |
| 858 | 962 | const ehdr = @field(elf.ehdrPtr(), @tagName(ct_class)); |
| 859 | 963 | ehdr.shstrndx = ehdr.shnum; |
| 860 | 964 | }, |
| 861 | 965 | } |
| 862 | | assert(try elf.addSection(Node.Known.rodata, .{ |
| 966 | assert(elf.si.shstrtab == try elf.addSection(elf.ni.file, .{ |
| 863 | 967 | .type = std.elf.SHT_STRTAB, |
| 864 | 968 | .addralign = elf.mf.flags.block_size, |
| 865 | 969 | .entsize = 1, |
| 866 | | }) == .shstrtab); |
| 970 | })); |
| 867 | 971 | try elf.renameSection(.symtab, ".symtab"); |
| 868 | 972 | try elf.renameSection(.shstrtab, ".shstrtab"); |
| 869 | | Symbol.Index.shstrtab.node(elf).slice(&elf.mf)[0] = 0; |
| 973 | elf.si.shstrtab.node(elf).slice(&elf.mf)[0] = 0; |
| 870 | 974 | |
| 871 | | assert(try elf.addSection(Node.Known.rodata, .{ |
| 975 | assert(elf.si.strtab == try elf.addSection(elf.ni.file, .{ |
| 872 | 976 | .name = ".strtab", |
| 873 | 977 | .type = std.elf.SHT_STRTAB, |
| 874 | | .addralign = elf.mf.flags.block_size, |
| 875 | 978 | .size = 1, |
| 979 | .addralign = elf.mf.flags.block_size, |
| 876 | 980 | .entsize = 1, |
| 877 | | }) == .strtab); |
| 981 | })); |
| 878 | 982 | try elf.linkSections(.symtab, .strtab); |
| 879 | | Symbol.Index.strtab.node(elf).slice(&elf.mf)[0] = 0; |
| 983 | elf.si.strtab.node(elf).slice(&elf.mf)[0] = 0; |
| 880 | 984 | |
| 881 | | assert(try elf.addSection(Node.Known.rodata, .{ |
| 985 | assert(elf.si.rodata == try elf.addSection(elf.ni.rodata, .{ |
| 882 | 986 | .name = ".rodata", |
| 883 | 987 | .flags = .{ .ALLOC = true }, |
| 884 | 988 | .addralign = elf.mf.flags.block_size, |
| 885 | | }) == .rodata); |
| 886 | | assert(try elf.addSection(Node.Known.text, .{ |
| 989 | })); |
| 990 | assert(elf.si.text == try elf.addSection(elf.ni.text, .{ |
| 887 | 991 | .name = ".text", |
| 888 | 992 | .flags = .{ .ALLOC = true, .EXECINSTR = true }, |
| 889 | 993 | .addralign = elf.mf.flags.block_size, |
| 890 | | }) == .text); |
| 891 | | assert(try elf.addSection(Node.Known.data, .{ |
| 994 | })); |
| 995 | assert(elf.si.data == try elf.addSection(elf.ni.data, .{ |
| 892 | 996 | .name = ".data", |
| 893 | 997 | .flags = .{ .WRITE = true, .ALLOC = true }, |
| 894 | 998 | .addralign = elf.mf.flags.block_size, |
| 895 | | }) == .data); |
| 896 | | if (comp.config.any_non_single_threaded) { |
| 897 | | try elf.nodes.ensureUnusedCapacity(gpa, 1); |
| 898 | | elf.known.tls = try elf.mf.addLastChildNode(gpa, Node.Known.rodata, .{ |
| 899 | | .alignment = elf.mf.flags.block_size, |
| 900 | | .moved = true, |
| 901 | | }); |
| 902 | | elf.nodes.appendAssumeCapacity(.{ .segment = tls_phndx }); |
| 903 | | elf.phdrs.items[tls_phndx] = elf.known.tls; |
| 904 | | |
| 905 | | assert(try elf.addSection(elf.known.tls, .{ |
| 906 | | .name = ".tdata", |
| 907 | | .flags = .{ .WRITE = true, .ALLOC = true, .TLS = true }, |
| 908 | | .addralign = elf.mf.flags.block_size, |
| 909 | | }) == .tdata); |
| 910 | | } |
| 999 | })); |
| 911 | 1000 | if (maybe_interp) |interp| { |
| 912 | | try elf.nodes.ensureUnusedCapacity(gpa, 1); |
| 913 | | const interp_ni = try elf.mf.addLastChildNode(gpa, Node.Known.rodata, .{ |
| 1001 | const interp_ni = try elf.mf.addLastChildNode(gpa, elf.ni.rodata, .{ |
| 914 | 1002 | .size = interp.len + 1, |
| 915 | 1003 | .moved = true, |
| 916 | 1004 | .resized = true, |
| 1005 | .bubbles_moved = false, |
| 917 | 1006 | }); |
| 918 | 1007 | elf.nodes.appendAssumeCapacity(.{ .segment = interp_phndx }); |
| 919 | 1008 | elf.phdrs.items[interp_phndx] = interp_ni; |
| 920 | 1009 | |
| 921 | 1010 | const sec_interp_si = try elf.addSection(interp_ni, .{ |
| 922 | 1011 | .name = ".interp", |
| 923 | | .size = @intCast(interp.len + 1), |
| 924 | 1012 | .flags = .{ .ALLOC = true }, |
| 1013 | .size = @intCast(interp.len + 1), |
| 925 | 1014 | }); |
| 926 | 1015 | const sec_interp = sec_interp_si.node(elf).slice(&elf.mf); |
| 927 | 1016 | @memcpy(sec_interp[0..interp.len], interp); |
| 928 | 1017 | sec_interp[interp.len] = 0; |
| 929 | 1018 | } |
| 1019 | if (have_dynamic_section) { |
| 1020 | const dynamic_ni = try elf.mf.addLastChildNode(gpa, elf.ni.data, .{ |
| 1021 | .moved = true, |
| 1022 | .bubbles_moved = false, |
| 1023 | }); |
| 1024 | elf.nodes.appendAssumeCapacity(.{ .segment = dynamic_phndx }); |
| 1025 | elf.phdrs.items[dynamic_phndx] = dynamic_ni; |
| 1026 | |
| 1027 | switch (class) { |
| 1028 | .NONE, _ => unreachable, |
| 1029 | inline else => |ct_class| { |
| 1030 | const ElfN = ct_class.ElfN(); |
| 1031 | elf.si.dynsym = try elf.addSection(elf.ni.rodata, .{ |
| 1032 | .name = ".dynsym", |
| 1033 | .type = std.elf.SHT_DYNSYM, |
| 1034 | .size = @sizeOf(ElfN.Sym) * 1, |
| 1035 | .addralign = addr_align, |
| 1036 | .entsize = @sizeOf(ElfN.Sym), |
| 1037 | }); |
| 1038 | const dynsym_null = &@field(elf.dynsymSlice(), @tagName(ct_class))[0]; |
| 1039 | dynsym_null.* = .{ |
| 1040 | .name = try elf.string(.dynstr, ""), |
| 1041 | .value = 0, |
| 1042 | .size = 0, |
| 1043 | .info = .{ .type = .NOTYPE, .bind = .LOCAL }, |
| 1044 | .other = .{ .visibility = .DEFAULT }, |
| 1045 | .shndx = std.elf.SHN_UNDEF, |
| 1046 | }; |
| 1047 | if (elf.targetEndian() != native_endian) std.mem.byteSwapAllFields(ElfN.Sym, dynsym_null); |
| 1048 | }, |
| 1049 | } |
| 1050 | elf.si.dynstr = try elf.addSection(elf.ni.rodata, .{ |
| 1051 | .name = ".dynstr", |
| 1052 | .type = std.elf.SHT_STRTAB, |
| 1053 | .size = 1, |
| 1054 | .addralign = elf.mf.flags.block_size, |
| 1055 | .entsize = 1, |
| 1056 | }); |
| 1057 | elf.si.dynamic = try elf.addSection(dynamic_ni, .{ |
| 1058 | .name = ".dynamic", |
| 1059 | .type = std.elf.SHT_DYNAMIC, |
| 1060 | .flags = .{ .ALLOC = true, .WRITE = true }, |
| 1061 | .addralign = addr_align, |
| 1062 | }); |
| 1063 | try elf.linkSections(elf.si.dynamic, elf.si.dynstr); |
| 1064 | try elf.linkSections(elf.si.dynsym, elf.si.dynstr); |
| 1065 | } |
| 1066 | if (comp.config.any_non_single_threaded) { |
| 1067 | elf.ni.tls = try elf.mf.addLastChildNode(gpa, elf.ni.rodata, .{ |
| 1068 | .alignment = elf.mf.flags.block_size, |
| 1069 | .moved = true, |
| 1070 | .bubbles_moved = false, |
| 1071 | }); |
| 1072 | elf.nodes.appendAssumeCapacity(.{ .segment = tls_phndx }); |
| 1073 | elf.phdrs.items[tls_phndx] = elf.ni.tls; |
| 1074 | |
| 1075 | elf.si.tdata = try elf.addSection(elf.ni.tls, .{ |
| 1076 | .name = ".tdata", |
| 1077 | .flags = .{ .WRITE = true, .ALLOC = true, .TLS = true }, |
| 1078 | .addralign = elf.mf.flags.block_size, |
| 1079 | }); |
| 1080 | } |
| 930 | 1081 | assert(elf.nodes.len == expected_nodes_len); |
| 931 | 1082 | } |
| 932 | 1083 | |
| ... | ... | @@ -962,7 +1113,8 @@ fn getNode(elf: *const Elf, ni: MappedFile.Node.Index) Node { |
| 962 | 1113 | fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 { |
| 963 | 1114 | const parent_vaddr = parent_vaddr: { |
| 964 | 1115 | const parent_si = switch (elf.getNode(ni.parent(&elf.mf))) { |
| 965 | | .file, .ehdr, .shdr => unreachable, |
| 1116 | .file => return 0, |
| 1117 | .ehdr, .shdr => unreachable, |
| 966 | 1118 | .segment => |phndx| break :parent_vaddr switch (elf.phdrSlice()) { |
| 967 | 1119 | inline else => |ph| elf.targetLoad(&ph[phndx].vaddr), |
| 968 | 1120 | }, |
| ... | ... | @@ -970,7 +1122,7 @@ fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 { |
| 970 | 1122 | .input_section => unreachable, |
| 971 | 1123 | inline .nav, .uav, .lazy_code, .lazy_const_data => |mi| mi.symbol(elf), |
| 972 | 1124 | }; |
| 973 | | break :parent_vaddr switch (elf.symPtr(parent_si)) { |
| 1125 | break :parent_vaddr if (parent_si == elf.si.tdata) 0 else switch (elf.symPtr(parent_si)) { |
| 974 | 1126 | inline else => |sym| elf.targetLoad(&sym.value), |
| 975 | 1127 | }; |
| 976 | 1128 | }; |
| ... | ... | @@ -1025,7 +1177,7 @@ pub const EhdrPtr = union(std.elf.CLASS) { |
| 1025 | 1177 | @"64": *std.elf.Elf64.Ehdr, |
| 1026 | 1178 | }; |
| 1027 | 1179 | pub fn ehdrPtr(elf: *Elf) EhdrPtr { |
| 1028 | | const slice = Node.Known.ehdr.slice(&elf.mf); |
| 1180 | const slice = elf.ni.ehdr.slice(&elf.mf); |
| 1029 | 1181 | return switch (elf.identClass()) { |
| 1030 | 1182 | .NONE, _ => unreachable, |
| 1031 | 1183 | inline else => |class| @unionInit( |
| ... | ... | @@ -1050,7 +1202,7 @@ pub const PhdrSlice = union(std.elf.CLASS) { |
| 1050 | 1202 | @"64": []std.elf.Elf64.Phdr, |
| 1051 | 1203 | }; |
| 1052 | 1204 | pub fn phdrSlice(elf: *Elf) PhdrSlice { |
| 1053 | | const slice = Node.Known.phdr.slice(&elf.mf); |
| 1205 | const slice = elf.ni.phdr.slice(&elf.mf); |
| 1054 | 1206 | return switch (elf.identClass()) { |
| 1055 | 1207 | .NONE, _ => unreachable, |
| 1056 | 1208 | inline else => |class| @unionInit( |
| ... | ... | @@ -1067,7 +1219,7 @@ pub const ShdrSlice = union(std.elf.CLASS) { |
| 1067 | 1219 | @"64": []std.elf.Elf64.Shdr, |
| 1068 | 1220 | }; |
| 1069 | 1221 | pub fn shdrSlice(elf: *Elf) ShdrSlice { |
| 1070 | | const slice = Node.Known.shdr.slice(&elf.mf); |
| 1222 | const slice = elf.ni.shdr.slice(&elf.mf); |
| 1071 | 1223 | return switch (elf.identClass()) { |
| 1072 | 1224 | .NONE, _ => unreachable, |
| 1073 | 1225 | inline else => |class| @unionInit( |
| ... | ... | @@ -1084,7 +1236,7 @@ pub const SymtabSlice = union(std.elf.CLASS) { |
| 1084 | 1236 | @"64": []std.elf.Elf64.Sym, |
| 1085 | 1237 | }; |
| 1086 | 1238 | pub fn symtabSlice(elf: *Elf) SymtabSlice { |
| 1087 | | const slice = Symbol.Index.symtab.node(elf).slice(&elf.mf); |
| 1239 | const slice = elf.si.symtab.node(elf).slice(&elf.mf); |
| 1088 | 1240 | return switch (elf.identClass()) { |
| 1089 | 1241 | .NONE, _ => unreachable, |
| 1090 | 1242 | inline else => |class| @unionInit( |
| ... | ... | @@ -1106,6 +1258,18 @@ pub fn symPtr(elf: *Elf, si: Symbol.Index) SymPtr { |
| 1106 | 1258 | }; |
| 1107 | 1259 | } |
| 1108 | 1260 | |
| 1261 | pub fn dynsymSlice(elf: *Elf) SymtabSlice { |
| 1262 | const slice = elf.si.dynsym.node(elf).slice(&elf.mf); |
| 1263 | return switch (elf.identClass()) { |
| 1264 | .NONE, _ => unreachable, |
| 1265 | inline else => |class| @unionInit( |
| 1266 | SymtabSlice, |
| 1267 | @tagName(class), |
| 1268 | @ptrCast(@alignCast(slice)), |
| 1269 | ), |
| 1270 | }; |
| 1271 | } |
| 1272 | |
| 1109 | 1273 | fn addSymbolAssumeCapacity(elf: *Elf) Symbol.Index { |
| 1110 | 1274 | defer elf.symtab.addOneAssumeCapacity().* = .{ |
| 1111 | 1275 | .ni = .none, |
| ... | ... | @@ -1124,6 +1288,7 @@ fn initSymbolAssumeCapacity(elf: *Elf, opts: Symbol.Index.InitOptions) !Symbol.I |
| 1124 | 1288 | |
| 1125 | 1289 | pub fn globalSymbol(elf: *Elf, opts: struct { |
| 1126 | 1290 | name: []const u8, |
| 1291 | lib_name: ?[]const u8 = null, |
| 1127 | 1292 | type: std.elf.STT, |
| 1128 | 1293 | bind: std.elf.STB = .GLOBAL, |
| 1129 | 1294 | visibility: std.elf.STV = .DEFAULT, |
| ... | ... | @@ -1133,6 +1298,7 @@ pub fn globalSymbol(elf: *Elf, opts: struct { |
| 1133 | 1298 | const global_gop = try elf.globals.getOrPut(gpa, try elf.string(.strtab, opts.name)); |
| 1134 | 1299 | if (!global_gop.found_existing) global_gop.value_ptr.* = try elf.initSymbolAssumeCapacity(.{ |
| 1135 | 1300 | .name = opts.name, |
| 1301 | .lib_name = opts.lib_name, |
| 1136 | 1302 | .type = opts.type, |
| 1137 | 1303 | .bind = opts.bind, |
| 1138 | 1304 | .visibility = opts.visibility, |
| ... | ... | @@ -1169,15 +1335,15 @@ fn navType( |
| 1169 | 1335 | }, |
| 1170 | 1336 | }; |
| 1171 | 1337 | } |
| 1172 | | fn namedSection(name: []const u8) ?Symbol.Index { |
| 1338 | fn namedSection(elf: *const Elf, name: []const u8) ?Symbol.Index { |
| 1173 | 1339 | if (std.mem.eql(u8, name, ".rodata") or |
| 1174 | | std.mem.startsWith(u8, name, ".rodata.")) return .rodata; |
| 1340 | std.mem.startsWith(u8, name, ".rodata.")) return elf.si.rodata; |
| 1175 | 1341 | if (std.mem.eql(u8, name, ".text") or |
| 1176 | | std.mem.startsWith(u8, name, ".text.")) return .text; |
| 1342 | std.mem.startsWith(u8, name, ".text.")) return elf.si.text; |
| 1177 | 1343 | if (std.mem.eql(u8, name, ".data") or |
| 1178 | | std.mem.startsWith(u8, name, ".data.")) return .data; |
| 1344 | std.mem.startsWith(u8, name, ".data.")) return elf.si.data; |
| 1179 | 1345 | if (std.mem.eql(u8, name, ".tdata") or |
| 1180 | | std.mem.startsWith(u8, name, ".tdata.")) return .tdata; |
| 1346 | std.mem.startsWith(u8, name, ".tdata.")) return elf.si.tdata; |
| 1181 | 1347 | return null; |
| 1182 | 1348 | } |
| 1183 | 1349 | fn navSection( |
| ... | ... | @@ -1186,16 +1352,16 @@ fn navSection( |
| 1186 | 1352 | nav_fr: @FieldType(@FieldType(InternPool.Nav, "status"), "fully_resolved"), |
| 1187 | 1353 | ) Symbol.Index { |
| 1188 | 1354 | if (nav_fr.@"linksection".toSlice(ip)) |@"linksection"| |
| 1189 | | if (namedSection(@"linksection")) |si| return si; |
| 1355 | if (elf.namedSection(@"linksection")) |si| return si; |
| 1190 | 1356 | return switch (navType( |
| 1191 | 1357 | ip, |
| 1192 | 1358 | .{ .fully_resolved = nav_fr }, |
| 1193 | 1359 | elf.base.comp.config.any_non_single_threaded, |
| 1194 | 1360 | )) { |
| 1195 | 1361 | else => unreachable, |
| 1196 | | .FUNC => .text, |
| 1197 | | .OBJECT => .data, |
| 1198 | | .TLS => .tdata, |
| 1362 | .FUNC => elf.si.text, |
| 1363 | .OBJECT => elf.si.data, |
| 1364 | .TLS => elf.si.tdata, |
| 1199 | 1365 | }; |
| 1200 | 1366 | } |
| 1201 | 1367 | fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Node.NavMapIndex { |
| ... | ... | @@ -1215,6 +1381,7 @@ pub fn navSymbol(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Symbol. |
| 1215 | 1381 | const nav = ip.getNav(nav_index); |
| 1216 | 1382 | if (nav.getExtern(ip)) |@"extern"| return elf.globalSymbol(.{ |
| 1217 | 1383 | .name = @"extern".name.toSlice(ip), |
| 1384 | .lib_name = @"extern".lib_name.toSlice(ip), |
| 1218 | 1385 | .type = navType(ip, nav.status, elf.base.comp.config.any_non_single_threaded), |
| 1219 | 1386 | .bind = switch (@"extern".linkage) { |
| 1220 | 1387 | .internal => .LOCAL, |
| ... | ... | @@ -1266,7 +1433,6 @@ pub fn loadInput(elf: *Elf, input: link.Input) (std.fs.File.Reader.SizeError || |
| 1266 | 1433 | const io = elf.base.comp.io; |
| 1267 | 1434 | var buf: [4096]u8 = undefined; |
| 1268 | 1435 | switch (input) { |
| 1269 | | else => {}, |
| 1270 | 1436 | .object => |object| { |
| 1271 | 1437 | var fr = object.file.reader(io, &buf); |
| 1272 | 1438 | elf.loadObject(object.path, null, &fr, .{ |
| ... | ... | @@ -1284,6 +1450,16 @@ pub fn loadInput(elf: *Elf, input: link.Input) (std.fs.File.Reader.SizeError || |
| 1284 | 1450 | else => |e| return e, |
| 1285 | 1451 | }; |
| 1286 | 1452 | }, |
| 1453 | .res => unreachable, |
| 1454 | .dso => |dso| { |
| 1455 | try elf.needed.ensureUnusedCapacity(elf.base.comp.gpa, 1); |
| 1456 | var fr = dso.file.reader(io, &buf); |
| 1457 | elf.loadDso(dso.path, &fr) catch |err| switch (err) { |
| 1458 | error.ReadFailed => return fr.err.?, |
| 1459 | else => |e| return e, |
| 1460 | }; |
| 1461 | }, |
| 1462 | .dso_exact => |dso_exact| try elf.loadDsoExact(dso_exact.name), |
| 1287 | 1463 | } |
| 1288 | 1464 | } |
| 1289 | 1465 | fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fr: *std.Io.File.Reader) !void { |
| ... | ... | @@ -1382,7 +1558,7 @@ fn loadObject( |
| 1382 | 1558 | return diags.failParse(path, "bad machine", .{}); |
| 1383 | 1559 | if (ehdr.shoff == 0 or ehdr.shnum <= 1) return; |
| 1384 | 1560 | if (ehdr.shoff + ehdr.shentsize * ehdr.shnum > fl.size) |
| 1385 | | return diags.failParse(path, "bad section header offset/size", .{}); |
| 1561 | return diags.failParse(path, "bad section header location", .{}); |
| 1386 | 1562 | if (ehdr.shentsize < @sizeOf(ElfN.Shdr)) |
| 1387 | 1563 | return diags.failParse(path, "unsupported shentsize", .{}); |
| 1388 | 1564 | const sections = try gpa.alloc(struct { shdr: ElfN.Shdr, si: Symbol.Index }, ehdr.shnum); |
| ... | ... | @@ -1397,7 +1573,7 @@ fn loadObject( |
| 1397 | 1573 | switch (section.shdr.type) { |
| 1398 | 1574 | std.elf.SHT_NULL, std.elf.SHT_NOBITS => {}, |
| 1399 | 1575 | else => if (section.shdr.offset + section.shdr.size > fl.size) |
| 1400 | | return diags.failParse(path, "bad section offset/size", .{}), |
| 1576 | return diags.failParse(path, "bad section location", .{}), |
| 1401 | 1577 | } |
| 1402 | 1578 | } |
| 1403 | 1579 | const shstrtab = shstrtab: { |
| ... | ... | @@ -1421,7 +1597,7 @@ fn loadObject( |
| 1421 | 1597 | std.elf.SHT_PROGBITS, std.elf.SHT_NOBITS => { |
| 1422 | 1598 | if (section.shdr.name >= shstrtab.len) continue; |
| 1423 | 1599 | const name = std.mem.sliceTo(shstrtab[section.shdr.name..], 0); |
| 1424 | | const parent_si = namedSection(name) orelse continue; |
| 1600 | const parent_si = elf.namedSection(name) orelse continue; |
| 1425 | 1601 | const ni = try elf.mf.addLastChildNode(gpa, parent_si.node(elf), .{ |
| 1426 | 1602 | .size = section.shdr.size, |
| 1427 | 1603 | .alignment = .fromByteUnits(std.math.ceilPowerOfTwoAssert( |
| ... | ... | @@ -1598,6 +1774,84 @@ fn loadObject( |
| 1598 | 1774 | }, |
| 1599 | 1775 | } |
| 1600 | 1776 | } |
| 1777 | fn loadDso(elf: *Elf, path: std.Build.Cache.Path, fr: *std.Io.File.Reader) !void { |
| 1778 | const comp = elf.base.comp; |
| 1779 | const diags = &comp.link_diags; |
| 1780 | const r = &fr.interface; |
| 1781 | |
| 1782 | log.debug("loadDso({f})", .{path.fmtEscapeString()}); |
| 1783 | const ident = try r.peek(std.elf.EI.NIDENT); |
| 1784 | if (!std.mem.eql(u8, ident, elf.mf.contents[0..std.elf.EI.NIDENT])) |
| 1785 | return diags.failParse(path, "bad ident", .{}); |
| 1786 | const target_endian = elf.targetEndian(); |
| 1787 | switch (elf.identClass()) { |
| 1788 | .NONE, _ => unreachable, |
| 1789 | inline else => |class| { |
| 1790 | const ElfN = class.ElfN(); |
| 1791 | const ehdr = try r.peekStruct(ElfN.Ehdr, target_endian); |
| 1792 | if (ehdr.type != .DYN) return diags.failParse(path, "unsupported dso type", .{}); |
| 1793 | if (ehdr.machine != elf.ehdrField(.machine)) |
| 1794 | return diags.failParse(path, "bad machine", .{}); |
| 1795 | if (ehdr.phoff == 0 or ehdr.phnum <= 1) |
| 1796 | return diags.failParse(path, "no program headers", .{}); |
| 1797 | try fr.seekTo(ehdr.phoff); |
| 1798 | const dynamic_ph = for (0..ehdr.phnum) |_| { |
| 1799 | const ph = try r.peekStruct(ElfN.Phdr, target_endian); |
| 1800 | try r.discardAll(ehdr.phentsize); |
| 1801 | switch (ph.type) { |
| 1802 | else => {}, |
| 1803 | std.elf.PT_DYNAMIC => break ph, |
| 1804 | } |
| 1805 | } else return diags.failParse(path, "no dynamic segment", .{}); |
| 1806 | const dynnum = std.math.divExact( |
| 1807 | u32, |
| 1808 | @intCast(dynamic_ph.filesz), |
| 1809 | @sizeOf(ElfN.Addr) * 2, |
| 1810 | ) catch return diags.failParse( |
| 1811 | path, |
| 1812 | "dynamic segment filesz (0x{x}) is not a multiple of entsize (0x{x})", |
| 1813 | .{ dynamic_ph.filesz, @sizeOf(ElfN.Addr) * 2 }, |
| 1814 | ); |
| 1815 | var strtab: ?ElfN.Addr = null; |
| 1816 | var strsz: ?ElfN.Addr = null; |
| 1817 | var soname: ?ElfN.Addr = null; |
| 1818 | try fr.seekTo(dynamic_ph.offset); |
| 1819 | for (0..dynnum) |_| { |
| 1820 | const key = try r.takeInt(ElfN.Addr, target_endian); |
| 1821 | const value = try r.takeInt(ElfN.Addr, target_endian); |
| 1822 | switch (key) { |
| 1823 | else => {}, |
| 1824 | std.elf.DT_STRTAB => strtab = value, |
| 1825 | std.elf.DT_STRSZ => strsz = value, |
| 1826 | std.elf.DT_SONAME => soname = value, |
| 1827 | } |
| 1828 | } |
| 1829 | if (strtab == null or soname == null) |
| 1830 | return elf.loadDsoExact(std.fs.path.basename(path.sub_path)); |
| 1831 | if (strsz) |size| if (soname.? >= size) |
| 1832 | return diags.failParse(path, "bad soname string", .{}); |
| 1833 | try fr.seekTo(ehdr.phoff); |
| 1834 | const ph = for (0..ehdr.phnum) |_| { |
| 1835 | const ph = try r.peekStruct(ElfN.Phdr, target_endian); |
| 1836 | try r.discardAll(ehdr.phentsize); |
| 1837 | switch (ph.type) { |
| 1838 | else => {}, |
| 1839 | std.elf.PT_LOAD => if (strtab.? >= ph.vaddr and |
| 1840 | strtab.? + (strsz orelse 0) <= ph.vaddr + ph.filesz) break ph, |
| 1841 | } |
| 1842 | } else return diags.failParse(path, "strtab not part of a loaded segment", .{}); |
| 1843 | try fr.seekTo(strtab.? + soname.? - ph.vaddr + ph.offset); |
| 1844 | return elf.loadDsoExact(r.peekSentinel(0) catch |err| switch (err) { |
| 1845 | error.StreamTooLong => return diags.failParse(path, "soname too lang", .{}), |
| 1846 | else => |e| return e, |
| 1847 | }); |
| 1848 | }, |
| 1849 | } |
| 1850 | } |
| 1851 | fn loadDsoExact(elf: *Elf, name: []const u8) !void { |
| 1852 | log.debug("loadDsoExact({f})", .{std.zig.fmtString(name)}); |
| 1853 | try elf.needed.put(elf.base.comp.gpa, try elf.string(.dynstr, name), {}); |
| 1854 | } |
| 1601 | 1855 | |
| 1602 | 1856 | pub fn prelink(elf: *Elf, prog_node: std.Progress.Node) !void { |
| 1603 | 1857 | _ = prog_node; |
| ... | ... | @@ -1624,6 +1878,66 @@ fn prelinkInner(elf: *Elf) !void { |
| 1624 | 1878 | .member = null, |
| 1625 | 1879 | .si = si, |
| 1626 | 1880 | }; |
| 1881 | |
| 1882 | if (elf.si.dynamic != .null) switch (elf.identClass()) { |
| 1883 | .NONE, _ => unreachable, |
| 1884 | inline else => |ct_class| { |
| 1885 | const ElfN = ct_class.ElfN(); |
| 1886 | const needed_len = elf.needed.count(); |
| 1887 | const dynamic_len = needed_len + @intFromBool(elf.options.soname != null) + 5; |
| 1888 | const dynamic_size: u32 = @intCast(@sizeOf(ElfN.Addr) * 2 * dynamic_len); |
| 1889 | const dynamic_ni = elf.si.dynamic.node(elf); |
| 1890 | try dynamic_ni.resize(&elf.mf, gpa, dynamic_size); |
| 1891 | const sec_dynamic = dynamic_ni.slice(&elf.mf); |
| 1892 | const dynamic_entries: [][2]ElfN.Addr = @ptrCast(@alignCast(sec_dynamic)); |
| 1893 | var dynamic_index: usize = 0; |
| 1894 | for ( |
| 1895 | dynamic_entries[dynamic_index..][0..needed_len], |
| 1896 | elf.needed.keys(), |
| 1897 | ) |*dynamic_entry, needed| dynamic_entry.* = .{ std.elf.DT_NEEDED, needed }; |
| 1898 | dynamic_index += needed_len; |
| 1899 | if (elf.options.soname) |soname| { |
| 1900 | dynamic_entries[dynamic_index] = .{ std.elf.DT_SONAME, try elf.string(.dynstr, soname) }; |
| 1901 | dynamic_index += 1; |
| 1902 | } |
| 1903 | dynamic_entries[dynamic_index..][0..5].* = .{ |
| 1904 | .{ std.elf.DT_SYMTAB, 0 }, |
| 1905 | .{ std.elf.DT_SYMENT, @sizeOf(ElfN.Sym) }, |
| 1906 | .{ std.elf.DT_STRTAB, 0 }, |
| 1907 | .{ std.elf.DT_STRSZ, 0 }, |
| 1908 | .{ std.elf.DT_NULL, 0 }, |
| 1909 | }; |
| 1910 | dynamic_index += 5; |
| 1911 | assert(dynamic_index == dynamic_len); |
| 1912 | if (elf.targetEndian() != native_endian) for (dynamic_entries) |*dynamic_entry| |
| 1913 | std.mem.byteSwapAllFields(@TypeOf(dynamic_entry.*), dynamic_entry); |
| 1914 | |
| 1915 | const dynamic_sym = elf.si.dynamic.get(elf); |
| 1916 | assert(dynamic_sym.loc_relocs == .none); |
| 1917 | dynamic_sym.loc_relocs = @enumFromInt(elf.relocs.items.len); |
| 1918 | try elf.addReloc( |
| 1919 | elf.si.dynamic, |
| 1920 | @sizeOf(ElfN.Addr) * (2 * (dynamic_len - 5) + 1), |
| 1921 | elf.si.dynsym, |
| 1922 | 0, |
| 1923 | .absAddr(elf), |
| 1924 | ); |
| 1925 | try elf.addReloc( |
| 1926 | elf.si.dynamic, |
| 1927 | @sizeOf(ElfN.Addr) * (2 * (dynamic_len - 3) + 1), |
| 1928 | elf.si.dynstr, |
| 1929 | 0, |
| 1930 | .absAddr(elf), |
| 1931 | ); |
| 1932 | try elf.addReloc( |
| 1933 | elf.si.dynamic, |
| 1934 | @sizeOf(ElfN.Addr) * (2 * (dynamic_len - 2) + 1), |
| 1935 | elf.si.dynstr, |
| 1936 | 0, |
| 1937 | .sizeAddr(elf), |
| 1938 | ); |
| 1939 | }, |
| 1940 | }; |
| 1627 | 1941 | } |
| 1628 | 1942 | |
| 1629 | 1943 | pub fn getNavVAddr( |
| ... | ... | @@ -1649,13 +1963,7 @@ pub fn getVAddr(elf: *Elf, reloc_info: link.File.RelocInfo, target_si: Symbol.In |
| 1649 | 1963 | reloc_info.offset, |
| 1650 | 1964 | target_si, |
| 1651 | 1965 | reloc_info.addend, |
| 1652 | | switch (elf.ehdrField(.machine)) { |
| 1653 | | else => unreachable, |
| 1654 | | .AARCH64 => .{ .AARCH64 = .ABS64 }, |
| 1655 | | .PPC64 => .{ .PPC64 = .ADDR64 }, |
| 1656 | | .RISCV => .{ .RISCV = .@"64" }, |
| 1657 | | .X86_64 => .{ .X86_64 = .@"64" }, |
| 1658 | | }, |
| 1966 | .absAddr(elf), |
| 1659 | 1967 | ); |
| 1660 | 1968 | return switch (elf.symPtr(target_si)) { |
| 1661 | 1969 | inline else => |sym| elf.targetLoad(&sym.value), |
| ... | ... | @@ -1665,11 +1973,16 @@ pub fn getVAddr(elf: *Elf, reloc_info: link.File.RelocInfo, target_si: Symbol.In |
| 1665 | 1973 | fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct { |
| 1666 | 1974 | name: []const u8 = "", |
| 1667 | 1975 | type: std.elf.Word = std.elf.SHT_NULL, |
| 1668 | | size: std.elf.Word = 0, |
| 1669 | 1976 | flags: std.elf.SHF = .{}, |
| 1977 | size: std.elf.Word = 0, |
| 1670 | 1978 | addralign: std.mem.Alignment = .@"1", |
| 1671 | 1979 | entsize: std.elf.Word = 0, |
| 1672 | 1980 | }) !Symbol.Index { |
| 1981 | switch (opts.type) { |
| 1982 | std.elf.SHT_NULL => assert(opts.size == 0), |
| 1983 | std.elf.SHT_PROGBITS => assert(opts.size > 0), |
| 1984 | else => {}, |
| 1985 | } |
| 1673 | 1986 | const gpa = elf.base.comp.gpa; |
| 1674 | 1987 | try elf.nodes.ensureUnusedCapacity(gpa, 1); |
| 1675 | 1988 | try elf.symtab.ensureUnusedCapacity(gpa, 1); |
| ... | ... | @@ -1683,16 +1996,23 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct { |
| 1683 | 1996 | break :shndx .{ shndx, elf.targetLoad(&ehdr.shentsize) * shnum }; |
| 1684 | 1997 | }, |
| 1685 | 1998 | }; |
| 1686 | | try Node.Known.shdr.resize(&elf.mf, gpa, shdr_size); |
| 1999 | try elf.ni.shdr.resize(&elf.mf, gpa, shdr_size); |
| 1687 | 2000 | const ni = try elf.mf.addLastChildNode(gpa, segment_ni, .{ |
| 1688 | 2001 | .alignment = opts.addralign, |
| 1689 | 2002 | .size = opts.size, |
| 1690 | | .moved = true, |
| 2003 | .resized = opts.size > 0, |
| 1691 | 2004 | }); |
| 1692 | 2005 | const si = elf.addSymbolAssumeCapacity(); |
| 1693 | 2006 | elf.nodes.appendAssumeCapacity(.{ .section = si }); |
| 1694 | 2007 | si.get(elf).ni = ni; |
| 1695 | | try si.init(elf, .{ .size = opts.size, .type = .SECTION, .shndx = shndx }); |
| 2008 | const addr = elf.computeNodeVAddr(ni); |
| 2009 | const offset = ni.fileLocation(&elf.mf, false).offset; |
| 2010 | try si.init(elf, .{ |
| 2011 | .value = addr, |
| 2012 | .size = opts.size, |
| 2013 | .type = .SECTION, |
| 2014 | .shndx = shndx, |
| 2015 | }); |
| 1696 | 2016 | switch (elf.shdrSlice()) { |
| 1697 | 2017 | inline else => |shdr| { |
| 1698 | 2018 | const sh = &shdr[shndx]; |
| ... | ... | @@ -1700,8 +2020,8 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct { |
| 1700 | 2020 | .name = shstrtab_entry, |
| 1701 | 2021 | .type = opts.type, |
| 1702 | 2022 | .flags = .{ .shf = opts.flags }, |
| 1703 | | .addr = 0, |
| 1704 | | .offset = 0, |
| 2023 | .addr = @intCast(addr), |
| 2024 | .offset = @intCast(offset), |
| 1705 | 2025 | .size = opts.size, |
| 1706 | 2026 | .link = 0, |
| 1707 | 2027 | .info = 0, |
| ... | ... | @@ -1733,7 +2053,7 @@ fn linkSections(elf: *Elf, si: Symbol.Index, link_si: Symbol.Index) !void { |
| 1733 | 2053 | } |
| 1734 | 2054 | |
| 1735 | 2055 | fn sectionName(elf: *Elf, si: Symbol.Index) [:0]const u8 { |
| 1736 | | const name = Symbol.Index.shstrtab.node(elf).slice(&elf.mf)[switch (elf.shdrSlice()) { |
| 2056 | const name = elf.si.shstrtab.node(elf).slice(&elf.mf)[switch (elf.shdrSlice()) { |
| 1737 | 2057 | inline else => |shndx, class| elf.targetLoad( |
| 1738 | 2058 | &shndx[elf.targetLoad(&@field(elf.symPtr(si), @tagName(class)).shndx)].name, |
| 1739 | 2059 | ), |
| ... | ... | @@ -1741,12 +2061,12 @@ fn sectionName(elf: *Elf, si: Symbol.Index) [:0]const u8 { |
| 1741 | 2061 | return name[0..std.mem.indexOfScalar(u8, name, 0).? :0]; |
| 1742 | 2062 | } |
| 1743 | 2063 | |
| 1744 | | fn string(elf: *Elf, comptime section: enum { shstrtab, strtab }, key: []const u8) !u32 { |
| 2064 | fn string(elf: *Elf, comptime section: enum { shstrtab, strtab, dynstr }, key: []const u8) !u32 { |
| 1745 | 2065 | if (key.len == 0) return 0; |
| 1746 | 2066 | return @field(elf, @tagName(section)).get( |
| 1747 | 2067 | elf.base.comp.gpa, |
| 1748 | 2068 | &elf.mf, |
| 1749 | | @field(Symbol.Index, @tagName(section)).node(elf), |
| 2069 | @field(elf.si, @tagName(section)).node(elf), |
| 1750 | 2070 | key, |
| 1751 | 2071 | ); |
| 1752 | 2072 | } |
| ... | ... | @@ -2144,7 +2464,7 @@ fn flushUav( |
| 2144 | 2464 | switch (sym.ni) { |
| 2145 | 2465 | .none => { |
| 2146 | 2466 | try elf.nodes.ensureUnusedCapacity(gpa, 1); |
| 2147 | | const ni = try elf.mf.addLastChildNode(gpa, Symbol.Index.data.node(elf), .{ |
| 2467 | const ni = try elf.mf.addLastChildNode(gpa, elf.si.data.node(elf), .{ |
| 2148 | 2468 | .alignment = uav_align.toStdMem(), |
| 2149 | 2469 | .moved = true, |
| 2150 | 2470 | }); |
| ... | ... | @@ -2256,9 +2576,9 @@ fn flushInputSection(elf: *Elf, isi: Node.InputSectionIndex) !void { |
| 2256 | 2576 | return error.EndOfStream; |
| 2257 | 2577 | } |
| 2258 | 2578 | |
| 2259 | | fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) !void { |
| 2579 | fn flushFileOffset(elf: *Elf, ni: MappedFile.Node.Index) !void { |
| 2260 | 2580 | switch (elf.getNode(ni)) { |
| 2261 | | .file => unreachable, |
| 2581 | else => unreachable, |
| 2262 | 2582 | .ehdr => assert(ni.fileLocation(&elf.mf, false).offset == 0), |
| 2263 | 2583 | .shdr => switch (elf.ehdrPtr()) { |
| 2264 | 2584 | inline else => |ehdr| elf.targetStore( |
| ... | ... | @@ -2266,32 +2586,61 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) !void { |
| 2266 | 2586 | @intCast(ni.fileLocation(&elf.mf, false).offset), |
| 2267 | 2587 | ), |
| 2268 | 2588 | }, |
| 2269 | | .segment => |phndx| switch (elf.phdrSlice()) { |
| 2270 | | inline else => |phdr, class| { |
| 2271 | | const ph = &phdr[phndx]; |
| 2272 | | elf.targetStore(&ph.offset, @intCast(ni.fileLocation(&elf.mf, false).offset)); |
| 2273 | | switch (elf.targetLoad(&ph.type)) { |
| 2274 | | else => unreachable, |
| 2275 | | std.elf.PT_NULL, std.elf.PT_LOAD => return, |
| 2276 | | std.elf.PT_DYNAMIC, std.elf.PT_INTERP => {}, |
| 2277 | | std.elf.PT_PHDR => @field(elf.ehdrPtr(), @tagName(class)).phoff = ph.offset, |
| 2278 | | std.elf.PT_TLS => {}, |
| 2279 | | } |
| 2280 | | elf.targetStore(&ph.vaddr, @intCast(elf.computeNodeVAddr(ni))); |
| 2281 | | ph.paddr = ph.vaddr; |
| 2282 | | }, |
| 2589 | .segment => |phndx| { |
| 2590 | switch (elf.phdrSlice()) { |
| 2591 | inline else => |phdr| elf.targetStore( |
| 2592 | &phdr[phndx].offset, |
| 2593 | @intCast(ni.fileLocation(&elf.mf, false).offset), |
| 2594 | ), |
| 2595 | } |
| 2596 | var child_it = ni.children(&elf.mf); |
| 2597 | while (child_it.next()) |child_ni| try elf.flushFileOffset(child_ni); |
| 2283 | 2598 | }, |
| 2284 | 2599 | .section => |si| switch (elf.shdrSlice()) { |
| 2285 | | inline else => |shdr, class| { |
| 2286 | | const sym = @field(elf.symPtr(si), @tagName(class)); |
| 2287 | | const sh = &shdr[elf.targetLoad(&sym.shndx)]; |
| 2288 | | elf.targetStore(&sh.offset, @intCast(ni.fileLocation(&elf.mf, false).offset)); |
| 2289 | | const flags = elf.targetLoad(&sh.flags).shf; |
| 2290 | | if (flags.ALLOC) { |
| 2291 | | elf.targetStore(&sh.addr, @intCast(elf.computeNodeVAddr(ni))); |
| 2292 | | if (!flags.TLS) sym.value = sh.addr; |
| 2293 | | } |
| 2294 | | }, |
| 2600 | inline else => |shdr, class| elf.targetStore( |
| 2601 | &shdr[elf.targetLoad(&@field(elf.symPtr(si), @tagName(class)).shndx)].offset, |
| 2602 | @intCast(ni.fileLocation(&elf.mf, false).offset), |
| 2603 | ), |
| 2604 | }, |
| 2605 | } |
| 2606 | } |
| 2607 | |
| 2608 | fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) !void { |
| 2609 | switch (elf.getNode(ni)) { |
| 2610 | .file => unreachable, |
| 2611 | .ehdr, .shdr => try elf.flushFileOffset(ni), |
| 2612 | .segment => |phndx| { |
| 2613 | try elf.flushFileOffset(ni); |
| 2614 | switch (elf.phdrSlice()) { |
| 2615 | inline else => |phdr, class| { |
| 2616 | const ph = &phdr[phndx]; |
| 2617 | switch (elf.targetLoad(&ph.type)) { |
| 2618 | else => unreachable, |
| 2619 | std.elf.PT_NULL, std.elf.PT_LOAD => return, |
| 2620 | std.elf.PT_DYNAMIC, std.elf.PT_INTERP => {}, |
| 2621 | std.elf.PT_PHDR => @field(elf.ehdrPtr(), @tagName(class)).phoff = ph.offset, |
| 2622 | std.elf.PT_TLS => {}, |
| 2623 | } |
| 2624 | elf.targetStore(&ph.vaddr, @intCast(elf.computeNodeVAddr(ni))); |
| 2625 | ph.paddr = ph.vaddr; |
| 2626 | }, |
| 2627 | } |
| 2628 | }, |
| 2629 | .section => |si| { |
| 2630 | try elf.flushFileOffset(ni); |
| 2631 | const addr = elf.computeNodeVAddr(ni); |
| 2632 | switch (elf.shdrSlice()) { |
| 2633 | inline else => |shdr, class| { |
| 2634 | const sym = @field(elf.symPtr(si), @tagName(class)); |
| 2635 | const sh = &shdr[elf.targetLoad(&sym.shndx)]; |
| 2636 | const flags = elf.targetLoad(&sh.flags).shf; |
| 2637 | if (flags.ALLOC) { |
| 2638 | elf.targetStore(&sh.addr, @intCast(addr)); |
| 2639 | sym.value = sh.addr; |
| 2640 | } |
| 2641 | }, |
| 2642 | } |
| 2643 | si.flushMoved(elf, addr); |
| 2295 | 2644 | }, |
| 2296 | 2645 | .input_section => |isi| { |
| 2297 | 2646 | const old_addr = switch (elf.symPtr(isi.symbol(elf))) { |
| ... | ... | @@ -2380,11 +2729,11 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) !void { |
| 2380 | 2729 | else => unreachable, |
| 2381 | 2730 | std.elf.SHT_NULL => if (size > 0) elf.targetStore(&sh.type, std.elf.SHT_PROGBITS), |
| 2382 | 2731 | std.elf.SHT_PROGBITS => if (size == 0) elf.targetStore(&sh.type, std.elf.SHT_NULL), |
| 2383 | | std.elf.SHT_SYMTAB => elf.targetStore( |
| 2732 | std.elf.SHT_SYMTAB, std.elf.SHT_DYNSYM => elf.targetStore( |
| 2384 | 2733 | &sh.info, |
| 2385 | 2734 | @intCast(@divExact(size, elf.targetLoad(&sh.entsize))), |
| 2386 | 2735 | ), |
| 2387 | | std.elf.SHT_STRTAB => {}, |
| 2736 | std.elf.SHT_STRTAB, std.elf.SHT_DYNAMIC => {}, |
| 2388 | 2737 | } |
| 2389 | 2738 | }, |
| 2390 | 2739 | }, |