authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-10-29 16:16:57-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-10-29 16:16:57-04:00
loge036cc48d59e5f7c025df7bbd9923a13e30c6ec9
tree6aa141080e273b933482672942e2af945989dff4
parenta70c86e6611b3f24c7e8959b25407602559b893a
parent3e926d868ef75e521476a73f6c8245a688ff06c8
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #13342 from ziglang/fix-glibc-race

glibc: fix race condition when building stubs

3 files changed, 344 insertions(+), 350 deletions(-)

ci/srht/freebsd_script+1-1
...@@ -9,7 +9,7 @@ sudo pkg install -y cmake py39-s3cmd wget curl jq samurai...@@ -9,7 +9,7 @@ sudo pkg install -y cmake py39-s3cmd wget curl jq samurai
9ZIGDIR="$(pwd)"9ZIGDIR="$(pwd)"
10TARGET="x86_64-freebsd-gnu"10TARGET="x86_64-freebsd-gnu"
11MCPU="baseline"11MCPU="baseline"
12CACHE_BASENAME="zig+llvm+lld+clang-$TARGET-0.10.0-dev.61+9be8396b7"12CACHE_BASENAME="zig+llvm+lld+clang-$TARGET-0.10.0-dev.4560+828735ac0"
13PREFIX="$HOME/$CACHE_BASENAME"13PREFIX="$HOME/$CACHE_BASENAME"
1414
15cd $HOME15cd $HOME
src/glibc.zig+332-348
...@@ -50,9 +50,12 @@ pub const LoadMetaDataError = error{...@@ -50,9 +50,12 @@ pub const LoadMetaDataError = error{
50 OutOfMemory,50 OutOfMemory,
51};51};
5252
53pub const abilists_path = "libc" ++ path.sep_str ++ "glibc" ++ path.sep_str ++ "abilists";
54pub const abilists_max_size = 800 * 1024; // Bigger than this and something is definitely borked.
55
53/// This function will emit a log error when there is a problem with the zig56/// This function will emit a log error when there is a problem with the zig
54/// installation and then return `error.ZigInstallationCorrupt`.57/// installation and then return `error.ZigInstallationCorrupt`.
55pub fn loadMetaData(gpa: Allocator, zig_lib_dir: fs.Dir) LoadMetaDataError!*ABI {58pub fn loadMetaData(gpa: Allocator, contents: []const u8) LoadMetaDataError!*ABI {
56 const tracy = trace(@src());59 const tracy = trace(@src());
57 defer tracy.end();60 defer tracy.end();
5861
...@@ -60,22 +63,6 @@ pub fn loadMetaData(gpa: Allocator, zig_lib_dir: fs.Dir) LoadMetaDataError!*ABI...@@ -60,22 +63,6 @@ pub fn loadMetaData(gpa: Allocator, zig_lib_dir: fs.Dir) LoadMetaDataError!*ABI
60 errdefer arena_allocator.deinit();63 errdefer arena_allocator.deinit();
61 const arena = arena_allocator.allocator();64 const arena = arena_allocator.allocator();
6265
63 var glibc_dir = zig_lib_dir.openDir("libc" ++ path.sep_str ++ "glibc", .{}) catch |err| {
64 log.err("unable to open glibc dir: {s}", .{@errorName(err)});
65 return error.ZigInstallationCorrupt;
66 };
67 defer glibc_dir.close();
68
69 const max_size = 500 * 1024; // Bigger than this and something is definitely borked.
70 const contents = glibc_dir.readFileAlloc(arena, "abilists", max_size) catch |err| switch (err) {
71 error.OutOfMemory => return error.OutOfMemory,
72 else => {
73 log.err("unable to read libc" ++ path.sep_str ++ "glibc" ++ path.sep_str ++
74 "abilists: {s}", .{@errorName(err)});
75 return error.ZigInstallationCorrupt;
76 },
77 };
78
79 var index: usize = 0;66 var index: usize = 0;
8067
81 {68 {
...@@ -662,386 +649,383 @@ pub fn buildSharedObjects(comp: *Compilation) !void {...@@ -662,386 +649,383 @@ pub fn buildSharedObjects(comp: *Compilation) !void {
662 const target_version = target.os.version_range.linux.glibc;649 const target_version = target.os.version_range.linux.glibc;
663650
664 // Use the global cache directory.651 // Use the global cache directory.
665 var cache_parent: Cache = .{652 var cache: Cache = .{
666 .gpa = comp.gpa,653 .gpa = comp.gpa,
667 .manifest_dir = try comp.global_cache_directory.handle.makeOpenPath("h", .{}),654 .manifest_dir = try comp.global_cache_directory.handle.makeOpenPath("h", .{}),
668 };655 };
669 defer cache_parent.manifest_dir.close();656 defer cache.manifest_dir.close();
670657
671 var cache = cache_parent.obtain();658 var man = cache.obtain();
672 defer cache.deinit();659 defer man.deinit();
673 cache.hash.addBytes(build_options.version);660 man.hash.addBytes(build_options.version);
674 cache.hash.addBytes(comp.zig_lib_directory.path orelse ".");661 man.hash.addBytes(comp.zig_lib_directory.path orelse ".");
675 cache.hash.add(target.cpu.arch);662 man.hash.add(target.cpu.arch);
676 cache.hash.add(target.abi);663 man.hash.add(target.abi);
677 cache.hash.add(target_version);664 man.hash.add(target_version);
678665
679 const hit = try cache.hit();666 const full_abilists_path = try comp.zig_lib_directory.join(arena, &.{abilists_path});
680 const digest = cache.final();667 const abilists_index = try man.addFile(full_abilists_path, abilists_max_size);
681 const o_sub_path = try path.join(arena, &[_][]const u8{ "o", &digest });668
669 if (try man.hit()) {
670 const digest = man.final();
671
672 assert(comp.glibc_so_files == null);
673 comp.glibc_so_files = BuiltSharedObjects{
674 .lock = man.toOwnedLock(),
675 .dir_path = try comp.global_cache_directory.join(comp.gpa, &.{ "o", &digest }),
676 };
677 return;
678 }
682679
683 // Even if we get a hit, it doesn't guarantee that we finished the job last time.680 const digest = man.final();
684 // We use the presence of an "ok" file to determine if it is a true hit.681 const o_sub_path = try path.join(arena, &[_][]const u8{ "o", &digest });
685682
686 var o_directory: Compilation.Directory = .{683 var o_directory: Compilation.Directory = .{
687 .handle = try comp.global_cache_directory.handle.makeOpenPath(o_sub_path, .{}),684 .handle = try comp.global_cache_directory.handle.makeOpenPath(o_sub_path, .{}),
688 .path = try path.join(arena, &[_][]const u8{ comp.global_cache_directory.path.?, o_sub_path }),685 .path = try comp.global_cache_directory.join(arena, &.{o_sub_path}),
689 };686 };
690 defer o_directory.handle.close();687 defer o_directory.handle.close();
691688
692 const ok_basename = "ok";689 const abilists_contents = man.files.items[abilists_index].contents.?;
693 const actual_hit = if (hit) blk: {690 const metadata = try loadMetaData(comp.gpa, abilists_contents);
694 o_directory.handle.access(ok_basename, .{}) catch |err| switch (err) {691 defer metadata.destroy(comp.gpa);
695 error.FileNotFound => break :blk false,
696 else => |e| return e,
697 };
698 break :blk true;
699 } else false;
700
701 if (!actual_hit) {
702 const metadata = try loadMetaData(comp.gpa, comp.zig_lib_directory.handle);
703 defer metadata.destroy(comp.gpa);
704692
705 const target_targ_index = for (metadata.all_targets) |targ, i| {693 const target_targ_index = for (metadata.all_targets) |targ, i| {
706 if (targ.arch == target.cpu.arch and694 if (targ.arch == target.cpu.arch and
707 targ.os == target.os.tag and695 targ.os == target.os.tag and
708 targ.abi == target.abi)696 targ.abi == target.abi)
709 {697 {
710 break i;698 break i;
711 }699 }
712 } else {700 } else {
713 unreachable; // target_util.available_libcs prevents us from getting here701 unreachable; // target_util.available_libcs prevents us from getting here
714 };702 };
715703
716 const target_ver_index = for (metadata.all_versions) |ver, i| {704 const target_ver_index = for (metadata.all_versions) |ver, i| {
717 switch (ver.order(target_version)) {705 switch (ver.order(target_version)) {
718 .eq => break i,706 .eq => break i,
719 .lt => continue,707 .lt => continue,
720 .gt => {708 .gt => {
721 // TODO Expose via compile error mechanism instead of log.709 // TODO Expose via compile error mechanism instead of log.
722 log.warn("invalid target glibc version: {}", .{target_version});710 log.warn("invalid target glibc version: {}", .{target_version});
723 return error.InvalidTargetGLibCVersion;711 return error.InvalidTargetGLibCVersion;
724 },712 },
725 }713 }
726 } else blk: {714 } else blk: {
727 const latest_index = metadata.all_versions.len - 1;715 const latest_index = metadata.all_versions.len - 1;
728 log.warn("zig cannot build new glibc version {}; providing instead {}", .{716 log.warn("zig cannot build new glibc version {}; providing instead {}", .{
729 target_version, metadata.all_versions[latest_index],717 target_version, metadata.all_versions[latest_index],
730 });718 });
731 break :blk latest_index;719 break :blk latest_index;
732 };720 };
733721
734 {722 {
735 var map_contents = std.ArrayList(u8).init(arena);723 var map_contents = std.ArrayList(u8).init(arena);
736 for (metadata.all_versions[0 .. target_ver_index + 1]) |ver| {724 for (metadata.all_versions[0 .. target_ver_index + 1]) |ver| {
737 if (ver.patch == 0) {725 if (ver.patch == 0) {
738 try map_contents.writer().print("GLIBC_{d}.{d} {{ }};\n", .{ ver.major, ver.minor });726 try map_contents.writer().print("GLIBC_{d}.{d} {{ }};\n", .{ ver.major, ver.minor });
739 } else {727 } else {
740 try map_contents.writer().print("GLIBC_{d}.{d}.{d} {{ }};\n", .{ ver.major, ver.minor, ver.patch });728 try map_contents.writer().print("GLIBC_{d}.{d}.{d} {{ }};\n", .{ ver.major, ver.minor, ver.patch });
741 }
742 }729 }
743 try o_directory.handle.writeFile(all_map_basename, map_contents.items);
744 map_contents.deinit(); // The most recent allocation of an arena can be freed :)
745 }730 }
731 try o_directory.handle.writeFile(all_map_basename, map_contents.items);
732 map_contents.deinit(); // The most recent allocation of an arena can be freed :)
733 }
746734
747 var stubs_asm = std.ArrayList(u8).init(comp.gpa);735 var stubs_asm = std.ArrayList(u8).init(comp.gpa);
748 defer stubs_asm.deinit();736 defer stubs_asm.deinit();
749737
750 for (libs) |lib, lib_i| {738 for (libs) |lib, lib_i| {
751 stubs_asm.shrinkRetainingCapacity(0);739 stubs_asm.shrinkRetainingCapacity(0);
752 try stubs_asm.appendSlice(".text\n");740 try stubs_asm.appendSlice(".text\n");
753741
754 var inc_i: usize = 0;742 var inc_i: usize = 0;
755743
756 const fn_inclusions_len = mem.readIntLittle(u16, metadata.inclusions[inc_i..][0..2]);744 const fn_inclusions_len = mem.readIntLittle(u16, metadata.inclusions[inc_i..][0..2]);
757 inc_i += 2;745 inc_i += 2;
758746
759 var sym_i: usize = 0;747 var sym_i: usize = 0;
760 var opt_symbol_name: ?[]const u8 = null;748 var opt_symbol_name: ?[]const u8 = null;
761 var versions_buffer: [32]u8 = undefined;749 var versions_buffer: [32]u8 = undefined;
762 var versions_len: usize = undefined;750 var versions_len: usize = undefined;
763 while (sym_i < fn_inclusions_len) : (sym_i += 1) {751 while (sym_i < fn_inclusions_len) : (sym_i += 1) {
764 const sym_name = opt_symbol_name orelse n: {752 const sym_name = opt_symbol_name orelse n: {
765 const name = mem.sliceTo(metadata.inclusions[inc_i..], 0);753 const name = mem.sliceTo(metadata.inclusions[inc_i..], 0);
766 inc_i += name.len + 1;754 inc_i += name.len + 1;
767755
768 opt_symbol_name = name;756 opt_symbol_name = name;
769 versions_buffer = undefined;757 versions_buffer = undefined;
770 versions_len = 0;758 versions_len = 0;
771 break :n name;759 break :n name;
772 };760 };
773 const targets = mem.readIntLittle(u32, metadata.inclusions[inc_i..][0..4]);761 const targets = mem.readIntLittle(u32, metadata.inclusions[inc_i..][0..4]);
774 inc_i += 4;762 inc_i += 4;
775763
776 const lib_index = metadata.inclusions[inc_i];764 const lib_index = metadata.inclusions[inc_i];
765 inc_i += 1;
766 const is_terminal = (targets & (1 << 31)) != 0;
767 if (is_terminal) opt_symbol_name = null;
768
769 // Test whether the inclusion applies to our current library and target.
770 const ok_lib_and_target =
771 (lib_index == lib_i) and
772 ((targets & (@as(u32, 1) << @intCast(u5, target_targ_index))) != 0);
773
774 while (true) {
775 const byte = metadata.inclusions[inc_i];
777 inc_i += 1;776 inc_i += 1;
778 const is_terminal = (targets & (1 << 31)) != 0;777 const last = (byte & 0b1000_0000) != 0;
779 if (is_terminal) opt_symbol_name = null;778 const ver_i = @truncate(u7, byte);
780779 if (ok_lib_and_target and ver_i <= target_ver_index) {
781 // Test whether the inclusion applies to our current library and target.780 versions_buffer[versions_len] = ver_i;
782 const ok_lib_and_target =781 versions_len += 1;
783 (lib_index == lib_i) and
784 ((targets & (@as(u32, 1) << @intCast(u5, target_targ_index))) != 0);
785
786 while (true) {
787 const byte = metadata.inclusions[inc_i];
788 inc_i += 1;
789 const last = (byte & 0b1000_0000) != 0;
790 const ver_i = @truncate(u7, byte);
791 if (ok_lib_and_target and ver_i <= target_ver_index) {
792 versions_buffer[versions_len] = ver_i;
793 versions_len += 1;
794 }
795 if (last) break;
796 }782 }
783 if (last) break;
784 }
797785
798 if (!is_terminal) continue;786 if (!is_terminal) continue;
799787
800 // Pick the default symbol version:788 // Pick the default symbol version:
801 // - If there are no versions, don't emit it789 // - If there are no versions, don't emit it
802 // - Take the greatest one <= than the target one790 // - Take the greatest one <= than the target one
803 // - If none of them is <= than the791 // - If none of them is <= than the
804 // specified one don't pick any default version792 // specified one don't pick any default version
805 if (versions_len == 0) continue;793 if (versions_len == 0) continue;
806 var chosen_def_ver_index: u8 = 255;794 var chosen_def_ver_index: u8 = 255;
807 {795 {
808 var ver_buf_i: u8 = 0;796 var ver_buf_i: u8 = 0;
809 while (ver_buf_i < versions_len) : (ver_buf_i += 1) {797 while (ver_buf_i < versions_len) : (ver_buf_i += 1) {
810 const ver_index = versions_buffer[ver_buf_i];798 const ver_index = versions_buffer[ver_buf_i];
811 if (chosen_def_ver_index == 255 or ver_index > chosen_def_ver_index) {799 if (chosen_def_ver_index == 255 or ver_index > chosen_def_ver_index) {
812 chosen_def_ver_index = ver_index;800 chosen_def_ver_index = ver_index;
813 }
814 }801 }
815 }802 }
816 {803 }
817 var ver_buf_i: u8 = 0;804 {
818 while (ver_buf_i < versions_len) : (ver_buf_i += 1) {805 var ver_buf_i: u8 = 0;
819 // Example:806 while (ver_buf_i < versions_len) : (ver_buf_i += 1) {
820 // .globl _Exit_2_2_5807 // Example:
821 // .type _Exit_2_2_5, %function;808 // .globl _Exit_2_2_5
822 // .symver _Exit_2_2_5, _Exit@@GLIBC_2.2.5809 // .type _Exit_2_2_5, %function;
823 // _Exit_2_2_5:810 // .symver _Exit_2_2_5, _Exit@@GLIBC_2.2.5
824 const ver_index = versions_buffer[ver_buf_i];811 // _Exit_2_2_5:
825 const ver = metadata.all_versions[ver_index];812 const ver_index = versions_buffer[ver_buf_i];
826 // Default symbol version definition vs normal symbol version definition813 const ver = metadata.all_versions[ver_index];
827 const want_default = chosen_def_ver_index != 255 and ver_index == chosen_def_ver_index;814 // Default symbol version definition vs normal symbol version definition
828 const at_sign_str: []const u8 = if (want_default) "@@" else "@";815 const want_default = chosen_def_ver_index != 255 and ver_index == chosen_def_ver_index;
829 if (ver.patch == 0) {816 const at_sign_str: []const u8 = if (want_default) "@@" else "@";
830 const sym_plus_ver = if (want_default)817 if (ver.patch == 0) {
831 sym_name818 const sym_plus_ver = if (want_default)
832 else819 sym_name
833 try std.fmt.allocPrint(820 else
834 arena,821 try std.fmt.allocPrint(
835 "{s}_GLIBC_{d}_{d}",822 arena,
836 .{ sym_name, ver.major, ver.minor },823 "{s}_GLIBC_{d}_{d}",
837 );824 .{ sym_name, ver.major, ver.minor },
838 try stubs_asm.writer().print(825 );
839 \\.globl {s}826 try stubs_asm.writer().print(
840 \\.type {s}, %function;827 \\.globl {s}
841 \\.symver {s}, {s}{s}GLIBC_{d}.{d}828 \\.type {s}, %function;
842 \\{s}:829 \\.symver {s}, {s}{s}GLIBC_{d}.{d}
843 \\830 \\{s}:
844 , .{831 \\
845 sym_plus_ver,832 , .{
846 sym_plus_ver,833 sym_plus_ver,
847 sym_plus_ver,834 sym_plus_ver,
848 sym_name,835 sym_plus_ver,
849 at_sign_str,836 sym_name,
850 ver.major,837 at_sign_str,
851 ver.minor,838 ver.major,
852 sym_plus_ver,839 ver.minor,
853 });840 sym_plus_ver,
854 } else {841 });
855 const sym_plus_ver = if (want_default)842 } else {
856 sym_name843 const sym_plus_ver = if (want_default)
857 else844 sym_name
858 try std.fmt.allocPrint(845 else
859 arena,846 try std.fmt.allocPrint(
860 "{s}_GLIBC_{d}_{d}_{d}",847 arena,
861 .{ sym_name, ver.major, ver.minor, ver.patch },848 "{s}_GLIBC_{d}_{d}_{d}",
862 );849 .{ sym_name, ver.major, ver.minor, ver.patch },
863 try stubs_asm.writer().print(850 );
864 \\.globl {s}851 try stubs_asm.writer().print(
865 \\.type {s}, %function;852 \\.globl {s}
866 \\.symver {s}, {s}{s}GLIBC_{d}.{d}.{d}853 \\.type {s}, %function;
867 \\{s}:854 \\.symver {s}, {s}{s}GLIBC_{d}.{d}.{d}
868 \\855 \\{s}:
869 , .{856 \\
870 sym_plus_ver,857 , .{
871 sym_plus_ver,858 sym_plus_ver,
872 sym_plus_ver,859 sym_plus_ver,
873 sym_name,860 sym_plus_ver,
874 at_sign_str,861 sym_name,
875 ver.major,862 at_sign_str,
876 ver.minor,863 ver.major,
877 ver.patch,864 ver.minor,
878 sym_plus_ver,865 ver.patch,
879 });866 sym_plus_ver,
880 }867 });
881 }868 }
882 }869 }
883 }870 }
871 }
872
873 try stubs_asm.appendSlice(".data\n");
874
875 const obj_inclusions_len = mem.readIntLittle(u16, metadata.inclusions[inc_i..][0..2]);
876 inc_i += 2;
884877
885 try stubs_asm.appendSlice(".data\n");878 sym_i = 0;
879 opt_symbol_name = null;
880 versions_buffer = undefined;
881 versions_len = undefined;
882 while (sym_i < obj_inclusions_len) : (sym_i += 1) {
883 const sym_name = opt_symbol_name orelse n: {
884 const name = mem.sliceTo(metadata.inclusions[inc_i..], 0);
885 inc_i += name.len + 1;
886886
887 const obj_inclusions_len = mem.readIntLittle(u16, metadata.inclusions[inc_i..][0..2]);887 opt_symbol_name = name;
888 versions_buffer = undefined;
889 versions_len = 0;
890 break :n name;
891 };
892 const targets = mem.readIntLittle(u32, metadata.inclusions[inc_i..][0..4]);
893 inc_i += 4;
894
895 const size = mem.readIntLittle(u16, metadata.inclusions[inc_i..][0..2]);
888 inc_i += 2;896 inc_i += 2;
889897
890 sym_i = 0;898 const lib_index = metadata.inclusions[inc_i];
891 opt_symbol_name = null;899 inc_i += 1;
892 versions_buffer = undefined;900 const is_terminal = (targets & (1 << 31)) != 0;
893 versions_len = undefined;901 if (is_terminal) opt_symbol_name = null;
894 while (sym_i < obj_inclusions_len) : (sym_i += 1) {
895 const sym_name = opt_symbol_name orelse n: {
896 const name = mem.sliceTo(metadata.inclusions[inc_i..], 0);
897 inc_i += name.len + 1;
898
899 opt_symbol_name = name;
900 versions_buffer = undefined;
901 versions_len = 0;
902 break :n name;
903 };
904 const targets = mem.readIntLittle(u32, metadata.inclusions[inc_i..][0..4]);
905 inc_i += 4;
906902
907 const size = mem.readIntLittle(u16, metadata.inclusions[inc_i..][0..2]);903 // Test whether the inclusion applies to our current library and target.
908 inc_i += 2;904 const ok_lib_and_target =
905 (lib_index == lib_i) and
906 ((targets & (@as(u32, 1) << @intCast(u5, target_targ_index))) != 0);
909907
910 const lib_index = metadata.inclusions[inc_i];908 while (true) {
909 const byte = metadata.inclusions[inc_i];
911 inc_i += 1;910 inc_i += 1;
912 const is_terminal = (targets & (1 << 31)) != 0;911 const last = (byte & 0b1000_0000) != 0;
913 if (is_terminal) opt_symbol_name = null;912 const ver_i = @truncate(u7, byte);
914913 if (ok_lib_and_target and ver_i <= target_ver_index) {
915 // Test whether the inclusion applies to our current library and target.914 versions_buffer[versions_len] = ver_i;
916 const ok_lib_and_target =915 versions_len += 1;
917 (lib_index == lib_i) and
918 ((targets & (@as(u32, 1) << @intCast(u5, target_targ_index))) != 0);
919
920 while (true) {
921 const byte = metadata.inclusions[inc_i];
922 inc_i += 1;
923 const last = (byte & 0b1000_0000) != 0;
924 const ver_i = @truncate(u7, byte);
925 if (ok_lib_and_target and ver_i <= target_ver_index) {
926 versions_buffer[versions_len] = ver_i;
927 versions_len += 1;
928 }
929 if (last) break;
930 }916 }
917 if (last) break;
918 }
919
920 if (!is_terminal) continue;
931921
932 if (!is_terminal) continue;922 // Pick the default symbol version:
933923 // - If there are no versions, don't emit it
934 // Pick the default symbol version:924 // - Take the greatest one <= than the target one
935 // - If there are no versions, don't emit it925 // - If none of them is <= than the
936 // - Take the greatest one <= than the target one926 // specified one don't pick any default version
937 // - If none of them is <= than the927 if (versions_len == 0) continue;
938 // specified one don't pick any default version928 var chosen_def_ver_index: u8 = 255;
939 if (versions_len == 0) continue;929 {
940 var chosen_def_ver_index: u8 = 255;930 var ver_buf_i: u8 = 0;
941 {931 while (ver_buf_i < versions_len) : (ver_buf_i += 1) {
942 var ver_buf_i: u8 = 0;932 const ver_index = versions_buffer[ver_buf_i];
943 while (ver_buf_i < versions_len) : (ver_buf_i += 1) {933 if (chosen_def_ver_index == 255 or ver_index > chosen_def_ver_index) {
944 const ver_index = versions_buffer[ver_buf_i];934 chosen_def_ver_index = ver_index;
945 if (chosen_def_ver_index == 255 or ver_index > chosen_def_ver_index) {
946 chosen_def_ver_index = ver_index;
947 }
948 }935 }
949 }936 }
950 {937 }
951 var ver_buf_i: u8 = 0;938 {
952 while (ver_buf_i < versions_len) : (ver_buf_i += 1) {939 var ver_buf_i: u8 = 0;
953 // Example:940 while (ver_buf_i < versions_len) : (ver_buf_i += 1) {
954 // .globl environ_2_2_5941 // Example:
955 // .type environ_2_2_5, %object;942 // .globl environ_2_2_5
956 // .size environ_2_2_5, 4;943 // .type environ_2_2_5, %object;
957 // .symver environ_2_2_5, environ@@GLIBC_2.2.5944 // .size environ_2_2_5, 4;
958 // environ_2_2_5:945 // .symver environ_2_2_5, environ@@GLIBC_2.2.5
959 const ver_index = versions_buffer[ver_buf_i];946 // environ_2_2_5:
960 const ver = metadata.all_versions[ver_index];947 const ver_index = versions_buffer[ver_buf_i];
961 // Default symbol version definition vs normal symbol version definition948 const ver = metadata.all_versions[ver_index];
962 const want_default = chosen_def_ver_index != 255 and ver_index == chosen_def_ver_index;949 // Default symbol version definition vs normal symbol version definition
963 const at_sign_str: []const u8 = if (want_default) "@@" else "@";950 const want_default = chosen_def_ver_index != 255 and ver_index == chosen_def_ver_index;
964 if (ver.patch == 0) {951 const at_sign_str: []const u8 = if (want_default) "@@" else "@";
965 const sym_plus_ver = if (want_default)952 if (ver.patch == 0) {
966 sym_name953 const sym_plus_ver = if (want_default)
967 else954 sym_name
968 try std.fmt.allocPrint(955 else
969 arena,956 try std.fmt.allocPrint(
970 "{s}_GLIBC_{d}_{d}",957 arena,
971 .{ sym_name, ver.major, ver.minor },958 "{s}_GLIBC_{d}_{d}",
972 );959 .{ sym_name, ver.major, ver.minor },
973 try stubs_asm.writer().print(960 );
974 \\.globl {s}961 try stubs_asm.writer().print(
975 \\.type {s}, %object;962 \\.globl {s}
976 \\.size {s}, {d};963 \\.type {s}, %object;
977 \\.symver {s}, {s}{s}GLIBC_{d}.{d}964 \\.size {s}, {d};
978 \\{s}:965 \\.symver {s}, {s}{s}GLIBC_{d}.{d}
979 \\966 \\{s}:
980 , .{967 \\
981 sym_plus_ver,968 , .{
982 sym_plus_ver,969 sym_plus_ver,
983 sym_plus_ver,970 sym_plus_ver,
984 size,971 sym_plus_ver,
985 sym_plus_ver,972 size,
986 sym_name,973 sym_plus_ver,
987 at_sign_str,974 sym_name,
988 ver.major,975 at_sign_str,
989 ver.minor,976 ver.major,
990 sym_plus_ver,977 ver.minor,
991 });978 sym_plus_ver,
992 } else {979 });
993 const sym_plus_ver = if (want_default)980 } else {
994 sym_name981 const sym_plus_ver = if (want_default)
995 else982 sym_name
996 try std.fmt.allocPrint(983 else
997 arena,984 try std.fmt.allocPrint(
998 "{s}_GLIBC_{d}_{d}_{d}",985 arena,
999 .{ sym_name, ver.major, ver.minor, ver.patch },986 "{s}_GLIBC_{d}_{d}_{d}",
1000 );987 .{ sym_name, ver.major, ver.minor, ver.patch },
1001 try stubs_asm.writer().print(988 );
1002 \\.globl {s}989 try stubs_asm.writer().print(
1003 \\.type {s}, %object;990 \\.globl {s}
1004 \\.size {s}, {d};991 \\.type {s}, %object;
1005 \\.symver {s}, {s}{s}GLIBC_{d}.{d}.{d}992 \\.size {s}, {d};
1006 \\{s}:993 \\.symver {s}, {s}{s}GLIBC_{d}.{d}.{d}
1007 \\994 \\{s}:
1008 , .{995 \\
1009 sym_plus_ver,996 , .{
1010 sym_plus_ver,997 sym_plus_ver,
1011 sym_plus_ver,998 sym_plus_ver,
1012 size,999 sym_plus_ver,
1013 sym_plus_ver,1000 size,
1014 sym_name,1001 sym_plus_ver,
1015 at_sign_str,1002 sym_name,
1016 ver.major,1003 at_sign_str,
1017 ver.minor,1004 ver.major,
1018 ver.patch,1005 ver.minor,
1019 sym_plus_ver,1006 ver.patch,
1020 });1007 sym_plus_ver,
1021 }1008 });
1022 }1009 }
1023 }1010 }
1024 }1011 }
1012 }
10251013
1026 var lib_name_buf: [32]u8 = undefined; // Larger than each of the names "c", "pthread", etc.1014 var lib_name_buf: [32]u8 = undefined; // Larger than each of the names "c", "pthread", etc.
1027 const asm_file_basename = std.fmt.bufPrint(&lib_name_buf, "{s}.s", .{lib.name}) catch unreachable;1015 const asm_file_basename = std.fmt.bufPrint(&lib_name_buf, "{s}.s", .{lib.name}) catch unreachable;
1028 try o_directory.handle.writeFile(asm_file_basename, stubs_asm.items);1016 try o_directory.handle.writeFile(asm_file_basename, stubs_asm.items);
10291017
1030 try buildSharedLib(comp, arena, comp.global_cache_directory, o_directory, asm_file_basename, lib);1018 try buildSharedLib(comp, arena, comp.global_cache_directory, o_directory, asm_file_basename, lib);
1031 }
1032 // No need to write the manifest because there are no file inputs associated with this cache hash.
1033 // However we do need to write the ok file now.
1034 if (o_directory.handle.createFile(ok_basename, .{})) |file| {
1035 file.close();
1036 } else |err| {
1037 log.warn("glibc shared objects: failed to mark completion: {s}", .{@errorName(err)});
1038 }
1039 }1019 }
10401020
1021 man.writeManifest() catch |err| {
1022 log.warn("failed to write cache manifest for glibc stubs: {s}", .{@errorName(err)});
1023 };
1024
1041 assert(comp.glibc_so_files == null);1025 assert(comp.glibc_so_files == null);
1042 comp.glibc_so_files = BuiltSharedObjects{1026 comp.glibc_so_files = BuiltSharedObjects{
1043 .lock = cache.toOwnedLock(),1027 .lock = man.toOwnedLock(),
1044 .dir_path = try path.join(comp.gpa, &[_][]const u8{ comp.global_cache_directory.path.?, o_sub_path }),1028 .dir_path = try comp.global_cache_directory.join(comp.gpa, &.{ "o", &digest }),
1045 };1029 };
1046}1030}
10471031
src/print_targets.zig+11-1
...@@ -25,7 +25,17 @@ pub fn cmdTargets(...@@ -25,7 +25,17 @@ pub fn cmdTargets(
25 defer zig_lib_directory.handle.close();25 defer zig_lib_directory.handle.close();
26 defer allocator.free(zig_lib_directory.path.?);26 defer allocator.free(zig_lib_directory.path.?);
2727
28 const glibc_abi = try glibc.loadMetaData(allocator, zig_lib_directory.handle);28 const abilists_contents = zig_lib_directory.handle.readFileAlloc(
29 allocator,
30 glibc.abilists_path,
31 glibc.abilists_max_size,
32 ) catch |err| switch (err) {
33 error.OutOfMemory => return error.OutOfMemory,
34 else => fatal("unable to read " ++ glibc.abilists_path ++ ": {s}", .{@errorName(err)}),
35 };
36 defer allocator.free(abilists_contents);
37
38 const glibc_abi = try glibc.loadMetaData(allocator, abilists_contents);
29 defer glibc_abi.destroy(allocator);39 defer glibc_abi.destroy(allocator);
3040
31 var bw = io.bufferedWriter(stdout);41 var bw = io.bufferedWriter(stdout);