| author | |
| committer | |
| log | c1add1e19ea35b4d96fbab317410276f757510ef |
| tree | 9791032b09046f6d5b785cd643439b266737cab4 |
| parent | 5b06daf52bdeaf18b40909ef878e8b19b3d14019 |
| parent | 728ce2d7c18e23ca6c36d86f4ee1ea4ce3ac81e2 |
| signature |
stage2: implement `--build-id` styles9 files changed, 210 insertions(+), 56 deletions(-)
build.zig+7-1| ... | ... | @@ -165,8 +165,14 @@ pub fn build(b: *std.Build) !void { |
| 165 | 165 | exe.strip = strip; |
| 166 | 166 | exe.pie = pie; |
| 167 | 167 | exe.sanitize_thread = sanitize_thread; |
| 168 | exe.build_id = b.option(bool, "build-id", "Include a build id note") orelse false; | |
| 169 | 168 | exe.entitlements = entitlements; |
| 169 | ||
| 170 | exe.build_id = b.option( | |
| 171 | std.Build.Step.Compile.BuildId, | |
| 172 | "build-id", | |
| 173 | "Request creation of '.note.gnu.build-id' section", | |
| 174 | ); | |
| 175 | ||
| 170 | 176 | b.installArtifact(exe); |
| 171 | 177 | |
| 172 | 178 | test_step.dependOn(&exe.step); |
lib/std/Build.zig+42-20| ... | ... | @@ -181,6 +181,7 @@ const TypeId = enum { |
| 181 | 181 | @"enum", |
| 182 | 182 | string, |
| 183 | 183 | list, |
| 184 | build_id, | |
| 184 | 185 | }; |
| 185 | 186 | |
| 186 | 187 | const TopLevelStep = struct { |
| ... | ... | @@ -832,13 +833,13 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_ |
| 832 | 833 | } else if (mem.eql(u8, s, "false")) { |
| 833 | 834 | return false; |
| 834 | 835 | } else { |
| 835 | log.err("Expected -D{s} to be a boolean, but received '{s}'\n", .{ name, s }); | |
| 836 | log.err("Expected -D{s} to be a boolean, but received '{s}'", .{ name, s }); | |
| 836 | 837 | self.markInvalidUserInput(); |
| 837 | 838 | return null; |
| 838 | 839 | } |
| 839 | 840 | }, |
| 840 | 841 | .list, .map => { |
| 841 | log.err("Expected -D{s} to be a boolean, but received a {s}.\n", .{ | |
| 842 | log.err("Expected -D{s} to be a boolean, but received a {s}.", .{ | |
| 842 | 843 | name, @tagName(option_ptr.value), |
| 843 | 844 | }); |
| 844 | 845 | self.markInvalidUserInput(); |
| ... | ... | @@ -847,7 +848,7 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_ |
| 847 | 848 | }, |
| 848 | 849 | .int => switch (option_ptr.value) { |
| 849 | 850 | .flag, .list, .map => { |
| 850 | log.err("Expected -D{s} to be an integer, but received a {s}.\n", .{ | |
| 851 | log.err("Expected -D{s} to be an integer, but received a {s}.", .{ | |
| 851 | 852 | name, @tagName(option_ptr.value), |
| 852 | 853 | }); |
| 853 | 854 | self.markInvalidUserInput(); |
| ... | ... | @@ -856,12 +857,12 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_ |
| 856 | 857 | .scalar => |s| { |
| 857 | 858 | const n = std.fmt.parseInt(T, s, 10) catch |err| switch (err) { |
| 858 | 859 | error.Overflow => { |
| 859 | log.err("-D{s} value {s} cannot fit into type {s}.\n", .{ name, s, @typeName(T) }); | |
| 860 | log.err("-D{s} value {s} cannot fit into type {s}.", .{ name, s, @typeName(T) }); | |
| 860 | 861 | self.markInvalidUserInput(); |
| 861 | 862 | return null; |
| 862 | 863 | }, |
| 863 | 864 | else => { |
| 864 | log.err("Expected -D{s} to be an integer of type {s}.\n", .{ name, @typeName(T) }); | |
| 865 | log.err("Expected -D{s} to be an integer of type {s}.", .{ name, @typeName(T) }); | |
| 865 | 866 | self.markInvalidUserInput(); |
| 866 | 867 | return null; |
| 867 | 868 | }, |
| ... | ... | @@ -871,7 +872,7 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_ |
| 871 | 872 | }, |
| 872 | 873 | .float => switch (option_ptr.value) { |
| 873 | 874 | .flag, .map, .list => { |
| 874 | log.err("Expected -D{s} to be a float, but received a {s}.\n", .{ | |
| 875 | log.err("Expected -D{s} to be a float, but received a {s}.", .{ | |
| 875 | 876 | name, @tagName(option_ptr.value), |
| 876 | 877 | }); |
| 877 | 878 | self.markInvalidUserInput(); |
| ... | ... | @@ -879,7 +880,7 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_ |
| 879 | 880 | }, |
| 880 | 881 | .scalar => |s| { |
| 881 | 882 | const n = std.fmt.parseFloat(T, s) catch { |
| 882 | log.err("Expected -D{s} to be a float of type {s}.\n", .{ name, @typeName(T) }); | |
| 883 | log.err("Expected -D{s} to be a float of type {s}.", .{ name, @typeName(T) }); | |
| 883 | 884 | self.markInvalidUserInput(); |
| 884 | 885 | return null; |
| 885 | 886 | }; |
| ... | ... | @@ -888,7 +889,7 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_ |
| 888 | 889 | }, |
| 889 | 890 | .@"enum" => switch (option_ptr.value) { |
| 890 | 891 | .flag, .map, .list => { |
| 891 | log.err("Expected -D{s} to be an enum, but received a {s}.\n", .{ | |
| 892 | log.err("Expected -D{s} to be an enum, but received a {s}.", .{ | |
| 892 | 893 | name, @tagName(option_ptr.value), |
| 893 | 894 | }); |
| 894 | 895 | self.markInvalidUserInput(); |
| ... | ... | @@ -898,7 +899,7 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_ |
| 898 | 899 | if (std.meta.stringToEnum(T, s)) |enum_lit| { |
| 899 | 900 | return enum_lit; |
| 900 | 901 | } else { |
| 901 | log.err("Expected -D{s} to be of type {s}.\n", .{ name, @typeName(T) }); | |
| 902 | log.err("Expected -D{s} to be of type {s}.", .{ name, @typeName(T) }); | |
| 902 | 903 | self.markInvalidUserInput(); |
| 903 | 904 | return null; |
| 904 | 905 | } |
| ... | ... | @@ -906,7 +907,7 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_ |
| 906 | 907 | }, |
| 907 | 908 | .string => switch (option_ptr.value) { |
| 908 | 909 | .flag, .list, .map => { |
| 909 | log.err("Expected -D{s} to be a string, but received a {s}.\n", .{ | |
| 910 | log.err("Expected -D{s} to be a string, but received a {s}.", .{ | |
| 910 | 911 | name, @tagName(option_ptr.value), |
| 911 | 912 | }); |
| 912 | 913 | self.markInvalidUserInput(); |
| ... | ... | @@ -914,9 +915,27 @@ pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_ |
| 914 | 915 | }, |
| 915 | 916 | .scalar => |s| return s, |
| 916 | 917 | }, |
| 918 | .build_id => switch (option_ptr.value) { | |
| 919 | .flag, .map, .list => { | |
| 920 | log.err("Expected -D{s} to be an enum, but received a {s}.", .{ | |
| 921 | name, @tagName(option_ptr.value), | |
| 922 | }); | |
| 923 | self.markInvalidUserInput(); | |
| 924 | return null; | |
| 925 | }, | |
| 926 | .scalar => |s| { | |
| 927 | if (Step.Compile.BuildId.parse(s)) |build_id| { | |
| 928 | return build_id; | |
| 929 | } else |err| { | |
| 930 | log.err("unable to parse option '-D{s}': {s}", .{ name, @errorName(err) }); | |
| 931 | self.markInvalidUserInput(); | |
| 932 | return null; | |
| 933 | } | |
| 934 | }, | |
| 935 | }, | |
| 917 | 936 | .list => switch (option_ptr.value) { |
| 918 | 937 | .flag, .map => { |
| 919 | log.err("Expected -D{s} to be a list, but received a {s}.\n", .{ | |
| 938 | log.err("Expected -D{s} to be a list, but received a {s}.", .{ | |
| 920 | 939 | name, @tagName(option_ptr.value), |
| 921 | 940 | }); |
| 922 | 941 | self.markInvalidUserInput(); |
| ... | ... | @@ -1183,15 +1202,18 @@ pub fn addUserInputFlag(self: *Build, name_raw: []const u8) !bool { |
| 1183 | 1202 | } |
| 1184 | 1203 | |
| 1185 | 1204 | fn typeToEnum(comptime T: type) TypeId { |
| 1186 | return switch (@typeInfo(T)) { | |
| 1187 | .Int => .int, | |
| 1188 | .Float => .float, | |
| 1189 | .Bool => .bool, | |
| 1190 | .Enum => .@"enum", | |
| 1191 | else => switch (T) { | |
| 1192 | []const u8 => .string, | |
| 1193 | []const []const u8 => .list, | |
| 1194 | else => @compileError("Unsupported type: " ++ @typeName(T)), | |
| 1205 | return switch (T) { | |
| 1206 | Step.Compile.BuildId => .build_id, | |
| 1207 | else => return switch (@typeInfo(T)) { | |
| 1208 | .Int => .int, | |
| 1209 | .Float => .float, | |
| 1210 | .Bool => .bool, | |
| 1211 | .Enum => .@"enum", | |
| 1212 | else => switch (T) { | |
| 1213 | []const u8 => .string, | |
| 1214 | []const []const u8 => .list, | |
| 1215 | else => @compileError("Unsupported type: " ++ @typeName(T)), | |
| 1216 | }, | |
| 1195 | 1217 | }, |
| 1196 | 1218 | }; |
| 1197 | 1219 | } |
lib/std/Build/Cache.zig+4| ... | ... | @@ -235,6 +235,10 @@ pub const HashHelper = struct { |
| 235 | 235 | .none => {}, |
| 236 | 236 | } |
| 237 | 237 | }, |
| 238 | std.Build.Step.Compile.BuildId => switch (x) { | |
| 239 | .none, .fast, .uuid, .sha1, .md5 => hh.add(std.meta.activeTag(x)), | |
| 240 | .hexstring => |hex_string| hh.addBytes(hex_string.toSlice()), | |
| 241 | }, | |
| 238 | 242 | else => switch (@typeInfo(@TypeOf(x))) { |
| 239 | 243 | .Bool, .Int, .Enum, .Array => hh.addBytes(mem.asBytes(&x)), |
| 240 | 244 | else => @compileError("unable to hash type " ++ @typeName(@TypeOf(x))), |
lib/std/Build/Step/Compile.zig+86-2| ... | ... | @@ -116,7 +116,7 @@ each_lib_rpath: ?bool = null, |
| 116 | 116 | /// As an example, the bloaty project refuses to work unless its inputs have |
| 117 | 117 | /// build ids, in order to prevent accidental mismatches. |
| 118 | 118 | /// The default is to not include this section because it slows down linking. |
| 119 | build_id: ?bool = null, | |
| 119 | build_id: ?BuildId = null, | |
| 120 | 120 | |
| 121 | 121 | /// Create a .eh_frame_hdr section and a PT_GNU_EH_FRAME segment in the ELF |
| 122 | 122 | /// file. |
| ... | ... | @@ -288,6 +288,82 @@ pub const Options = struct { |
| 288 | 288 | use_lld: ?bool = null, |
| 289 | 289 | }; |
| 290 | 290 | |
| 291 | pub const BuildId = union(enum) { | |
| 292 | none, | |
| 293 | fast, | |
| 294 | uuid, | |
| 295 | sha1, | |
| 296 | md5, | |
| 297 | hexstring: HexString, | |
| 298 | ||
| 299 | pub fn eql(a: BuildId, b: BuildId) bool { | |
| 300 | const a_tag = std.meta.activeTag(a); | |
| 301 | const b_tag = std.meta.activeTag(b); | |
| 302 | if (a_tag != b_tag) return false; | |
| 303 | return switch (a) { | |
| 304 | .none, .fast, .uuid, .sha1, .md5 => true, | |
| 305 | .hexstring => |a_hexstring| mem.eql(u8, a_hexstring.toSlice(), b.hexstring.toSlice()), | |
| 306 | }; | |
| 307 | } | |
| 308 | ||
| 309 | pub const HexString = struct { | |
| 310 | bytes: [32]u8, | |
| 311 | len: u8, | |
| 312 | ||
| 313 | /// Result is byte values, *not* hex-encoded. | |
| 314 | pub fn toSlice(hs: *const HexString) []const u8 { | |
| 315 | return hs.bytes[0..hs.len]; | |
| 316 | } | |
| 317 | }; | |
| 318 | ||
| 319 | /// Input is byte values, *not* hex-encoded. | |
| 320 | /// Asserts `bytes` fits inside `HexString` | |
| 321 | pub fn initHexString(bytes: []const u8) BuildId { | |
| 322 | var result: BuildId = .{ .hexstring = .{ | |
| 323 | .bytes = undefined, | |
| 324 | .len = @intCast(u8, bytes.len), | |
| 325 | } }; | |
| 326 | @memcpy(result.hexstring.bytes[0..bytes.len], bytes); | |
| 327 | return result; | |
| 328 | } | |
| 329 | ||
| 330 | /// Converts UTF-8 text to a `BuildId`. | |
| 331 | pub fn parse(text: []const u8) !BuildId { | |
| 332 | if (mem.eql(u8, text, "none")) { | |
| 333 | return .none; | |
| 334 | } else if (mem.eql(u8, text, "fast")) { | |
| 335 | return .fast; | |
| 336 | } else if (mem.eql(u8, text, "uuid")) { | |
| 337 | return .uuid; | |
| 338 | } else if (mem.eql(u8, text, "sha1") or mem.eql(u8, text, "tree")) { | |
| 339 | return .sha1; | |
| 340 | } else if (mem.eql(u8, text, "md5")) { | |
| 341 | return .md5; | |
| 342 | } else if (mem.startsWith(u8, text, "0x")) { | |
| 343 | var result: BuildId = .{ .hexstring = undefined }; | |
| 344 | const slice = try std.fmt.hexToBytes(&result.hexstring.bytes, text[2..]); | |
| 345 | result.hexstring.len = @intCast(u8, slice.len); | |
| 346 | return result; | |
| 347 | } | |
| 348 | return error.InvalidBuildIdStyle; | |
| 349 | } | |
| 350 | ||
| 351 | test parse { | |
| 352 | try std.testing.expectEqual(BuildId.md5, try parse("md5")); | |
| 353 | try std.testing.expectEqual(BuildId.none, try parse("none")); | |
| 354 | try std.testing.expectEqual(BuildId.fast, try parse("fast")); | |
| 355 | try std.testing.expectEqual(BuildId.uuid, try parse("uuid")); | |
| 356 | try std.testing.expectEqual(BuildId.sha1, try parse("sha1")); | |
| 357 | try std.testing.expectEqual(BuildId.sha1, try parse("tree")); | |
| 358 | ||
| 359 | try std.testing.expect(BuildId.initHexString("").eql(try parse("0x"))); | |
| 360 | try std.testing.expect(BuildId.initHexString("\x12\x34\x56").eql(try parse("0x123456"))); | |
| 361 | try std.testing.expectError(error.InvalidLength, parse("0x12-34")); | |
| 362 | try std.testing.expectError(error.InvalidCharacter, parse("0xfoobbb")); | |
| 363 | try std.testing.expectError(error.InvalidBuildIdStyle, parse("yaddaxxx")); | |
| 364 | } | |
| 365 | }; | |
| 366 | ||
| 291 | 367 | pub const Kind = enum { |
| 292 | 368 | exe, |
| 293 | 369 | lib, |
| ... | ... | @@ -1810,7 +1886,15 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 1810 | 1886 | |
| 1811 | 1887 | try addFlag(&zig_args, "valgrind", self.valgrind_support); |
| 1812 | 1888 | try addFlag(&zig_args, "each-lib-rpath", self.each_lib_rpath); |
| 1813 | try addFlag(&zig_args, "build-id", self.build_id); | |
| 1889 | ||
| 1890 | if (self.build_id) |build_id| { | |
| 1891 | try zig_args.append(switch (build_id) { | |
| 1892 | .hexstring => |hs| b.fmt("--build-id=0x{s}", .{ | |
| 1893 | std.fmt.fmtSliceHexLower(hs.toSlice()), | |
| 1894 | }), | |
| 1895 | .none, .fast, .uuid, .sha1, .md5 => b.fmt("--build-id={s}", .{@tagName(build_id)}), | |
| 1896 | }); | |
| 1897 | } | |
| 1814 | 1898 | |
| 1815 | 1899 | if (self.zig_lib_dir) |dir| { |
| 1816 | 1900 | try zig_args.append("--zig-lib-dir"); |
src/Compilation.zig+4-3| ... | ... | @@ -29,6 +29,7 @@ const wasi_libc = @import("wasi_libc.zig"); |
| 29 | 29 | const fatal = @import("main.zig").fatal; |
| 30 | 30 | const clangMain = @import("main.zig").clangMain; |
| 31 | 31 | const Module = @import("Module.zig"); |
| 32 | const BuildId = std.Build.CompileStep.BuildId; | |
| 32 | 33 | const Cache = std.Build.Cache; |
| 33 | 34 | const translate_c = @import("translate_c.zig"); |
| 34 | 35 | const clang = @import("clang.zig"); |
| ... | ... | @@ -563,7 +564,7 @@ pub const InitOptions = struct { |
| 563 | 564 | linker_print_map: bool = false, |
| 564 | 565 | linker_opt_bisect_limit: i32 = -1, |
| 565 | 566 | each_lib_rpath: ?bool = null, |
| 566 | build_id: ?bool = null, | |
| 567 | build_id: ?BuildId = null, | |
| 567 | 568 | disable_c_depfile: bool = false, |
| 568 | 569 | linker_z_nodelete: bool = false, |
| 569 | 570 | linker_z_notext: bool = false, |
| ... | ... | @@ -797,7 +798,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { |
| 797 | 798 | const unwind_tables = options.want_unwind_tables orelse |
| 798 | 799 | (link_libunwind or target_util.needUnwindTables(options.target)); |
| 799 | 800 | const link_eh_frame_hdr = options.link_eh_frame_hdr or unwind_tables; |
| 800 | const build_id = options.build_id orelse false; | |
| 801 | const build_id = options.build_id orelse .none; | |
| 801 | 802 | |
| 802 | 803 | // Make a decision on whether to use LLD or our own linker. |
| 803 | 804 | const use_lld = options.use_lld orelse blk: { |
| ... | ... | @@ -828,7 +829,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { |
| 828 | 829 | options.output_mode == .Lib or |
| 829 | 830 | options.linker_script != null or options.version_script != null or |
| 830 | 831 | options.emit_implib != null or |
| 831 | build_id or | |
| 832 | build_id != .none or | |
| 832 | 833 | options.symbol_wrap_set.count() > 0) |
| 833 | 834 | { |
| 834 | 835 | break :blk true; |
src/link.zig+2-1| ... | ... | @@ -10,6 +10,7 @@ const wasi_libc = @import("wasi_libc.zig"); |
| 10 | 10 | |
| 11 | 11 | const Air = @import("Air.zig"); |
| 12 | 12 | const Allocator = std.mem.Allocator; |
| 13 | const BuildId = std.Build.CompileStep.BuildId; | |
| 13 | 14 | const Cache = std.Build.Cache; |
| 14 | 15 | const Compilation = @import("Compilation.zig"); |
| 15 | 16 | const LibCInstallation = @import("libc_installation.zig").LibCInstallation; |
| ... | ... | @@ -157,7 +158,7 @@ pub const Options = struct { |
| 157 | 158 | skip_linker_dependencies: bool, |
| 158 | 159 | parent_compilation_link_libc: bool, |
| 159 | 160 | each_lib_rpath: bool, |
| 160 | build_id: bool, | |
| 161 | build_id: BuildId, | |
| 161 | 162 | disable_lld_caching: bool, |
| 162 | 163 | is_test: bool, |
| 163 | 164 | hash_style: HashStyle, |
src/link/Elf.zig+12-2| ... | ... | @@ -1542,8 +1542,18 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v |
| 1542 | 1542 | try argv.append("-z"); |
| 1543 | 1543 | try argv.append(try std.fmt.allocPrint(arena, "stack-size={d}", .{stack_size})); |
| 1544 | 1544 | |
| 1545 | if (self.base.options.build_id) { | |
| 1546 | try argv.append("--build-id"); | |
| 1545 | switch (self.base.options.build_id) { | |
| 1546 | .none => {}, | |
| 1547 | .fast, .uuid, .sha1, .md5 => { | |
| 1548 | try argv.append(try std.fmt.allocPrint(arena, "--build-id={s}", .{ | |
| 1549 | @tagName(self.base.options.build_id), | |
| 1550 | })); | |
| 1551 | }, | |
| 1552 | .hexstring => |hs| { | |
| 1553 | try argv.append(try std.fmt.allocPrint(arena, "--build-id=0x{s}", .{ | |
| 1554 | std.fmt.fmtSliceHexLower(hs.toSlice()), | |
| 1555 | })); | |
| 1556 | }, | |
| 1547 | 1557 | } |
| 1548 | 1558 | } |
| 1549 | 1559 |
src/link/Wasm.zig+29-16| ... | ... | @@ -3797,8 +3797,29 @@ fn writeToFile( |
| 3797 | 3797 | if (!wasm.base.options.strip) { |
| 3798 | 3798 | // The build id must be computed on the main sections only, |
| 3799 | 3799 | // so we have to do it now, before the debug sections. |
| 3800 | if (wasm.base.options.build_id) { | |
| 3801 | try emitBuildIdSection(&binary_bytes); | |
| 3800 | switch (wasm.base.options.build_id) { | |
| 3801 | .none => {}, | |
| 3802 | .fast => { | |
| 3803 | var id: [16]u8 = undefined; | |
| 3804 | std.crypto.hash.sha3.TurboShake128(null).hash(binary_bytes.items, &id, .{}); | |
| 3805 | var uuid: [36]u8 = undefined; | |
| 3806 | _ = try std.fmt.bufPrint(&uuid, "{s}-{s}-{s}-{s}-{s}", .{ | |
| 3807 | std.fmt.fmtSliceHexLower(id[0..4]), | |
| 3808 | std.fmt.fmtSliceHexLower(id[4..6]), | |
| 3809 | std.fmt.fmtSliceHexLower(id[6..8]), | |
| 3810 | std.fmt.fmtSliceHexLower(id[8..10]), | |
| 3811 | std.fmt.fmtSliceHexLower(id[10..]), | |
| 3812 | }); | |
| 3813 | try emitBuildIdSection(&binary_bytes, &uuid); | |
| 3814 | }, | |
| 3815 | .hexstring => |hs| { | |
| 3816 | var buffer: [32 * 2]u8 = undefined; | |
| 3817 | const str = std.fmt.bufPrint(&buffer, "{s}", .{ | |
| 3818 | std.fmt.fmtSliceHexLower(hs.toSlice()), | |
| 3819 | }) catch unreachable; | |
| 3820 | try emitBuildIdSection(&binary_bytes, str); | |
| 3821 | }, | |
| 3822 | else => |mode| log.err("build-id '{s}' is not supported for WASM", .{@tagName(mode)}), | |
| 3802 | 3823 | } |
| 3803 | 3824 | |
| 3804 | 3825 | // if (wasm.dwarf) |*dwarf| { |
| ... | ... | @@ -3942,25 +3963,17 @@ fn emitProducerSection(binary_bytes: *std.ArrayList(u8)) !void { |
| 3942 | 3963 | ); |
| 3943 | 3964 | } |
| 3944 | 3965 | |
| 3945 | fn emitBuildIdSection(binary_bytes: *std.ArrayList(u8)) !void { | |
| 3966 | fn emitBuildIdSection(binary_bytes: *std.ArrayList(u8), build_id: []const u8) !void { | |
| 3946 | 3967 | const header_offset = try reserveCustomSectionHeader(binary_bytes); |
| 3947 | 3968 | |
| 3948 | 3969 | const writer = binary_bytes.writer(); |
| 3949 | const build_id = "build_id"; | |
| 3950 | try leb.writeULEB128(writer, @intCast(u32, build_id.len)); | |
| 3951 | try writer.writeAll(build_id); | |
| 3952 | ||
| 3953 | var id: [16]u8 = undefined; | |
| 3954 | std.crypto.hash.sha3.TurboShake128(null).hash(binary_bytes.items, &id, .{}); | |
| 3955 | var uuid: [36]u8 = undefined; | |
| 3956 | _ = try std.fmt.bufPrint(&uuid, "{s}-{s}-{s}-{s}-{s}", .{ | |
| 3957 | std.fmt.fmtSliceHexLower(id[0..4]), std.fmt.fmtSliceHexLower(id[4..6]), std.fmt.fmtSliceHexLower(id[6..8]), | |
| 3958 | std.fmt.fmtSliceHexLower(id[8..10]), std.fmt.fmtSliceHexLower(id[10..]), | |
| 3959 | }); | |
| 3970 | const hdr_build_id = "build_id"; | |
| 3971 | try leb.writeULEB128(writer, @intCast(u32, hdr_build_id.len)); | |
| 3972 | try writer.writeAll(hdr_build_id); | |
| 3960 | 3973 | |
| 3961 | 3974 | try leb.writeULEB128(writer, @as(u32, 1)); |
| 3962 | try leb.writeULEB128(writer, @as(u32, uuid.len)); | |
| 3963 | try writer.writeAll(&uuid); | |
| 3975 | try leb.writeULEB128(writer, @intCast(u32, build_id.len)); | |
| 3976 | try writer.writeAll(build_id); | |
| 3964 | 3977 | |
| 3965 | 3978 | try writeCustomSectionHeader( |
| 3966 | 3979 | binary_bytes.items, |
src/main.zig+24-11| ... | ... | @@ -22,6 +22,7 @@ const LibCInstallation = @import("libc_installation.zig").LibCInstallation; |
| 22 | 22 | const wasi_libc = @import("wasi_libc.zig"); |
| 23 | 23 | const translate_c = @import("translate_c.zig"); |
| 24 | 24 | const clang = @import("clang.zig"); |
| 25 | const BuildId = std.Build.CompileStep.BuildId; | |
| 25 | 26 | const Cache = std.Build.Cache; |
| 26 | 27 | const target_util = @import("target.zig"); |
| 27 | 28 | const crash_report = @import("crash_report.zig"); |
| ... | ... | @@ -493,8 +494,10 @@ const usage_build_generic = |
| 493 | 494 | \\ -fno-each-lib-rpath Prevent adding rpath for each used dynamic library |
| 494 | 495 | \\ -fallow-shlib-undefined Allows undefined symbols in shared libraries |
| 495 | 496 | \\ -fno-allow-shlib-undefined Disallows undefined symbols in shared libraries |
| 496 | \\ -fbuild-id Helps coordinate stripped binaries with debug symbols | |
| 497 | \\ -fno-build-id (default) Saves a bit of time linking | |
| 497 | \\ --build-id[=style] At a minor link-time expense, coordinates stripped binaries | |
| 498 | \\ fast, uuid, sha1, md5 with debug symbols via a '.note.gnu.build-id' section | |
| 499 | \\ 0x[hexstring] Maximum 32 bytes | |
| 500 | \\ none (default) Disable build-id | |
| 498 | 501 | \\ --eh-frame-hdr Enable C++ exception handling by passing --eh-frame-hdr to linker |
| 499 | 502 | \\ --emit-relocs Enable output of relocation sections for post build tools |
| 500 | 503 | \\ -z [arg] Set linker extension flags |
| ... | ... | @@ -817,7 +820,7 @@ fn buildOutputType( |
| 817 | 820 | var link_eh_frame_hdr = false; |
| 818 | 821 | var link_emit_relocs = false; |
| 819 | 822 | var each_lib_rpath: ?bool = null; |
| 820 | var build_id: ?bool = null; | |
| 823 | var build_id: ?BuildId = null; | |
| 821 | 824 | var sysroot: ?[]const u8 = null; |
| 822 | 825 | var libc_paths_file: ?[]const u8 = try optionalStringEnvVar(arena, "ZIG_LIBC"); |
| 823 | 826 | var machine_code_model: std.builtin.CodeModel = .default; |
| ... | ... | @@ -1202,10 +1205,6 @@ fn buildOutputType( |
| 1202 | 1205 | each_lib_rpath = true; |
| 1203 | 1206 | } else if (mem.eql(u8, arg, "-fno-each-lib-rpath")) { |
| 1204 | 1207 | each_lib_rpath = false; |
| 1205 | } else if (mem.eql(u8, arg, "-fbuild-id")) { | |
| 1206 | build_id = true; | |
| 1207 | } else if (mem.eql(u8, arg, "-fno-build-id")) { | |
| 1208 | build_id = false; | |
| 1209 | 1208 | } else if (mem.eql(u8, arg, "--test-cmd-bin")) { |
| 1210 | 1209 | try test_exec_args.append(null); |
| 1211 | 1210 | } else if (mem.eql(u8, arg, "--test-evented-io")) { |
| ... | ... | @@ -1446,6 +1445,15 @@ fn buildOutputType( |
| 1446 | 1445 | linker_gc_sections = true; |
| 1447 | 1446 | } else if (mem.eql(u8, arg, "--no-gc-sections")) { |
| 1448 | 1447 | linker_gc_sections = false; |
| 1448 | } else if (mem.eql(u8, arg, "--build-id")) { | |
| 1449 | build_id = .fast; | |
| 1450 | } else if (mem.startsWith(u8, arg, "--build-id=")) { | |
| 1451 | const style = arg["--build-id=".len..]; | |
| 1452 | build_id = BuildId.parse(style) catch |err| { | |
| 1453 | fatal("unable to parse --build-id style '{s}': {s}", .{ | |
| 1454 | style, @errorName(err), | |
| 1455 | }); | |
| 1456 | }; | |
| 1449 | 1457 | } else if (mem.eql(u8, arg, "--debug-compile-errors")) { |
| 1450 | 1458 | if (!crash_report.is_enabled) { |
| 1451 | 1459 | std.log.warn("Zig was compiled in a release mode. --debug-compile-errors has no effect.", .{}); |
| ... | ... | @@ -1684,9 +1692,12 @@ fn buildOutputType( |
| 1684 | 1692 | if (mem.indexOfScalar(u8, linker_arg, '=')) |equals_pos| { |
| 1685 | 1693 | const key = linker_arg[0..equals_pos]; |
| 1686 | 1694 | const value = linker_arg[equals_pos + 1 ..]; |
| 1687 | if (mem.eql(u8, key, "build-id")) { | |
| 1688 | build_id = true; | |
| 1689 | warn("ignoring build-id style argument: '{s}'", .{value}); | |
| 1695 | if (mem.eql(u8, key, "--build-id")) { | |
| 1696 | build_id = BuildId.parse(value) catch |err| { | |
| 1697 | fatal("unable to parse --build-id style '{s}': {s}", .{ | |
| 1698 | value, @errorName(err), | |
| 1699 | }); | |
| 1700 | }; | |
| 1690 | 1701 | continue; |
| 1691 | 1702 | } else if (mem.eql(u8, key, "--sort-common")) { |
| 1692 | 1703 | // this ignores --sort=common=<anything>; ignoring plain --sort-common |
| ... | ... | @@ -1698,7 +1709,9 @@ fn buildOutputType( |
| 1698 | 1709 | continue; |
| 1699 | 1710 | } |
| 1700 | 1711 | } |
| 1701 | if (mem.eql(u8, linker_arg, "--as-needed")) { | |
| 1712 | if (mem.eql(u8, linker_arg, "--build-id")) { | |
| 1713 | build_id = .fast; | |
| 1714 | } else if (mem.eql(u8, linker_arg, "--as-needed")) { | |
| 1702 | 1715 | needed = false; |
| 1703 | 1716 | } else if (mem.eql(u8, linker_arg, "--no-as-needed")) { |
| 1704 | 1717 | needed = true; |