authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-09-16 14:33:13-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-09-16 14:33:13-07:00
log17f094ec5bce9737f733de08ce0ca049f6d2a186
tree4f935fb83efb54c24dd26a08863a584249aa98a5
parent3256b3c48536407e64b641b55bde064a9ac34606

stage2: build glibc shared objects using assembly files

closes #6358

2 files changed, 58 insertions(+), 43 deletions(-)

BRANCH_TODO+2-5
......@@ -1,8 +1,5 @@
1 * glibc .so files
2 - without stage1 c++ code integration it should fail with a better error message
3 instead of lld not getting the object file on the linker line for some reason.
4 - stage1 C++ code integration
5 - ok file
1 * libunwind
2 * stage1 C++ code integration
63 * support rpaths in ELF linker code
74 * build & link against compiler-rt
85 * build & link againstn freestanding libc
src-self-hosted/glibc.zig+56-38
......@@ -744,6 +744,9 @@ pub const BuiltSharedObjects = struct {
744744
745745const all_map_basename = "all.map";
746746
747// TODO Turn back on zig fmt when https://github.com/ziglang/zig/issues/5948 is implemented.
748// zig fmt: off
749
747750pub fn buildSharedObjects(comp: *Compilation) !void {
748751 const tracy = trace(@src());
749752 defer tracy.end();
......@@ -765,8 +768,6 @@ pub fn buildSharedObjects(comp: *Compilation) !void {
765768 cache.hash.addBytes(build_options.version);
766769 cache.hash.addBytes(comp.zig_lib_directory.path orelse ".");
767770 cache.hash.add(target.cpu.arch);
768 cache.hash.addBytes(target.cpu.model.name);
769 cache.hash.add(target.cpu.features.ints);
770771 cache.hash.add(target.abi);
771772 cache.hash.add(target_version);
772773
......@@ -832,17 +833,9 @@ pub fn buildSharedObjects(comp: *Compilation) !void {
832833 }
833834 var zig_body = std.ArrayList(u8).init(comp.gpa);
834835 defer zig_body.deinit();
835 var zig_footer = std.ArrayList(u8).init(comp.gpa);
836 defer zig_footer.deinit();
837836 for (libs) |*lib| {
838837 zig_body.shrinkRetainingCapacity(0);
839 zig_footer.shrinkRetainingCapacity(0);
840838
841 try zig_body.appendSlice(
842 \\comptime {
843 \\ asm (
844 \\
845 );
846839 for (metadata.all_functions) |*libc_fn, fn_i| {
847840 if (libc_fn.lib != lib) continue;
848841
......@@ -868,46 +861,66 @@ pub fn buildSharedObjects(comp: *Compilation) !void {
868861 {
869862 var ver_i: u8 = 0;
870863 while (ver_i < ver_list.len) : (ver_i += 1) {
864 // Example:
865 // .globl _Exit_2_2_5
866 // .type _Exit_2_2_5, @function;
867 // .symver _Exit_2_2_5, _Exit@@GLIBC_2.2.5
868 // .hidden _Exit_2_2_5
869 // _Exit_2_2_5:
871870 const ver_index = ver_list.versions[ver_i];
872871 const ver = metadata.all_versions[ver_index];
873872 const sym_name = libc_fn.name;
874 const stub_name = if (ver.patch == 0)
875 try std.fmt.allocPrint(arena, "{s}_{d}_{d}", .{ sym_name, ver.major, ver.minor })
876 else
877 try std.fmt.allocPrint(arena, "{s}_{d}_{d}_{d}", .{ sym_name, ver.major, ver.minor, ver.patch });
878
879 try zig_footer.writer().print("export fn {s}() void {{}}\n", .{stub_name});
880
881873 // Default symbol version definition vs normal symbol version definition
882874 const want_two_ats = chosen_def_ver_index != 255 and ver_index == chosen_def_ver_index;
883875 const at_sign_str = "@@"[0 .. @boolToInt(want_two_ats) + @as(usize, 1)];
876
884877 if (ver.patch == 0) {
885 try zig_body.writer().print(" \\\\.symver {s}, {s}{s}GLIBC_{d}.{d}\n", .{
886 stub_name, sym_name, at_sign_str, ver.major, ver.minor,
878 const sym_plus_ver = try std.fmt.allocPrint(
879 arena, "{s}_{d}_{d}",
880 .{sym_name, ver.major, ver.minor},
881 );
882 try zig_body.writer().print(
883 \\.globl {s}
884 \\.type {s}, @function;
885 \\.symver {s}, {s}{s}GLIBC_{d}.{d}
886 \\.hidden {s}
887 \\{s}:
888 \\
889 , .{
890 sym_plus_ver,
891 sym_plus_ver,
892 sym_plus_ver, sym_name, at_sign_str, ver.major, ver.minor,
893 sym_plus_ver,
894 sym_plus_ver,
887895 });
888896 } else {
889 try zig_body.writer().print(" \\\\.symver {s}, {s}{s}GLIBC_{d}.{d}.{d}\n", .{
890 stub_name, sym_name, at_sign_str, ver.major, ver.minor, ver.patch,
897 const sym_plus_ver = try std.fmt.allocPrint(arena, "{s}_{d}_{d}_{d}",
898 .{sym_name, ver.major, ver.minor, ver.patch},
899 );
900 try zig_body.writer().print(
901 \\.globl {s}
902 \\.type {s}, @function;
903 \\.symver {s}, {s}{s}GLIBC_{d}.{d}.{d}
904 \\.hidden {s}
905 \\{s}:
906 \\
907 , .{
908 sym_plus_ver,
909 sym_plus_ver,
910 sym_plus_ver, sym_name, at_sign_str, ver.major, ver.minor, ver.patch,
911 sym_plus_ver,
912 sym_plus_ver,
891913 });
892914 }
893 // Hide the stub to keep the symbol table clean
894 try zig_body.writer().print(" \\\\.hidden {s}\n", .{stub_name});
895915 }
896916 }
897917 }
898918
899 try zig_body.appendSlice(
900 \\ );
901 \\}
902 \\
903 );
904 try zig_body.appendSlice(zig_footer.items);
905
906919 var lib_name_buf: [32]u8 = undefined; // Larger than each of the names "c", "pthread", etc.
907 const zig_file_basename = std.fmt.bufPrint(&lib_name_buf, "{s}.zig", .{lib.name}) catch unreachable;
908 try o_directory.handle.writeFile(zig_file_basename, zig_body.items);
920 const asm_file_basename = std.fmt.bufPrint(&lib_name_buf, "{s}.s", .{lib.name}) catch unreachable;
921 try o_directory.handle.writeFile(asm_file_basename, zig_body.items);
909922
910 try buildSharedLib(comp, arena, comp.zig_cache_directory, o_directory, zig_file_basename, lib);
923 try buildSharedLib(comp, arena, comp.zig_cache_directory, o_directory, asm_file_basename, lib);
911924 }
912925 // No need to write the manifest because there are no file inputs associated with this cache hash.
913926 // However we do need to write the ok file now.
......@@ -925,12 +938,14 @@ pub fn buildSharedObjects(comp: *Compilation) !void {
925938 };
926939}
927940
941// zig fmt: on
942
928943fn buildSharedLib(
929944 comp: *Compilation,
930945 arena: *Allocator,
931946 zig_cache_directory: Compilation.Directory,
932947 bin_directory: Compilation.Directory,
933 zig_file_basename: []const u8,
948 asm_file_basename: []const u8,
934949 lib: *const Lib,
935950) !void {
936951 const tracy = trace(@src());
......@@ -944,15 +959,17 @@ fn buildSharedLib(
944959 const ld_basename = path.basename(comp.getTarget().standardDynamicLinkerPath().get().?);
945960 const override_soname = if (mem.eql(u8, lib.name, "ld")) ld_basename else null;
946961 const map_file_path = try path.join(arena, &[_][]const u8{ bin_directory.path.?, all_map_basename });
947 // TODO we should be able to just give the open directory to Package
948 const root_pkg = try Package.create(comp.gpa, std.fs.cwd(), bin_directory.path.?, zig_file_basename);
949 defer root_pkg.destroy(comp.gpa);
962 const c_source_files = [1]Compilation.CSourceFile{
963 .{
964 .src_path = try path.join(arena, &[_][]const u8{ bin_directory.path.?, asm_file_basename }),
965 },
966 };
950967 const sub_compilation = try Compilation.create(comp.gpa, .{
951968 .zig_cache_directory = zig_cache_directory,
952969 .zig_lib_directory = comp.zig_lib_directory,
953970 .target = comp.getTarget(),
954971 .root_name = lib.name,
955 .root_pkg = root_pkg,
972 .root_pkg = null,
956973 .output_mode = .Lib,
957974 .link_mode = .Dynamic,
958975 .rand = comp.rand,
......@@ -973,6 +990,7 @@ fn buildSharedLib(
973990 .stage1_is_dummy_so = true,
974991 .version_script = map_file_path,
975992 .override_soname = override_soname,
993 .c_source_files = &c_source_files,
976994 });
977995 defer sub_compilation.destroy();
978996