From 4cfeb9a541b3e6db2c67a494abf4f6bd12900353 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 28 Oct 2022 19:40:01 -0700 Subject: [PATCH 1/2] glibc: fix race condition when building stubs Before, the code for building glibc stubs used a special case of the Cache API that did not add any file inputs, and did not use writeManifest(). This is not really how the Cache API is designed to work and it shows because there was a race condition. This commit adds as an input file the abilists file that comes with Zig's installation, which has the added benefit of making glibc stub caching properly detect cache invalidation when the user decides to overwrite their abilists file. This harmonizes with the rest of how Zig works, which intentionally allows you to hack the installation files and have it behave properly with the cache system. Finally, because of having any file inputs, the normal API flow of the Cache system can be used, eliminating the one place that used the Cache API in a special way. In other words, it uses writeManifest() now and properly obeys the cache hit/miss semantics. closes #13160 --- src/glibc.zig | 734 +++++++++++++++++++++--------------------- src/print_targets.zig | 12 +- 2 files changed, 370 insertions(+), 376 deletions(-) diff --git a/src/glibc.zig b/src/glibc.zig index 3dd7565e96..ddbf3ac050 100644 --- a/src/glibc.zig +++ b/src/glibc.zig @@ -50,9 +50,12 @@ pub const LoadMetaDataError = error{ OutOfMemory, }; +pub const abilists_path = "libc" ++ path.sep_str ++ "glibc" ++ path.sep_str ++ "abilists"; +pub const abilists_max_size = 800 * 1024; // Bigger than this and something is definitely borked. + /// This function will emit a log error when there is a problem with the zig /// installation and then return `error.ZigInstallationCorrupt`. -pub fn loadMetaData(gpa: Allocator, zig_lib_dir: fs.Dir) LoadMetaDataError!*ABI { +pub fn loadMetaData(gpa: Allocator, contents: []const u8) LoadMetaDataError!*ABI { const tracy = trace(@src()); defer tracy.end(); @@ -60,22 +63,6 @@ pub fn loadMetaData(gpa: Allocator, zig_lib_dir: fs.Dir) LoadMetaDataError!*ABI errdefer arena_allocator.deinit(); const arena = arena_allocator.allocator(); - var glibc_dir = zig_lib_dir.openDir("libc" ++ path.sep_str ++ "glibc", .{}) catch |err| { - log.err("unable to open glibc dir: {s}", .{@errorName(err)}); - return error.ZigInstallationCorrupt; - }; - defer glibc_dir.close(); - - const max_size = 500 * 1024; // Bigger than this and something is definitely borked. - const contents = glibc_dir.readFileAlloc(arena, "abilists", max_size) catch |err| switch (err) { - error.OutOfMemory => return error.OutOfMemory, - else => { - log.err("unable to read libc" ++ path.sep_str ++ "glibc" ++ path.sep_str ++ - "abilists: {s}", .{@errorName(err)}); - return error.ZigInstallationCorrupt; - }, - }; - var index: usize = 0; { @@ -662,386 +649,383 @@ pub fn buildSharedObjects(comp: *Compilation) !void { const target_version = target.os.version_range.linux.glibc; // Use the global cache directory. - var cache_parent: Cache = .{ + var cache: Cache = .{ .gpa = comp.gpa, .manifest_dir = try comp.global_cache_directory.handle.makeOpenPath("h", .{}), }; - defer cache_parent.manifest_dir.close(); + defer cache.manifest_dir.close(); - var cache = cache_parent.obtain(); - defer cache.deinit(); - cache.hash.addBytes(build_options.version); - cache.hash.addBytes(comp.zig_lib_directory.path orelse "."); - cache.hash.add(target.cpu.arch); - cache.hash.add(target.abi); - cache.hash.add(target_version); + var man = cache.obtain(); + defer man.deinit(); + man.hash.addBytes(build_options.version); + man.hash.addBytes(comp.zig_lib_directory.path orelse "."); + man.hash.add(target.cpu.arch); + man.hash.add(target.abi); + man.hash.add(target_version); - const hit = try cache.hit(); - const digest = cache.final(); + const full_abilists_path = try comp.zig_lib_directory.join(arena, &.{abilists_path}); + const abilists_index = try man.addFile(full_abilists_path, abilists_max_size); + + if (try man.hit()) { + const digest = man.final(); + + assert(comp.glibc_so_files == null); + comp.glibc_so_files = BuiltSharedObjects{ + .lock = man.toOwnedLock(), + .dir_path = try comp.global_cache_directory.join(comp.gpa, &.{ "o", &digest }), + }; + return; + } + + const digest = man.final(); const o_sub_path = try path.join(arena, &[_][]const u8{ "o", &digest }); - // Even if we get a hit, it doesn't guarantee that we finished the job last time. - // We use the presence of an "ok" file to determine if it is a true hit. - var o_directory: Compilation.Directory = .{ .handle = try comp.global_cache_directory.handle.makeOpenPath(o_sub_path, .{}), - .path = try path.join(arena, &[_][]const u8{ comp.global_cache_directory.path.?, o_sub_path }), + .path = try comp.global_cache_directory.join(arena, &.{o_sub_path}), }; defer o_directory.handle.close(); - const ok_basename = "ok"; - const actual_hit = if (hit) blk: { - o_directory.handle.access(ok_basename, .{}) catch |err| switch (err) { - error.FileNotFound => break :blk false, - else => |e| return e, - }; - break :blk true; - } else false; - - if (!actual_hit) { - const metadata = try loadMetaData(comp.gpa, comp.zig_lib_directory.handle); - defer metadata.destroy(comp.gpa); - - const target_targ_index = for (metadata.all_targets) |targ, i| { - if (targ.arch == target.cpu.arch and - targ.os == target.os.tag and - targ.abi == target.abi) - { - break i; - } - } else { - unreachable; // target_util.available_libcs prevents us from getting here - }; - - const target_ver_index = for (metadata.all_versions) |ver, i| { - switch (ver.order(target_version)) { - .eq => break i, - .lt => continue, - .gt => { - // TODO Expose via compile error mechanism instead of log. - log.warn("invalid target glibc version: {}", .{target_version}); - return error.InvalidTargetGLibCVersion; - }, - } - } else blk: { - const latest_index = metadata.all_versions.len - 1; - log.warn("zig cannot build new glibc version {}; providing instead {}", .{ - target_version, metadata.all_versions[latest_index], - }); - break :blk latest_index; - }; + const abilists_contents = man.files.items[abilists_index].contents.?; + const metadata = try loadMetaData(comp.gpa, abilists_contents); + defer metadata.destroy(comp.gpa); + const target_targ_index = for (metadata.all_targets) |targ, i| { + if (targ.arch == target.cpu.arch and + targ.os == target.os.tag and + targ.abi == target.abi) { - var map_contents = std.ArrayList(u8).init(arena); - for (metadata.all_versions[0 .. target_ver_index + 1]) |ver| { - if (ver.patch == 0) { - try map_contents.writer().print("GLIBC_{d}.{d} {{ }};\n", .{ ver.major, ver.minor }); - } else { - try map_contents.writer().print("GLIBC_{d}.{d}.{d} {{ }};\n", .{ ver.major, ver.minor, ver.patch }); - } - } - try o_directory.handle.writeFile(all_map_basename, map_contents.items); - map_contents.deinit(); // The most recent allocation of an arena can be freed :) + break i; } + } else { + unreachable; // target_util.available_libcs prevents us from getting here + }; - var stubs_asm = std.ArrayList(u8).init(comp.gpa); - defer stubs_asm.deinit(); - - for (libs) |lib, lib_i| { - stubs_asm.shrinkRetainingCapacity(0); - try stubs_asm.appendSlice(".text\n"); - - var inc_i: usize = 0; - - const fn_inclusions_len = mem.readIntLittle(u16, metadata.inclusions[inc_i..][0..2]); - inc_i += 2; - - var sym_i: usize = 0; - var opt_symbol_name: ?[]const u8 = null; - var versions_buffer: [32]u8 = undefined; - var versions_len: usize = undefined; - while (sym_i < fn_inclusions_len) : (sym_i += 1) { - const sym_name = opt_symbol_name orelse n: { - const name = mem.sliceTo(metadata.inclusions[inc_i..], 0); - inc_i += name.len + 1; - - opt_symbol_name = name; - versions_buffer = undefined; - versions_len = 0; - break :n name; - }; - const targets = mem.readIntLittle(u32, metadata.inclusions[inc_i..][0..4]); - inc_i += 4; - - const lib_index = metadata.inclusions[inc_i]; - inc_i += 1; - const is_terminal = (targets & (1 << 31)) != 0; - if (is_terminal) opt_symbol_name = null; - - // Test whether the inclusion applies to our current library and target. - const ok_lib_and_target = - (lib_index == lib_i) and - ((targets & (@as(u32, 1) << @intCast(u5, target_targ_index))) != 0); - - while (true) { - const byte = metadata.inclusions[inc_i]; - inc_i += 1; - const last = (byte & 0b1000_0000) != 0; - const ver_i = @truncate(u7, byte); - if (ok_lib_and_target and ver_i <= target_ver_index) { - versions_buffer[versions_len] = ver_i; - versions_len += 1; - } - if (last) break; - } - - if (!is_terminal) continue; - - // Pick the default symbol version: - // - If there are no versions, don't emit it - // - Take the greatest one <= than the target one - // - If none of them is <= than the - // specified one don't pick any default version - if (versions_len == 0) continue; - var chosen_def_ver_index: u8 = 255; - { - var ver_buf_i: u8 = 0; - while (ver_buf_i < versions_len) : (ver_buf_i += 1) { - const ver_index = versions_buffer[ver_buf_i]; - if (chosen_def_ver_index == 255 or ver_index > chosen_def_ver_index) { - chosen_def_ver_index = ver_index; - } - } - } - { - var ver_buf_i: u8 = 0; - while (ver_buf_i < versions_len) : (ver_buf_i += 1) { - // Example: - // .globl _Exit_2_2_5 - // .type _Exit_2_2_5, %function; - // .symver _Exit_2_2_5, _Exit@@GLIBC_2.2.5 - // _Exit_2_2_5: - const ver_index = versions_buffer[ver_buf_i]; - const ver = metadata.all_versions[ver_index]; - // Default symbol version definition vs normal symbol version definition - const want_default = chosen_def_ver_index != 255 and ver_index == chosen_def_ver_index; - const at_sign_str: []const u8 = if (want_default) "@@" else "@"; - if (ver.patch == 0) { - const sym_plus_ver = if (want_default) - sym_name - else - try std.fmt.allocPrint( - arena, - "{s}_GLIBC_{d}_{d}", - .{ sym_name, ver.major, ver.minor }, - ); - try stubs_asm.writer().print( - \\.globl {s} - \\.type {s}, %function; - \\.symver {s}, {s}{s}GLIBC_{d}.{d} - \\{s}: - \\ - , .{ - sym_plus_ver, - sym_plus_ver, - sym_plus_ver, - sym_name, - at_sign_str, - ver.major, - ver.minor, - sym_plus_ver, - }); - } else { - const sym_plus_ver = if (want_default) - sym_name - else - try std.fmt.allocPrint( - arena, - "{s}_GLIBC_{d}_{d}_{d}", - .{ sym_name, ver.major, ver.minor, ver.patch }, - ); - try stubs_asm.writer().print( - \\.globl {s} - \\.type {s}, %function; - \\.symver {s}, {s}{s}GLIBC_{d}.{d}.{d} - \\{s}: - \\ - , .{ - sym_plus_ver, - sym_plus_ver, - sym_plus_ver, - sym_name, - at_sign_str, - ver.major, - ver.minor, - ver.patch, - sym_plus_ver, - }); - } - } - } - } - - try stubs_asm.appendSlice(".data\n"); - - const obj_inclusions_len = mem.readIntLittle(u16, metadata.inclusions[inc_i..][0..2]); - inc_i += 2; - - sym_i = 0; - opt_symbol_name = null; - versions_buffer = undefined; - versions_len = undefined; - while (sym_i < obj_inclusions_len) : (sym_i += 1) { - const sym_name = opt_symbol_name orelse n: { - const name = mem.sliceTo(metadata.inclusions[inc_i..], 0); - inc_i += name.len + 1; - - opt_symbol_name = name; - versions_buffer = undefined; - versions_len = 0; - break :n name; - }; - const targets = mem.readIntLittle(u32, metadata.inclusions[inc_i..][0..4]); - inc_i += 4; - - const size = mem.readIntLittle(u16, metadata.inclusions[inc_i..][0..2]); - inc_i += 2; - - const lib_index = metadata.inclusions[inc_i]; - inc_i += 1; - const is_terminal = (targets & (1 << 31)) != 0; - if (is_terminal) opt_symbol_name = null; - - // Test whether the inclusion applies to our current library and target. - const ok_lib_and_target = - (lib_index == lib_i) and - ((targets & (@as(u32, 1) << @intCast(u5, target_targ_index))) != 0); - - while (true) { - const byte = metadata.inclusions[inc_i]; - inc_i += 1; - const last = (byte & 0b1000_0000) != 0; - const ver_i = @truncate(u7, byte); - if (ok_lib_and_target and ver_i <= target_ver_index) { - versions_buffer[versions_len] = ver_i; - versions_len += 1; - } - if (last) break; - } - - if (!is_terminal) continue; - - // Pick the default symbol version: - // - If there are no versions, don't emit it - // - Take the greatest one <= than the target one - // - If none of them is <= than the - // specified one don't pick any default version - if (versions_len == 0) continue; - var chosen_def_ver_index: u8 = 255; - { - var ver_buf_i: u8 = 0; - while (ver_buf_i < versions_len) : (ver_buf_i += 1) { - const ver_index = versions_buffer[ver_buf_i]; - if (chosen_def_ver_index == 255 or ver_index > chosen_def_ver_index) { - chosen_def_ver_index = ver_index; - } - } - } - { - var ver_buf_i: u8 = 0; - while (ver_buf_i < versions_len) : (ver_buf_i += 1) { - // Example: - // .globl environ_2_2_5 - // .type environ_2_2_5, %object; - // .size environ_2_2_5, 4; - // .symver environ_2_2_5, environ@@GLIBC_2.2.5 - // environ_2_2_5: - const ver_index = versions_buffer[ver_buf_i]; - const ver = metadata.all_versions[ver_index]; - // Default symbol version definition vs normal symbol version definition - const want_default = chosen_def_ver_index != 255 and ver_index == chosen_def_ver_index; - const at_sign_str: []const u8 = if (want_default) "@@" else "@"; - if (ver.patch == 0) { - const sym_plus_ver = if (want_default) - sym_name - else - try std.fmt.allocPrint( - arena, - "{s}_GLIBC_{d}_{d}", - .{ sym_name, ver.major, ver.minor }, - ); - try stubs_asm.writer().print( - \\.globl {s} - \\.type {s}, %object; - \\.size {s}, {d}; - \\.symver {s}, {s}{s}GLIBC_{d}.{d} - \\{s}: - \\ - , .{ - sym_plus_ver, - sym_plus_ver, - sym_plus_ver, - size, - sym_plus_ver, - sym_name, - at_sign_str, - ver.major, - ver.minor, - sym_plus_ver, - }); - } else { - const sym_plus_ver = if (want_default) - sym_name - else - try std.fmt.allocPrint( - arena, - "{s}_GLIBC_{d}_{d}_{d}", - .{ sym_name, ver.major, ver.minor, ver.patch }, - ); - try stubs_asm.writer().print( - \\.globl {s} - \\.type {s}, %object; - \\.size {s}, {d}; - \\.symver {s}, {s}{s}GLIBC_{d}.{d}.{d} - \\{s}: - \\ - , .{ - sym_plus_ver, - sym_plus_ver, - sym_plus_ver, - size, - sym_plus_ver, - sym_name, - at_sign_str, - ver.major, - ver.minor, - ver.patch, - sym_plus_ver, - }); - } - } - } - } - - var lib_name_buf: [32]u8 = undefined; // Larger than each of the names "c", "pthread", etc. - const asm_file_basename = std.fmt.bufPrint(&lib_name_buf, "{s}.s", .{lib.name}) catch unreachable; - try o_directory.handle.writeFile(asm_file_basename, stubs_asm.items); - - try buildSharedLib(comp, arena, comp.global_cache_directory, o_directory, asm_file_basename, lib); + const target_ver_index = for (metadata.all_versions) |ver, i| { + switch (ver.order(target_version)) { + .eq => break i, + .lt => continue, + .gt => { + // TODO Expose via compile error mechanism instead of log. + log.warn("invalid target glibc version: {}", .{target_version}); + return error.InvalidTargetGLibCVersion; + }, } - // No need to write the manifest because there are no file inputs associated with this cache hash. - // However we do need to write the ok file now. - if (o_directory.handle.createFile(ok_basename, .{})) |file| { - file.close(); - } else |err| { - log.warn("glibc shared objects: failed to mark completion: {s}", .{@errorName(err)}); + } else blk: { + const latest_index = metadata.all_versions.len - 1; + log.warn("zig cannot build new glibc version {}; providing instead {}", .{ + target_version, metadata.all_versions[latest_index], + }); + break :blk latest_index; + }; + + { + var map_contents = std.ArrayList(u8).init(arena); + for (metadata.all_versions[0 .. target_ver_index + 1]) |ver| { + if (ver.patch == 0) { + try map_contents.writer().print("GLIBC_{d}.{d} {{ }};\n", .{ ver.major, ver.minor }); + } else { + try map_contents.writer().print("GLIBC_{d}.{d}.{d} {{ }};\n", .{ ver.major, ver.minor, ver.patch }); + } } + try o_directory.handle.writeFile(all_map_basename, map_contents.items); + map_contents.deinit(); // The most recent allocation of an arena can be freed :) } + var stubs_asm = std.ArrayList(u8).init(comp.gpa); + defer stubs_asm.deinit(); + + for (libs) |lib, lib_i| { + stubs_asm.shrinkRetainingCapacity(0); + try stubs_asm.appendSlice(".text\n"); + + var inc_i: usize = 0; + + const fn_inclusions_len = mem.readIntLittle(u16, metadata.inclusions[inc_i..][0..2]); + inc_i += 2; + + var sym_i: usize = 0; + var opt_symbol_name: ?[]const u8 = null; + var versions_buffer: [32]u8 = undefined; + var versions_len: usize = undefined; + while (sym_i < fn_inclusions_len) : (sym_i += 1) { + const sym_name = opt_symbol_name orelse n: { + const name = mem.sliceTo(metadata.inclusions[inc_i..], 0); + inc_i += name.len + 1; + + opt_symbol_name = name; + versions_buffer = undefined; + versions_len = 0; + break :n name; + }; + const targets = mem.readIntLittle(u32, metadata.inclusions[inc_i..][0..4]); + inc_i += 4; + + const lib_index = metadata.inclusions[inc_i]; + inc_i += 1; + const is_terminal = (targets & (1 << 31)) != 0; + if (is_terminal) opt_symbol_name = null; + + // Test whether the inclusion applies to our current library and target. + const ok_lib_and_target = + (lib_index == lib_i) and + ((targets & (@as(u32, 1) << @intCast(u5, target_targ_index))) != 0); + + while (true) { + const byte = metadata.inclusions[inc_i]; + inc_i += 1; + const last = (byte & 0b1000_0000) != 0; + const ver_i = @truncate(u7, byte); + if (ok_lib_and_target and ver_i <= target_ver_index) { + versions_buffer[versions_len] = ver_i; + versions_len += 1; + } + if (last) break; + } + + if (!is_terminal) continue; + + // Pick the default symbol version: + // - If there are no versions, don't emit it + // - Take the greatest one <= than the target one + // - If none of them is <= than the + // specified one don't pick any default version + if (versions_len == 0) continue; + var chosen_def_ver_index: u8 = 255; + { + var ver_buf_i: u8 = 0; + while (ver_buf_i < versions_len) : (ver_buf_i += 1) { + const ver_index = versions_buffer[ver_buf_i]; + if (chosen_def_ver_index == 255 or ver_index > chosen_def_ver_index) { + chosen_def_ver_index = ver_index; + } + } + } + { + var ver_buf_i: u8 = 0; + while (ver_buf_i < versions_len) : (ver_buf_i += 1) { + // Example: + // .globl _Exit_2_2_5 + // .type _Exit_2_2_5, %function; + // .symver _Exit_2_2_5, _Exit@@GLIBC_2.2.5 + // _Exit_2_2_5: + const ver_index = versions_buffer[ver_buf_i]; + const ver = metadata.all_versions[ver_index]; + // Default symbol version definition vs normal symbol version definition + const want_default = chosen_def_ver_index != 255 and ver_index == chosen_def_ver_index; + const at_sign_str: []const u8 = if (want_default) "@@" else "@"; + if (ver.patch == 0) { + const sym_plus_ver = if (want_default) + sym_name + else + try std.fmt.allocPrint( + arena, + "{s}_GLIBC_{d}_{d}", + .{ sym_name, ver.major, ver.minor }, + ); + try stubs_asm.writer().print( + \\.globl {s} + \\.type {s}, %function; + \\.symver {s}, {s}{s}GLIBC_{d}.{d} + \\{s}: + \\ + , .{ + sym_plus_ver, + sym_plus_ver, + sym_plus_ver, + sym_name, + at_sign_str, + ver.major, + ver.minor, + sym_plus_ver, + }); + } else { + const sym_plus_ver = if (want_default) + sym_name + else + try std.fmt.allocPrint( + arena, + "{s}_GLIBC_{d}_{d}_{d}", + .{ sym_name, ver.major, ver.minor, ver.patch }, + ); + try stubs_asm.writer().print( + \\.globl {s} + \\.type {s}, %function; + \\.symver {s}, {s}{s}GLIBC_{d}.{d}.{d} + \\{s}: + \\ + , .{ + sym_plus_ver, + sym_plus_ver, + sym_plus_ver, + sym_name, + at_sign_str, + ver.major, + ver.minor, + ver.patch, + sym_plus_ver, + }); + } + } + } + } + + try stubs_asm.appendSlice(".data\n"); + + const obj_inclusions_len = mem.readIntLittle(u16, metadata.inclusions[inc_i..][0..2]); + inc_i += 2; + + sym_i = 0; + opt_symbol_name = null; + versions_buffer = undefined; + versions_len = undefined; + while (sym_i < obj_inclusions_len) : (sym_i += 1) { + const sym_name = opt_symbol_name orelse n: { + const name = mem.sliceTo(metadata.inclusions[inc_i..], 0); + inc_i += name.len + 1; + + opt_symbol_name = name; + versions_buffer = undefined; + versions_len = 0; + break :n name; + }; + const targets = mem.readIntLittle(u32, metadata.inclusions[inc_i..][0..4]); + inc_i += 4; + + const size = mem.readIntLittle(u16, metadata.inclusions[inc_i..][0..2]); + inc_i += 2; + + const lib_index = metadata.inclusions[inc_i]; + inc_i += 1; + const is_terminal = (targets & (1 << 31)) != 0; + if (is_terminal) opt_symbol_name = null; + + // Test whether the inclusion applies to our current library and target. + const ok_lib_and_target = + (lib_index == lib_i) and + ((targets & (@as(u32, 1) << @intCast(u5, target_targ_index))) != 0); + + while (true) { + const byte = metadata.inclusions[inc_i]; + inc_i += 1; + const last = (byte & 0b1000_0000) != 0; + const ver_i = @truncate(u7, byte); + if (ok_lib_and_target and ver_i <= target_ver_index) { + versions_buffer[versions_len] = ver_i; + versions_len += 1; + } + if (last) break; + } + + if (!is_terminal) continue; + + // Pick the default symbol version: + // - If there are no versions, don't emit it + // - Take the greatest one <= than the target one + // - If none of them is <= than the + // specified one don't pick any default version + if (versions_len == 0) continue; + var chosen_def_ver_index: u8 = 255; + { + var ver_buf_i: u8 = 0; + while (ver_buf_i < versions_len) : (ver_buf_i += 1) { + const ver_index = versions_buffer[ver_buf_i]; + if (chosen_def_ver_index == 255 or ver_index > chosen_def_ver_index) { + chosen_def_ver_index = ver_index; + } + } + } + { + var ver_buf_i: u8 = 0; + while (ver_buf_i < versions_len) : (ver_buf_i += 1) { + // Example: + // .globl environ_2_2_5 + // .type environ_2_2_5, %object; + // .size environ_2_2_5, 4; + // .symver environ_2_2_5, environ@@GLIBC_2.2.5 + // environ_2_2_5: + const ver_index = versions_buffer[ver_buf_i]; + const ver = metadata.all_versions[ver_index]; + // Default symbol version definition vs normal symbol version definition + const want_default = chosen_def_ver_index != 255 and ver_index == chosen_def_ver_index; + const at_sign_str: []const u8 = if (want_default) "@@" else "@"; + if (ver.patch == 0) { + const sym_plus_ver = if (want_default) + sym_name + else + try std.fmt.allocPrint( + arena, + "{s}_GLIBC_{d}_{d}", + .{ sym_name, ver.major, ver.minor }, + ); + try stubs_asm.writer().print( + \\.globl {s} + \\.type {s}, %object; + \\.size {s}, {d}; + \\.symver {s}, {s}{s}GLIBC_{d}.{d} + \\{s}: + \\ + , .{ + sym_plus_ver, + sym_plus_ver, + sym_plus_ver, + size, + sym_plus_ver, + sym_name, + at_sign_str, + ver.major, + ver.minor, + sym_plus_ver, + }); + } else { + const sym_plus_ver = if (want_default) + sym_name + else + try std.fmt.allocPrint( + arena, + "{s}_GLIBC_{d}_{d}_{d}", + .{ sym_name, ver.major, ver.minor, ver.patch }, + ); + try stubs_asm.writer().print( + \\.globl {s} + \\.type {s}, %object; + \\.size {s}, {d}; + \\.symver {s}, {s}{s}GLIBC_{d}.{d}.{d} + \\{s}: + \\ + , .{ + sym_plus_ver, + sym_plus_ver, + sym_plus_ver, + size, + sym_plus_ver, + sym_name, + at_sign_str, + ver.major, + ver.minor, + ver.patch, + sym_plus_ver, + }); + } + } + } + } + + var lib_name_buf: [32]u8 = undefined; // Larger than each of the names "c", "pthread", etc. + const asm_file_basename = std.fmt.bufPrint(&lib_name_buf, "{s}.s", .{lib.name}) catch unreachable; + try o_directory.handle.writeFile(asm_file_basename, stubs_asm.items); + + try buildSharedLib(comp, arena, comp.global_cache_directory, o_directory, asm_file_basename, lib); + } + + man.writeManifest() catch |err| { + log.warn("failed to write cache manifest for glibc stubs: {s}", .{@errorName(err)}); + }; + assert(comp.glibc_so_files == null); comp.glibc_so_files = BuiltSharedObjects{ - .lock = cache.toOwnedLock(), - .dir_path = try path.join(comp.gpa, &[_][]const u8{ comp.global_cache_directory.path.?, o_sub_path }), + .lock = man.toOwnedLock(), + .dir_path = try comp.global_cache_directory.join(comp.gpa, &.{ "o", &digest }), }; } diff --git a/src/print_targets.zig b/src/print_targets.zig index 02f894d401..33d4f523ab 100644 --- a/src/print_targets.zig +++ b/src/print_targets.zig @@ -25,7 +25,17 @@ pub fn cmdTargets( defer zig_lib_directory.handle.close(); defer allocator.free(zig_lib_directory.path.?); - const glibc_abi = try glibc.loadMetaData(allocator, zig_lib_directory.handle); + const abilists_contents = zig_lib_directory.handle.readFileAlloc( + allocator, + glibc.abilists_path, + glibc.abilists_max_size, + ) catch |err| switch (err) { + error.OutOfMemory => return error.OutOfMemory, + else => fatal("unable to read " ++ glibc.abilists_path ++ ": {s}", .{@errorName(err)}), + }; + defer allocator.free(abilists_contents); + + const glibc_abi = try glibc.loadMetaData(allocator, abilists_contents); defer glibc_abi.destroy(allocator); var bw = io.bufferedWriter(stdout); From 3e926d868ef75e521476a73f6c8245a688ff06c8 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 29 Oct 2022 12:15:38 -0700 Subject: [PATCH 2/2] CI: update freebsd tarball --- ci/srht/freebsd_script | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/srht/freebsd_script b/ci/srht/freebsd_script index b70a63f9cb..a810725932 100755 --- a/ci/srht/freebsd_script +++ b/ci/srht/freebsd_script @@ -9,7 +9,7 @@ sudo pkg install -y cmake py39-s3cmd wget curl jq samurai ZIGDIR="$(pwd)" TARGET="x86_64-freebsd-gnu" MCPU="baseline" -CACHE_BASENAME="zig+llvm+lld+clang-$TARGET-0.10.0-dev.61+9be8396b7" +CACHE_BASENAME="zig+llvm+lld+clang-$TARGET-0.10.0-dev.4560+828735ac0" PREFIX="$HOME/$CACHE_BASENAME" cd $HOME