| ... | ... | @@ -164,7 +164,26 @@ pub const Node = union(enum) { |
| 164 | 164 | } |
| 165 | 165 | }; |
| 166 | 166 | |
| 167 | | pub const Section = struct { si: Symbol.Index, rela_si: Symbol.Index }; |
| 167 | pub const Section = struct { |
| 168 | si: Symbol.Index, |
| 169 | rela_si: Symbol.Index, |
| 170 | rela_free: RelIndex, |
| 171 | |
| 172 | pub const RelIndex = enum(u32) { |
| 173 | none, |
| 174 | _, |
| 175 | |
| 176 | pub fn wrap(i: ?u32) RelIndex { |
| 177 | return @enumFromInt((i orelse return .none) + 1); |
| 178 | } |
| 179 | pub fn unwrap(ri: RelIndex) ?u32 { |
| 180 | return switch (ri) { |
| 181 | .none => null, |
| 182 | else => @intFromEnum(ri) - 1, |
| 183 | }; |
| 184 | } |
| 185 | }; |
| 186 | }; |
| 168 | 187 | |
| 169 | 188 | pub const StringTable = struct { |
| 170 | 189 | map: std.HashMapUnmanaged(u32, void, StringTable.Context, std.hash_map.default_max_load_percentage), |
| ... | ... | @@ -462,7 +481,7 @@ pub const Reloc = extern struct { |
| 462 | 481 | next: Reloc.Index, |
| 463 | 482 | loc: Symbol.Index, |
| 464 | 483 | target: Symbol.Index, |
| 465 | | rel_index: u32, |
| 484 | index: Section.RelIndex, |
| 466 | 485 | offset: u64, |
| 467 | 486 | addend: i64, |
| 468 | 487 | |
| ... | ... | @@ -472,6 +491,16 @@ pub const Reloc = extern struct { |
| 472 | 491 | RISCV: std.elf.R_RISCV, |
| 473 | 492 | PPC64: std.elf.R_PPC64, |
| 474 | 493 | |
| 494 | pub fn none(elf: *Elf) Reloc.Type { |
| 495 | return switch (elf.ehdrField(.machine)) { |
| 496 | else => unreachable, |
| 497 | .AARCH64 => .{ .AARCH64 = .NONE }, |
| 498 | .PPC64 => .{ .PPC64 = .NONE }, |
| 499 | .RISCV => .{ .RISCV = .NONE }, |
| 500 | .X86_64 => .{ .X86_64 = .NONE }, |
| 501 | }; |
| 502 | } |
| 503 | |
| 475 | 504 | pub fn absAddr(elf: *Elf) Reloc.Type { |
| 476 | 505 | return switch (elf.ehdrField(.machine)) { |
| 477 | 506 | else => unreachable, |
| ... | ... | @@ -481,12 +510,35 @@ pub const Reloc = extern struct { |
| 481 | 510 | .X86_64 => .{ .X86_64 = .@"64" }, |
| 482 | 511 | }; |
| 483 | 512 | } |
| 513 | |
| 484 | 514 | pub fn sizeAddr(elf: *Elf) Reloc.Type { |
| 485 | 515 | return switch (elf.ehdrField(.machine)) { |
| 486 | 516 | else => unreachable, |
| 487 | 517 | .X86_64 => .{ .X86_64 = .SIZE64 }, |
| 488 | 518 | }; |
| 489 | 519 | } |
| 520 | |
| 521 | pub fn wrap(int: u32, elf: *Elf) Reloc.Type { |
| 522 | return switch (elf.ehdrField(.machine)) { |
| 523 | else => unreachable, |
| 524 | inline .AARCH64, |
| 525 | .PPC64, |
| 526 | .RISCV, |
| 527 | .X86_64, |
| 528 | => |machine| @unionInit(Reloc.Type, @tagName(machine), @enumFromInt(int)), |
| 529 | }; |
| 530 | } |
| 531 | |
| 532 | pub fn unwrap(rt: Reloc.Type, elf: *Elf) u32 { |
| 533 | return switch (elf.ehdrField(.machine)) { |
| 534 | else => unreachable, |
| 535 | inline .AARCH64, |
| 536 | .PPC64, |
| 537 | .RISCV, |
| 538 | .X86_64, |
| 539 | => |machine| @intFromEnum(@field(rt, @tagName(machine))), |
| 540 | }; |
| 541 | } |
| 490 | 542 | }; |
| 491 | 543 | |
| 492 | 544 | pub const Index = enum(u32) { |
| ... | ... | @@ -590,6 +642,33 @@ pub const Reloc = extern struct { |
| 590 | 642 | .none => {}, |
| 591 | 643 | else => |next| next.get(elf).prev = reloc.prev, |
| 592 | 644 | } |
| 645 | switch (elf.ehdrField(.type)) { |
| 646 | .NONE, .CORE, _ => unreachable, |
| 647 | .REL => { |
| 648 | const sh = reloc.loc.shndx(elf).get(elf); |
| 649 | switch (elf.shdrPtr(sh.rela_si.shndx(elf))) { |
| 650 | inline else => |shdr, class| { |
| 651 | const Rela = class.ElfN().Rela; |
| 652 | const ent_size = elf.targetLoad(&shdr.entsize); |
| 653 | const start = ent_size * reloc.index.unwrap().?; |
| 654 | const rela_slice = sh.rela_si.node(elf).slice(&elf.mf); |
| 655 | const rela: *Rela = @ptrCast(@alignCast( |
| 656 | rela_slice[@intCast(start)..][0..@intCast(ent_size)], |
| 657 | )); |
| 658 | rela.* = .{ |
| 659 | .offset = @intFromEnum(sh.rela_free), |
| 660 | .info = .{ |
| 661 | .type = @intCast(Reloc.Type.none(elf).unwrap(elf)), |
| 662 | .sym = 0, |
| 663 | }, |
| 664 | .addend = 0, |
| 665 | }; |
| 666 | }, |
| 667 | } |
| 668 | sh.rela_free = reloc.index; |
| 669 | }, |
| 670 | .EXEC, .DYN => assert(reloc.index == .none), |
| 671 | } |
| 593 | 672 | reloc.* = undefined; |
| 594 | 673 | } |
| 595 | 674 | |
| ... | ... | @@ -1036,7 +1115,7 @@ fn initHeaders( |
| 1036 | 1115 | .entsize = 0, |
| 1037 | 1116 | }; |
| 1038 | 1117 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Shdr, sh_undef); |
| 1039 | | elf.shdrs.appendAssumeCapacity(.{ .si = .null, .rela_si = .null }); |
| 1118 | elf.shdrs.appendAssumeCapacity(.{ .si = .null, .rela_si = .null, .rela_free = .none }); |
| 1040 | 1119 | |
| 1041 | 1120 | try elf.symtab.ensureTotalCapacity(gpa, 1); |
| 1042 | 1121 | elf.symtab.addOneAssumeCapacity().* = .{ |
| ... | ... | @@ -1880,18 +1959,7 @@ fn loadObject( |
| 1880 | 1959 | rel.offset - loc_sec.shdr.addr, |
| 1881 | 1960 | target_si, |
| 1882 | 1961 | rel.addend, |
| 1883 | | switch (elf.ehdrField(.machine)) { |
| 1884 | | else => unreachable, |
| 1885 | | inline .AARCH64, |
| 1886 | | .PPC64, |
| 1887 | | .RISCV, |
| 1888 | | .X86_64, |
| 1889 | | => |machine| @unionInit( |
| 1890 | | Reloc.Type, |
| 1891 | | @tagName(machine), |
| 1892 | | @enumFromInt(rel.info.type), |
| 1893 | | ), |
| 1894 | | }, |
| 1962 | .wrap(rel.info.type, elf), |
| 1895 | 1963 | ); |
| 1896 | 1964 | } |
| 1897 | 1965 | }, |
| ... | ... | @@ -2156,7 +2224,7 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct { |
| 2156 | 2224 | }); |
| 2157 | 2225 | const si = elf.addSymbolAssumeCapacity(); |
| 2158 | 2226 | elf.nodes.appendAssumeCapacity(.{ .section = si }); |
| 2159 | | elf.shdrs.appendAssumeCapacity(.{ .si = si, .rela_si = .null }); |
| 2227 | elf.shdrs.appendAssumeCapacity(.{ .si = si, .rela_si = .null, .rela_free = .none }); |
| 2160 | 2228 | si.get(elf).ni = ni; |
| 2161 | 2229 | const addr = elf.computeNodeVAddr(ni); |
| 2162 | 2230 | const offset = ni.fileLocation(&elf.mf, false).offset; |
| ... | ... | @@ -2275,39 +2343,44 @@ pub fn addRelocAssumeCapacity( |
| 2275 | 2343 | .next = target.target_relocs, |
| 2276 | 2344 | .loc = loc_si, |
| 2277 | 2345 | .target = target_si, |
| 2278 | | .rel_index = switch (elf.ehdrField(.type)) { |
| 2346 | .index = index: switch (elf.ehdrField(.type)) { |
| 2279 | 2347 | .NONE, .CORE, _ => unreachable, |
| 2280 | | .REL => rel_index: { |
| 2281 | | const rela_si = loc_si.shndx(elf).get(elf).rela_si; |
| 2282 | | switch (elf.shdrPtr(rela_si.shndx(elf))) { |
| 2348 | .REL => { |
| 2349 | const sh = loc_si.shndx(elf).get(elf); |
| 2350 | switch (elf.shdrPtr(sh.rela_si.shndx(elf))) { |
| 2283 | 2351 | inline else => |shdr, class| { |
| 2284 | 2352 | const Rela = class.ElfN().Rela; |
| 2285 | | const old_size = elf.targetLoad(&shdr.size); |
| 2286 | 2353 | const ent_size = elf.targetLoad(&shdr.entsize); |
| 2287 | | const new_size = old_size + ent_size; |
| 2288 | | elf.targetStore(&shdr.size, @intCast(new_size)); |
| 2354 | const rela_slice = sh.rela_si.node(elf).slice(&elf.mf); |
| 2355 | const index: u32 = if (sh.rela_free.unwrap()) |index| alloc_index: { |
| 2356 | const rela: *Rela = @ptrCast(@alignCast( |
| 2357 | rela_slice[@intCast(ent_size * index)..][0..@intCast(ent_size)], |
| 2358 | )); |
| 2359 | sh.rela_free = @enumFromInt(rela.offset); |
| 2360 | break :alloc_index index; |
| 2361 | } else alloc_index: { |
| 2362 | const old_size = elf.targetLoad(&shdr.size); |
| 2363 | const new_size = old_size + ent_size; |
| 2364 | elf.targetStore(&shdr.size, @intCast(new_size)); |
| 2365 | break :alloc_index @intCast(@divExact(old_size, ent_size)); |
| 2366 | }; |
| 2289 | 2367 | const rela: *Rela = @ptrCast(@alignCast( |
| 2290 | | rela_si.node(elf).slice(&elf.mf)[@intCast(old_size)..@intCast(new_size)], |
| 2368 | rela_slice[@intCast(ent_size * index)..][0..@intCast(ent_size)], |
| 2291 | 2369 | )); |
| 2292 | 2370 | rela.* = .{ |
| 2293 | 2371 | .offset = @intCast(offset), |
| 2294 | 2372 | .info = .{ |
| 2295 | | .type = switch (elf.ehdrField(.machine)) { |
| 2296 | | else => |machine| @panic(@tagName(machine)), |
| 2297 | | inline .X86_64, .AARCH64, .RISCV, .PPC64 => |machine| @intCast( |
| 2298 | | @intFromEnum(@field(@"type", @tagName(machine))), |
| 2299 | | ), |
| 2300 | | }, |
| 2373 | .type = @intCast(@"type".unwrap(elf)), |
| 2301 | 2374 | .sym = @intCast(@intFromEnum(target_si)), |
| 2302 | 2375 | }, |
| 2303 | 2376 | .addend = @intCast(addend), |
| 2304 | 2377 | }; |
| 2305 | 2378 | if (elf.targetEndian() != native_endian) std.mem.byteSwapAllFields(Rela, rela); |
| 2306 | | break :rel_index @intCast(@divExact(old_size, ent_size)); |
| 2379 | break :index .wrap(index); |
| 2307 | 2380 | }, |
| 2308 | 2381 | } |
| 2309 | 2382 | }, |
| 2310 | | .EXEC, .DYN => 0, |
| 2383 | .EXEC, .DYN => .none, |
| 2311 | 2384 | }, |
| 2312 | 2385 | .offset = offset, |
| 2313 | 2386 | .addend = addend, |