Merge pull request #25819 from jacobly0/elfv2-emit-obj

This commit is contained in:
Jacob Young 2025-11-10 00:10:17 -05:00 committed by GitHub
commit f3309a96a7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 976 additions and 579 deletions

View File

@ -3971,7 +3971,7 @@ pub const dl_phdr_info = switch (native_os) {
/// Module name. /// Module name.
name: ?[*:0]const u8, name: ?[*:0]const u8,
/// Pointer to module's phdr. /// Pointer to module's phdr.
phdr: [*]std.elf.Phdr, phdr: [*]std.elf.ElfN.Phdr,
/// Number of entries in phdr. /// Number of entries in phdr.
phnum: u16, phnum: u16,
/// Total number of loads. /// Total number of loads.
@ -3984,7 +3984,7 @@ pub const dl_phdr_info = switch (native_os) {
.illumos => extern struct { .illumos => extern struct {
addr: std.elf.Addr, addr: std.elf.Addr,
name: ?[*:0]const u8, name: ?[*:0]const u8,
phdr: [*]std.elf.Phdr, phdr: [*]std.elf.ElfN.Phdr,
phnum: std.elf.Half, phnum: std.elf.Half,
/// Incremented when a new object is mapped into the process. /// Incremented when a new object is mapped into the process.
adds: u64, adds: u64,
@ -3995,7 +3995,7 @@ pub const dl_phdr_info = switch (native_os) {
.openbsd, .haiku, .dragonfly, .netbsd, .serenity => extern struct { .openbsd, .haiku, .dragonfly, .netbsd, .serenity => extern struct {
addr: usize, addr: usize,
name: ?[*:0]const u8, name: ?[*:0]const u8,
phdr: [*]std.elf.Phdr, phdr: [*]std.elf.ElfN.Phdr,
phnum: std.elf.Half, phnum: std.elf.Half,
}, },
else => void, else => void,

View File

@ -441,11 +441,11 @@ const DlIterContext = struct {
// Populate `build_id` and `gnu_eh_frame` // Populate `build_id` and `gnu_eh_frame`
for (info.phdr[0..info.phnum]) |phdr| { for (info.phdr[0..info.phnum]) |phdr| {
switch (phdr.p_type) { switch (phdr.type) {
std.elf.PT_NOTE => { .NOTE => {
// Look for .note.gnu.build-id // Look for .note.gnu.build-id
const segment_ptr: [*]const u8 = @ptrFromInt(info.addr + phdr.p_vaddr); const segment_ptr: [*]const u8 = @ptrFromInt(info.addr + phdr.vaddr);
var r: std.Io.Reader = .fixed(segment_ptr[0..phdr.p_memsz]); var r: std.Io.Reader = .fixed(segment_ptr[0..phdr.memsz]);
const name_size = r.takeInt(u32, native_endian) catch continue; const name_size = r.takeInt(u32, native_endian) catch continue;
const desc_size = r.takeInt(u32, native_endian) catch continue; const desc_size = r.takeInt(u32, native_endian) catch continue;
const note_type = r.takeInt(u32, native_endian) catch continue; const note_type = r.takeInt(u32, native_endian) catch continue;
@ -455,9 +455,9 @@ const DlIterContext = struct {
const desc = r.take(desc_size) catch continue; const desc = r.take(desc_size) catch continue;
build_id = desc; build_id = desc;
}, },
std.elf.PT_GNU_EH_FRAME => { std.elf.PT.GNU_EH_FRAME => {
const segment_ptr: [*]const u8 = @ptrFromInt(info.addr + phdr.p_vaddr); const segment_ptr: [*]const u8 = @ptrFromInt(info.addr + phdr.vaddr);
gnu_eh_frame = segment_ptr[0..phdr.p_memsz]; gnu_eh_frame = segment_ptr[0..phdr.memsz];
}, },
else => {}, else => {},
} }
@ -478,11 +478,11 @@ const DlIterContext = struct {
}); });
for (info.phdr[0..info.phnum]) |phdr| { for (info.phdr[0..info.phnum]) |phdr| {
if (phdr.p_type != std.elf.PT_LOAD) continue; if (phdr.type != .LOAD) continue;
try context.si.ranges.append(gpa, .{ try context.si.ranges.append(gpa, .{
// Overflowing addition handles VSDOs having p_vaddr = 0xffffffffff700000 // Overflowing addition handles VSDOs having p_vaddr = 0xffffffffff700000
.start = info.addr +% phdr.p_vaddr, .start = info.addr +% phdr.vaddr,
.len = phdr.p_memsz, .len = phdr.memsz,
.module_index = module_index, .module_index = module_index,
}); });
} }

View File

@ -92,8 +92,7 @@ pub fn get_DYNAMIC() ?[*]const elf.Dyn {
}); });
} }
pub fn linkmap_iterator(phdrs: []const elf.Phdr) error{InvalidExe}!LinkMap.Iterator { pub fn linkmap_iterator() error{InvalidExe}!LinkMap.Iterator {
_ = phdrs;
const _DYNAMIC = get_DYNAMIC() orelse { const _DYNAMIC = get_DYNAMIC() orelse {
// No PT_DYNAMIC means this is a statically-linked non-PIE program. // No PT_DYNAMIC means this is a statically-linked non-PIE program.
return .{ .current = null }; return .{ .current = null };

View File

@ -50,6 +50,7 @@ pub const AT_L2_CACHESIZE = 44;
pub const AT_L2_CACHEGEOMETRY = 45; pub const AT_L2_CACHEGEOMETRY = 45;
pub const AT_L3_CACHESIZE = 46; pub const AT_L3_CACHESIZE = 46;
pub const AT_L3_CACHEGEOMETRY = 47; pub const AT_L3_CACHEGEOMETRY = 47;
pub const AT_MINSIGSTKSZ = 51;
pub const DT_NULL = 0; pub const DT_NULL = 0;
pub const DT_NEEDED = 1; pub const DT_NEEDED = 1;
@ -286,105 +287,111 @@ pub const VER_FLG_BASE = 1;
/// Weak version identifier /// Weak version identifier
pub const VER_FLG_WEAK = 2; pub const VER_FLG_WEAK = 2;
/// Program header table entry unused /// Deprecated, use `@intFromEnum(std.elf.PT.NULL)`
pub const PT_NULL = 0; pub const PT_NULL = @intFromEnum(std.elf.PT.NULL);
/// Loadable program segment /// Deprecated, use `@intFromEnum(std.elf.PT.LOAD)`
pub const PT_LOAD = 1; pub const PT_LOAD = @intFromEnum(std.elf.PT.LOAD);
/// Dynamic linking information /// Deprecated, use `@intFromEnum(std.elf.PT.DYNAMIC)`
pub const PT_DYNAMIC = 2; pub const PT_DYNAMIC = @intFromEnum(std.elf.PT.DYNAMIC);
/// Program interpreter /// Deprecated, use `@intFromEnum(std.elf.PT.INTERP)`
pub const PT_INTERP = 3; pub const PT_INTERP = @intFromEnum(std.elf.PT.INTERP);
/// Auxiliary information /// Deprecated, use `@intFromEnum(std.elf.PT.NOTE)`
pub const PT_NOTE = 4; pub const PT_NOTE = @intFromEnum(std.elf.PT.NOTE);
/// Reserved /// Deprecated, use `@intFromEnum(std.elf.PT.SHLIB)`
pub const PT_SHLIB = 5; pub const PT_SHLIB = @intFromEnum(std.elf.PT.SHLIB);
/// Entry for header table itself /// Deprecated, use `@intFromEnum(std.elf.PT.PHDR)`
pub const PT_PHDR = 6; pub const PT_PHDR = @intFromEnum(std.elf.PT.PHDR);
/// Thread-local storage segment /// Deprecated, use `@intFromEnum(std.elf.PT.TLS)`
pub const PT_TLS = 7; pub const PT_TLS = @intFromEnum(std.elf.PT.TLS);
/// Number of defined types /// Deprecated, use `std.elf.PT.NUM`.
pub const PT_NUM = 8; pub const PT_NUM = PT.NUM;
/// Start of OS-specific /// Deprecated, use `@intFromEnum(std.elf.PT.LOOS)`
pub const PT_LOOS = 0x60000000; pub const PT_LOOS = @intFromEnum(std.elf.PT.LOOS);
/// GCC .eh_frame_hdr segment /// Deprecated, use `@intFromEnum(std.elf.PT.GNU_EH_FRAME)`
pub const PT_GNU_EH_FRAME = 0x6474e550; pub const PT_GNU_EH_FRAME = @intFromEnum(std.elf.PT.GNU_EH_FRAME);
/// Indicates stack executability /// Deprecated, use `@intFromEnum(std.elf.PT.GNU_STACK)`
pub const PT_GNU_STACK = 0x6474e551; pub const PT_GNU_STACK = @intFromEnum(std.elf.PT.GNU_STACK);
/// Read-only after relocation /// Deprecated, use `@intFromEnum(std.elf.PT.GNU_RELRO)`
pub const PT_GNU_RELRO = 0x6474e552; pub const PT_GNU_RELRO = @intFromEnum(std.elf.PT.GNU_RELRO);
pub const PT_LOSUNW = 0x6ffffffa; /// Deprecated, use `@intFromEnum(std.elf.PT.LOSUNW)`
/// Sun specific segment pub const PT_LOSUNW = @intFromEnum(std.elf.PT.LOSUNW);
pub const PT_SUNWBSS = 0x6ffffffa; /// Deprecated, use `@intFromEnum(std.elf.PT.SUNWBSS)`
/// Stack segment pub const PT_SUNWBSS = @intFromEnum(std.elf.PT.SUNWBSS);
pub const PT_SUNWSTACK = 0x6ffffffb; /// Deprecated, use `@intFromEnum(std.elf.PT.SUNWSTACK)`
pub const PT_HISUNW = 0x6fffffff; pub const PT_SUNWSTACK = @intFromEnum(std.elf.PT.SUNWSTACK);
/// End of OS-specific /// Deprecated, use `@intFromEnum(std.elf.PT.HISUNW)`
pub const PT_HIOS = 0x6fffffff; pub const PT_HISUNW = @intFromEnum(std.elf.PT.HISUNW);
/// Start of processor-specific /// Deprecated, use `@intFromEnum(std.elf.PT.HIOS)`
pub const PT_LOPROC = 0x70000000; pub const PT_HIOS = @intFromEnum(std.elf.PT.HIOS);
/// End of processor-specific /// Deprecated, use `@intFromEnum(std.elf.PT.LOPROC)`
pub const PT_HIPROC = 0x7fffffff; pub const PT_LOPROC = @intFromEnum(std.elf.PT.LOPROC);
/// Deprecated, use `@intFromEnum(std.elf.PT.HIPROC)`
pub const PT_HIPROC = @intFromEnum(std.elf.PT.HIPROC);
pub const PN_XNUM = 0xffff; pub const PN_XNUM = 0xffff;
/// Section header table entry unused /// Deprecated, use `@intFromEnum(std.elf.SHT.NULL)`
pub const SHT_NULL = 0; pub const SHT_NULL = @intFromEnum(std.elf.SHT.NULL);
/// Program data /// Deprecated, use `@intFromEnum(std.elf.SHT.PROGBITS)`
pub const SHT_PROGBITS = 1; pub const SHT_PROGBITS = @intFromEnum(std.elf.SHT.PROGBITS);
/// Symbol table /// Deprecated, use `@intFromEnum(std.elf.SHT.SYMTAB)`
pub const SHT_SYMTAB = 2; pub const SHT_SYMTAB = @intFromEnum(std.elf.SHT.SYMTAB);
/// String table /// Deprecated, use `@intFromEnum(std.elf.SHT.STRTAB)`
pub const SHT_STRTAB = 3; pub const SHT_STRTAB = @intFromEnum(std.elf.SHT.STRTAB);
/// Relocation entries with addends /// Deprecated, use `@intFromEnum(std.elf.SHT.RELA)`
pub const SHT_RELA = 4; pub const SHT_RELA = @intFromEnum(std.elf.SHT.RELA);
/// Symbol hash table /// Deprecated, use `@intFromEnum(std.elf.SHT.HASH)`
pub const SHT_HASH = 5; pub const SHT_HASH = @intFromEnum(std.elf.SHT.HASH);
/// Dynamic linking information /// Deprecated, use `@intFromEnum(std.elf.SHT.DYNAMIC)`
pub const SHT_DYNAMIC = 6; pub const SHT_DYNAMIC = @intFromEnum(std.elf.SHT.DYNAMIC);
/// Notes /// Deprecated, use `@intFromEnum(std.elf.SHT.NOTE)`
pub const SHT_NOTE = 7; pub const SHT_NOTE = @intFromEnum(std.elf.SHT.NOTE);
/// Program space with no data (bss) /// Deprecated, use `@intFromEnum(std.elf.SHT.NOBITS)`
pub const SHT_NOBITS = 8; pub const SHT_NOBITS = @intFromEnum(std.elf.SHT.NOBITS);
/// Relocation entries, no addends /// Deprecated, use `@intFromEnum(std.elf.SHT.REL)`
pub const SHT_REL = 9; pub const SHT_REL = @intFromEnum(std.elf.SHT.REL);
/// Reserved /// Deprecated, use `@intFromEnum(std.elf.SHT.SHLIB)`
pub const SHT_SHLIB = 10; pub const SHT_SHLIB = @intFromEnum(std.elf.SHT.SHLIB);
/// Dynamic linker symbol table /// Deprecated, use `@intFromEnum(std.elf.SHT.DYNSYM)`
pub const SHT_DYNSYM = 11; pub const SHT_DYNSYM = @intFromEnum(std.elf.SHT.DYNSYM);
/// Array of constructors /// Deprecated, use `@intFromEnum(std.elf.SHT.INIT_ARRAY)`
pub const SHT_INIT_ARRAY = 14; pub const SHT_INIT_ARRAY = @intFromEnum(std.elf.SHT.INIT_ARRAY);
/// Array of destructors /// Deprecated, use `@intFromEnum(std.elf.SHT.FINI_ARRAY)`
pub const SHT_FINI_ARRAY = 15; pub const SHT_FINI_ARRAY = @intFromEnum(std.elf.SHT.FINI_ARRAY);
/// Array of pre-constructors /// Deprecated, use `@intFromEnum(std.elf.SHT.PREINIT_ARRAY)`
pub const SHT_PREINIT_ARRAY = 16; pub const SHT_PREINIT_ARRAY = @intFromEnum(std.elf.SHT.PREINIT_ARRAY);
/// Section group /// Deprecated, use `@intFromEnum(std.elf.SHT.GROUP)`
pub const SHT_GROUP = 17; pub const SHT_GROUP = @intFromEnum(std.elf.SHT.GROUP);
/// Extended section indices /// Deprecated, use `@intFromEnum(std.elf.SHT.SYMTAB_SHNDX)`
pub const SHT_SYMTAB_SHNDX = 18; pub const SHT_SYMTAB_SHNDX = @intFromEnum(std.elf.SHT.SYMTAB_SHNDX);
/// Start of OS-specific /// Deprecated, use `@intFromEnum(std.elf.SHT.RELR)`
pub const SHT_LOOS = 0x60000000; pub const SHT_RELR = @intFromEnum(std.elf.SHT.RELR);
/// LLVM address-significance table /// Deprecated, use `std.elf.SHT.NUM`.
pub const SHT_LLVM_ADDRSIG = 0x6fff4c03; pub const SHT_NUM = SHT.NUM;
/// GNU hash table /// Deprecated, use `@intFromEnum(std.elf.SHT.LOOS)`
pub const SHT_GNU_HASH = 0x6ffffff6; pub const SHT_LOOS = @intFromEnum(std.elf.SHT.LOOS);
/// GNU version definition table /// Deprecated, use `@intFromEnum(std.elf.SHT.LLVM_ADDRSIG)`
pub const SHT_GNU_VERDEF = 0x6ffffffd; pub const SHT_LLVM_ADDRSIG = @intFromEnum(std.elf.SHT.LLVM_ADDRSIG);
/// GNU needed versions table /// Deprecated, use `@intFromEnum(std.elf.SHT.GNU_HASH)`
pub const SHT_GNU_VERNEED = 0x6ffffffe; pub const SHT_GNU_HASH = @intFromEnum(std.elf.SHT.GNU_HASH);
/// GNU symbol version table /// Deprecated, use `@intFromEnum(std.elf.SHT.GNU_VERDEF)`
pub const SHT_GNU_VERSYM = 0x6fffffff; pub const SHT_GNU_VERDEF = @intFromEnum(std.elf.SHT.GNU_VERDEF);
/// End of OS-specific /// Deprecated, use `@intFromEnum(std.elf.SHT.GNU_VERNEED)`
pub const SHT_HIOS = 0x6fffffff; pub const SHT_GNU_VERNEED = @intFromEnum(std.elf.SHT.GNU_VERNEED);
/// Start of processor-specific /// Deprecated, use `@intFromEnum(std.elf.SHT.GNU_VERSYM)`
pub const SHT_LOPROC = 0x70000000; pub const SHT_GNU_VERSYM = @intFromEnum(std.elf.SHT.GNU_VERSYM);
/// Unwind information /// Deprecated, use `@intFromEnum(std.elf.SHT.HIOS)`
pub const SHT_X86_64_UNWIND = 0x70000001; pub const SHT_HIOS = @intFromEnum(std.elf.SHT.HIOS);
/// End of processor-specific /// Deprecated, use `@intFromEnum(std.elf.SHT.LOPROC)`
pub const SHT_HIPROC = 0x7fffffff; pub const SHT_LOPROC = @intFromEnum(std.elf.SHT.LOPROC);
/// Start of application-specific /// Deprecated, use `@intFromEnum(std.elf.SHT.X86_64_UNWIND)`
pub const SHT_LOUSER = 0x80000000; pub const SHT_X86_64_UNWIND = @intFromEnum(std.elf.SHT.X86_64_UNWIND);
/// End of application-specific /// Deprecated, use `@intFromEnum(std.elf.SHT.HIPROC)`
pub const SHT_HIUSER = 0xffffffff; pub const SHT_HIPROC = @intFromEnum(std.elf.SHT.HIPROC);
/// Deprecated, use `@intFromEnum(std.elf.SHT.LOUSER)`
pub const SHT_LOUSER = @intFromEnum(std.elf.SHT.LOUSER);
/// Deprecated, use `@intFromEnum(std.elf.SHT.HIUSER)`
pub const SHT_HIUSER = @intFromEnum(std.elf.SHT.HIUSER);
// Note type for .note.gnu.build_id // Note type for .note.gnu.build_id
pub const NT_GNU_BUILD_ID = 3; pub const NT_GNU_BUILD_ID = 3;
@ -454,6 +461,127 @@ pub const STT_ARM_TFUNC = @intFromEnum(STT.ARM_TFUNC);
/// Deprecated, use `@intFromEnum(std.elf.STT.ARM_16BIT)` /// Deprecated, use `@intFromEnum(std.elf.STT.ARM_16BIT)`
pub const STT_ARM_16BIT = @intFromEnum(STT.ARM_16BIT); pub const STT_ARM_16BIT = @intFromEnum(STT.ARM_16BIT);
pub const PT = enum(Word) {
/// Program header table entry unused
NULL = 0,
/// Loadable program segment
LOAD = 1,
/// Dynamic linking information
DYNAMIC = 2,
/// Program interpreter
INTERP = 3,
/// Auxiliary information
NOTE = 4,
/// Reserved
SHLIB = 5,
/// Entry for header table itself
PHDR = 6,
/// Thread-local storage segment
TLS = 7,
_,
/// Number of defined types
pub const NUM = @typeInfo(PT).@"enum".fields.len;
/// Start of OS-specific
pub const LOOS: PT = @enumFromInt(0x60000000);
/// End of OS-specific
pub const HIOS: PT = @enumFromInt(0x6fffffff);
/// GCC .eh_frame_hdr segment
pub const GNU_EH_FRAME: PT = @enumFromInt(0x6474e550);
/// Indicates stack executability
pub const GNU_STACK: PT = @enumFromInt(0x6474e551);
/// Read-only after relocation
pub const GNU_RELRO: PT = @enumFromInt(0x6474e552);
pub const LOSUNW: PT = @enumFromInt(0x6ffffffa);
pub const HISUNW: PT = @enumFromInt(0x6fffffff);
/// Sun specific segment
pub const SUNWBSS: PT = @enumFromInt(0x6ffffffa);
/// Stack segment
pub const SUNWSTACK: PT = @enumFromInt(0x6ffffffb);
/// Start of processor-specific
pub const LOPROC: PT = @enumFromInt(0x70000000);
/// End of processor-specific
pub const HIPROC: PT = @enumFromInt(0x7fffffff);
};
pub const SHT = enum(Word) {
/// Section header table entry unused
NULL = 0,
/// Program data
PROGBITS = 1,
/// Symbol table
SYMTAB = 2,
/// String table
STRTAB = 3,
/// Relocation entries with addends
RELA = 4,
/// Symbol hash table
HASH = 5,
/// Dynamic linking information
DYNAMIC = 6,
/// Notes
NOTE = 7,
/// Program space with no data (bss)
NOBITS = 8,
/// Relocation entries, no addends
REL = 9,
/// Reserved
SHLIB = 10,
/// Dynamic linker symbol table
DYNSYM = 11,
/// Array of constructors
INIT_ARRAY = 14,
/// Array of destructors
FINI_ARRAY = 15,
/// Array of pre-constructors
PREINIT_ARRAY = 16,
/// Section group
GROUP = 17,
/// Extended section indices
SYMTAB_SHNDX = 18,
/// RELR relative relocations
RELR = 19,
_,
/// Number of defined types
pub const NUM = @typeInfo(SHT).@"enum".fields.len;
/// Start of OS-specific
pub const LOOS: SHT = @enumFromInt(0x60000000);
/// End of OS-specific
pub const HIOS: SHT = @enumFromInt(0x6fffffff);
/// LLVM address-significance table
pub const LLVM_ADDRSIG: SHT = @enumFromInt(0x6fff4c03);
/// GNU hash table
pub const GNU_HASH: SHT = @enumFromInt(0x6ffffff6);
/// GNU version definition table
pub const GNU_VERDEF: SHT = @enumFromInt(0x6ffffffd);
/// GNU needed versions table
pub const GNU_VERNEED: SHT = @enumFromInt(0x6ffffffe);
/// GNU symbol version table
pub const GNU_VERSYM: SHT = @enumFromInt(0x6fffffff);
/// Start of processor-specific
pub const LOPROC: SHT = @enumFromInt(0x70000000);
/// End of processor-specific
pub const HIPROC: SHT = @enumFromInt(0x7fffffff);
/// Unwind information
pub const X86_64_UNWIND: SHT = @enumFromInt(0x70000001);
/// Start of application-specific
pub const LOUSER: SHT = @enumFromInt(0x80000000);
/// End of application-specific
pub const HIUSER: SHT = @enumFromInt(0xffffffff);
};
pub const STB = enum(u4) { pub const STB = enum(u4) {
/// Local symbol /// Local symbol
LOCAL = 0, LOCAL = 0,
@ -899,7 +1027,7 @@ pub const Elf32 = struct {
shstrndx: Half, shstrndx: Half,
}; };
pub const Phdr = extern struct { pub const Phdr = extern struct {
type: Word, type: PT,
offset: Elf32.Off, offset: Elf32.Off,
vaddr: Elf32.Addr, vaddr: Elf32.Addr,
paddr: Elf32.Addr, paddr: Elf32.Addr,
@ -910,7 +1038,7 @@ pub const Elf32 = struct {
}; };
pub const Shdr = extern struct { pub const Shdr = extern struct {
name: Word, name: Word,
type: Word, type: SHT,
flags: packed struct { shf: SHF }, flags: packed struct { shf: SHF },
addr: Elf32.Addr, addr: Elf32.Addr,
offset: Elf32.Off, offset: Elf32.Off,
@ -989,7 +1117,7 @@ pub const Elf64 = struct {
shstrndx: Half, shstrndx: Half,
}; };
pub const Phdr = extern struct { pub const Phdr = extern struct {
type: Word, type: PT,
flags: PF, flags: PF,
offset: Elf64.Off, offset: Elf64.Off,
vaddr: Elf64.Addr, vaddr: Elf64.Addr,
@ -1000,7 +1128,7 @@ pub const Elf64 = struct {
}; };
pub const Shdr = extern struct { pub const Shdr = extern struct {
name: Word, name: Word,
type: Word, type: SHT,
flags: packed struct { shf: SHF, unused: Word = 0 }, flags: packed struct { shf: SHF, unused: Word = 0 },
addr: Elf64.Addr, addr: Elf64.Addr,
offset: Elf64.Off, offset: Elf64.Off,

View File

@ -6101,7 +6101,7 @@ pub const dirent64 = extern struct {
pub const dl_phdr_info = extern struct { pub const dl_phdr_info = extern struct {
addr: usize, addr: usize,
name: ?[*:0]const u8, name: ?[*:0]const u8,
phdr: [*]std.elf.Phdr, phdr: [*]std.elf.ElfN.Phdr,
phnum: u16, phnum: u16,
}; };

View File

@ -5048,6 +5048,13 @@ pub fn nanosleep(seconds: u64, nanoseconds: u64) void {
} }
} }
pub fn getSelfPhdrs() []std.elf.ElfN.Phdr {
const getauxval = if (builtin.link_libc) std.c.getauxval else std.os.linux.getauxval;
assert(getauxval(std.elf.AT_PHENT) == @sizeOf(std.elf.ElfN.Phdr));
const phdrs: [*]std.elf.ElfN.Phdr = @ptrFromInt(getauxval(std.elf.AT_PHDR));
return phdrs[0..getauxval(std.elf.AT_PHNUM)];
}
pub fn dl_iterate_phdr( pub fn dl_iterate_phdr(
context: anytype, context: anytype,
comptime Error: type, comptime Error: type,
@ -5075,34 +5082,24 @@ pub fn dl_iterate_phdr(
} }
} }
const elf_base = std.process.getBaseAddress(); var it = dl.linkmap_iterator() catch unreachable;
const ehdr: *elf.Ehdr = @ptrFromInt(elf_base);
// Make sure the base address points to an ELF image.
assert(mem.eql(u8, ehdr.e_ident[0..4], elf.MAGIC));
const n_phdr = ehdr.e_phnum;
const phdrs = (@as([*]elf.Phdr, @ptrFromInt(elf_base + ehdr.e_phoff)))[0..n_phdr];
var it = dl.linkmap_iterator(phdrs) catch unreachable;
// The executable has no dynamic link segment, create a single entry for // The executable has no dynamic link segment, create a single entry for
// the whole ELF image. // the whole ELF image.
if (it.end()) { if (it.end()) {
// Find the base address for the ELF image, if this is a PIE the value const getauxval = if (builtin.link_libc) std.c.getauxval else std.os.linux.getauxval;
// is non-zero. const phdrs = getSelfPhdrs();
const base_address = for (phdrs) |*phdr| { var info: dl_phdr_info = .{
if (phdr.p_type == elf.PT_PHDR) { .addr = for (phdrs) |phdr| switch (phdr.type) {
break @intFromPtr(phdrs.ptr) - phdr.p_vaddr; .PHDR => break @intFromPtr(phdrs.ptr) - phdr.vaddr,
// We could try computing the difference between _DYNAMIC and else => {},
// the p_vaddr of the PT_DYNAMIC section, but using the phdr is } else unreachable,
// good enough (Is it?). .name = switch (getauxval(std.elf.AT_EXECFN)) {
} 0 => "/proc/self/exe",
} else unreachable; else => |name| @ptrFromInt(name),
},
var info = dl_phdr_info{
.addr = base_address,
.name = "/proc/self/exe",
.phdr = phdrs.ptr, .phdr = phdrs.ptr,
.phnum = ehdr.e_phnum, .phnum = @intCast(phdrs.len),
}; };
return callback(&info, @sizeOf(dl_phdr_info), context); return callback(&info, @sizeOf(dl_phdr_info), context);
@ -5110,24 +5107,18 @@ pub fn dl_iterate_phdr(
// Last return value from the callback function. // Last return value from the callback function.
while (it.next()) |entry| { while (it.next()) |entry| {
var phdr: [*]elf.Phdr = undefined; const phdrs: []elf.ElfN.Phdr = if (entry.l_addr != 0) phdrs: {
var phnum: u16 = undefined; const ehdr: *elf.ElfN.Ehdr = @ptrFromInt(entry.l_addr);
assert(mem.eql(u8, ehdr.ident[0..4], elf.MAGIC));
const phdrs: [*]elf.ElfN.Phdr = @ptrFromInt(entry.l_addr + ehdr.phoff);
break :phdrs phdrs[0..ehdr.phnum];
} else getSelfPhdrs();
if (entry.l_addr != 0) { var info: dl_phdr_info = .{
const elf_header: *elf.Ehdr = @ptrFromInt(entry.l_addr);
phdr = @ptrFromInt(entry.l_addr + elf_header.e_phoff);
phnum = elf_header.e_phnum;
} else {
// This is the running ELF image
phdr = @ptrFromInt(elf_base + ehdr.e_phoff);
phnum = ehdr.e_phnum;
}
var info = dl_phdr_info{
.addr = entry.l_addr, .addr = entry.l_addr,
.name = entry.l_name, .name = entry.l_name,
.phdr = phdr, .phdr = phdrs.ptr,
.phnum = phnum, .phnum = @intCast(phdrs.len),
}; };
try callback(&info, @sizeOf(dl_phdr_info), context); try callback(&info, @sizeOf(dl_phdr_info), context);

View File

@ -257,11 +257,11 @@ fn iter_fn(info: *dl_phdr_info, size: usize, counter: *usize) IterFnError!void {
while (i < info.phnum) : (i += 1) { while (i < info.phnum) : (i += 1) {
const phdr = info.phdr[i]; const phdr = info.phdr[i];
if (phdr.p_type != elf.PT_LOAD) continue; if (phdr.type != .LOAD) continue;
const reloc_addr = info.addr + phdr.p_vaddr; const reloc_addr = info.addr + phdr.vaddr;
// Find the ELF header // Find the ELF header
const elf_header = @as(*elf.Ehdr, @ptrFromInt(reloc_addr - phdr.p_offset)); const elf_header = @as(*elf.Ehdr, @ptrFromInt(reloc_addr - phdr.offset));
// Validate the magic // Validate the magic
if (!mem.eql(u8, elf_header.e_ident[0..4], elf.MAGIC)) return error.BadElfMagic; if (!mem.eql(u8, elf_header.e_ident[0..4], elf.MAGIC)) return error.BadElfMagic;
// Consistency check // Consistency check

View File

@ -1658,13 +1658,13 @@ fn posixGetUserInfoPasswdStream(name: []const u8, reader: *std.Io.Reader) !UserI
pub fn getBaseAddress() usize { pub fn getBaseAddress() usize {
switch (native_os) { switch (native_os) {
.linux => { .linux => {
const getauxval = if (builtin.link_libc) std.c.getauxval else std.os.linux.getauxval; const phdrs = std.posix.getSelfPhdrs();
const base = getauxval(std.elf.AT_BASE); var base: usize = 0;
if (base != 0) { for (phdrs) |phdr| switch (phdr.type) {
return base; .LOAD => return base + phdr.vaddr,
} .PHDR => base = @intFromPtr(phdrs.ptr) - phdr.vaddr,
const phdr = getauxval(std.elf.AT_PHDR); else => {},
return phdr - @sizeOf(std.elf.Ehdr); } else unreachable;
}, },
.driverkit, .ios, .macos, .tvos, .visionos, .watchos => { .driverkit, .ios, .macos, .tvos, .visionos, .watchos => {
return @intFromPtr(&std.c._mh_execute_header); return @intFromPtr(&std.c._mh_execute_header);

File diff suppressed because it is too large Load Diff

View File

@ -486,6 +486,14 @@ fn addNode(mf: *MappedFile, gpa: std.mem.Allocator, opts: struct {
break :free .{ free_ni, free_node }; break :free .{ free_ni, free_node };
}, },
}; };
switch (opts.prev) {
.none => opts.parent.get(mf).first = free_ni,
else => |prev_ni| prev_ni.get(mf).next = free_ni,
}
switch (opts.next) {
.none => opts.parent.get(mf).last = free_ni,
else => |next_ni| next_ni.get(mf).prev = free_ni,
}
free_node.* = .{ free_node.* = .{
.parent = opts.parent, .parent = opts.parent,
.prev = opts.prev, .prev = opts.prev,
@ -535,13 +543,10 @@ pub fn addOnlyChildNode(
try mf.nodes.ensureUnusedCapacity(gpa, 1); try mf.nodes.ensureUnusedCapacity(gpa, 1);
const parent = parent_ni.get(mf); const parent = parent_ni.get(mf);
assert(parent.first == .none and parent.last == .none); assert(parent.first == .none and parent.last == .none);
const ni = try mf.addNode(gpa, .{ return mf.addNode(gpa, .{
.parent = parent_ni, .parent = parent_ni,
.add_node = opts, .add_node = opts,
}); });
parent.first = ni;
parent.last = ni;
return ni;
} }
pub fn addFirstChildNode( pub fn addFirstChildNode(
@ -552,17 +557,11 @@ pub fn addFirstChildNode(
) !Node.Index { ) !Node.Index {
try mf.nodes.ensureUnusedCapacity(gpa, 1); try mf.nodes.ensureUnusedCapacity(gpa, 1);
const parent = parent_ni.get(mf); const parent = parent_ni.get(mf);
const ni = try mf.addNode(gpa, .{ return mf.addNode(gpa, .{
.parent = parent_ni, .parent = parent_ni,
.next = parent.first, .next = parent.first,
.add_node = opts, .add_node = opts,
}); });
switch (parent.first) {
.none => parent.last = ni,
else => |first_ni| first_ni.get(mf).prev = ni,
}
parent.first = ni;
return ni;
} }
pub fn addLastChildNode( pub fn addLastChildNode(
@ -573,7 +572,7 @@ pub fn addLastChildNode(
) !Node.Index { ) !Node.Index {
try mf.nodes.ensureUnusedCapacity(gpa, 1); try mf.nodes.ensureUnusedCapacity(gpa, 1);
const parent = parent_ni.get(mf); const parent = parent_ni.get(mf);
const ni = try mf.addNode(gpa, .{ return mf.addNode(gpa, .{
.parent = parent_ni, .parent = parent_ni,
.prev = parent.last, .prev = parent.last,
.offset = offset: switch (parent.last) { .offset = offset: switch (parent.last) {
@ -585,12 +584,6 @@ pub fn addLastChildNode(
}, },
.add_node = opts, .add_node = opts,
}); });
switch (parent.last) {
.none => parent.first = ni,
else => |last_ni| last_ni.get(mf).next = ni,
}
parent.last = ni;
return ni;
} }
pub fn addNodeAfter( pub fn addNodeAfter(
@ -603,19 +596,13 @@ pub fn addNodeAfter(
try mf.nodes.ensureUnusedCapacity(gpa, 1); try mf.nodes.ensureUnusedCapacity(gpa, 1);
const prev = prev_ni.get(mf); const prev = prev_ni.get(mf);
const prev_offset, const prev_size = prev.location().resolve(mf); const prev_offset, const prev_size = prev.location().resolve(mf);
const ni = try mf.addNode(gpa, .{ return mf.addNode(gpa, .{
.parent = prev.parent, .parent = prev.parent,
.prev = prev_ni, .prev = prev_ni,
.next = prev.next, .next = prev.next,
.offset = prev_offset + prev_size, .offset = prev_offset + prev_size,
.add_node = opts, .add_node = opts,
}); });
switch (prev.next) {
.none => prev.parent.get(mf).last = ni,
else => |next_ni| next_ni.get(mf).prev = ni,
}
prev.next = ni;
return ni;
} }
fn resizeNode(mf: *MappedFile, gpa: std.mem.Allocator, ni: Node.Index, requested_size: u64) !void { fn resizeNode(mf: *MappedFile, gpa: std.mem.Allocator, ni: Node.Index, requested_size: u64) !void {