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
99ZIGDIR="$(pwd)"
1010TARGET="x86_64-freebsd-gnu"
1111MCPU="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"
1313PREFIX="$HOME/$CACHE_BASENAME"
1414
1515cd $HOME
src/glibc.zig+332-348
......@@ -50,9 +50,12 @@ pub const LoadMetaDataError = error{
5050 OutOfMemory,
5151};
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
5356/// This function will emit a log error when there is a problem with the zig
5457/// 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 {
5659 const tracy = trace(@src());
5760 defer tracy.end();
5861
......@@ -60,22 +63,6 @@ pub fn loadMetaData(gpa: Allocator, zig_lib_dir: fs.Dir) LoadMetaDataError!*ABI
6063 errdefer arena_allocator.deinit();
6164 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
7966 var index: usize = 0;
8067
8168 {
......@@ -662,386 +649,383 @@ pub fn buildSharedObjects(comp: *Compilation) !void {
662649 const target_version = target.os.version_range.linux.glibc;
663650
664651 // Use the global cache directory.
665 var cache_parent: Cache = .{
652 var cache: Cache = .{
666653 .gpa = comp.gpa,
667654 .manifest_dir = try comp.global_cache_directory.handle.makeOpenPath("h", .{}),
668655 };
669 defer cache_parent.manifest_dir.close();
670
671 var cache = cache_parent.obtain();
672 defer cache.deinit();
673 cache.hash.addBytes(build_options.version);
674 cache.hash.addBytes(comp.zig_lib_directory.path orelse ".");
675 cache.hash.add(target.cpu.arch);
676 cache.hash.add(target.abi);
677 cache.hash.add(target_version);
678
679 const hit = try cache.hit();
680 const digest = cache.final();
681 const o_sub_path = try path.join(arena, &[_][]const u8{ "o", &digest });
656 defer cache.manifest_dir.close();
657
658 var man = cache.obtain();
659 defer man.deinit();
660 man.hash.addBytes(build_options.version);
661 man.hash.addBytes(comp.zig_lib_directory.path orelse ".");
662 man.hash.add(target.cpu.arch);
663 man.hash.add(target.abi);
664 man.hash.add(target_version);
665
666 const full_abilists_path = try comp.zig_lib_directory.join(arena, &.{abilists_path});
667 const abilists_index = try man.addFile(full_abilists_path, abilists_max_size);
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.
684 // We use the presence of an "ok" file to determine if it is a true hit.
680 const digest = man.final();
681 const o_sub_path = try path.join(arena, &[_][]const u8{ "o", &digest });
685682
686683 var o_directory: Compilation.Directory = .{
687684 .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}),
689686 };
690687 defer o_directory.handle.close();
691688
692 const ok_basename = "ok";
693 const actual_hit = if (hit) blk: {
694 o_directory.handle.access(ok_basename, .{}) catch |err| switch (err) {
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);
689 const abilists_contents = man.files.items[abilists_index].contents.?;
690 const metadata = try loadMetaData(comp.gpa, abilists_contents);
691 defer metadata.destroy(comp.gpa);
704692
705 const target_targ_index = for (metadata.all_targets) |targ, i| {
706 if (targ.arch == target.cpu.arch and
707 targ.os == target.os.tag and
708 targ.abi == target.abi)
709 {
710 break i;
711 }
712 } else {
713 unreachable; // target_util.available_libcs prevents us from getting here
714 };
693 const target_targ_index = for (metadata.all_targets) |targ, i| {
694 if (targ.arch == target.cpu.arch and
695 targ.os == target.os.tag and
696 targ.abi == target.abi)
697 {
698 break i;
699 }
700 } else {
701 unreachable; // target_util.available_libcs prevents us from getting here
702 };
715703
716 const target_ver_index = for (metadata.all_versions) |ver, i| {
717 switch (ver.order(target_version)) {
718 .eq => break i,
719 .lt => continue,
720 .gt => {
721 // TODO Expose via compile error mechanism instead of log.
722 log.warn("invalid target glibc version: {}", .{target_version});
723 return error.InvalidTargetGLibCVersion;
724 },
725 }
726 } else blk: {
727 const latest_index = metadata.all_versions.len - 1;
728 log.warn("zig cannot build new glibc version {}; providing instead {}", .{
729 target_version, metadata.all_versions[latest_index],
730 });
731 break :blk latest_index;
732 };
704 const target_ver_index = for (metadata.all_versions) |ver, i| {
705 switch (ver.order(target_version)) {
706 .eq => break i,
707 .lt => continue,
708 .gt => {
709 // TODO Expose via compile error mechanism instead of log.
710 log.warn("invalid target glibc version: {}", .{target_version});
711 return error.InvalidTargetGLibCVersion;
712 },
713 }
714 } else blk: {
715 const latest_index = metadata.all_versions.len - 1;
716 log.warn("zig cannot build new glibc version {}; providing instead {}", .{
717 target_version, metadata.all_versions[latest_index],
718 });
719 break :blk latest_index;
720 };
733721
734 {
735 var map_contents = std.ArrayList(u8).init(arena);
736 for (metadata.all_versions[0 .. target_ver_index + 1]) |ver| {
737 if (ver.patch == 0) {
738 try map_contents.writer().print("GLIBC_{d}.{d} {{ }};\n", .{ ver.major, ver.minor });
739 } else {
740 try map_contents.writer().print("GLIBC_{d}.{d}.{d} {{ }};\n", .{ ver.major, ver.minor, ver.patch });
741 }
722 {
723 var map_contents = std.ArrayList(u8).init(arena);
724 for (metadata.all_versions[0 .. target_ver_index + 1]) |ver| {
725 if (ver.patch == 0) {
726 try map_contents.writer().print("GLIBC_{d}.{d} {{ }};\n", .{ ver.major, ver.minor });
727 } else {
728 try map_contents.writer().print("GLIBC_{d}.{d}.{d} {{ }};\n", .{ ver.major, ver.minor, ver.patch });
742729 }
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 :)
745730 }
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);
748 defer stubs_asm.deinit();
735 var stubs_asm = std.ArrayList(u8).init(comp.gpa);
736 defer stubs_asm.deinit();
749737
750 for (libs) |lib, lib_i| {
751 stubs_asm.shrinkRetainingCapacity(0);
752 try stubs_asm.appendSlice(".text\n");
738 for (libs) |lib, lib_i| {
739 stubs_asm.shrinkRetainingCapacity(0);
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]);
757 inc_i += 2;
744 const fn_inclusions_len = mem.readIntLittle(u16, metadata.inclusions[inc_i..][0..2]);
745 inc_i += 2;
758746
759 var sym_i: usize = 0;
760 var opt_symbol_name: ?[]const u8 = null;
761 var versions_buffer: [32]u8 = undefined;
762 var versions_len: usize = undefined;
763 while (sym_i < fn_inclusions_len) : (sym_i += 1) {
764 const sym_name = opt_symbol_name orelse n: {
765 const name = mem.sliceTo(metadata.inclusions[inc_i..], 0);
766 inc_i += name.len + 1;
767
768 opt_symbol_name = name;
769 versions_buffer = undefined;
770 versions_len = 0;
771 break :n name;
772 };
773 const targets = mem.readIntLittle(u32, metadata.inclusions[inc_i..][0..4]);
774 inc_i += 4;
747 var sym_i: usize = 0;
748 var opt_symbol_name: ?[]const u8 = null;
749 var versions_buffer: [32]u8 = undefined;
750 var versions_len: usize = undefined;
751 while (sym_i < fn_inclusions_len) : (sym_i += 1) {
752 const sym_name = opt_symbol_name orelse n: {
753 const name = mem.sliceTo(metadata.inclusions[inc_i..], 0);
754 inc_i += name.len + 1;
755
756 opt_symbol_name = name;
757 versions_buffer = undefined;
758 versions_len = 0;
759 break :n name;
760 };
761 const targets = mem.readIntLittle(u32, metadata.inclusions[inc_i..][0..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];
777776 inc_i += 1;
778 const is_terminal = (targets & (1 << 31)) != 0;
779 if (is_terminal) opt_symbol_name = null;
780
781 // Test whether the inclusion applies to our current library and target.
782 const ok_lib_and_target =
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;
777 const last = (byte & 0b1000_0000) != 0;
778 const ver_i = @truncate(u7, byte);
779 if (ok_lib_and_target and ver_i <= target_ver_index) {
780 versions_buffer[versions_len] = ver_i;
781 versions_len += 1;
796782 }
783 if (last) break;
784 }
797785
798 if (!is_terminal) continue;
799
800 // Pick the default symbol version:
801 // - If there are no versions, don't emit it
802 // - Take the greatest one <= than the target one
803 // - If none of them is <= than the
804 // specified one don't pick any default version
805 if (versions_len == 0) continue;
806 var chosen_def_ver_index: u8 = 255;
807 {
808 var ver_buf_i: u8 = 0;
809 while (ver_buf_i < versions_len) : (ver_buf_i += 1) {
810 const ver_index = versions_buffer[ver_buf_i];
811 if (chosen_def_ver_index == 255 or ver_index > chosen_def_ver_index) {
812 chosen_def_ver_index = ver_index;
813 }
786 if (!is_terminal) continue;
787
788 // Pick the default symbol version:
789 // - If there are no versions, don't emit it
790 // - Take the greatest one <= than the target one
791 // - If none of them is <= than the
792 // specified one don't pick any default version
793 if (versions_len == 0) continue;
794 var chosen_def_ver_index: u8 = 255;
795 {
796 var ver_buf_i: u8 = 0;
797 while (ver_buf_i < versions_len) : (ver_buf_i += 1) {
798 const ver_index = versions_buffer[ver_buf_i];
799 if (chosen_def_ver_index == 255 or ver_index > chosen_def_ver_index) {
800 chosen_def_ver_index = ver_index;
814801 }
815802 }
816 {
817 var ver_buf_i: u8 = 0;
818 while (ver_buf_i < versions_len) : (ver_buf_i += 1) {
819 // Example:
820 // .globl _Exit_2_2_5
821 // .type _Exit_2_2_5, %function;
822 // .symver _Exit_2_2_5, _Exit@@GLIBC_2.2.5
823 // _Exit_2_2_5:
824 const ver_index = versions_buffer[ver_buf_i];
825 const ver = metadata.all_versions[ver_index];
826 // Default symbol version definition vs normal symbol version definition
827 const want_default = chosen_def_ver_index != 255 and ver_index == chosen_def_ver_index;
828 const at_sign_str: []const u8 = if (want_default) "@@" else "@";
829 if (ver.patch == 0) {
830 const sym_plus_ver = if (want_default)
831 sym_name
832 else
833 try std.fmt.allocPrint(
834 arena,
835 "{s}_GLIBC_{d}_{d}",
836 .{ sym_name, ver.major, ver.minor },
837 );
838 try stubs_asm.writer().print(
839 \\.globl {s}
840 \\.type {s}, %function;
841 \\.symver {s}, {s}{s}GLIBC_{d}.{d}
842 \\{s}:
843 \\
844 , .{
845 sym_plus_ver,
846 sym_plus_ver,
847 sym_plus_ver,
848 sym_name,
849 at_sign_str,
850 ver.major,
851 ver.minor,
852 sym_plus_ver,
853 });
854 } else {
855 const sym_plus_ver = if (want_default)
856 sym_name
857 else
858 try std.fmt.allocPrint(
859 arena,
860 "{s}_GLIBC_{d}_{d}_{d}",
861 .{ sym_name, ver.major, ver.minor, ver.patch },
862 );
863 try stubs_asm.writer().print(
864 \\.globl {s}
865 \\.type {s}, %function;
866 \\.symver {s}, {s}{s}GLIBC_{d}.{d}.{d}
867 \\{s}:
868 \\
869 , .{
870 sym_plus_ver,
871 sym_plus_ver,
872 sym_plus_ver,
873 sym_name,
874 at_sign_str,
875 ver.major,
876 ver.minor,
877 ver.patch,
878 sym_plus_ver,
879 });
880 }
803 }
804 {
805 var ver_buf_i: u8 = 0;
806 while (ver_buf_i < versions_len) : (ver_buf_i += 1) {
807 // Example:
808 // .globl _Exit_2_2_5
809 // .type _Exit_2_2_5, %function;
810 // .symver _Exit_2_2_5, _Exit@@GLIBC_2.2.5
811 // _Exit_2_2_5:
812 const ver_index = versions_buffer[ver_buf_i];
813 const ver = metadata.all_versions[ver_index];
814 // Default symbol version definition vs normal symbol version definition
815 const want_default = chosen_def_ver_index != 255 and ver_index == chosen_def_ver_index;
816 const at_sign_str: []const u8 = if (want_default) "@@" else "@";
817 if (ver.patch == 0) {
818 const sym_plus_ver = if (want_default)
819 sym_name
820 else
821 try std.fmt.allocPrint(
822 arena,
823 "{s}_GLIBC_{d}_{d}",
824 .{ sym_name, ver.major, ver.minor },
825 );
826 try stubs_asm.writer().print(
827 \\.globl {s}
828 \\.type {s}, %function;
829 \\.symver {s}, {s}{s}GLIBC_{d}.{d}
830 \\{s}:
831 \\
832 , .{
833 sym_plus_ver,
834 sym_plus_ver,
835 sym_plus_ver,
836 sym_name,
837 at_sign_str,
838 ver.major,
839 ver.minor,
840 sym_plus_ver,
841 });
842 } else {
843 const sym_plus_ver = if (want_default)
844 sym_name
845 else
846 try std.fmt.allocPrint(
847 arena,
848 "{s}_GLIBC_{d}_{d}_{d}",
849 .{ sym_name, ver.major, ver.minor, ver.patch },
850 );
851 try stubs_asm.writer().print(
852 \\.globl {s}
853 \\.type {s}, %function;
854 \\.symver {s}, {s}{s}GLIBC_{d}.{d}.{d}
855 \\{s}:
856 \\
857 , .{
858 sym_plus_ver,
859 sym_plus_ver,
860 sym_plus_ver,
861 sym_name,
862 at_sign_str,
863 ver.major,
864 ver.minor,
865 ver.patch,
866 sym_plus_ver,
867 });
881868 }
882869 }
883870 }
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]);
888896 inc_i += 2;
889897
890 sym_i = 0;
891 opt_symbol_name = null;
892 versions_buffer = undefined;
893 versions_len = undefined;
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;
898 const lib_index = metadata.inclusions[inc_i];
899 inc_i += 1;
900 const is_terminal = (targets & (1 << 31)) != 0;
901 if (is_terminal) opt_symbol_name = null;
906902
907 const size = mem.readIntLittle(u16, metadata.inclusions[inc_i..][0..2]);
908 inc_i += 2;
903 // Test whether the inclusion applies to our current library and target.
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];
911910 inc_i += 1;
912 const is_terminal = (targets & (1 << 31)) != 0;
913 if (is_terminal) opt_symbol_name = null;
914
915 // Test whether the inclusion applies to our current library and target.
916 const ok_lib_and_target =
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;
911 const last = (byte & 0b1000_0000) != 0;
912 const ver_i = @truncate(u7, byte);
913 if (ok_lib_and_target and ver_i <= target_ver_index) {
914 versions_buffer[versions_len] = ver_i;
915 versions_len += 1;
930916 }
917 if (last) break;
918 }
919
920 if (!is_terminal) continue;
931921
932 if (!is_terminal) continue;
933
934 // Pick the default symbol version:
935 // - If there are no versions, don't emit it
936 // - Take the greatest one <= than the target one
937 // - If none of them is <= than the
938 // specified one don't pick any default version
939 if (versions_len == 0) continue;
940 var chosen_def_ver_index: u8 = 255;
941 {
942 var ver_buf_i: u8 = 0;
943 while (ver_buf_i < versions_len) : (ver_buf_i += 1) {
944 const ver_index = versions_buffer[ver_buf_i];
945 if (chosen_def_ver_index == 255 or ver_index > chosen_def_ver_index) {
946 chosen_def_ver_index = ver_index;
947 }
922 // Pick the default symbol version:
923 // - If there are no versions, don't emit it
924 // - Take the greatest one <= than the target one
925 // - If none of them is <= than the
926 // specified one don't pick any default version
927 if (versions_len == 0) continue;
928 var chosen_def_ver_index: u8 = 255;
929 {
930 var ver_buf_i: u8 = 0;
931 while (ver_buf_i < versions_len) : (ver_buf_i += 1) {
932 const ver_index = versions_buffer[ver_buf_i];
933 if (chosen_def_ver_index == 255 or ver_index > chosen_def_ver_index) {
934 chosen_def_ver_index = ver_index;
948935 }
949936 }
950 {
951 var ver_buf_i: u8 = 0;
952 while (ver_buf_i < versions_len) : (ver_buf_i += 1) {
953 // Example:
954 // .globl environ_2_2_5
955 // .type environ_2_2_5, %object;
956 // .size environ_2_2_5, 4;
957 // .symver environ_2_2_5, environ@@GLIBC_2.2.5
958 // environ_2_2_5:
959 const ver_index = versions_buffer[ver_buf_i];
960 const ver = metadata.all_versions[ver_index];
961 // Default symbol version definition vs normal symbol version definition
962 const want_default = chosen_def_ver_index != 255 and ver_index == chosen_def_ver_index;
963 const at_sign_str: []const u8 = if (want_default) "@@" else "@";
964 if (ver.patch == 0) {
965 const sym_plus_ver = if (want_default)
966 sym_name
967 else
968 try std.fmt.allocPrint(
969 arena,
970 "{s}_GLIBC_{d}_{d}",
971 .{ sym_name, ver.major, ver.minor },
972 );
973 try stubs_asm.writer().print(
974 \\.globl {s}
975 \\.type {s}, %object;
976 \\.size {s}, {d};
977 \\.symver {s}, {s}{s}GLIBC_{d}.{d}
978 \\{s}:
979 \\
980 , .{
981 sym_plus_ver,
982 sym_plus_ver,
983 sym_plus_ver,
984 size,
985 sym_plus_ver,
986 sym_name,
987 at_sign_str,
988 ver.major,
989 ver.minor,
990 sym_plus_ver,
991 });
992 } else {
993 const sym_plus_ver = if (want_default)
994 sym_name
995 else
996 try std.fmt.allocPrint(
997 arena,
998 "{s}_GLIBC_{d}_{d}_{d}",
999 .{ sym_name, ver.major, ver.minor, ver.patch },
1000 );
1001 try stubs_asm.writer().print(
1002 \\.globl {s}
1003 \\.type {s}, %object;
1004 \\.size {s}, {d};
1005 \\.symver {s}, {s}{s}GLIBC_{d}.{d}.{d}
1006 \\{s}:
1007 \\
1008 , .{
1009 sym_plus_ver,
1010 sym_plus_ver,
1011 sym_plus_ver,
1012 size,
1013 sym_plus_ver,
1014 sym_name,
1015 at_sign_str,
1016 ver.major,
1017 ver.minor,
1018 ver.patch,
1019 sym_plus_ver,
1020 });
1021 }
937 }
938 {
939 var ver_buf_i: u8 = 0;
940 while (ver_buf_i < versions_len) : (ver_buf_i += 1) {
941 // Example:
942 // .globl environ_2_2_5
943 // .type environ_2_2_5, %object;
944 // .size environ_2_2_5, 4;
945 // .symver environ_2_2_5, environ@@GLIBC_2.2.5
946 // environ_2_2_5:
947 const ver_index = versions_buffer[ver_buf_i];
948 const ver = metadata.all_versions[ver_index];
949 // Default symbol version definition vs normal symbol version definition
950 const want_default = chosen_def_ver_index != 255 and ver_index == chosen_def_ver_index;
951 const at_sign_str: []const u8 = if (want_default) "@@" else "@";
952 if (ver.patch == 0) {
953 const sym_plus_ver = if (want_default)
954 sym_name
955 else
956 try std.fmt.allocPrint(
957 arena,
958 "{s}_GLIBC_{d}_{d}",
959 .{ sym_name, ver.major, ver.minor },
960 );
961 try stubs_asm.writer().print(
962 \\.globl {s}
963 \\.type {s}, %object;
964 \\.size {s}, {d};
965 \\.symver {s}, {s}{s}GLIBC_{d}.{d}
966 \\{s}:
967 \\
968 , .{
969 sym_plus_ver,
970 sym_plus_ver,
971 sym_plus_ver,
972 size,
973 sym_plus_ver,
974 sym_name,
975 at_sign_str,
976 ver.major,
977 ver.minor,
978 sym_plus_ver,
979 });
980 } else {
981 const sym_plus_ver = if (want_default)
982 sym_name
983 else
984 try std.fmt.allocPrint(
985 arena,
986 "{s}_GLIBC_{d}_{d}_{d}",
987 .{ sym_name, ver.major, ver.minor, ver.patch },
988 );
989 try stubs_asm.writer().print(
990 \\.globl {s}
991 \\.type {s}, %object;
992 \\.size {s}, {d};
993 \\.symver {s}, {s}{s}GLIBC_{d}.{d}.{d}
994 \\{s}:
995 \\
996 , .{
997 sym_plus_ver,
998 sym_plus_ver,
999 sym_plus_ver,
1000 size,
1001 sym_plus_ver,
1002 sym_name,
1003 at_sign_str,
1004 ver.major,
1005 ver.minor,
1006 ver.patch,
1007 sym_plus_ver,
1008 });
10221009 }
10231010 }
10241011 }
1012 }
10251013
1026 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;
1028 try o_directory.handle.writeFile(asm_file_basename, stubs_asm.items);
1014 var lib_name_buf: [32]u8 = undefined; // Larger than each of the names "c", "pthread", etc.
1015 const asm_file_basename = std.fmt.bufPrint(&lib_name_buf, "{s}.s", .{lib.name}) catch unreachable;
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);
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 }
1018 try buildSharedLib(comp, arena, comp.global_cache_directory, o_directory, asm_file_basename, lib);
10391019 }
10401020
1021 man.writeManifest() catch |err| {
1022 log.warn("failed to write cache manifest for glibc stubs: {s}", .{@errorName(err)});
1023 };
1024
10411025 assert(comp.glibc_so_files == null);
10421026 comp.glibc_so_files = BuiltSharedObjects{
1043 .lock = cache.toOwnedLock(),
1044 .dir_path = try path.join(comp.gpa, &[_][]const u8{ comp.global_cache_directory.path.?, o_sub_path }),
1027 .lock = man.toOwnedLock(),
1028 .dir_path = try comp.global_cache_directory.join(comp.gpa, &.{ "o", &digest }),
10451029 };
10461030}
10471031
src/print_targets.zig+11-1
......@@ -25,7 +25,17 @@ pub fn cmdTargets(
2525 defer zig_lib_directory.handle.close();
2626 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);
2939 defer glibc_abi.destroy(allocator);
3040
3141 var bw = io.bufferedWriter(stdout);