mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 12:59:04 +00:00
complete the native target detection based on /usr/bin/env
This commit is contained in:
parent
fd006c1c74
commit
3683ba87ac
@ -108,6 +108,7 @@ pub extern "c" fn execve(path: [*:0]const u8, argv: [*:null]const ?[*:0]const u8
|
||||
pub extern "c" fn dup(fd: fd_t) c_int;
|
||||
pub extern "c" fn dup2(old_fd: fd_t, new_fd: fd_t) c_int;
|
||||
pub extern "c" fn readlink(noalias path: [*:0]const u8, noalias buf: [*]u8, bufsize: usize) isize;
|
||||
pub extern "c" fn readlinkat(dirfd: fd_t, noalias path: [*:0]const u8, noalias buf: [*]u8, bufsize: usize) isize;
|
||||
pub extern "c" fn realpath(noalias file_name: [*:0]const u8, noalias resolved_name: [*]u8) ?[*:0]u8;
|
||||
pub extern "c" fn sigprocmask(how: c_int, noalias set: ?*const sigset_t, noalias oset: ?*sigset_t) c_int;
|
||||
pub extern "c" fn gettimeofday(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int;
|
||||
|
||||
@ -82,12 +82,12 @@ pub fn linkmap_iterator(phdrs: []elf.Phdr) !LinkMap.Iterator {
|
||||
for (dyn_table) |*dyn| {
|
||||
switch (dyn.d_tag) {
|
||||
elf.DT_DEBUG => {
|
||||
const r_debug = @intToPtr(*RDebug, dyn.d_un.d_ptr);
|
||||
const r_debug = @intToPtr(*RDebug, dyn.d_val);
|
||||
if (r_debug.r_version != 1) return error.InvalidExe;
|
||||
break :init r_debug.r_map;
|
||||
},
|
||||
elf.DT_PLTGOT => {
|
||||
const got_table = @intToPtr([*]usize, dyn.d_un.d_ptr);
|
||||
const got_table = @intToPtr([*]usize, dyn.d_val);
|
||||
// The address to the link_map structure is stored in the
|
||||
// second slot
|
||||
break :init @intToPtr(?*LinkMap, got_table[1]);
|
||||
|
||||
@ -708,17 +708,11 @@ pub const Elf64_Rela = extern struct {
|
||||
};
|
||||
pub const Elf32_Dyn = extern struct {
|
||||
d_tag: Elf32_Sword,
|
||||
d_un: extern union {
|
||||
d_val: Elf32_Word,
|
||||
d_ptr: Elf32_Addr,
|
||||
},
|
||||
d_val: Elf32_Addr,
|
||||
};
|
||||
pub const Elf64_Dyn = extern struct {
|
||||
d_tag: Elf64_Sxword,
|
||||
d_un: extern union {
|
||||
d_val: Elf64_Xword,
|
||||
d_ptr: Elf64_Addr,
|
||||
},
|
||||
d_val: Elf64_Addr,
|
||||
};
|
||||
pub const Elf32_Verdef = extern struct {
|
||||
vd_version: Elf32_Half,
|
||||
|
||||
@ -238,16 +238,6 @@ pub const NativeTargetInfo = struct {
|
||||
// A user could then run that zig compiler on riscv64-linux-gnu. This use case is well-defined
|
||||
// and supported by Zig. But that means that we must detect the system ABI here rather than
|
||||
// relying on `Target.current`.
|
||||
const LdInfo = struct {
|
||||
ld_path_buffer: [255]u8,
|
||||
ld_path_max: u8,
|
||||
abi: Target.Abi,
|
||||
|
||||
pub fn ldPath(self: *const @This()) []const u8 {
|
||||
const m: usize = self.ld_path_max;
|
||||
return self.ld_path_buffer[0 .. m + 1];
|
||||
}
|
||||
};
|
||||
const all_abis = comptime blk: {
|
||||
assert(@enumToInt(Target.Abi.none) == 0);
|
||||
const fields = std.meta.fields(Target.Abi)[1..];
|
||||
@ -333,7 +323,7 @@ pub const NativeTargetInfo = struct {
|
||||
// trick won't work. The next thing we fall back to is the same thing, but for /usr/bin/env.
|
||||
// Since that path is hard-coded into the shebang line of many portable scripts, it's a
|
||||
// reasonably reliable path to check for.
|
||||
return abiAndDynamicLinkerFromUsrBinEnv(cpu, os) catch |err| switch (err) {
|
||||
return abiAndDynamicLinkerFromUsrBinEnv(cpu, os, ld_info_list) catch |err| switch (err) {
|
||||
error.FileSystem,
|
||||
error.SystemResources,
|
||||
error.SymLinkLoop,
|
||||
@ -343,8 +333,6 @@ pub const NativeTargetInfo = struct {
|
||||
=> |e| return e,
|
||||
|
||||
error.UnableToReadElfFile,
|
||||
error.ElfNotADynamicExecutable,
|
||||
error.InvalidElfProgramHeaders,
|
||||
error.InvalidElfClass,
|
||||
error.InvalidElfVersion,
|
||||
error.InvalidElfEndian,
|
||||
@ -373,6 +361,10 @@ pub const NativeTargetInfo = struct {
|
||||
error.NotDir => return error.GnuLibCVersionUnavailable,
|
||||
error.Unexpected => return error.GnuLibCVersionUnavailable,
|
||||
};
|
||||
return glibcVerFromLinkName(link_name);
|
||||
}
|
||||
|
||||
fn glibcVerFromLinkName(link_name: []const u8) !std.builtin.Version {
|
||||
// example: "libc-2.3.4.so"
|
||||
// example: "libc-2.27.so"
|
||||
const prefix = "libc-";
|
||||
@ -389,7 +381,11 @@ pub const NativeTargetInfo = struct {
|
||||
};
|
||||
}
|
||||
|
||||
fn abiAndDynamicLinkerFromUsrBinEnv(cpu: Target.Cpu, os: Target.Os) !NativeTargetInfo {
|
||||
fn abiAndDynamicLinkerFromUsrBinEnv(
|
||||
cpu: Target.Cpu,
|
||||
os: Target.Os,
|
||||
ld_info_list: []const LdInfo,
|
||||
) !NativeTargetInfo {
|
||||
const env_file = std.fs.openFileAbsoluteC("/usr/bin/env", .{}) catch |err| switch (err) {
|
||||
error.NoSpaceLeft => unreachable,
|
||||
error.NameTooLong => unreachable,
|
||||
@ -409,8 +405,7 @@ pub const NativeTargetInfo = struct {
|
||||
else => |e| return e,
|
||||
};
|
||||
var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 align(@alignOf(elf.Elf64_Ehdr)) = undefined;
|
||||
const hdr_bytes_len = try wrapRead(env_file.pread(&hdr_buf, 0));
|
||||
if (hdr_bytes_len < @sizeOf(elf.Elf32_Ehdr)) return error.InvalidElfFile;
|
||||
_ = try preadFull(env_file, &hdr_buf, 0, hdr_buf.len);
|
||||
const hdr32 = @ptrCast(*elf.Elf32_Ehdr, &hdr_buf);
|
||||
const hdr64 = @ptrCast(*elf.Elf64_Ehdr, &hdr_buf);
|
||||
if (!mem.eql(u8, hdr32.e_ident[0..4], "\x7fELF")) return error.InvalidElfMagic;
|
||||
@ -430,7 +425,6 @@ pub const NativeTargetInfo = struct {
|
||||
var phoff = elfInt(is_64, need_bswap, hdr32.e_phoff, hdr64.e_phoff);
|
||||
const phentsize = elfInt(is_64, need_bswap, hdr32.e_phentsize, hdr64.e_phentsize);
|
||||
const phnum = elfInt(is_64, need_bswap, hdr32.e_phnum, hdr64.e_phnum);
|
||||
const shstrndx = elfInt(is_64, need_bswap, hdr32.e_shstrndx, hdr64.e_shstrndx);
|
||||
|
||||
var result: NativeTargetInfo = .{
|
||||
.target = .{
|
||||
@ -439,67 +433,234 @@ pub const NativeTargetInfo = struct {
|
||||
.abi = Target.Abi.default(cpu.arch, os),
|
||||
},
|
||||
};
|
||||
var rpath_offset: ?u64 = null; // Found inside PT_DYNAMIC
|
||||
|
||||
const ph_total_size = std.math.mul(u32, phentsize, phnum) catch |err| switch (err) {
|
||||
error.Overflow => return error.InvalidElfProgramHeaders,
|
||||
};
|
||||
var ph_buf: [16 * @sizeOf(elf.Elf64_Phdr)]u8 align(@alignOf(elf.Elf64_Phdr)) = undefined;
|
||||
if (phentsize > @sizeOf(elf.Elf64_Phdr)) return error.InvalidElfFile;
|
||||
|
||||
var ph_i: u16 = 0;
|
||||
while (ph_i < phnum) {
|
||||
// Reserve some bytes so that we can deref the 64-bit struct fields even when the ELF file is 32-bits.
|
||||
const reserve = @sizeOf(elf.Elf64_Phdr) - @sizeOf(elf.Elf32_Phdr);
|
||||
const read_byte_len = try wrapRead(env_file.pread(ph_buf[0 .. ph_buf.len - reserve], phoff));
|
||||
if (read_byte_len < phentsize) return error.ElfNotADynamicExecutable;
|
||||
var buf_i: usize = 0;
|
||||
while (buf_i < read_byte_len and ph_i < phnum) : ({
|
||||
// Reserve some bytes so that we can deref the 64-bit struct fields
|
||||
// even when the ELF file is 32-bits.
|
||||
const ph_reserve: usize = @sizeOf(elf.Elf64_Phdr) - @sizeOf(elf.Elf32_Phdr);
|
||||
const ph_read_byte_len = try preadFull(env_file, ph_buf[0 .. ph_buf.len - ph_reserve], phoff, phentsize);
|
||||
var ph_buf_i: usize = 0;
|
||||
while (ph_buf_i < ph_read_byte_len and ph_i < phnum) : ({
|
||||
ph_i += 1;
|
||||
phoff += phentsize;
|
||||
buf_i += phentsize;
|
||||
ph_buf_i += phentsize;
|
||||
}) {
|
||||
const ph32 = @ptrCast(*elf.Elf32_Phdr, @alignCast(@alignOf(elf.Elf32_Phdr), &ph_buf[buf_i]));
|
||||
const ph64 = @ptrCast(*elf.Elf64_Phdr, @alignCast(@alignOf(elf.Elf64_Phdr), &ph_buf[buf_i]));
|
||||
const ph32 = @ptrCast(*elf.Elf32_Phdr, @alignCast(@alignOf(elf.Elf32_Phdr), &ph_buf[ph_buf_i]));
|
||||
const ph64 = @ptrCast(*elf.Elf64_Phdr, @alignCast(@alignOf(elf.Elf64_Phdr), &ph_buf[ph_buf_i]));
|
||||
const p_type = elfInt(is_64, need_bswap, ph32.p_type, ph64.p_type);
|
||||
switch (p_type) {
|
||||
elf.PT_INTERP => {
|
||||
const p_offset = elfInt(is_64, need_bswap, ph32.p_offset, ph64.p_offset);
|
||||
const p_filesz = elfInt(is_64, need_bswap, ph32.p_filesz, ph64.p_filesz);
|
||||
var interp_buf: [255]u8 = undefined;
|
||||
if (p_filesz > interp_buf.len) return error.NameTooLong;
|
||||
var read_offset: usize = 0;
|
||||
while (true) {
|
||||
const len = try wrapRead(env_file.pread(
|
||||
interp_buf[read_offset .. p_filesz - read_offset],
|
||||
p_offset + read_offset,
|
||||
));
|
||||
if (len == 0) return error.UnexpectedEndOfFile;
|
||||
read_offset += len;
|
||||
if (read_offset == p_filesz) break;
|
||||
}
|
||||
if (p_filesz > result.dynamic_linker_buffer.len) return error.NameTooLong;
|
||||
_ = try preadFull(env_file, result.dynamic_linker_buffer[0..p_filesz], p_offset, p_filesz);
|
||||
// PT_INTERP includes a null byte in p_filesz.
|
||||
result.setDynamicLinker(interp_buf[0 .. p_filesz - 1]);
|
||||
const len = p_filesz - 1;
|
||||
// dynamic_linker_max is "max", not "len".
|
||||
// We know it will fit in u8 because we check against dynamic_linker_buffer.len above.
|
||||
result.dynamic_linker_max = @intCast(u8, len - 1);
|
||||
|
||||
// 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.ldPath());
|
||||
if (std.mem.endsWith(u8, full_ld_path, standard_ld_basename)) {
|
||||
result.target.abi = ld_info.abi;
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
elf.PT_DYNAMIC => {
|
||||
std.debug.warn("found PT_DYNAMIC\n", .{});
|
||||
// We only need this for detecting glibc version.
|
||||
elf.PT_DYNAMIC => if (Target.current.os.tag == .linux and result.target.isGnuLibC()) {
|
||||
var dyn_off = elfInt(is_64, need_bswap, ph32.p_offset, ph64.p_offset);
|
||||
const p_filesz = elfInt(is_64, need_bswap, ph32.p_filesz, ph64.p_filesz);
|
||||
const dyn_size: u64 = if (is_64) @sizeOf(elf.Elf64_Dyn) else @sizeOf(elf.Elf32_Dyn);
|
||||
const dyn_num = p_filesz / dyn_size;
|
||||
var dyn_buf: [16 * @sizeOf(elf.Elf64_Dyn)]u8 align(@alignOf(elf.Elf64_Dyn)) = undefined;
|
||||
var dyn_i: usize = 0;
|
||||
dyn: while (dyn_i < dyn_num) {
|
||||
// Reserve some bytes so that we can deref the 64-bit struct fields
|
||||
// even when the ELF file is 32-bits.
|
||||
const dyn_reserve: usize = @sizeOf(elf.Elf64_Dyn) - @sizeOf(elf.Elf32_Dyn);
|
||||
const dyn_read_byte_len = try preadFull(
|
||||
env_file,
|
||||
dyn_buf[0 .. dyn_buf.len - dyn_reserve],
|
||||
dyn_off,
|
||||
dyn_size,
|
||||
);
|
||||
var dyn_buf_i: usize = 0;
|
||||
while (dyn_buf_i < dyn_read_byte_len and dyn_i < dyn_num) : ({
|
||||
dyn_i += 1;
|
||||
dyn_off += dyn_size;
|
||||
dyn_buf_i += dyn_size;
|
||||
}) {
|
||||
const dyn32 = @ptrCast(
|
||||
*elf.Elf32_Dyn,
|
||||
@alignCast(@alignOf(elf.Elf32_Dyn), &dyn_buf[dyn_buf_i]),
|
||||
);
|
||||
const dyn64 = @ptrCast(
|
||||
*elf.Elf64_Dyn,
|
||||
@alignCast(@alignOf(elf.Elf64_Dyn), &dyn_buf[dyn_buf_i]),
|
||||
);
|
||||
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);
|
||||
if (tag == elf.DT_RUNPATH) {
|
||||
rpath_offset = val;
|
||||
break :dyn;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
else => continue,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Target.current.os.tag == .linux and result.target.isGnuLibC()) {
|
||||
if (rpath_offset) |rpoff| {
|
||||
const shstrndx = elfInt(is_64, need_bswap, hdr32.e_shstrndx, hdr64.e_shstrndx);
|
||||
|
||||
var shoff = elfInt(is_64, need_bswap, hdr32.e_shoff, hdr64.e_shoff);
|
||||
const shentsize = elfInt(is_64, need_bswap, hdr32.e_shentsize, hdr64.e_shentsize);
|
||||
const str_section_off = shoff + @as(u64, shentsize) * @as(u64, shstrndx);
|
||||
|
||||
var sh_buf: [16 * @sizeOf(elf.Elf64_Shdr)]u8 align(@alignOf(elf.Elf64_Shdr)) = undefined;
|
||||
if (sh_buf.len < shentsize) return error.InvalidElfFile;
|
||||
|
||||
_ = try preadFull(env_file, &sh_buf, str_section_off, shentsize);
|
||||
const shstr32 = @ptrCast(*elf.Elf32_Shdr, @alignCast(@alignOf(elf.Elf32_Shdr), &sh_buf));
|
||||
const shstr64 = @ptrCast(*elf.Elf64_Shdr, @alignCast(@alignOf(elf.Elf64_Shdr), &sh_buf));
|
||||
const shstrtab_off = elfInt(is_64, need_bswap, shstr32.sh_offset, shstr64.sh_offset);
|
||||
const shstrtab_size = elfInt(is_64, need_bswap, shstr32.sh_size, shstr64.sh_size);
|
||||
var strtab_buf: [4096:0]u8 = undefined;
|
||||
const shstrtab_len = std.math.min(shstrtab_size, strtab_buf.len);
|
||||
const shstrtab_read_len = try preadFull(env_file, &strtab_buf, shstrtab_off, shstrtab_len);
|
||||
const shstrtab = strtab_buf[0..shstrtab_read_len];
|
||||
|
||||
const shnum = elfInt(is_64, need_bswap, hdr32.e_shnum, hdr64.e_shnum);
|
||||
var sh_i: u16 = 0;
|
||||
const dynstr: ?struct { offset: u64, size: u64 } = find_dyn_str: while (sh_i < shnum) {
|
||||
// Reserve some bytes so that we can deref the 64-bit struct fields
|
||||
// even when the ELF file is 32-bits.
|
||||
const sh_reserve: usize = @sizeOf(elf.Elf64_Shdr) - @sizeOf(elf.Elf32_Shdr);
|
||||
const sh_read_byte_len = try preadFull(
|
||||
env_file,
|
||||
sh_buf[0 .. sh_buf.len - sh_reserve],
|
||||
shoff,
|
||||
shentsize,
|
||||
);
|
||||
var sh_buf_i: usize = 0;
|
||||
while (sh_buf_i < sh_read_byte_len and sh_i < shnum) : ({
|
||||
sh_i += 1;
|
||||
shoff += shentsize;
|
||||
sh_buf_i += shentsize;
|
||||
}) {
|
||||
const sh32 = @ptrCast(
|
||||
*elf.Elf32_Shdr,
|
||||
@alignCast(@alignOf(elf.Elf32_Shdr), &sh_buf[sh_buf_i]),
|
||||
);
|
||||
const sh64 = @ptrCast(
|
||||
*elf.Elf64_Shdr,
|
||||
@alignCast(@alignOf(elf.Elf64_Shdr), &sh_buf[sh_buf_i]),
|
||||
);
|
||||
const sh_name_off = elfInt(is_64, need_bswap, sh32.sh_name, sh64.sh_name);
|
||||
// TODO this pointer cast should not be necessary
|
||||
const sh_name = mem.toSliceConst(u8, @ptrCast([*:0]u8, shstrtab[sh_name_off..].ptr));
|
||||
if (mem.eql(u8, sh_name, ".dynstr")) {
|
||||
break :find_dyn_str .{
|
||||
.offset = elfInt(is_64, need_bswap, sh32.sh_offset, sh64.sh_offset),
|
||||
.size = elfInt(is_64, need_bswap, sh32.sh_size, sh64.sh_size),
|
||||
};
|
||||
}
|
||||
}
|
||||
} else null;
|
||||
|
||||
if (dynstr) |ds| {
|
||||
const strtab_len = std.math.min(ds.size, strtab_buf.len);
|
||||
const strtab_read_len = try preadFull(env_file, &strtab_buf, ds.offset, shstrtab_len);
|
||||
const strtab = strtab_buf[0..strtab_read_len];
|
||||
// TODO this pointer cast should not be necessary
|
||||
const rpath_list = mem.toSliceConst(u8, @ptrCast([*:0]u8, strtab[rpoff..].ptr));
|
||||
var it = mem.tokenize(rpath_list, ":");
|
||||
while (it.next()) |rpath| {
|
||||
var dir = fs.cwd().openDirList(rpath) catch |err| switch (err) {
|
||||
error.NameTooLong => unreachable,
|
||||
error.InvalidUtf8 => unreachable,
|
||||
error.BadPathName => unreachable,
|
||||
error.DeviceBusy => unreachable,
|
||||
|
||||
error.FileNotFound,
|
||||
error.NotDir,
|
||||
error.AccessDenied,
|
||||
error.NoDevice,
|
||||
=> continue,
|
||||
|
||||
error.ProcessFdQuotaExceeded,
|
||||
error.SystemFdQuotaExceeded,
|
||||
error.SystemResources,
|
||||
error.SymLinkLoop,
|
||||
error.Unexpected,
|
||||
=> |e| return e,
|
||||
};
|
||||
defer dir.close();
|
||||
|
||||
var link_buf: [std.os.PATH_MAX]u8 = undefined;
|
||||
const link_name = std.os.readlinkatC(
|
||||
dir.fd,
|
||||
glibc_so_basename,
|
||||
&link_buf,
|
||||
) catch |err| switch (err) {
|
||||
error.NameTooLong => unreachable,
|
||||
|
||||
error.AccessDenied,
|
||||
error.FileNotFound,
|
||||
error.NotDir,
|
||||
=> continue,
|
||||
|
||||
error.SystemResources,
|
||||
error.FileSystem,
|
||||
error.SymLinkLoop,
|
||||
error.Unexpected,
|
||||
=> |e| return e,
|
||||
};
|
||||
result.target.os.version_range.linux.glibc = glibcVerFromLinkName(
|
||||
link_name,
|
||||
) catch |err| switch (err) {
|
||||
error.UnrecognizedGnuLibCFileName,
|
||||
error.InvalidGnuLibCVersion,
|
||||
=> continue,
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
fn wrapRead(res: std.os.ReadError!usize) !usize {
|
||||
return res catch |err| switch (err) {
|
||||
error.OperationAborted => unreachable, // Windows-only
|
||||
error.WouldBlock => unreachable, // Did not request blocking mode
|
||||
error.SystemResources => return error.SystemResources,
|
||||
error.IsDir => return error.UnableToReadElfFile,
|
||||
error.BrokenPipe => return error.UnableToReadElfFile,
|
||||
error.ConnectionResetByPeer => return error.UnableToReadElfFile,
|
||||
error.Unexpected => return error.Unexpected,
|
||||
error.InputOutput => return error.FileSystem,
|
||||
};
|
||||
fn preadFull(file: fs.File, buf: []u8, offset: u64, min_read_len: usize) !usize {
|
||||
var i: u64 = 0;
|
||||
while (i < min_read_len) {
|
||||
const len = file.pread(buf[i .. buf.len - i], offset + i) catch |err| switch (err) {
|
||||
error.OperationAborted => unreachable, // Windows-only
|
||||
error.WouldBlock => unreachable, // Did not request blocking mode
|
||||
error.SystemResources => return error.SystemResources,
|
||||
error.IsDir => return error.UnableToReadElfFile,
|
||||
error.BrokenPipe => return error.UnableToReadElfFile,
|
||||
error.ConnectionResetByPeer => return error.UnableToReadElfFile,
|
||||
error.Unexpected => return error.Unexpected,
|
||||
error.InputOutput => return error.FileSystem,
|
||||
};
|
||||
if (len == 0) return error.UnexpectedEndOfFile;
|
||||
i += len;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
fn defaultAbiAndDynamicLinker(cpu: Target.Cpu, os: Target.Os) !NativeTargetInfo {
|
||||
@ -513,20 +674,31 @@ pub const NativeTargetInfo = struct {
|
||||
result.dynamic_linker_max = result.target.standardDynamicLinkerPath(&result.dynamic_linker_buffer);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
fn elfInt(is_64: bool, need_bswap: bool, int_32: var, int_64: var) @TypeOf(int_64) {
|
||||
if (is_64) {
|
||||
if (need_bswap) {
|
||||
return @byteSwap(@TypeOf(int_64), int_64);
|
||||
} else {
|
||||
return int_64;
|
||||
const LdInfo = struct {
|
||||
ld_path_buffer: [255]u8,
|
||||
ld_path_max: u8,
|
||||
abi: Target.Abi,
|
||||
|
||||
pub fn ldPath(self: *const LdInfo) []const u8 {
|
||||
const m: usize = self.ld_path_max;
|
||||
return self.ld_path_buffer[0 .. m + 1];
|
||||
}
|
||||
} else {
|
||||
if (need_bswap) {
|
||||
return @byteSwap(@TypeOf(int_32), int_32);
|
||||
};
|
||||
|
||||
fn elfInt(is_64: bool, need_bswap: bool, int_32: var, int_64: var) @TypeOf(int_64) {
|
||||
if (is_64) {
|
||||
if (need_bswap) {
|
||||
return @byteSwap(@TypeOf(int_64), int_64);
|
||||
} else {
|
||||
return int_64;
|
||||
}
|
||||
} else {
|
||||
return int_32;
|
||||
if (need_bswap) {
|
||||
return @byteSwap(@TypeOf(int_32), int_32);
|
||||
} else {
|
||||
return int_32;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user