| ... | @@ -820,55 +820,87 @@ pub fn abiAndDynamicLinkerFromFile( | ... | @@ -820,55 +820,87 @@ pub fn abiAndDynamicLinkerFromFile( |
| 820 | while (it.next()) |rpath| { | 820 | while (it.next()) |rpath| { |
| 821 | if (glibcVerFromRPath(rpath)) |ver| { | 821 | if (glibcVerFromRPath(rpath)) |ver| { |
| 822 | result.target.os.version_range.linux.glibc = ver; | 822 | result.target.os.version_range.linux.glibc = ver; |
| 823 | break; | 823 | return result; |
| 824 | } else |err| switch (err) { | 824 | } else |err| switch (err) { |
| 825 | error.GLibCNotFound => continue, | 825 | error.GLibCNotFound => continue, |
| 826 | else => |e| return e, | 826 | else => |e| return e, |
| 827 | } | 827 | } |
| 828 | } | 828 | } |
| 829 | } else if (result.dynamic_linker.get()) |dl_path| glibc_ver: { | 829 | } |
| 830 | // There is no DT_RUNPATH so we try to find libc.so.6 inside the same | 830 | } |
| 831 | // directory as the dynamic linker. | | |
| 832 | if (fs.path.dirname(dl_path)) |rpath| { | | |
| 833 | if (glibcVerFromRPath(rpath)) |ver| { | | |
| 834 | result.target.os.version_range.linux.glibc = ver; | | |
| 835 | break :glibc_ver; | | |
| 836 | } else |err| switch (err) { | | |
| 837 | error.GLibCNotFound => {}, | | |
| 838 | else => |e| return e, | | |
| 839 | } | | |
| 840 | } | | |
| 841 | | 831 | |
| 842 | // So far, no luck. Next we try to see if the information is | 832 | if (result.dynamic_linker.get()) |dl_path| glibc_ver: { |
| 843 | // present in the symlink data for the dynamic linker path. | 833 | // There is no DT_RUNPATH so we try to find libc.so.6 inside the same |
| 844 | var link_buf: [std.os.PATH_MAX]u8 = undefined; | 834 | // directory as the dynamic linker. |
| 845 | const link_name = std.os.readlink(dl_path, &link_buf) catch |err| switch (err) { | 835 | if (fs.path.dirname(dl_path)) |rpath| { |
| 846 | error.NameTooLong => unreachable, | 836 | if (glibcVerFromRPath(rpath)) |ver| { |
| 847 | error.InvalidUtf8 => unreachable, // Windows only | 837 | result.target.os.version_range.linux.glibc = ver; |
| 848 | error.BadPathName => unreachable, // Windows only | 838 | return result; |
| 849 | error.UnsupportedReparsePointType => unreachable, // Windows only | 839 | } else |err| switch (err) { |
| 850 | | 840 | error.GLibCNotFound => {}, |
| 851 | error.AccessDenied, | 841 | else => |e| return e, |
| 852 | error.FileNotFound, | 842 | } |
| 853 | error.NotLink, | | |
| 854 | error.NotDir, | | |
| 855 | => break :glibc_ver, | | |
| 856 | | | |
| 857 | error.SystemResources, | | |
| 858 | error.FileSystem, | | |
| 859 | error.SymLinkLoop, | | |
| 860 | error.Unexpected, | | |
| 861 | => |e| return e, | | |
| 862 | }; | | |
| 863 | result.target.os.version_range.linux.glibc = glibcVerFromLinkName( | | |
| 864 | fs.path.basename(link_name), | | |
| 865 | "ld-", | | |
| 866 | ) catch |err| switch (err) { | | |
| 867 | error.UnrecognizedGnuLibCFileName, | | |
| 868 | error.InvalidGnuLibCVersion, | | |
| 869 | => break :glibc_ver, | | |
| 870 | }; | | |
| 871 | } | 843 | } |
| | 844 | |
| | 845 | // So far, no luck. Next we try to see if the information is |
| | 846 | // present in the symlink data for the dynamic linker path. |
| | 847 | var link_buf: [std.os.PATH_MAX]u8 = undefined; |
| | 848 | const link_name = std.os.readlink(dl_path, &link_buf) catch |err| switch (err) { |
| | 849 | error.NameTooLong => unreachable, |
| | 850 | error.InvalidUtf8 => unreachable, // Windows only |
| | 851 | error.BadPathName => unreachable, // Windows only |
| | 852 | error.UnsupportedReparsePointType => unreachable, // Windows only |
| | 853 | |
| | 854 | error.AccessDenied, |
| | 855 | error.FileNotFound, |
| | 856 | error.NotLink, |
| | 857 | error.NotDir, |
| | 858 | => break :glibc_ver, |
| | 859 | |
| | 860 | error.SystemResources, |
| | 861 | error.FileSystem, |
| | 862 | error.SymLinkLoop, |
| | 863 | error.Unexpected, |
| | 864 | => |e| return e, |
| | 865 | }; |
| | 866 | result.target.os.version_range.linux.glibc = glibcVerFromLinkName( |
| | 867 | fs.path.basename(link_name), |
| | 868 | "ld-", |
| | 869 | ) catch |err| switch (err) { |
| | 870 | error.UnrecognizedGnuLibCFileName, |
| | 871 | error.InvalidGnuLibCVersion, |
| | 872 | => break :glibc_ver, |
| | 873 | }; |
| | 874 | return result; |
| | 875 | } |
| | 876 | |
| | 877 | // Nothing worked so far. Finally we fall back to hard-coded search paths. |
| | 878 | // Some distros such as Debian keep their libc.so.6 in `/lib/$triple/`. |
| | 879 | var path_buf: [std.os.PATH_MAX]u8 = undefined; |
| | 880 | var index: usize = 0; |
| | 881 | const prefix = "/lib/"; |
| | 882 | const cpu_arch = @tagName(result.target.cpu.arch); |
| | 883 | const os_tag = @tagName(result.target.os.tag); |
| | 884 | const abi = @tagName(result.target.abi); |
| | 885 | mem.copy(u8, path_buf[index..], prefix); |
| | 886 | index += prefix.len; |
| | 887 | mem.copy(u8, path_buf[index..], cpu_arch); |
| | 888 | index += cpu_arch.len; |
| | 889 | path_buf[index] = '-'; |
| | 890 | index += 1; |
| | 891 | mem.copy(u8, path_buf[index..], os_tag); |
| | 892 | index += os_tag.len; |
| | 893 | path_buf[index] = '-'; |
| | 894 | index += 1; |
| | 895 | mem.copy(u8, path_buf[index..], abi); |
| | 896 | index += abi.len; |
| | 897 | const rpath = path_buf[0..index]; |
| | 898 | if (glibcVerFromRPath(rpath)) |ver| { |
| | 899 | result.target.os.version_range.linux.glibc = ver; |
| | 900 | return result; |
| | 901 | } else |err| switch (err) { |
| | 902 | error.GLibCNotFound => {}, |
| | 903 | else => |e| return e, |
| 872 | } | 904 | } |
| 873 | } | 905 | } |
| 874 | | 906 | |