authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-02-29 21:31:03-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-02-29 21:31:03-05:00
log48cef8d5be24c40b4c845f6b07c78abd6c3d1b0d
treef4fe25e66e34a7549c12cb9fedfc35703b8a97e4
parentc903b760106ff9db5b3de74fa0c4034eddbd9cbf
signaturelock-open Commit is signed but in an unrecognized format.

refactor std.zig.system.NativeTargetInfo functions

to make them a bit easier to test.

1 files changed, 34 insertions(+), 31 deletions(-)

lib/std/zig/system.zig+34-31
...@@ -399,17 +399,38 @@ pub const NativeTargetInfo = struct {...@@ -399,17 +399,38 @@ pub const NativeTargetInfo = struct {
399 return result;399 return result;
400 }400 }
401401
402 const env_file = std.fs.openFileAbsoluteC("/usr/bin/env", .{}) catch |err| switch (err) {
403 error.NoSpaceLeft => unreachable,
404 error.NameTooLong => unreachable,
405 error.PathAlreadyExists => unreachable,
406 error.SharingViolation => unreachable,
407 error.InvalidUtf8 => unreachable,
408 error.BadPathName => unreachable,
409 error.PipeBusy => unreachable,
410
411 error.IsDir,
412 error.NotDir,
413 error.AccessDenied,
414 error.NoDevice,
415 error.FileNotFound,
416 error.FileTooBig,
417 error.Unexpected,
418 => return defaultAbiAndDynamicLinker(cpu, os, cross_target),
419
420 else => |e| return e,
421 };
422 defer env_file.close();
423
402 // If Zig is statically linked, such as via distributed binary static builds, the above424 // If Zig is statically linked, such as via distributed binary static builds, the above
403 // trick won't work. The next thing we fall back to is the same thing, but for /usr/bin/env.425 // trick won't work. The next thing we fall back to is the same thing, but for /usr/bin/env.
404 // Since that path is hard-coded into the shebang line of many portable scripts, it's a426 // Since that path is hard-coded into the shebang line of many portable scripts, it's a
405 // reasonably reliable path to check for.427 // reasonably reliable path to check for.
406 return abiAndDynamicLinkerFromUsrBinEnv(cpu, os, ld_info_list, cross_target) catch |err| switch (err) {428 return abiAndDynamicLinkerFromFile(env_file, cpu, os, ld_info_list, cross_target) catch |err| switch (err) {
407 error.FileSystem,429 error.FileSystem,
408 error.SystemResources,430 error.SystemResources,
409 error.SymLinkLoop,431 error.SymLinkLoop,
410 error.ProcessFdQuotaExceeded,432 error.ProcessFdQuotaExceeded,
411 error.SystemFdQuotaExceeded,433 error.SystemFdQuotaExceeded,
412 error.DeviceBusy,
413 => |e| return e,434 => |e| return e,
414435
415 error.UnableToReadElfFile,436 error.UnableToReadElfFile,
...@@ -418,7 +439,6 @@ pub const NativeTargetInfo = struct {...@@ -418,7 +439,6 @@ pub const NativeTargetInfo = struct {
418 error.InvalidElfEndian,439 error.InvalidElfEndian,
419 error.InvalidElfFile,440 error.InvalidElfFile,
420 error.InvalidElfMagic,441 error.InvalidElfMagic,
421 error.UsrBinEnvNotAvailable,
422 error.Unexpected,442 error.Unexpected,
423 error.UnexpectedEndOfFile,443 error.UnexpectedEndOfFile,
424 error.NameTooLong,444 error.NameTooLong,
...@@ -461,32 +481,15 @@ pub const NativeTargetInfo = struct {...@@ -461,32 +481,15 @@ pub const NativeTargetInfo = struct {
461 };481 };
462 }482 }
463483
464 fn abiAndDynamicLinkerFromUsrBinEnv(484 pub fn abiAndDynamicLinkerFromFile(
485 file: fs.File,
465 cpu: Target.Cpu,486 cpu: Target.Cpu,
466 os: Target.Os,487 os: Target.Os,
467 ld_info_list: []const LdInfo,488 ld_info_list: []const LdInfo,
468 cross_target: CrossTarget,489 cross_target: CrossTarget,
469 ) !NativeTargetInfo {490 ) !NativeTargetInfo {
470 const env_file = std.fs.openFileAbsoluteC("/usr/bin/env", .{}) catch |err| switch (err) {
471 error.NoSpaceLeft => unreachable,
472 error.NameTooLong => unreachable,
473 error.PathAlreadyExists => unreachable,
474 error.SharingViolation => unreachable,
475 error.InvalidUtf8 => unreachable,
476 error.BadPathName => unreachable,
477 error.PipeBusy => unreachable,
478
479 error.IsDir => return error.UsrBinEnvNotAvailable,
480 error.NotDir => return error.UsrBinEnvNotAvailable,
481 error.AccessDenied => return error.UsrBinEnvNotAvailable,
482 error.NoDevice => return error.UsrBinEnvNotAvailable,
483 error.FileNotFound => return error.UsrBinEnvNotAvailable,
484 error.FileTooBig => return error.UsrBinEnvNotAvailable,
485
486 else => |e| return e,
487 };
488 var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 align(@alignOf(elf.Elf64_Ehdr)) = undefined;491 var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 align(@alignOf(elf.Elf64_Ehdr)) = undefined;
489 _ = try preadFull(env_file, &hdr_buf, 0, hdr_buf.len);492 _ = try preadFull(file, &hdr_buf, 0, hdr_buf.len);
490 const hdr32 = @ptrCast(*elf.Elf32_Ehdr, &hdr_buf);493 const hdr32 = @ptrCast(*elf.Elf32_Ehdr, &hdr_buf);
491 const hdr64 = @ptrCast(*elf.Elf64_Ehdr, &hdr_buf);494 const hdr64 = @ptrCast(*elf.Elf64_Ehdr, &hdr_buf);
492 if (!mem.eql(u8, hdr32.e_ident[0..4], "\x7fELF")) return error.InvalidElfMagic;495 if (!mem.eql(u8, hdr32.e_ident[0..4], "\x7fELF")) return error.InvalidElfMagic;
...@@ -526,7 +529,7 @@ pub const NativeTargetInfo = struct {...@@ -526,7 +529,7 @@ pub const NativeTargetInfo = struct {
526 // Reserve some bytes so that we can deref the 64-bit struct fields529 // Reserve some bytes so that we can deref the 64-bit struct fields
527 // even when the ELF file is 32-bits.530 // even when the ELF file is 32-bits.
528 const ph_reserve: usize = @sizeOf(elf.Elf64_Phdr) - @sizeOf(elf.Elf32_Phdr);531 const ph_reserve: usize = @sizeOf(elf.Elf64_Phdr) - @sizeOf(elf.Elf32_Phdr);
529 const ph_read_byte_len = try preadFull(env_file, ph_buf[0 .. ph_buf.len - ph_reserve], phoff, phentsize);532 const ph_read_byte_len = try preadFull(file, ph_buf[0 .. ph_buf.len - ph_reserve], phoff, phentsize);
530 var ph_buf_i: usize = 0;533 var ph_buf_i: usize = 0;
531 while (ph_buf_i < ph_read_byte_len and ph_i < phnum) : ({534 while (ph_buf_i < ph_read_byte_len and ph_i < phnum) : ({
532 ph_i += 1;535 ph_i += 1;
...@@ -541,7 +544,7 @@ pub const NativeTargetInfo = struct {...@@ -541,7 +544,7 @@ pub const NativeTargetInfo = struct {
541 const p_offset = elfInt(is_64, need_bswap, ph32.p_offset, ph64.p_offset);544 const p_offset = elfInt(is_64, need_bswap, ph32.p_offset, ph64.p_offset);
542 const p_filesz = elfInt(is_64, need_bswap, ph32.p_filesz, ph64.p_filesz);545 const p_filesz = elfInt(is_64, need_bswap, ph32.p_filesz, ph64.p_filesz);
543 if (p_filesz > result.dynamic_linker.buffer.len) return error.NameTooLong;546 if (p_filesz > result.dynamic_linker.buffer.len) return error.NameTooLong;
544 _ = try preadFull(env_file, result.dynamic_linker.buffer[0..p_filesz], p_offset, p_filesz);547 _ = try preadFull(file, result.dynamic_linker.buffer[0..p_filesz], p_offset, p_filesz);
545 // PT_INTERP includes a null byte in p_filesz.548 // PT_INTERP includes a null byte in p_filesz.
546 const len = p_filesz - 1;549 const len = p_filesz - 1;
547 // dynamic_linker.max_byte is "max", not "len".550 // dynamic_linker.max_byte is "max", not "len".
...@@ -573,7 +576,7 @@ pub const NativeTargetInfo = struct {...@@ -573,7 +576,7 @@ pub const NativeTargetInfo = struct {
573 // even when the ELF file is 32-bits.576 // even when the ELF file is 32-bits.
574 const dyn_reserve: usize = @sizeOf(elf.Elf64_Dyn) - @sizeOf(elf.Elf32_Dyn);577 const dyn_reserve: usize = @sizeOf(elf.Elf64_Dyn) - @sizeOf(elf.Elf32_Dyn);
575 const dyn_read_byte_len = try preadFull(578 const dyn_read_byte_len = try preadFull(
576 env_file,579 file,
577 dyn_buf[0 .. dyn_buf.len - dyn_reserve],580 dyn_buf[0 .. dyn_buf.len - dyn_reserve],
578 dyn_off,581 dyn_off,
579 dyn_size,582 dyn_size,
...@@ -617,14 +620,14 @@ pub const NativeTargetInfo = struct {...@@ -617,14 +620,14 @@ pub const NativeTargetInfo = struct {
617 var sh_buf: [16 * @sizeOf(elf.Elf64_Shdr)]u8 align(@alignOf(elf.Elf64_Shdr)) = undefined;620 var sh_buf: [16 * @sizeOf(elf.Elf64_Shdr)]u8 align(@alignOf(elf.Elf64_Shdr)) = undefined;
618 if (sh_buf.len < shentsize) return error.InvalidElfFile;621 if (sh_buf.len < shentsize) return error.InvalidElfFile;
619622
620 _ = try preadFull(env_file, &sh_buf, str_section_off, shentsize);623 _ = try preadFull(file, &sh_buf, str_section_off, shentsize);
621 const shstr32 = @ptrCast(*elf.Elf32_Shdr, @alignCast(@alignOf(elf.Elf32_Shdr), &sh_buf));624 const shstr32 = @ptrCast(*elf.Elf32_Shdr, @alignCast(@alignOf(elf.Elf32_Shdr), &sh_buf));
622 const shstr64 = @ptrCast(*elf.Elf64_Shdr, @alignCast(@alignOf(elf.Elf64_Shdr), &sh_buf));625 const shstr64 = @ptrCast(*elf.Elf64_Shdr, @alignCast(@alignOf(elf.Elf64_Shdr), &sh_buf));
623 const shstrtab_off = elfInt(is_64, need_bswap, shstr32.sh_offset, shstr64.sh_offset);626 const shstrtab_off = elfInt(is_64, need_bswap, shstr32.sh_offset, shstr64.sh_offset);
624 const shstrtab_size = elfInt(is_64, need_bswap, shstr32.sh_size, shstr64.sh_size);627 const shstrtab_size = elfInt(is_64, need_bswap, shstr32.sh_size, shstr64.sh_size);
625 var strtab_buf: [4096:0]u8 = undefined;628 var strtab_buf: [4096:0]u8 = undefined;
626 const shstrtab_len = std.math.min(shstrtab_size, strtab_buf.len);629 const shstrtab_len = std.math.min(shstrtab_size, strtab_buf.len);
627 const shstrtab_read_len = try preadFull(env_file, &strtab_buf, shstrtab_off, shstrtab_len);630 const shstrtab_read_len = try preadFull(file, &strtab_buf, shstrtab_off, shstrtab_len);
628 const shstrtab = strtab_buf[0..shstrtab_read_len];631 const shstrtab = strtab_buf[0..shstrtab_read_len];
629632
630 const shnum = elfInt(is_64, need_bswap, hdr32.e_shnum, hdr64.e_shnum);633 const shnum = elfInt(is_64, need_bswap, hdr32.e_shnum, hdr64.e_shnum);
...@@ -634,7 +637,7 @@ pub const NativeTargetInfo = struct {...@@ -634,7 +637,7 @@ pub const NativeTargetInfo = struct {
634 // even when the ELF file is 32-bits.637 // even when the ELF file is 32-bits.
635 const sh_reserve: usize = @sizeOf(elf.Elf64_Shdr) - @sizeOf(elf.Elf32_Shdr);638 const sh_reserve: usize = @sizeOf(elf.Elf64_Shdr) - @sizeOf(elf.Elf32_Shdr);
636 const sh_read_byte_len = try preadFull(639 const sh_read_byte_len = try preadFull(
637 env_file,640 file,
638 sh_buf[0 .. sh_buf.len - sh_reserve],641 sh_buf[0 .. sh_buf.len - sh_reserve],
639 shoff,642 shoff,
640 shentsize,643 shentsize,
...@@ -667,7 +670,7 @@ pub const NativeTargetInfo = struct {...@@ -667,7 +670,7 @@ pub const NativeTargetInfo = struct {
667670
668 if (dynstr) |ds| {671 if (dynstr) |ds| {
669 const strtab_len = std.math.min(ds.size, strtab_buf.len);672 const strtab_len = std.math.min(ds.size, strtab_buf.len);
670 const strtab_read_len = try preadFull(env_file, &strtab_buf, ds.offset, shstrtab_len);673 const strtab_read_len = try preadFull(file, &strtab_buf, ds.offset, shstrtab_len);
671 const strtab = strtab_buf[0..strtab_read_len];674 const strtab = strtab_buf[0..strtab_read_len];
672 // TODO this pointer cast should not be necessary675 // TODO this pointer cast should not be necessary
673 const rpath_list = mem.toSliceConst(u8, @ptrCast([*:0]u8, strtab[rpoff..].ptr));676 const rpath_list = mem.toSliceConst(u8, @ptrCast([*:0]u8, strtab[rpoff..].ptr));
...@@ -763,7 +766,7 @@ pub const NativeTargetInfo = struct {...@@ -763,7 +766,7 @@ pub const NativeTargetInfo = struct {
763 };766 };
764 }767 }
765768
766 const LdInfo = struct {769 pub const LdInfo = struct {
767 ld: DynamicLinker,770 ld: DynamicLinker,
768 abi: Target.Abi,771 abi: Target.Abi,
769 };772 };