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