mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-09 15:19:07 +00:00
abiAndDynamicLinkerFromFile: return an error when the file is not actually dynamic (#19928)
This commit is contained in:
parent
263ba34619
commit
5bb9963bbb
1 changed files with 66 additions and 50 deletions
|
|
@ -505,6 +505,7 @@ pub const AbiAndDynamicLinkerFromFileError = error{
|
||||||
UnexpectedEndOfFile,
|
UnexpectedEndOfFile,
|
||||||
NameTooLong,
|
NameTooLong,
|
||||||
ProcessNotFound,
|
ProcessNotFound,
|
||||||
|
StaticElfFile,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn abiAndDynamicLinkerFromFile(
|
pub fn abiAndDynamicLinkerFromFile(
|
||||||
|
|
@ -550,6 +551,8 @@ pub fn abiAndDynamicLinkerFromFile(
|
||||||
if (phentsize > @sizeOf(elf.Elf64_Phdr)) return error.InvalidElfFile;
|
if (phentsize > @sizeOf(elf.Elf64_Phdr)) return error.InvalidElfFile;
|
||||||
|
|
||||||
var ph_i: u16 = 0;
|
var ph_i: u16 = 0;
|
||||||
|
var got_dyn_section: bool = false;
|
||||||
|
|
||||||
while (ph_i < phnum) {
|
while (ph_i < phnum) {
|
||||||
// Reserve some bytes so that we can deref the 64-bit struct fields
|
// Reserve some bytes so that we can deref the 64-bit struct fields
|
||||||
// even when the ELF file is 32-bits.
|
// even when the ELF file is 32-bits.
|
||||||
|
|
@ -565,61 +568,69 @@ pub fn abiAndDynamicLinkerFromFile(
|
||||||
const ph64: *elf.Elf64_Phdr = @ptrCast(@alignCast(&ph_buf[ph_buf_i]));
|
const ph64: *elf.Elf64_Phdr = @ptrCast(@alignCast(&ph_buf[ph_buf_i]));
|
||||||
const p_type = elfInt(is_64, need_bswap, ph32.p_type, ph64.p_type);
|
const p_type = elfInt(is_64, need_bswap, ph32.p_type, ph64.p_type);
|
||||||
switch (p_type) {
|
switch (p_type) {
|
||||||
elf.PT_INTERP => if (look_for_ld) {
|
elf.PT_INTERP => {
|
||||||
const p_offset = elfInt(is_64, need_bswap, ph32.p_offset, ph64.p_offset);
|
got_dyn_section = true;
|
||||||
const p_filesz = elfInt(is_64, need_bswap, ph32.p_filesz, ph64.p_filesz);
|
|
||||||
if (p_filesz > result.dynamic_linker.buffer.len) return error.NameTooLong;
|
|
||||||
const filesz: usize = @intCast(p_filesz);
|
|
||||||
_ = try preadAtLeast(file, result.dynamic_linker.buffer[0..filesz], p_offset, filesz);
|
|
||||||
// PT_INTERP includes a null byte in filesz.
|
|
||||||
const len = filesz - 1;
|
|
||||||
// dynamic_linker.max_byte is "max", not "len".
|
|
||||||
// We know it will fit in u8 because we check against dynamic_linker.buffer.len above.
|
|
||||||
result.dynamic_linker.len = @intCast(len);
|
|
||||||
|
|
||||||
// Use it to determine ABI.
|
if (look_for_ld) {
|
||||||
const full_ld_path = result.dynamic_linker.buffer[0..len];
|
const p_offset = elfInt(is_64, need_bswap, ph32.p_offset, ph64.p_offset);
|
||||||
for (ld_info_list) |ld_info| {
|
const p_filesz = elfInt(is_64, need_bswap, ph32.p_filesz, ph64.p_filesz);
|
||||||
const standard_ld_basename = fs.path.basename(ld_info.ld.get().?);
|
if (p_filesz > result.dynamic_linker.buffer.len) return error.NameTooLong;
|
||||||
if (std.mem.endsWith(u8, full_ld_path, standard_ld_basename)) {
|
const filesz: usize = @intCast(p_filesz);
|
||||||
result.abi = ld_info.abi;
|
_ = try preadAtLeast(file, result.dynamic_linker.buffer[0..filesz], p_offset, filesz);
|
||||||
break;
|
// PT_INTERP includes a null byte in filesz.
|
||||||
|
const len = filesz - 1;
|
||||||
|
// dynamic_linker.max_byte is "max", not "len".
|
||||||
|
// We know it will fit in u8 because we check against dynamic_linker.buffer.len above.
|
||||||
|
result.dynamic_linker.len = @intCast(len);
|
||||||
|
|
||||||
|
// Use it to determine ABI.
|
||||||
|
const full_ld_path = result.dynamic_linker.buffer[0..len];
|
||||||
|
for (ld_info_list) |ld_info| {
|
||||||
|
const standard_ld_basename = fs.path.basename(ld_info.ld.get().?);
|
||||||
|
if (std.mem.endsWith(u8, full_ld_path, standard_ld_basename)) {
|
||||||
|
result.abi = ld_info.abi;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// We only need this for detecting glibc version.
|
// We only need this for detecting glibc version.
|
||||||
elf.PT_DYNAMIC => if (builtin.target.os.tag == .linux and result.isGnuLibC() and
|
elf.PT_DYNAMIC => {
|
||||||
query.glibc_version == null)
|
got_dyn_section = true;
|
||||||
{
|
|
||||||
var dyn_off = elfInt(is_64, need_bswap, ph32.p_offset, ph64.p_offset);
|
if (builtin.target.os.tag == .linux and result.isGnuLibC() and
|
||||||
const p_filesz = elfInt(is_64, need_bswap, ph32.p_filesz, ph64.p_filesz);
|
query.glibc_version == null)
|
||||||
const dyn_size: usize = if (is_64) @sizeOf(elf.Elf64_Dyn) else @sizeOf(elf.Elf32_Dyn);
|
{
|
||||||
const dyn_num = p_filesz / dyn_size;
|
var dyn_off = elfInt(is_64, need_bswap, ph32.p_offset, ph64.p_offset);
|
||||||
var dyn_buf: [16 * @sizeOf(elf.Elf64_Dyn)]u8 align(@alignOf(elf.Elf64_Dyn)) = undefined;
|
const p_filesz = elfInt(is_64, need_bswap, ph32.p_filesz, ph64.p_filesz);
|
||||||
var dyn_i: usize = 0;
|
const dyn_size: usize = if (is_64) @sizeOf(elf.Elf64_Dyn) else @sizeOf(elf.Elf32_Dyn);
|
||||||
dyn: while (dyn_i < dyn_num) {
|
const dyn_num = p_filesz / dyn_size;
|
||||||
// Reserve some bytes so that we can deref the 64-bit struct fields
|
var dyn_buf: [16 * @sizeOf(elf.Elf64_Dyn)]u8 align(@alignOf(elf.Elf64_Dyn)) = undefined;
|
||||||
// even when the ELF file is 32-bits.
|
var dyn_i: usize = 0;
|
||||||
const dyn_reserve: usize = @sizeOf(elf.Elf64_Dyn) - @sizeOf(elf.Elf32_Dyn);
|
dyn: while (dyn_i < dyn_num) {
|
||||||
const dyn_read_byte_len = try preadAtLeast(
|
// Reserve some bytes so that we can deref the 64-bit struct fields
|
||||||
file,
|
// even when the ELF file is 32-bits.
|
||||||
dyn_buf[0 .. dyn_buf.len - dyn_reserve],
|
const dyn_reserve: usize = @sizeOf(elf.Elf64_Dyn) - @sizeOf(elf.Elf32_Dyn);
|
||||||
dyn_off,
|
const dyn_read_byte_len = try preadAtLeast(
|
||||||
dyn_size,
|
file,
|
||||||
);
|
dyn_buf[0 .. dyn_buf.len - dyn_reserve],
|
||||||
var dyn_buf_i: usize = 0;
|
dyn_off,
|
||||||
while (dyn_buf_i < dyn_read_byte_len and dyn_i < dyn_num) : ({
|
dyn_size,
|
||||||
dyn_i += 1;
|
);
|
||||||
dyn_off += dyn_size;
|
var dyn_buf_i: usize = 0;
|
||||||
dyn_buf_i += dyn_size;
|
while (dyn_buf_i < dyn_read_byte_len and dyn_i < dyn_num) : ({
|
||||||
}) {
|
dyn_i += 1;
|
||||||
const dyn32: *elf.Elf32_Dyn = @ptrCast(@alignCast(&dyn_buf[dyn_buf_i]));
|
dyn_off += dyn_size;
|
||||||
const dyn64: *elf.Elf64_Dyn = @ptrCast(@alignCast(&dyn_buf[dyn_buf_i]));
|
dyn_buf_i += dyn_size;
|
||||||
const tag = elfInt(is_64, need_bswap, dyn32.d_tag, dyn64.d_tag);
|
}) {
|
||||||
const val = elfInt(is_64, need_bswap, dyn32.d_val, dyn64.d_val);
|
const dyn32: *elf.Elf32_Dyn = @ptrCast(@alignCast(&dyn_buf[dyn_buf_i]));
|
||||||
if (tag == elf.DT_RUNPATH) {
|
const dyn64: *elf.Elf64_Dyn = @ptrCast(@alignCast(&dyn_buf[dyn_buf_i]));
|
||||||
rpath_offset = val;
|
const tag = elfInt(is_64, need_bswap, dyn32.d_tag, dyn64.d_tag);
|
||||||
break :dyn;
|
const val = elfInt(is_64, need_bswap, dyn32.d_val, dyn64.d_val);
|
||||||
|
if (tag == elf.DT_RUNPATH) {
|
||||||
|
rpath_offset = val;
|
||||||
|
break :dyn;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -629,6 +640,10 @@ pub fn abiAndDynamicLinkerFromFile(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!got_dyn_section) {
|
||||||
|
return error.StaticElfFile;
|
||||||
|
}
|
||||||
|
|
||||||
if (builtin.target.os.tag == .linux and result.isGnuLibC() and
|
if (builtin.target.os.tag == .linux and result.isGnuLibC() and
|
||||||
query.glibc_version == null)
|
query.glibc_version == null)
|
||||||
{
|
{
|
||||||
|
|
@ -1208,6 +1223,7 @@ fn detectAbiAndDynamicLinker(
|
||||||
error.Unexpected,
|
error.Unexpected,
|
||||||
error.UnexpectedEndOfFile,
|
error.UnexpectedEndOfFile,
|
||||||
error.NameTooLong,
|
error.NameTooLong,
|
||||||
|
error.StaticElfFile,
|
||||||
// Finally, we fall back on the standard path.
|
// Finally, we fall back on the standard path.
|
||||||
=> |e| {
|
=> |e| {
|
||||||
std.log.warn("Encountered error: {s}, falling back to default ABI and dynamic linker.", .{@errorName(e)});
|
std.log.warn("Encountered error: {s}, falling back to default ABI and dynamic linker.", .{@errorName(e)});
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue