╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭ gen_stubs.zig ────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭ find file ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ ╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │ │ │http│ ssh │ │ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
511 for (arches, 0..) |arch, i| { 512 log.info("symbol '{s}' size on {s}: {d}", .{ 513 name, @tagName(arch), multi_sym.size[i], 514 }); 515 } 516 //try stdout.print(".size {s}, {d}\n", .{ name, size }); 517 } 518 }, 519 else => unreachable, 520 } 521 522 switch (multi_sym.visib) { 523 .DEFAULT => {}, 524 .PROTECTED => try stdout.print(".protected {s}\n", .{name}), 525 .INTERNAL, .HIDDEN => unreachable, 526 } 527 528 try stdout.print("{s}:\n", .{name}); 529 } 530 531 switch (prev_pp_state) { 532 .all => {}, 533 .single, .multi, .family, .time32 => try stdout.writeAll("#endif\n"), 534 } 535 536 try stdout.flush(); 537 } 538 539 fn parseElf(parse: Parse, comptime is_64: bool, comptime endian: std.builtin.Endian) !void { 540 const arena = parse.arena; 541 const elf_bytes = parse.elf_bytes; 542 const header = parse.header; 543 const Sym = if (is_64) elf.Elf64_Sym else elf.Elf32_Sym; 544 const S = struct { 545 fn endianSwap(x: anytype) @TypeOf(x) { 546 if (endian != native_endian) { 547 return @byteSwap(x); 548 } else { 549 return x; 550 } 551 } 552 fn symbolAddrLessThan(_: void, lhs: Sym, rhs: Sym) bool { 553 return endianSwap(lhs.st_value) < endianSwap(rhs.st_value); 554 } 555 }; 556 // A little helper to do endian swapping. 557 const s = S.endianSwap; 558 559 // Obtain list of sections. 560 const Shdr = if (is_64) elf.Elf64_Shdr else elf.Elf32_Shdr; 561 const shdrs = mem.bytesAsSlice(Shdr, elf_bytes[header.shoff..])[0..header.shnum]; 562 563 // Obtain the section header string table. 564 const shstrtab_offset = s(shdrs[header.shstrndx].sh_offset); 565 log.debug("shstrtab is at offset {d}", .{shstrtab_offset}); 566 const shstrtab = elf_bytes[shstrtab_offset..]; 567 568 // Maps this ELF file's section header index to the multi arch section ArrayHashMap index. 569 const section_index_map = try arena.alloc(u16, shdrs.len); 570 571 // Find the offset of the dynamic symbol table. 572 var dynsym_index: u16 = 0; 573 for (shdrs, 0..) |shdr, i| { 574 const sh_name = try arena.dupe(u8, mem.sliceTo(shstrtab[s(shdr.sh_name)..], 0)); 575 log.debug("found section: {s}", .{sh_name}); 576 if (mem.eql(u8, sh_name, ".dynsym")) { 577 dynsym_index = @as(u16, @intCast(i)); 578 } 579 const gop = try parse.sections.getOrPut(arena, sh_name); 580 section_index_map[i] = @as(u16, @intCast(gop.index)); 581 } 582 if (dynsym_index == 0) @panic("did not find the .dynsym section"); 583 584 log.debug("found .dynsym section at index {d}", .{dynsym_index}); 585 586 // Read the dynamic symbols into a list. 587 const dyn_syms_off = s(shdrs[dynsym_index].sh_offset); 588 const dyn_syms_size = s(shdrs[dynsym_index].sh_size); 589 const dyn_syms = mem.bytesAsSlice(Sym, elf_bytes[dyn_syms_off..][0..dyn_syms_size]); 590 591 const dynstr_offset = s(shdrs[s(shdrs[dynsym_index].sh_link)].sh_offset); 592 const dynstr = elf_bytes[dynstr_offset..]; 593 594 // Sort the list by address, ascending. 595 // We need a copy to fix alignment. 596 const copied_dyn_syms = copy: { 597 const ptr = try arena.alloc(Sym, dyn_syms.len); 598 @memcpy(ptr, dyn_syms); 599 break :copy ptr; 600 }; 601 mem.sort(Sym, copied_dyn_syms, {}, S.symbolAddrLessThan); 602 603 for (copied_dyn_syms) |sym| { 604 const this_section = s(sym.st_shndx); 605 const name = try arena.dupe(u8, mem.sliceTo(dynstr[s(sym.st_name)..], 0)); 606 const ty = @as(u4, @truncate(sym.st_info)); 607 const binding = @as(u4, @truncate(sym.st_info >> 4)); 608 const visib = @as(elf.STV, @fromBackingInt(@intCast(@as(u3, @truncate(sym.st_other))))); 609 const size = s(sym.st_size); 610 611 if (size == 0) { 612 log.warn("{s}: symbol '{s}' has size 0", .{ @tagName(parse.arch), name }); 613 } 614 615 if (sym.st_shndx == elf.SHN_UNDEF) { 616 log.debug("{s}: skipping '{s}' due to it being undefined", .{ 617 @tagName(parse.arch), name, 618 }); 619 continue; 620 } 621 622 switch (binding) { 623 elf.STB_GLOBAL, elf.STB_WEAK => {}, 624 else => { 625 log.debug("{s}: skipping '{s}' due to it having binding '{d}'", .{ 626 @tagName(parse.arch), name, binding, 627 }); 628 continue; 629 }, 630 } 631 632 switch (ty) { 633 elf.STT_NOTYPE, elf.STT_FUNC, elf.STT_OBJECT => {}, 634 else => { 635 log.debug("{s}: skipping '{s}' due to it having type '{d}'", .{ 636 @tagName(parse.arch), name, ty, 637 }); 638 continue; 639 }, 640 } 641 642 switch (visib) { 643 .DEFAULT, .PROTECTED => {}, 644 .INTERNAL, .HIDDEN => { 645 log.debug("{s}: skipping '{s}' due to it having visibility '{s}'", .{ 646 @tagName(parse.arch), name, @tagName(visib), 647 }); 648 continue; 649 }, 650 } 651 652 const gop = try parse.sym_table.getOrPut(arena, name); 653 if (gop.found_existing) { 654 if (gop.value_ptr.section != section_index_map[this_section]) { 655 const sh_name = mem.sliceTo(shstrtab[s(shdrs[this_section].sh_name)..], 0); 656 fatal("symbol '{s}' in arch {s} is in section {s} but in arch {s} is in section {s}", .{ 657 name, 658 @tagName(parse.arch), 659 sh_name, 660 archSetName(gop.value_ptr.present), 661 parse.sections.keys()[gop.value_ptr.section], 662 }); 663 } 664 if (gop.value_ptr.ty != ty) blk: { 665 if (ty == elf.STT_NOTYPE) { 666 log.warn("symbol '{s}' in arch {s} has type {d} but in arch {s} has type {d}. going with the one that is not STT_NOTYPE", .{ 667 name, 668 @tagName(parse.arch), 669 ty, 670 archSetName(gop.value_ptr.present), 671 gop.value_ptr.ty, 672 }); 673 break :blk; 674 } 675 if (gop.value_ptr.ty == elf.STT_NOTYPE) { 676 log.warn("symbol '{s}' in arch {s} has type {d} but in arch {s} has type {d}. going with the one that is not STT_NOTYPE", .{ 677 name, 678 @tagName(parse.arch), 679 ty, 680 archSetName(gop.value_ptr.present), 681 gop.value_ptr.ty, 682 }); 683 gop.value_ptr.ty = ty; 684 break :blk; 685 } 686 fatal("symbol '{s}' in arch {s} has type {d} but in arch {s} has type {d}", .{ 687 name, 688 @tagName(parse.arch), 689 ty, 690 archSetName(gop.value_ptr.present), 691 gop.value_ptr.ty, 692 }); 693 } 694 if (gop.value_ptr.visib != visib) { 695 fatal("symbol '{s}' in arch {s} has visib {s} but in arch {s} has visib {s}", .{ 696 name, 697 @tagName(parse.arch), 698 @tagName(visib), 699 archSetName(gop.value_ptr.present), 700 @tagName(gop.value_ptr.visib), 701 }); 702 } 703 } else { 704 gop.value_ptr.* = .{ 705 .present = @splat(false), 706 .section = section_index_map[this_section], 707 .ty = ty, 708 .binding = @splat(0), 709 .visib = visib, 710 .size = @splat(0), 711 }; 712 } 713 gop.value_ptr.present[archIndex(parse.arch)] = true; 714 gop.value_ptr.size[archIndex(parse.arch)] = size; 715 gop.value_ptr.binding[archIndex(parse.arch)] = binding; 716 } 717 } 718 719 fn archIndex(arch: Arch) u8 { 720 return @backingInt(arch); 721 } 722 723 fn archSetName(arch_set: [arches.len]bool) []const u8 { 724 for (arches, arch_set) |arch, set_item| { 725 if (set_item) { 726 return @tagName(arch); 727 } 728 } 729 return "(none)"; 730 } 731 732 fn fatal(comptime format: []const u8, args: anytype) noreturn { 733 log.err(format, args); 734 std.process.exit(1); 735 } 736