| ... | @@ -1,11 +1,16 @@ | ... | @@ -1,11 +1,16 @@ |
| 1 | base: link.File, | 1 | base: link.File, |
| | 2 | options: link.File.OpenOptions, |
| 2 | mf: MappedFile, | 3 | mf: MappedFile, |
| 3 | known: Node.Known, | 4 | ni: Node.Known, |
| 4 | nodes: std.MultiArrayList(Node), | 5 | nodes: std.MultiArrayList(Node), |
| 5 | phdrs: std.ArrayList(MappedFile.Node.Index), | 6 | phdrs: std.ArrayList(MappedFile.Node.Index), |
| | 7 | si: Symbol.Known, |
| 6 | symtab: std.ArrayList(Symbol), | 8 | symtab: std.ArrayList(Symbol), |
| 7 | shstrtab: StringTable, | 9 | shstrtab: StringTable, |
| 8 | strtab: StringTable, | 10 | strtab: StringTable, |
| | 11 | dynsym: std.ArrayList(Symbol.Index), |
| | 12 | dynstr: StringTable, |
| | 13 | needed: std.AutoArrayHashMapUnmanaged(u32, void), |
| 9 | inputs: std.ArrayList(struct { | 14 | inputs: std.ArrayList(struct { |
| 10 | path: std.Build.Cache.Path, | 15 | path: std.Build.Cache.Path, |
| 11 | member: ?[]const u8, | 16 | member: ?[]const u8, |
| ... | @@ -143,13 +148,13 @@ pub const Node = union(enum) { | ... | @@ -143,13 +148,13 @@ pub const Node = union(enum) { |
| 143 | }; | 148 | }; |
| 144 | | 149 | |
| 145 | pub const Known = struct { | 150 | pub const Known = struct { |
| 146 | pub const rodata: MappedFile.Node.Index = @enumFromInt(1); | 151 | comptime file: MappedFile.Node.Index = .root, |
| 147 | pub const ehdr: MappedFile.Node.Index = @enumFromInt(2); | 152 | comptime ehdr: MappedFile.Node.Index = @enumFromInt(1), |
| 148 | pub const phdr: MappedFile.Node.Index = @enumFromInt(3); | 153 | comptime shdr: MappedFile.Node.Index = @enumFromInt(2), |
| 149 | pub const shdr: MappedFile.Node.Index = @enumFromInt(4); | 154 | comptime rodata: MappedFile.Node.Index = @enumFromInt(3), |
| 150 | pub const text: MappedFile.Node.Index = @enumFromInt(5); | 155 | comptime phdr: MappedFile.Node.Index = @enumFromInt(4), |
| 151 | pub const data: MappedFile.Node.Index = @enumFromInt(6); | 156 | comptime text: MappedFile.Node.Index = @enumFromInt(5), |
| 152 | | 157 | comptime data: MappedFile.Node.Index = @enumFromInt(6), |
| 153 | tls: MappedFile.Node.Index, | 158 | tls: MappedFile.Node.Index, |
| 154 | }; | 159 | }; |
| 155 | | 160 | |
| ... | @@ -231,7 +236,6 @@ pub const Symbol = struct { | ... | @@ -231,7 +236,6 @@ pub const Symbol = struct { |
| 231 | rodata, | 236 | rodata, |
| 232 | text, | 237 | text, |
| 233 | data, | 238 | data, |
| 234 | tdata, | | |
| 235 | _, | 239 | _, |
| 236 | | 240 | |
| 237 | pub fn get(si: Symbol.Index, elf: *Elf) *Symbol { | 241 | pub fn get(si: Symbol.Index, elf: *Elf) *Symbol { |
| ... | @@ -250,6 +254,7 @@ pub const Symbol = struct { | ... | @@ -250,6 +254,7 @@ pub const Symbol = struct { |
| 250 | | 254 | |
| 251 | pub const InitOptions = struct { | 255 | pub const InitOptions = struct { |
| 252 | name: []const u8 = "", | 256 | name: []const u8 = "", |
| | 257 | lib_name: ?[]const u8 = null, |
| 253 | value: u64 = 0, | 258 | value: u64 = 0, |
| 254 | size: u64 = 0, | 259 | size: u64 = 0, |
| 255 | type: std.elf.STT, | 260 | type: std.elf.STT, |
| ... | @@ -258,29 +263,45 @@ pub const Symbol = struct { | ... | @@ -258,29 +263,45 @@ pub const Symbol = struct { |
| 258 | shndx: std.elf.Section = std.elf.SHN_UNDEF, | 263 | shndx: std.elf.Section = std.elf.SHN_UNDEF, |
| 259 | }; | 264 | }; |
| 260 | pub fn init(si: Symbol.Index, elf: *Elf, opts: InitOptions) !void { | 265 | pub fn init(si: Symbol.Index, elf: *Elf, opts: InitOptions) !void { |
| 261 | const name_entry = try elf.string(.strtab, opts.name); | 266 | const gpa = elf.base.comp.gpa; |
| 262 | try Symbol.Index.symtab.node(elf).resize( | 267 | const target_endian = elf.targetEndian(); |
| 263 | &elf.mf, | 268 | const sym_size: usize = switch (elf.identClass()) { |
| 264 | elf.base.comp.gpa, | 269 | .NONE, _ => unreachable, |
| 265 | @as(usize, switch (elf.identClass()) { | 270 | inline else => |class| @sizeOf(class.ElfN().Sym), |
| 266 | .NONE, _ => unreachable, | 271 | }; |
| 267 | .@"32" => @sizeOf(std.elf.Elf32.Sym), | 272 | const name_strtab_entry = try elf.string(.strtab, opts.name); |
| 268 | .@"64" => @sizeOf(std.elf.Elf64.Sym), | 273 | try elf.si.symtab.node(elf).resize(&elf.mf, gpa, sym_size * elf.symtab.items.len); |
| 269 | }) * elf.symtab.items.len, | | |
| 270 | ); | | |
| 271 | switch (elf.symPtr(si)) { | 274 | switch (elf.symPtr(si)) { |
| 272 | inline else => |sym| sym.* = .{ | 275 | inline else => |sym, class| { |
| 273 | .name = name_entry, | 276 | sym.* = .{ |
| 274 | .value = @intCast(opts.value), | 277 | .name = name_strtab_entry, |
| 275 | .size = @intCast(opts.size), | 278 | .value = @intCast(opts.value), |
| 276 | .info = .{ | 279 | .size = @intCast(opts.size), |
| 277 | .type = opts.type, | 280 | .info = .{ .type = opts.type, .bind = opts.bind }, |
| 278 | .bind = opts.bind, | 281 | .other = .{ .visibility = opts.visibility }, |
| 279 | }, | 282 | .shndx = opts.shndx, |
| 280 | .other = .{ | 283 | }; |
| 281 | .visibility = opts.visibility, | 284 | if (target_endian != native_endian) std.mem.byteSwapAllFields(class.ElfN().Sym, sym); |
| 282 | }, | 285 | }, |
| 283 | .shndx = opts.shndx, | 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,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 | comptime { | 366 | comptime { |
| 333 | if (!std.debug.runtime_safety) std.debug.assert(@sizeOf(Symbol) == 16); | 367 | if (!std.debug.runtime_safety) std.debug.assert(@sizeOf(Symbol) == 16); |
| 334 | } | 368 | } |
| ... | @@ -349,6 +383,22 @@ pub const Reloc = extern struct { | ... | @@ -349,6 +383,22 @@ pub const Reloc = extern struct { |
| 349 | AARCH64: std.elf.R_AARCH64, | 383 | AARCH64: std.elf.R_AARCH64, |
| 350 | RISCV: std.elf.R_RISCV, | 384 | RISCV: std.elf.R_RISCV, |
| 351 | PPC64: std.elf.R_PPC64, | 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 | pub const Index = enum(u32) { | 404 | pub const Index = enum(u32) { |
| ... | @@ -411,7 +461,7 @@ pub const Reloc = extern struct { | ... | @@ -411,7 +461,7 @@ pub const Reloc = extern struct { |
| 411 | ), | 461 | ), |
| 412 | .TPOFF32 => { | 462 | .TPOFF32 => { |
| 413 | const phdr = @field(elf.phdrSlice(), @tagName(class)); | 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 | assert(elf.targetLoad(&ph.type) == std.elf.PT_TLS); | 465 | assert(elf.targetLoad(&ph.type) == std.elf.PT_TLS); |
| 416 | std.mem.writeInt( | 466 | std.mem.writeInt( |
| 417 | i32, | 467 | i32, |
| ... | @@ -420,6 +470,18 @@ pub const Reloc = extern struct { | ... | @@ -420,6 +470,18 @@ pub const Reloc = extern struct { |
| 420 | target_endian, | 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,7 +531,6 @@ fn create( |
| 469 | path: std.Build.Cache.Path, | 531 | path: std.Build.Cache.Path, |
| 470 | options: link.File.OpenOptions, | 532 | options: link.File.OpenOptions, |
| 471 | ) !*Elf { | 533 | ) !*Elf { |
| 472 | _ = options; | | |
| 473 | const target = &comp.root_mod.resolved_target.result; | 534 | const target = &comp.root_mod.resolved_target.result; |
| 474 | assert(target.ofmt == .elf); | 535 | assert(target.ofmt == .elf); |
| 475 | const class: std.elf.CLASS = switch (target.ptrBitWidth()) { | 536 | const class: std.elf.CLASS = switch (target.ptrBitWidth()) { |
| ... | @@ -502,12 +563,16 @@ fn create( | ... | @@ -502,12 +563,16 @@ fn create( |
| 502 | .Obj => .REL, | 563 | .Obj => .REL, |
| 503 | }; | 564 | }; |
| 504 | const machine = target.toElfMachine(); | 565 | const machine = target.toElfMachine(); |
| 505 | const maybe_interp = switch (comp.config.output_mode) { | 566 | const maybe_interp = switch (comp.config.link_mode) { |
| 506 | .Exe, .Lib => switch (comp.config.link_mode) { | 567 | .static => null, |
| 507 | .static => null, | 568 | .dynamic => switch (comp.config.output_mode) { |
| 508 | .dynamic => target.dynamic_linker.get(), | 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 | const elf = try arena.create(Elf); | 578 | const elf = try arena.create(Elf); |
| ... | @@ -530,12 +595,19 @@ fn create( | ... | @@ -530,12 +595,19 @@ fn create( |
| 530 | .allow_shlib_undefined = false, | 595 | .allow_shlib_undefined = false, |
| 531 | .stack_size = 0, | 596 | .stack_size = 0, |
| 532 | }, | 597 | }, |
| | 598 | .options = options, |
| 533 | .mf = try .init(file, comp.gpa), | 599 | .mf = try .init(file, comp.gpa), |
| 534 | .known = .{ | 600 | .ni = .{ |
| 535 | .tls = .none, | 601 | .tls = .none, |
| 536 | }, | 602 | }, |
| 537 | .nodes = .empty, | 603 | .nodes = .empty, |
| 538 | .phdrs = .empty, | 604 | .phdrs = .empty, |
| | 605 | .si = .{ |
| | 606 | .dynsym = .null, |
| | 607 | .dynstr = .null, |
| | 608 | .dynamic = .null, |
| | 609 | .tdata = .null, |
| | 610 | }, |
| 539 | .symtab = .empty, | 611 | .symtab = .empty, |
| 540 | .shstrtab = .{ | 612 | .shstrtab = .{ |
| 541 | .map = .empty, | 613 | .map = .empty, |
| ... | @@ -545,6 +617,12 @@ fn create( | ... | @@ -545,6 +617,12 @@ fn create( |
| 545 | .map = .empty, | 617 | .map = .empty, |
| 546 | .size = 1, | 618 | .size = 1, |
| 547 | }, | 619 | }, |
| | 620 | .dynsym = .empty, |
| | 621 | .dynstr = .{ |
| | 622 | .map = .empty, |
| | 623 | .size = 1, |
| | 624 | }, |
| | 625 | .needed = .empty, |
| 548 | .inputs = .empty, | 626 | .inputs = .empty, |
| 549 | .input_sections = .empty, | 627 | .input_sections = .empty, |
| 550 | .input_section_pending_index = 0, | 628 | .input_section_pending_index = 0, |
| ... | @@ -576,6 +654,9 @@ pub fn deinit(elf: *Elf) void { | ... | @@ -576,6 +654,9 @@ pub fn deinit(elf: *Elf) void { |
| 576 | elf.symtab.deinit(gpa); | 654 | elf.symtab.deinit(gpa); |
| 577 | elf.shstrtab.map.deinit(gpa); | 655 | elf.shstrtab.map.deinit(gpa); |
| 578 | elf.strtab.map.deinit(gpa); | 656 | elf.strtab.map.deinit(gpa); |
| | 657 | elf.dynsym.deinit(gpa); |
| | 658 | elf.dynstr.map.deinit(gpa); |
| | 659 | elf.needed.deinit(gpa); |
| 579 | for (elf.inputs.items) |input| if (input.member) |m| gpa.free(m); | 660 | for (elf.inputs.items) |input| if (input.member) |m| gpa.free(m); |
| 580 | elf.inputs.deinit(gpa); | 661 | elf.inputs.deinit(gpa); |
| 581 | elf.input_sections.deinit(gpa); | 662 | elf.input_sections.deinit(gpa); |
| ... | @@ -599,6 +680,13 @@ fn initHeaders( | ... | @@ -599,6 +680,13 @@ fn initHeaders( |
| 599 | ) !void { | 680 | ) !void { |
| 600 | const comp = elf.base.comp; | 681 | const comp = elf.base.comp; |
| 601 | const gpa = comp.gpa; | 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 | const addr_align: std.mem.Alignment = switch (class) { | 690 | const addr_align: std.mem.Alignment = switch (class) { |
| 603 | .NONE, _ => unreachable, | 691 | .NONE, _ => unreachable, |
| 604 | .@"32" => .@"4", | 692 | .@"32" => .@"4", |
| ... | @@ -618,37 +706,32 @@ fn initHeaders( | ... | @@ -618,37 +706,32 @@ fn initHeaders( |
| 618 | phnum += 1; | 706 | phnum += 1; |
| 619 | const data_phndx = phnum; | 707 | const data_phndx = phnum; |
| 620 | phnum += 1; | 708 | phnum += 1; |
| | 709 | const dynamic_phndx = if (have_dynamic_section) phndx: { |
| | 710 | defer phnum += 1; |
| | 711 | break :phndx phnum; |
| | 712 | } else undefined; |
| 621 | const tls_phndx = if (comp.config.any_non_single_threaded) phndx: { | 713 | const tls_phndx = if (comp.config.any_non_single_threaded) phndx: { |
| 622 | defer phnum += 1; | 714 | defer phnum += 1; |
| 623 | break :phndx phnum; | 715 | break :phndx phnum; |
| 624 | } else undefined; | 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 | try elf.nodes.ensureTotalCapacity(gpa, expected_nodes_len); | 719 | try elf.nodes.ensureTotalCapacity(gpa, expected_nodes_len); |
| 628 | try elf.phdrs.resize(gpa, phnum); | 720 | try elf.phdrs.resize(gpa, phnum); |
| 629 | elf.nodes.appendAssumeCapacity(.file); | 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 | switch (class) { | 723 | switch (class) { |
| 641 | .NONE, _ => unreachable, | 724 | .NONE, _ => unreachable, |
| 642 | inline else => |ct_class| { | 725 | inline else => |ct_class| { |
| 643 | const ElfN = ct_class.ElfN(); | 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 | .size = @sizeOf(ElfN.Ehdr), | 728 | .size = @sizeOf(ElfN.Ehdr), |
| 646 | .alignment = addr_align, | 729 | .alignment = addr_align, |
| 647 | .fixed = true, | 730 | .fixed = true, |
| 648 | })); | 731 | })); |
| 649 | elf.nodes.appendAssumeCapacity(.ehdr); | 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 | const EI = std.elf.EI; | 735 | const EI = std.elf.EI; |
| 653 | @memcpy(ehdr.ident[0..std.elf.MAGIC.len], std.elf.MAGIC); | 736 | @memcpy(ehdr.ident[0..std.elf.MAGIC.len], std.elf.MAGIC); |
| 654 | ehdr.ident[EI.CLASS] = @intFromEnum(class); | 737 | ehdr.ident[EI.CLASS] = @intFromEnum(class); |
| ... | @@ -674,37 +757,47 @@ fn initHeaders( | ... | @@ -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, .{ | 760 | assert(elf.ni.shdr == try elf.mf.addLastChildNode(gpa, elf.ni.file, .{ |
| 678 | .size = elf.ehdrField(.phentsize) * elf.ehdrField(.phnum), | 761 | .size = elf.ehdrField(.shentsize) * elf.ehdrField(.shnum), |
| 679 | .alignment = addr_align, | 762 | .alignment = addr_align, |
| 680 | .moved = true, | 763 | .moved = true, |
| 681 | .resized = true, | 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 | .bubbles_moved = false, | 771 | .bubbles_moved = false, |
| 683 | })); | 772 | })); |
| 684 | elf.nodes.appendAssumeCapacity(.{ .segment = phdr_phndx }); | 773 | elf.nodes.appendAssumeCapacity(.{ .segment = rodata_phndx }); |
| 685 | elf.phdrs.items[phdr_phndx] = Node.Known.phdr; | 774 | elf.phdrs.items[rodata_phndx] = elf.ni.rodata; |
| 686 | | 775 | |
| 687 | assert(Node.Known.shdr == try elf.mf.addLastChildNode(gpa, Node.Known.rodata, .{ | 776 | assert(elf.ni.phdr == try elf.mf.addOnlyChildNode(gpa, elf.ni.rodata, .{ |
| 688 | .size = elf.ehdrField(.shentsize) * elf.ehdrField(.shnum), | 777 | .size = elf.ehdrField(.phentsize) * elf.ehdrField(.phnum), |
| 689 | .alignment = addr_align, | 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 | .alignment = elf.mf.flags.block_size, | 787 | .alignment = elf.mf.flags.block_size, |
| 695 | .moved = true, | 788 | .moved = true, |
| 696 | .bubbles_moved = false, | 789 | .bubbles_moved = false, |
| 697 | })); | 790 | })); |
| 698 | elf.nodes.appendAssumeCapacity(.{ .segment = text_phndx }); | 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 | .alignment = elf.mf.flags.block_size, | 795 | .alignment = elf.mf.flags.block_size, |
| 703 | .moved = true, | 796 | .moved = true, |
| 704 | .bubbles_moved = false, | 797 | .bubbles_moved = false, |
| 705 | })); | 798 | })); |
| 706 | elf.nodes.appendAssumeCapacity(.{ .segment = data_phndx }); | 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 | var ph_vaddr: u32 = switch (elf.ehdrField(.type)) { | 802 | var ph_vaddr: u32 = switch (elf.ehdrField(.type)) { |
| 710 | else => 0, | 803 | else => 0, |
| ... | @@ -723,7 +816,7 @@ fn initHeaders( | ... | @@ -723,7 +816,7 @@ fn initHeaders( |
| 723 | const ElfN = ct_class.ElfN(); | 816 | const ElfN = ct_class.ElfN(); |
| 724 | const target_endian = elf.targetEndian(); | 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 | const ph_phdr = &phdr[phdr_phndx]; | 820 | const ph_phdr = &phdr[phdr_phndx]; |
| 728 | ph_phdr.* = .{ | 821 | ph_phdr.* = .{ |
| 729 | .type = std.elf.PT_PHDR, | 822 | .type = std.elf.PT_PHDR, |
| ... | @@ -733,7 +826,7 @@ fn initHeaders( | ... | @@ -733,7 +826,7 @@ fn initHeaders( |
| 733 | .filesz = 0, | 826 | .filesz = 0, |
| 734 | .memsz = 0, | 827 | .memsz = 0, |
| 735 | .flags = .{ .R = true }, | 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 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_phdr); | 831 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_phdr); |
| 739 | | 832 | |
| ... | @@ -752,7 +845,7 @@ fn initHeaders( | ... | @@ -752,7 +845,7 @@ fn initHeaders( |
| 752 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_interp); | 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 | const ph_rodata = &phdr[rodata_phndx]; | 849 | const ph_rodata = &phdr[rodata_phndx]; |
| 757 | ph_rodata.* = .{ | 850 | ph_rodata.* = .{ |
| 758 | .type = std.elf.PT_NULL, | 851 | .type = std.elf.PT_NULL, |
| ... | @@ -762,12 +855,12 @@ fn initHeaders( | ... | @@ -762,12 +855,12 @@ fn initHeaders( |
| 762 | .filesz = @intCast(rodata_size), | 855 | .filesz = @intCast(rodata_size), |
| 763 | .memsz = @intCast(rodata_size), | 856 | .memsz = @intCast(rodata_size), |
| 764 | .flags = .{ .R = true }, | 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 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_rodata); | 860 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_rodata); |
| 768 | ph_vaddr += @intCast(rodata_size); | 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 | const ph_text = &phdr[text_phndx]; | 864 | const ph_text = &phdr[text_phndx]; |
| 772 | ph_text.* = .{ | 865 | ph_text.* = .{ |
| 773 | .type = std.elf.PT_NULL, | 866 | .type = std.elf.PT_NULL, |
| ... | @@ -777,12 +870,12 @@ fn initHeaders( | ... | @@ -777,12 +870,12 @@ fn initHeaders( |
| 777 | .filesz = @intCast(text_size), | 870 | .filesz = @intCast(text_size), |
| 778 | .memsz = @intCast(text_size), | 871 | .memsz = @intCast(text_size), |
| 779 | .flags = .{ .R = true, .X = true }, | 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 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_text); | 875 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_text); |
| 783 | ph_vaddr += @intCast(text_size); | 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 | const ph_data = &phdr[data_phndx]; | 879 | const ph_data = &phdr[data_phndx]; |
| 787 | ph_data.* = .{ | 880 | ph_data.* = .{ |
| 788 | .type = std.elf.PT_NULL, | 881 | .type = std.elf.PT_NULL, |
| ... | @@ -792,11 +885,26 @@ fn initHeaders( | ... | @@ -792,11 +885,26 @@ fn initHeaders( |
| 792 | .filesz = @intCast(data_size), | 885 | .filesz = @intCast(data_size), |
| 793 | .memsz = @intCast(data_size), | 886 | .memsz = @intCast(data_size), |
| 794 | .flags = .{ .R = true, .W = true }, | 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 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_data); | 890 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_data); |
| 798 | ph_vaddr += @intCast(data_size); | 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 | if (comp.config.any_non_single_threaded) { | 908 | if (comp.config.any_non_single_threaded) { |
| 801 | const ph_tls = &phdr[tls_phndx]; | 909 | const ph_tls = &phdr[tls_phndx]; |
| 802 | ph_tls.* = .{ | 910 | ph_tls.* = .{ |
| ... | @@ -812,7 +920,7 @@ fn initHeaders( | ... | @@ -812,7 +920,7 @@ fn initHeaders( |
| 812 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_tls); | 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 | sh_null.* = .{ | 924 | sh_null.* = .{ |
| 817 | .name = try elf.string(.shstrtab, ""), | 925 | .name = try elf.string(.shstrtab, ""), |
| 818 | .type = std.elf.SHT_NULL, | 926 | .type = std.elf.SHT_NULL, |
| ... | @@ -834,99 +942,142 @@ fn initHeaders( | ... | @@ -834,99 +942,142 @@ fn initHeaders( |
| 834 | .target_relocs = .none, | 942 | .target_relocs = .none, |
| 835 | .unused = 0, | 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 | .type = std.elf.SHT_SYMTAB, | 946 | .type = std.elf.SHT_SYMTAB, |
| | 947 | .size = @sizeOf(ElfN.Sym) * 1, |
| 839 | .addralign = addr_align, | 948 | .addralign = addr_align, |
| 840 | .entsize = @sizeOf(ElfN.Sym), | 949 | .entsize = @sizeOf(ElfN.Sym), |
| 841 | }) == .symtab); | 950 | })); |
| 842 | | 951 | const symtab_null = @field(elf.symPtr(.null), @tagName(ct_class)); |
| 843 | const symtab: *ElfN.Sym = @ptrCast(@alignCast(Symbol.Index.symtab.node(elf).slice(&elf.mf))); | 952 | symtab_null.* = .{ |
| 844 | symtab.* = .{ | | |
| 845 | .name = try elf.string(.strtab, ""), | 953 | .name = try elf.string(.strtab, ""), |
| 846 | .value = 0, | 954 | .value = 0, |
| 847 | .size = 0, | 955 | .size = 0, |
| 848 | .info = .{ | 956 | .info = .{ .type = .NOTYPE, .bind = .LOCAL }, |
| 849 | .type = .NOTYPE, | 957 | .other = .{ .visibility = .DEFAULT }, |
| 850 | .bind = .LOCAL, | | |
| 851 | }, | | |
| 852 | .other = .{ | | |
| 853 | .visibility = .DEFAULT, | | |
| 854 | }, | | |
| 855 | .shndx = std.elf.SHN_UNDEF, | 958 | .shndx = std.elf.SHN_UNDEF, |
| 856 | }; | 959 | }; |
| | 960 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Sym, symtab_null); |
| 857 | | 961 | |
| 858 | const ehdr = @field(elf.ehdrPtr(), @tagName(ct_class)); | 962 | const ehdr = @field(elf.ehdrPtr(), @tagName(ct_class)); |
| 859 | ehdr.shstrndx = ehdr.shnum; | 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 | .type = std.elf.SHT_STRTAB, | 967 | .type = std.elf.SHT_STRTAB, |
| 864 | .addralign = elf.mf.flags.block_size, | 968 | .addralign = elf.mf.flags.block_size, |
| 865 | .entsize = 1, | 969 | .entsize = 1, |
| 866 | }) == .shstrtab); | 970 | })); |
| 867 | try elf.renameSection(.symtab, ".symtab"); | 971 | try elf.renameSection(.symtab, ".symtab"); |
| 868 | try elf.renameSection(.shstrtab, ".shstrtab"); | 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 | .name = ".strtab", | 976 | .name = ".strtab", |
| 873 | .type = std.elf.SHT_STRTAB, | 977 | .type = std.elf.SHT_STRTAB, |
| 874 | .addralign = elf.mf.flags.block_size, | | |
| 875 | .size = 1, | 978 | .size = 1, |
| | 979 | .addralign = elf.mf.flags.block_size, |
| 876 | .entsize = 1, | 980 | .entsize = 1, |
| 877 | }) == .strtab); | 981 | })); |
| 878 | try elf.linkSections(.symtab, .strtab); | 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 | .name = ".rodata", | 986 | .name = ".rodata", |
| 883 | .flags = .{ .ALLOC = true }, | 987 | .flags = .{ .ALLOC = true }, |
| 884 | .addralign = elf.mf.flags.block_size, | 988 | .addralign = elf.mf.flags.block_size, |
| 885 | }) == .rodata); | 989 | })); |
| 886 | assert(try elf.addSection(Node.Known.text, .{ | 990 | assert(elf.si.text == try elf.addSection(elf.ni.text, .{ |
| 887 | .name = ".text", | 991 | .name = ".text", |
| 888 | .flags = .{ .ALLOC = true, .EXECINSTR = true }, | 992 | .flags = .{ .ALLOC = true, .EXECINSTR = true }, |
| 889 | .addralign = elf.mf.flags.block_size, | 993 | .addralign = elf.mf.flags.block_size, |
| 890 | }) == .text); | 994 | })); |
| 891 | assert(try elf.addSection(Node.Known.data, .{ | 995 | assert(elf.si.data == try elf.addSection(elf.ni.data, .{ |
| 892 | .name = ".data", | 996 | .name = ".data", |
| 893 | .flags = .{ .WRITE = true, .ALLOC = true }, | 997 | .flags = .{ .WRITE = true, .ALLOC = true }, |
| 894 | .addralign = elf.mf.flags.block_size, | 998 | .addralign = elf.mf.flags.block_size, |
| 895 | }) == .data); | 999 | })); |
| 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 | } | | |
| 911 | if (maybe_interp) |interp| { | 1000 | if (maybe_interp) |interp| { |
| 912 | try elf.nodes.ensureUnusedCapacity(gpa, 1); | 1001 | const interp_ni = try elf.mf.addLastChildNode(gpa, elf.ni.rodata, .{ |
| 913 | const interp_ni = try elf.mf.addLastChildNode(gpa, Node.Known.rodata, .{ | | |
| 914 | .size = interp.len + 1, | 1002 | .size = interp.len + 1, |
| 915 | .moved = true, | 1003 | .moved = true, |
| 916 | .resized = true, | 1004 | .resized = true, |
| | 1005 | .bubbles_moved = false, |
| 917 | }); | 1006 | }); |
| 918 | elf.nodes.appendAssumeCapacity(.{ .segment = interp_phndx }); | 1007 | elf.nodes.appendAssumeCapacity(.{ .segment = interp_phndx }); |
| 919 | elf.phdrs.items[interp_phndx] = interp_ni; | 1008 | elf.phdrs.items[interp_phndx] = interp_ni; |
| 920 | | 1009 | |
| 921 | const sec_interp_si = try elf.addSection(interp_ni, .{ | 1010 | const sec_interp_si = try elf.addSection(interp_ni, .{ |
| 922 | .name = ".interp", | 1011 | .name = ".interp", |
| 923 | .size = @intCast(interp.len + 1), | | |
| 924 | .flags = .{ .ALLOC = true }, | 1012 | .flags = .{ .ALLOC = true }, |
| | 1013 | .size = @intCast(interp.len + 1), |
| 925 | }); | 1014 | }); |
| 926 | const sec_interp = sec_interp_si.node(elf).slice(&elf.mf); | 1015 | const sec_interp = sec_interp_si.node(elf).slice(&elf.mf); |
| 927 | @memcpy(sec_interp[0..interp.len], interp); | 1016 | @memcpy(sec_interp[0..interp.len], interp); |
| 928 | sec_interp[interp.len] = 0; | 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 | assert(elf.nodes.len == expected_nodes_len); | 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,7 +1113,8 @@ fn getNode(elf: *const Elf, ni: MappedFile.Node.Index) Node { |
| 962 | fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 { | 1113 | fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 { |
| 963 | const parent_vaddr = parent_vaddr: { | 1114 | const parent_vaddr = parent_vaddr: { |
| 964 | const parent_si = switch (elf.getNode(ni.parent(&elf.mf))) { | 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 | .segment => |phndx| break :parent_vaddr switch (elf.phdrSlice()) { | 1118 | .segment => |phndx| break :parent_vaddr switch (elf.phdrSlice()) { |
| 967 | inline else => |ph| elf.targetLoad(&ph[phndx].vaddr), | 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,7 +1122,7 @@ fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 { |
| 970 | .input_section => unreachable, | 1122 | .input_section => unreachable, |
| 971 | inline .nav, .uav, .lazy_code, .lazy_const_data => |mi| mi.symbol(elf), | 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 | inline else => |sym| elf.targetLoad(&sym.value), | 1126 | inline else => |sym| elf.targetLoad(&sym.value), |
| 975 | }; | 1127 | }; |
| 976 | }; | 1128 | }; |
| ... | @@ -1025,7 +1177,7 @@ pub const EhdrPtr = union(std.elf.CLASS) { | ... | @@ -1025,7 +1177,7 @@ pub const EhdrPtr = union(std.elf.CLASS) { |
| 1025 | @"64": *std.elf.Elf64.Ehdr, | 1177 | @"64": *std.elf.Elf64.Ehdr, |
| 1026 | }; | 1178 | }; |
| 1027 | pub fn ehdrPtr(elf: *Elf) EhdrPtr { | 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 | return switch (elf.identClass()) { | 1181 | return switch (elf.identClass()) { |
| 1030 | .NONE, _ => unreachable, | 1182 | .NONE, _ => unreachable, |
| 1031 | inline else => |class| @unionInit( | 1183 | inline else => |class| @unionInit( |
| ... | @@ -1050,7 +1202,7 @@ pub const PhdrSlice = union(std.elf.CLASS) { | ... | @@ -1050,7 +1202,7 @@ pub const PhdrSlice = union(std.elf.CLASS) { |
| 1050 | @"64": []std.elf.Elf64.Phdr, | 1202 | @"64": []std.elf.Elf64.Phdr, |
| 1051 | }; | 1203 | }; |
| 1052 | pub fn phdrSlice(elf: *Elf) PhdrSlice { | 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 | return switch (elf.identClass()) { | 1206 | return switch (elf.identClass()) { |
| 1055 | .NONE, _ => unreachable, | 1207 | .NONE, _ => unreachable, |
| 1056 | inline else => |class| @unionInit( | 1208 | inline else => |class| @unionInit( |
| ... | @@ -1067,7 +1219,7 @@ pub const ShdrSlice = union(std.elf.CLASS) { | ... | @@ -1067,7 +1219,7 @@ pub const ShdrSlice = union(std.elf.CLASS) { |
| 1067 | @"64": []std.elf.Elf64.Shdr, | 1219 | @"64": []std.elf.Elf64.Shdr, |
| 1068 | }; | 1220 | }; |
| 1069 | pub fn shdrSlice(elf: *Elf) ShdrSlice { | 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 | return switch (elf.identClass()) { | 1223 | return switch (elf.identClass()) { |
| 1072 | .NONE, _ => unreachable, | 1224 | .NONE, _ => unreachable, |
| 1073 | inline else => |class| @unionInit( | 1225 | inline else => |class| @unionInit( |
| ... | @@ -1084,7 +1236,7 @@ pub const SymtabSlice = union(std.elf.CLASS) { | ... | @@ -1084,7 +1236,7 @@ pub const SymtabSlice = union(std.elf.CLASS) { |
| 1084 | @"64": []std.elf.Elf64.Sym, | 1236 | @"64": []std.elf.Elf64.Sym, |
| 1085 | }; | 1237 | }; |
| 1086 | pub fn symtabSlice(elf: *Elf) SymtabSlice { | 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 | return switch (elf.identClass()) { | 1240 | return switch (elf.identClass()) { |
| 1089 | .NONE, _ => unreachable, | 1241 | .NONE, _ => unreachable, |
| 1090 | inline else => |class| @unionInit( | 1242 | inline else => |class| @unionInit( |
| ... | @@ -1106,6 +1258,18 @@ pub fn symPtr(elf: *Elf, si: Symbol.Index) SymPtr { | ... | @@ -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 | fn addSymbolAssumeCapacity(elf: *Elf) Symbol.Index { | 1273 | fn addSymbolAssumeCapacity(elf: *Elf) Symbol.Index { |
| 1110 | defer elf.symtab.addOneAssumeCapacity().* = .{ | 1274 | defer elf.symtab.addOneAssumeCapacity().* = .{ |
| 1111 | .ni = .none, | 1275 | .ni = .none, |
| ... | @@ -1124,6 +1288,7 @@ fn initSymbolAssumeCapacity(elf: *Elf, opts: Symbol.Index.InitOptions) !Symbol.I | ... | @@ -1124,6 +1288,7 @@ fn initSymbolAssumeCapacity(elf: *Elf, opts: Symbol.Index.InitOptions) !Symbol.I |
| 1124 | | 1288 | |
| 1125 | pub fn globalSymbol(elf: *Elf, opts: struct { | 1289 | pub fn globalSymbol(elf: *Elf, opts: struct { |
| 1126 | name: []const u8, | 1290 | name: []const u8, |
| | 1291 | lib_name: ?[]const u8 = null, |
| 1127 | type: std.elf.STT, | 1292 | type: std.elf.STT, |
| 1128 | bind: std.elf.STB = .GLOBAL, | 1293 | bind: std.elf.STB = .GLOBAL, |
| 1129 | visibility: std.elf.STV = .DEFAULT, | 1294 | visibility: std.elf.STV = .DEFAULT, |
| ... | @@ -1133,6 +1298,7 @@ pub fn globalSymbol(elf: *Elf, opts: struct { | ... | @@ -1133,6 +1298,7 @@ pub fn globalSymbol(elf: *Elf, opts: struct { |
| 1133 | const global_gop = try elf.globals.getOrPut(gpa, try elf.string(.strtab, opts.name)); | 1298 | const global_gop = try elf.globals.getOrPut(gpa, try elf.string(.strtab, opts.name)); |
| 1134 | if (!global_gop.found_existing) global_gop.value_ptr.* = try elf.initSymbolAssumeCapacity(.{ | 1299 | if (!global_gop.found_existing) global_gop.value_ptr.* = try elf.initSymbolAssumeCapacity(.{ |
| 1135 | .name = opts.name, | 1300 | .name = opts.name, |
| | 1301 | .lib_name = opts.lib_name, |
| 1136 | .type = opts.type, | 1302 | .type = opts.type, |
| 1137 | .bind = opts.bind, | 1303 | .bind = opts.bind, |
| 1138 | .visibility = opts.visibility, | 1304 | .visibility = opts.visibility, |
| ... | @@ -1169,15 +1335,15 @@ fn navType( | ... | @@ -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 | if (std.mem.eql(u8, name, ".rodata") or | 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 | if (std.mem.eql(u8, name, ".text") or | 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 | if (std.mem.eql(u8, name, ".data") or | 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 | if (std.mem.eql(u8, name, ".tdata") or | 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 | return null; | 1347 | return null; |
| 1182 | } | 1348 | } |
| 1183 | fn navSection( | 1349 | fn navSection( |
| ... | @@ -1186,16 +1352,16 @@ fn navSection( | ... | @@ -1186,16 +1352,16 @@ fn navSection( |
| 1186 | nav_fr: @FieldType(@FieldType(InternPool.Nav, "status"), "fully_resolved"), | 1352 | nav_fr: @FieldType(@FieldType(InternPool.Nav, "status"), "fully_resolved"), |
| 1187 | ) Symbol.Index { | 1353 | ) Symbol.Index { |
| 1188 | if (nav_fr.@"linksection".toSlice(ip)) |@"linksection"| | 1354 | if (nav_fr.@"linksection".toSlice(ip)) |@"linksection"| |
| 1189 | if (namedSection(@"linksection")) |si| return si; | 1355 | if (elf.namedSection(@"linksection")) |si| return si; |
| 1190 | return switch (navType( | 1356 | return switch (navType( |
| 1191 | ip, | 1357 | ip, |
| 1192 | .{ .fully_resolved = nav_fr }, | 1358 | .{ .fully_resolved = nav_fr }, |
| 1193 | elf.base.comp.config.any_non_single_threaded, | 1359 | elf.base.comp.config.any_non_single_threaded, |
| 1194 | )) { | 1360 | )) { |
| 1195 | else => unreachable, | 1361 | else => unreachable, |
| 1196 | .FUNC => .text, | 1362 | .FUNC => elf.si.text, |
| 1197 | .OBJECT => .data, | 1363 | .OBJECT => elf.si.data, |
| 1198 | .TLS => .tdata, | 1364 | .TLS => elf.si.tdata, |
| 1199 | }; | 1365 | }; |
| 1200 | } | 1366 | } |
| 1201 | fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Node.NavMapIndex { | 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,6 +1381,7 @@ pub fn navSymbol(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) !Symbol. |
| 1215 | const nav = ip.getNav(nav_index); | 1381 | const nav = ip.getNav(nav_index); |
| 1216 | if (nav.getExtern(ip)) |@"extern"| return elf.globalSymbol(.{ | 1382 | if (nav.getExtern(ip)) |@"extern"| return elf.globalSymbol(.{ |
| 1217 | .name = @"extern".name.toSlice(ip), | 1383 | .name = @"extern".name.toSlice(ip), |
| | 1384 | .lib_name = @"extern".lib_name.toSlice(ip), |
| 1218 | .type = navType(ip, nav.status, elf.base.comp.config.any_non_single_threaded), | 1385 | .type = navType(ip, nav.status, elf.base.comp.config.any_non_single_threaded), |
| 1219 | .bind = switch (@"extern".linkage) { | 1386 | .bind = switch (@"extern".linkage) { |
| 1220 | .internal => .LOCAL, | 1387 | .internal => .LOCAL, |
| ... | @@ -1266,7 +1433,6 @@ pub fn loadInput(elf: *Elf, input: link.Input) (std.fs.File.Reader.SizeError || | ... | @@ -1266,7 +1433,6 @@ pub fn loadInput(elf: *Elf, input: link.Input) (std.fs.File.Reader.SizeError || |
| 1266 | const io = elf.base.comp.io; | 1433 | const io = elf.base.comp.io; |
| 1267 | var buf: [4096]u8 = undefined; | 1434 | var buf: [4096]u8 = undefined; |
| 1268 | switch (input) { | 1435 | switch (input) { |
| 1269 | else => {}, | | |
| 1270 | .object => |object| { | 1436 | .object => |object| { |
| 1271 | var fr = object.file.reader(io, &buf); | 1437 | var fr = object.file.reader(io, &buf); |
| 1272 | elf.loadObject(object.path, null, &fr, .{ | 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,6 +1450,16 @@ pub fn loadInput(elf: *Elf, input: link.Input) (std.fs.File.Reader.SizeError || |
| 1284 | else => |e| return e, | 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 | fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fr: *std.Io.File.Reader) !void { | 1465 | fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fr: *std.Io.File.Reader) !void { |
| ... | @@ -1382,7 +1558,7 @@ fn loadObject( | ... | @@ -1382,7 +1558,7 @@ fn loadObject( |
| 1382 | return diags.failParse(path, "bad machine", .{}); | 1558 | return diags.failParse(path, "bad machine", .{}); |
| 1383 | if (ehdr.shoff == 0 or ehdr.shnum <= 1) return; | 1559 | if (ehdr.shoff == 0 or ehdr.shnum <= 1) return; |
| 1384 | if (ehdr.shoff + ehdr.shentsize * ehdr.shnum > fl.size) | 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 | if (ehdr.shentsize < @sizeOf(ElfN.Shdr)) | 1562 | if (ehdr.shentsize < @sizeOf(ElfN.Shdr)) |
| 1387 | return diags.failParse(path, "unsupported shentsize", .{}); | 1563 | return diags.failParse(path, "unsupported shentsize", .{}); |
| 1388 | const sections = try gpa.alloc(struct { shdr: ElfN.Shdr, si: Symbol.Index }, ehdr.shnum); | 1564 | const sections = try gpa.alloc(struct { shdr: ElfN.Shdr, si: Symbol.Index }, ehdr.shnum); |
| ... | @@ -1397,7 +1573,7 @@ fn loadObject( | ... | @@ -1397,7 +1573,7 @@ fn loadObject( |
| 1397 | switch (section.shdr.type) { | 1573 | switch (section.shdr.type) { |
| 1398 | std.elf.SHT_NULL, std.elf.SHT_NOBITS => {}, | 1574 | std.elf.SHT_NULL, std.elf.SHT_NOBITS => {}, |
| 1399 | else => if (section.shdr.offset + section.shdr.size > fl.size) | 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 | const shstrtab = shstrtab: { | 1579 | const shstrtab = shstrtab: { |
| ... | @@ -1421,7 +1597,7 @@ fn loadObject( | ... | @@ -1421,7 +1597,7 @@ fn loadObject( |
| 1421 | std.elf.SHT_PROGBITS, std.elf.SHT_NOBITS => { | 1597 | std.elf.SHT_PROGBITS, std.elf.SHT_NOBITS => { |
| 1422 | if (section.shdr.name >= shstrtab.len) continue; | 1598 | if (section.shdr.name >= shstrtab.len) continue; |
| 1423 | const name = std.mem.sliceTo(shstrtab[section.shdr.name..], 0); | 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 | const ni = try elf.mf.addLastChildNode(gpa, parent_si.node(elf), .{ | 1601 | const ni = try elf.mf.addLastChildNode(gpa, parent_si.node(elf), .{ |
| 1426 | .size = section.shdr.size, | 1602 | .size = section.shdr.size, |
| 1427 | .alignment = .fromByteUnits(std.math.ceilPowerOfTwoAssert( | 1603 | .alignment = .fromByteUnits(std.math.ceilPowerOfTwoAssert( |
| ... | @@ -1598,6 +1774,84 @@ fn loadObject( | ... | @@ -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 | pub fn prelink(elf: *Elf, prog_node: std.Progress.Node) !void { | 1856 | pub fn prelink(elf: *Elf, prog_node: std.Progress.Node) !void { |
| 1603 | _ = prog_node; | 1857 | _ = prog_node; |
| ... | @@ -1624,6 +1878,66 @@ fn prelinkInner(elf: *Elf) !void { | ... | @@ -1624,6 +1878,66 @@ fn prelinkInner(elf: *Elf) !void { |
| 1624 | .member = null, | 1878 | .member = null, |
| 1625 | .si = si, | 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 | pub fn getNavVAddr( | 1943 | pub fn getNavVAddr( |
| ... | @@ -1649,13 +1963,7 @@ pub fn getVAddr(elf: *Elf, reloc_info: link.File.RelocInfo, target_si: Symbol.In | ... | @@ -1649,13 +1963,7 @@ pub fn getVAddr(elf: *Elf, reloc_info: link.File.RelocInfo, target_si: Symbol.In |
| 1649 | reloc_info.offset, | 1963 | reloc_info.offset, |
| 1650 | target_si, | 1964 | target_si, |
| 1651 | reloc_info.addend, | 1965 | reloc_info.addend, |
| 1652 | switch (elf.ehdrField(.machine)) { | 1966 | .absAddr(elf), |
| 1653 | else => unreachable, | | |
| 1654 | .AARCH64 => .{ .AARCH64 = .ABS64 }, | | |
| 1655 | .PPC64 => .{ .PPC64 = .ADDR64 }, | | |
| 1656 | .RISCV => .{ .RISCV = .@"64" }, | | |
| 1657 | .X86_64 => .{ .X86_64 = .@"64" }, | | |
| 1658 | }, | | |
| 1659 | ); | 1967 | ); |
| 1660 | return switch (elf.symPtr(target_si)) { | 1968 | return switch (elf.symPtr(target_si)) { |
| 1661 | inline else => |sym| elf.targetLoad(&sym.value), | 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,11 +1973,16 @@ pub fn getVAddr(elf: *Elf, reloc_info: link.File.RelocInfo, target_si: Symbol.In |
| 1665 | fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct { | 1973 | fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct { |
| 1666 | name: []const u8 = "", | 1974 | name: []const u8 = "", |
| 1667 | type: std.elf.Word = std.elf.SHT_NULL, | 1975 | type: std.elf.Word = std.elf.SHT_NULL, |
| 1668 | size: std.elf.Word = 0, | | |
| 1669 | flags: std.elf.SHF = .{}, | 1976 | flags: std.elf.SHF = .{}, |
| | 1977 | size: std.elf.Word = 0, |
| 1670 | addralign: std.mem.Alignment = .@"1", | 1978 | addralign: std.mem.Alignment = .@"1", |
| 1671 | entsize: std.elf.Word = 0, | 1979 | entsize: std.elf.Word = 0, |
| 1672 | }) !Symbol.Index { | 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 | const gpa = elf.base.comp.gpa; | 1986 | const gpa = elf.base.comp.gpa; |
| 1674 | try elf.nodes.ensureUnusedCapacity(gpa, 1); | 1987 | try elf.nodes.ensureUnusedCapacity(gpa, 1); |
| 1675 | try elf.symtab.ensureUnusedCapacity(gpa, 1); | 1988 | try elf.symtab.ensureUnusedCapacity(gpa, 1); |
| ... | @@ -1683,16 +1996,23 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct { | ... | @@ -1683,16 +1996,23 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct { |
| 1683 | break :shndx .{ shndx, elf.targetLoad(&ehdr.shentsize) * shnum }; | 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 | const ni = try elf.mf.addLastChildNode(gpa, segment_ni, .{ | 2000 | const ni = try elf.mf.addLastChildNode(gpa, segment_ni, .{ |
| 1688 | .alignment = opts.addralign, | 2001 | .alignment = opts.addralign, |
| 1689 | .size = opts.size, | 2002 | .size = opts.size, |
| 1690 | .moved = true, | 2003 | .resized = opts.size > 0, |
| 1691 | }); | 2004 | }); |
| 1692 | const si = elf.addSymbolAssumeCapacity(); | 2005 | const si = elf.addSymbolAssumeCapacity(); |
| 1693 | elf.nodes.appendAssumeCapacity(.{ .section = si }); | 2006 | elf.nodes.appendAssumeCapacity(.{ .section = si }); |
| 1694 | si.get(elf).ni = ni; | 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 | switch (elf.shdrSlice()) { | 2016 | switch (elf.shdrSlice()) { |
| 1697 | inline else => |shdr| { | 2017 | inline else => |shdr| { |
| 1698 | const sh = &shdr[shndx]; | 2018 | const sh = &shdr[shndx]; |
| ... | @@ -1700,8 +2020,8 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct { | ... | @@ -1700,8 +2020,8 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct { |
| 1700 | .name = shstrtab_entry, | 2020 | .name = shstrtab_entry, |
| 1701 | .type = opts.type, | 2021 | .type = opts.type, |
| 1702 | .flags = .{ .shf = opts.flags }, | 2022 | .flags = .{ .shf = opts.flags }, |
| 1703 | .addr = 0, | 2023 | .addr = @intCast(addr), |
| 1704 | .offset = 0, | 2024 | .offset = @intCast(offset), |
| 1705 | .size = opts.size, | 2025 | .size = opts.size, |
| 1706 | .link = 0, | 2026 | .link = 0, |
| 1707 | .info = 0, | 2027 | .info = 0, |
| ... | @@ -1733,7 +2053,7 @@ fn linkSections(elf: *Elf, si: Symbol.Index, link_si: Symbol.Index) !void { | ... | @@ -1733,7 +2053,7 @@ fn linkSections(elf: *Elf, si: Symbol.Index, link_si: Symbol.Index) !void { |
| 1733 | } | 2053 | } |
| 1734 | | 2054 | |
| 1735 | fn sectionName(elf: *Elf, si: Symbol.Index) [:0]const u8 { | 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 | inline else => |shndx, class| elf.targetLoad( | 2057 | inline else => |shndx, class| elf.targetLoad( |
| 1738 | &shndx[elf.targetLoad(&@field(elf.symPtr(si), @tagName(class)).shndx)].name, | 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,12 +2061,12 @@ fn sectionName(elf: *Elf, si: Symbol.Index) [:0]const u8 { |
| 1741 | return name[0..std.mem.indexOfScalar(u8, name, 0).? :0]; | 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 | if (key.len == 0) return 0; | 2065 | if (key.len == 0) return 0; |
| 1746 | return @field(elf, @tagName(section)).get( | 2066 | return @field(elf, @tagName(section)).get( |
| 1747 | elf.base.comp.gpa, | 2067 | elf.base.comp.gpa, |
| 1748 | &elf.mf, | 2068 | &elf.mf, |
| 1749 | @field(Symbol.Index, @tagName(section)).node(elf), | 2069 | @field(elf.si, @tagName(section)).node(elf), |
| 1750 | key, | 2070 | key, |
| 1751 | ); | 2071 | ); |
| 1752 | } | 2072 | } |
| ... | @@ -2144,7 +2464,7 @@ fn flushUav( | ... | @@ -2144,7 +2464,7 @@ fn flushUav( |
| 2144 | switch (sym.ni) { | 2464 | switch (sym.ni) { |
| 2145 | .none => { | 2465 | .none => { |
| 2146 | try elf.nodes.ensureUnusedCapacity(gpa, 1); | 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 | .alignment = uav_align.toStdMem(), | 2468 | .alignment = uav_align.toStdMem(), |
| 2149 | .moved = true, | 2469 | .moved = true, |
| 2150 | }); | 2470 | }); |
| ... | @@ -2256,9 +2576,9 @@ fn flushInputSection(elf: *Elf, isi: Node.InputSectionIndex) !void { | ... | @@ -2256,9 +2576,9 @@ fn flushInputSection(elf: *Elf, isi: Node.InputSectionIndex) !void { |
| 2256 | return error.EndOfStream; | 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 | switch (elf.getNode(ni)) { | 2580 | switch (elf.getNode(ni)) { |
| 2261 | .file => unreachable, | 2581 | else => unreachable, |
| 2262 | .ehdr => assert(ni.fileLocation(&elf.mf, false).offset == 0), | 2582 | .ehdr => assert(ni.fileLocation(&elf.mf, false).offset == 0), |
| 2263 | .shdr => switch (elf.ehdrPtr()) { | 2583 | .shdr => switch (elf.ehdrPtr()) { |
| 2264 | inline else => |ehdr| elf.targetStore( | 2584 | inline else => |ehdr| elf.targetStore( |
| ... | @@ -2266,32 +2586,61 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) !void { | ... | @@ -2266,32 +2586,61 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) !void { |
| 2266 | @intCast(ni.fileLocation(&elf.mf, false).offset), | 2586 | @intCast(ni.fileLocation(&elf.mf, false).offset), |
| 2267 | ), | 2587 | ), |
| 2268 | }, | 2588 | }, |
| 2269 | .segment => |phndx| switch (elf.phdrSlice()) { | 2589 | .segment => |phndx| { |
| 2270 | inline else => |phdr, class| { | 2590 | switch (elf.phdrSlice()) { |
| 2271 | const ph = &phdr[phndx]; | 2591 | inline else => |phdr| elf.targetStore( |
| 2272 | elf.targetStore(&ph.offset, @intCast(ni.fileLocation(&elf.mf, false).offset)); | 2592 | &phdr[phndx].offset, |
| 2273 | switch (elf.targetLoad(&ph.type)) { | 2593 | @intCast(ni.fileLocation(&elf.mf, false).offset), |
| 2274 | else => unreachable, | 2594 | ), |
| 2275 | std.elf.PT_NULL, std.elf.PT_LOAD => return, | 2595 | } |
| 2276 | std.elf.PT_DYNAMIC, std.elf.PT_INTERP => {}, | 2596 | var child_it = ni.children(&elf.mf); |
| 2277 | std.elf.PT_PHDR => @field(elf.ehdrPtr(), @tagName(class)).phoff = ph.offset, | 2597 | while (child_it.next()) |child_ni| try elf.flushFileOffset(child_ni); |
| 2278 | std.elf.PT_TLS => {}, | | |
| 2279 | } | | |
| 2280 | elf.targetStore(&ph.vaddr, @intCast(elf.computeNodeVAddr(ni))); | | |
| 2281 | ph.paddr = ph.vaddr; | | |
| 2282 | }, | | |
| 2283 | }, | 2598 | }, |
| 2284 | .section => |si| switch (elf.shdrSlice()) { | 2599 | .section => |si| switch (elf.shdrSlice()) { |
| 2285 | inline else => |shdr, class| { | 2600 | inline else => |shdr, class| elf.targetStore( |
| 2286 | const sym = @field(elf.symPtr(si), @tagName(class)); | 2601 | &shdr[elf.targetLoad(&@field(elf.symPtr(si), @tagName(class)).shndx)].offset, |
| 2287 | const sh = &shdr[elf.targetLoad(&sym.shndx)]; | 2602 | @intCast(ni.fileLocation(&elf.mf, false).offset), |
| 2288 | elf.targetStore(&sh.offset, @intCast(ni.fileLocation(&elf.mf, false).offset)); | 2603 | ), |
| 2289 | const flags = elf.targetLoad(&sh.flags).shf; | 2604 | }, |
| 2290 | if (flags.ALLOC) { | 2605 | } |
| 2291 | elf.targetStore(&sh.addr, @intCast(elf.computeNodeVAddr(ni))); | 2606 | } |
| 2292 | if (!flags.TLS) sym.value = sh.addr; | 2607 | |
| 2293 | } | 2608 | fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) !void { |
| 2294 | }, | 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 | .input_section => |isi| { | 2645 | .input_section => |isi| { |
| 2297 | const old_addr = switch (elf.symPtr(isi.symbol(elf))) { | 2646 | const old_addr = switch (elf.symPtr(isi.symbol(elf))) { |
| ... | @@ -2380,11 +2729,11 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) !void { | ... | @@ -2380,11 +2729,11 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) !void { |
| 2380 | else => unreachable, | 2729 | else => unreachable, |
| 2381 | std.elf.SHT_NULL => if (size > 0) elf.targetStore(&sh.type, std.elf.SHT_PROGBITS), | 2730 | std.elf.SHT_NULL => if (size > 0) elf.targetStore(&sh.type, std.elf.SHT_PROGBITS), |
| 2382 | std.elf.SHT_PROGBITS => if (size == 0) elf.targetStore(&sh.type, std.elf.SHT_NULL), | 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 | &sh.info, | 2733 | &sh.info, |
| 2385 | @intCast(@divExact(size, elf.targetLoad(&sh.entsize))), | 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 | }, |