authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-02-16 03:46:12-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-01 16:35:25-07:00
logff3581ca2d21ed0557aa6bc10fba8168375a77c7
tree6fefb478e5428707b92c77c09cf2cb619596676e
parent1d0495678dc3729feb40939ddcaaef552efadbda

update some of the build system to new API


8 files changed, 506 insertions(+), 474 deletions(-)

lib/std/Build/Cache/DepTokenizer.zig+7-9
...@@ -435,7 +435,7 @@ pub const Token = union(enum) {...@@ -435,7 +435,7 @@ pub const Token = union(enum) {
435 .incomplete_quoted_prerequisite,435 .incomplete_quoted_prerequisite,
436 .incomplete_target,436 .incomplete_target,
437 => |index_and_bytes| {437 => |index_and_bytes| {
438 try list.print("{s} '", .{self.errStr()});438 try list.print(gpa, "{s} '", .{self.errStr()});
439 if (self == .incomplete_target) {439 if (self == .incomplete_target) {
440 const tmp = Token{ .target_must_resolve = index_and_bytes.bytes };440 const tmp = Token{ .target_must_resolve = index_and_bytes.bytes };
441 try tmp.resolve(gpa, list);441 try tmp.resolve(gpa, list);
...@@ -451,7 +451,7 @@ pub const Token = union(enum) {...@@ -451,7 +451,7 @@ pub const Token = union(enum) {
451 .incomplete_escape,451 .incomplete_escape,
452 .expected_colon,452 .expected_colon,
453 => |index_and_char| {453 => |index_and_char| {
454 try list.appendSlice("illegal char ");454 try list.appendSlice(gpa, "illegal char ");
455 try printUnderstandableChar(gpa, list, index_and_char.char);455 try printUnderstandableChar(gpa, list, index_and_char.char);
456 try list.print(gpa, " at position {d}: {s}", .{ index_and_char.index, self.errStr() });456 try list.print(gpa, " at position {d}: {s}", .{ index_and_char.index, self.errStr() });
457 },457 },
...@@ -1076,17 +1076,15 @@ fn depTokenizer(input: []const u8, expect: []const u8) !void {...@@ -1076,17 +1076,15 @@ fn depTokenizer(input: []const u8, expect: []const u8) !void {
1076 try testing.expectEqualStrings(expect, buffer.items);1076 try testing.expectEqualStrings(expect, buffer.items);
1077}1077}
10781078
1079fn printCharValues(out: anytype, bytes: []const u8) !void {1079fn printCharValues(gpa: Allocator, list: *std.ArrayListUnmanaged(u8), bytes: []const u8) !void {
1080 for (bytes) |b| {1080 for (bytes) |b| try list.append(gpa, printable_char_tab[b]);
1081 try out.writeAll(&[_]u8{printable_char_tab[b]});
1082 }
1083}1081}
10841082
1085fn printUnderstandableChar(out: anytype, char: u8) !void {1083fn printUnderstandableChar(gpa: Allocator, list: *std.ArrayListUnmanaged(u8), char: u8) !void {
1086 if (std.ascii.isPrint(char)) {1084 if (std.ascii.isPrint(char)) {
1087 try out.print("'{c}'", .{char});1085 try list.print(gpa, "'{c}'", .{char});
1088 } else {1086 } else {
1089 try out.print("\\x{X:0>2}", .{char});1087 try list.print(gpa, "\\x{X:0>2}", .{char});
1090 }1088 }
1091}1089}
10921090
lib/std/Build/Step.zig+19-19
...@@ -287,26 +287,26 @@ pub fn cast(step: *Step, comptime T: type) ?*T {...@@ -287,26 +287,26 @@ pub fn cast(step: *Step, comptime T: type) ?*T {
287287
288/// For debugging purposes, prints identifying information about this Step.288/// For debugging purposes, prints identifying information about this Step.
289pub fn dump(step: *Step, file: std.fs.File) void {289pub fn dump(step: *Step, file: std.fs.File) void {
290 const w = file.writer();290 var bw = file.unbufferedWriter();
291 const tty_config = std.io.tty.detectConfig(file);291 const tty_config = std.io.tty.detectConfig(file);
292 const debug_info = std.debug.getSelfDebugInfo() catch |err| {292 const debug_info = std.debug.getSelfDebugInfo() catch |err| {
293 w.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{293 bw.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{
294 @errorName(err),294 @errorName(err),
295 }) catch {};295 }) catch {};
296 return;296 return;
297 };297 };
298 if (step.getStackTrace()) |stack_trace| {298 if (step.getStackTrace()) |stack_trace| {
299 w.print("name: '{s}'. creation stack trace:\n", .{step.name}) catch {};299 bw.print("name: '{s}'. creation stack trace:\n", .{step.name}) catch {};
300 std.debug.writeStackTrace(stack_trace, w, debug_info, tty_config) catch |err| {300 std.debug.writeStackTrace(stack_trace, &bw, debug_info, tty_config) catch |err| {
301 w.print("Unable to dump stack trace: {s}\n", .{@errorName(err)}) catch {};301 bw.print("Unable to dump stack trace: {s}\n", .{@errorName(err)}) catch {};
302 return;302 return;
303 };303 };
304 } else {304 } else {
305 const field = "debug_stack_frames_count";305 const field = "debug_stack_frames_count";
306 comptime assert(@hasField(Build, field));306 comptime assert(@hasField(Build, field));
307 tty_config.setColor(w, .yellow) catch {};307 tty_config.setColor(&bw, .yellow) catch {};
308 w.print("name: '{s}'. no stack trace collected for this step, see std.Build." ++ field ++ "\n", .{step.name}) catch {};308 bw.print("name: '{s}'. no stack trace collected for this step, see std.Build." ++ field ++ "\n", .{step.name}) catch {};
309 tty_config.setColor(w, .reset) catch {};309 tty_config.setColor(&bw, .reset) catch {};
310 }310 }
311}311}
312312
...@@ -738,7 +738,7 @@ pub fn allocPrintCmd2(...@@ -738,7 +738,7 @@ pub fn allocPrintCmd2(
738 argv: []const []const u8,738 argv: []const []const u8,
739) Allocator.Error![]u8 {739) Allocator.Error![]u8 {
740 const shell = struct {740 const shell = struct {
741 fn escape(writer: anytype, string: []const u8, is_argv0: bool) !void {741 fn escape(writer: *std.io.Writer, string: []const u8, is_argv0: bool) !void {
742 for (string) |c| {742 for (string) |c| {
743 if (switch (c) {743 if (switch (c) {
744 else => true,744 else => true,
...@@ -772,9 +772,9 @@ pub fn allocPrintCmd2(...@@ -772,9 +772,9 @@ pub fn allocPrintCmd2(
772 }772 }
773 };773 };
774774
775 var buf: std.ArrayListUnmanaged(u8) = .empty;775 var aw: std.io.Writer.Allocating = .init(arena);
776 const writer = buf.writer(arena);776 const w = &aw.interface;
777 if (opt_cwd) |cwd| try writer.print("cd {s} && ", .{cwd});777 if (opt_cwd) |cwd| try w.print(arena, "cd {s} && ", .{cwd});
778 if (opt_env) |env| {778 if (opt_env) |env| {
779 const process_env_map = std.process.getEnvMap(arena) catch std.process.EnvMap.init(arena);779 const process_env_map = std.process.getEnvMap(arena) catch std.process.EnvMap.init(arena);
780 var it = env.iterator();780 var it = env.iterator();
...@@ -784,17 +784,17 @@ pub fn allocPrintCmd2(...@@ -784,17 +784,17 @@ pub fn allocPrintCmd2(
784 if (process_env_map.get(key)) |process_value| {784 if (process_env_map.get(key)) |process_value| {
785 if (std.mem.eql(u8, value, process_value)) continue;785 if (std.mem.eql(u8, value, process_value)) continue;
786 }786 }
787 try writer.print("{s}=", .{key});787 try w.print(arena, "{s}=", .{key});
788 try shell.escape(writer, value, false);788 try shell.escape(w, value, false);
789 try writer.writeByte(' ');789 try w.writeByte(arena, ' ');
790 }790 }
791 }791 }
792 try shell.escape(writer, argv[0], true);792 try shell.escape(w, argv[0], true);
793 for (argv[1..]) |arg| {793 for (argv[1..]) |arg| {
794 try writer.writeByte(' ');794 try w.writeByte(arena, ' ');
795 try shell.escape(writer, arg, false);795 try shell.escape(w, arg, false);
796 }796 }
797 return buf.toOwnedSlice(arena);797 return aw.getWritten();
798}798}
799799
800/// Prefer `cacheHitAndWatch` unless you already added watch inputs800/// Prefer `cacheHitAndWatch` unless you already added watch inputs
lib/std/Build/Step/CheckObject.zig+321-314
...@@ -248,56 +248,63 @@ const ComputeCompareExpected = struct {...@@ -248,56 +248,63 @@ const ComputeCompareExpected = struct {
248const Check = struct {248const Check = struct {
249 kind: Kind,249 kind: Kind,
250 payload: Payload,250 payload: Payload,
251 data: std.ArrayList(u8),251 allocator: Allocator,
252 actions: std.ArrayList(Action),252 data: std.ArrayListUnmanaged(u8),
253 actions: std.ArrayListUnmanaged(Action),
253254
254 fn create(allocator: Allocator, kind: Kind) Check {255 fn create(allocator: Allocator, kind: Kind) Check {
255 return .{256 return .{
256 .kind = kind,257 .kind = kind,
257 .payload = .{ .none = {} },258 .payload = .{ .none = {} },
258 .data = std.ArrayList(u8).init(allocator),259 .allocator = allocator,
259 .actions = std.ArrayList(Action).init(allocator),260 .data = .empty,
261 .actions = .empty,
260 };262 };
261 }263 }
262264
263 fn dumpSection(allocator: Allocator, name: [:0]const u8) Check {265 fn dumpSection(gpa: Allocator, name: [:0]const u8) Check {
264 var check = Check.create(allocator, .dump_section);266 var check = Check.create(gpa, .dump_section);
265 const off: u32 = @intCast(check.data.items.len);267 const off: u32 = @intCast(check.data.items.len);
266 check.data.writer().print("{s}\x00", .{name}) catch @panic("OOM");268 check.data.print(gpa, "{s}\x00", .{name}) catch @panic("OOM");
267 check.payload = .{ .dump_section = off };269 check.payload = .{ .dump_section = off };
268 return check;270 return check;
269 }271 }
270272
271 fn extract(check: *Check, phrase: SearchPhrase) void {273 fn extract(check: *Check, phrase: SearchPhrase) void {
272 check.actions.append(.{274 const gpa = check.allocator;
275 check.actions.append(gpa, .{
273 .tag = .extract,276 .tag = .extract,
274 .phrase = phrase,277 .phrase = phrase,
275 }) catch @panic("OOM");278 }) catch @panic("OOM");
276 }279 }
277280
278 fn exact(check: *Check, phrase: SearchPhrase) void {281 fn exact(check: *Check, phrase: SearchPhrase) void {
279 check.actions.append(.{282 const gpa = check.allocator;
283 check.actions.append(gpa, .{
280 .tag = .exact,284 .tag = .exact,
281 .phrase = phrase,285 .phrase = phrase,
282 }) catch @panic("OOM");286 }) catch @panic("OOM");
283 }287 }
284288
285 fn contains(check: *Check, phrase: SearchPhrase) void {289 fn contains(check: *Check, phrase: SearchPhrase) void {
286 check.actions.append(.{290 const gpa = check.allocator;
291 check.actions.append(gpa, .{
287 .tag = .contains,292 .tag = .contains,
288 .phrase = phrase,293 .phrase = phrase,
289 }) catch @panic("OOM");294 }) catch @panic("OOM");
290 }295 }
291296
292 fn notPresent(check: *Check, phrase: SearchPhrase) void {297 fn notPresent(check: *Check, phrase: SearchPhrase) void {
293 check.actions.append(.{298 const gpa = check.allocator;
299 check.actions.append(gpa, .{
294 .tag = .not_present,300 .tag = .not_present,
295 .phrase = phrase,301 .phrase = phrase,
296 }) catch @panic("OOM");302 }) catch @panic("OOM");
297 }303 }
298304
299 fn computeCmp(check: *Check, phrase: SearchPhrase, expected: ComputeCompareExpected) void {305 fn computeCmp(check: *Check, phrase: SearchPhrase, expected: ComputeCompareExpected) void {
300 check.actions.append(.{306 const gpa = check.allocator;
307 check.actions.append(gpa, .{
301 .tag = .compute_cmp,308 .tag = .compute_cmp,
302 .phrase = phrase,309 .phrase = phrase,
303 .expected = expected,310 .expected = expected,
...@@ -810,7 +817,7 @@ const MachODumper = struct {...@@ -810,7 +817,7 @@ const MachODumper = struct {
810 return null;817 return null;
811 }818 }
812819
813 fn dumpHeader(hdr: macho.mach_header_64, writer: anytype) !void {820 fn dumpHeader(hdr: macho.mach_header_64, bw: *std.io.BufferedWriter) !void {
814 const cputype = switch (hdr.cputype) {821 const cputype = switch (hdr.cputype) {
815 macho.CPU_TYPE_ARM64 => "ARM64",822 macho.CPU_TYPE_ARM64 => "ARM64",
816 macho.CPU_TYPE_X86_64 => "X86_64",823 macho.CPU_TYPE_X86_64 => "X86_64",
...@@ -831,7 +838,7 @@ const MachODumper = struct {...@@ -831,7 +838,7 @@ const MachODumper = struct {
831 else => "Unknown",838 else => "Unknown",
832 };839 };
833840
834 try writer.print(841 try bw.print(
835 \\header842 \\header
836 \\cputype {s}843 \\cputype {s}
837 \\filetype {s}844 \\filetype {s}
...@@ -846,41 +853,41 @@ const MachODumper = struct {...@@ -846,41 +853,41 @@ const MachODumper = struct {
846 });853 });
847854
848 if (hdr.flags > 0) {855 if (hdr.flags > 0) {
849 if (hdr.flags & macho.MH_NOUNDEFS != 0) try writer.writeAll(" NOUNDEFS");856 if (hdr.flags & macho.MH_NOUNDEFS != 0) try bw.writeAll(" NOUNDEFS");
850 if (hdr.flags & macho.MH_INCRLINK != 0) try writer.writeAll(" INCRLINK");857 if (hdr.flags & macho.MH_INCRLINK != 0) try bw.writeAll(" INCRLINK");
851 if (hdr.flags & macho.MH_DYLDLINK != 0) try writer.writeAll(" DYLDLINK");858 if (hdr.flags & macho.MH_DYLDLINK != 0) try bw.writeAll(" DYLDLINK");
852 if (hdr.flags & macho.MH_BINDATLOAD != 0) try writer.writeAll(" BINDATLOAD");859 if (hdr.flags & macho.MH_BINDATLOAD != 0) try bw.writeAll(" BINDATLOAD");
853 if (hdr.flags & macho.MH_PREBOUND != 0) try writer.writeAll(" PREBOUND");860 if (hdr.flags & macho.MH_PREBOUND != 0) try bw.writeAll(" PREBOUND");
854 if (hdr.flags & macho.MH_SPLIT_SEGS != 0) try writer.writeAll(" SPLIT_SEGS");861 if (hdr.flags & macho.MH_SPLIT_SEGS != 0) try bw.writeAll(" SPLIT_SEGS");
855 if (hdr.flags & macho.MH_LAZY_INIT != 0) try writer.writeAll(" LAZY_INIT");862 if (hdr.flags & macho.MH_LAZY_INIT != 0) try bw.writeAll(" LAZY_INIT");
856 if (hdr.flags & macho.MH_TWOLEVEL != 0) try writer.writeAll(" TWOLEVEL");863 if (hdr.flags & macho.MH_TWOLEVEL != 0) try bw.writeAll(" TWOLEVEL");
857 if (hdr.flags & macho.MH_FORCE_FLAT != 0) try writer.writeAll(" FORCE_FLAT");864 if (hdr.flags & macho.MH_FORCE_FLAT != 0) try bw.writeAll(" FORCE_FLAT");
858 if (hdr.flags & macho.MH_NOMULTIDEFS != 0) try writer.writeAll(" NOMULTIDEFS");865 if (hdr.flags & macho.MH_NOMULTIDEFS != 0) try bw.writeAll(" NOMULTIDEFS");
859 if (hdr.flags & macho.MH_NOFIXPREBINDING != 0) try writer.writeAll(" NOFIXPREBINDING");866 if (hdr.flags & macho.MH_NOFIXPREBINDING != 0) try bw.writeAll(" NOFIXPREBINDING");
860 if (hdr.flags & macho.MH_PREBINDABLE != 0) try writer.writeAll(" PREBINDABLE");867 if (hdr.flags & macho.MH_PREBINDABLE != 0) try bw.writeAll(" PREBINDABLE");
861 if (hdr.flags & macho.MH_ALLMODSBOUND != 0) try writer.writeAll(" ALLMODSBOUND");868 if (hdr.flags & macho.MH_ALLMODSBOUND != 0) try bw.writeAll(" ALLMODSBOUND");
862 if (hdr.flags & macho.MH_SUBSECTIONS_VIA_SYMBOLS != 0) try writer.writeAll(" SUBSECTIONS_VIA_SYMBOLS");869 if (hdr.flags & macho.MH_SUBSECTIONS_VIA_SYMBOLS != 0) try bw.writeAll(" SUBSECTIONS_VIA_SYMBOLS");
863 if (hdr.flags & macho.MH_CANONICAL != 0) try writer.writeAll(" CANONICAL");870 if (hdr.flags & macho.MH_CANONICAL != 0) try bw.writeAll(" CANONICAL");
864 if (hdr.flags & macho.MH_WEAK_DEFINES != 0) try writer.writeAll(" WEAK_DEFINES");871 if (hdr.flags & macho.MH_WEAK_DEFINES != 0) try bw.writeAll(" WEAK_DEFINES");
865 if (hdr.flags & macho.MH_BINDS_TO_WEAK != 0) try writer.writeAll(" BINDS_TO_WEAK");872 if (hdr.flags & macho.MH_BINDS_TO_WEAK != 0) try bw.writeAll(" BINDS_TO_WEAK");
866 if (hdr.flags & macho.MH_ALLOW_STACK_EXECUTION != 0) try writer.writeAll(" ALLOW_STACK_EXECUTION");873 if (hdr.flags & macho.MH_ALLOW_STACK_EXECUTION != 0) try bw.writeAll(" ALLOW_STACK_EXECUTION");
867 if (hdr.flags & macho.MH_ROOT_SAFE != 0) try writer.writeAll(" ROOT_SAFE");874 if (hdr.flags & macho.MH_ROOT_SAFE != 0) try bw.writeAll(" ROOT_SAFE");
868 if (hdr.flags & macho.MH_SETUID_SAFE != 0) try writer.writeAll(" SETUID_SAFE");875 if (hdr.flags & macho.MH_SETUID_SAFE != 0) try bw.writeAll(" SETUID_SAFE");
869 if (hdr.flags & macho.MH_NO_REEXPORTED_DYLIBS != 0) try writer.writeAll(" NO_REEXPORTED_DYLIBS");876 if (hdr.flags & macho.MH_NO_REEXPORTED_DYLIBS != 0) try bw.writeAll(" NO_REEXPORTED_DYLIBS");
870 if (hdr.flags & macho.MH_PIE != 0) try writer.writeAll(" PIE");877 if (hdr.flags & macho.MH_PIE != 0) try bw.writeAll(" PIE");
871 if (hdr.flags & macho.MH_DEAD_STRIPPABLE_DYLIB != 0) try writer.writeAll(" DEAD_STRIPPABLE_DYLIB");878 if (hdr.flags & macho.MH_DEAD_STRIPPABLE_DYLIB != 0) try bw.writeAll(" DEAD_STRIPPABLE_DYLIB");
872 if (hdr.flags & macho.MH_HAS_TLV_DESCRIPTORS != 0) try writer.writeAll(" HAS_TLV_DESCRIPTORS");879 if (hdr.flags & macho.MH_HAS_TLV_DESCRIPTORS != 0) try bw.writeAll(" HAS_TLV_DESCRIPTORS");
873 if (hdr.flags & macho.MH_NO_HEAP_EXECUTION != 0) try writer.writeAll(" NO_HEAP_EXECUTION");880 if (hdr.flags & macho.MH_NO_HEAP_EXECUTION != 0) try bw.writeAll(" NO_HEAP_EXECUTION");
874 if (hdr.flags & macho.MH_APP_EXTENSION_SAFE != 0) try writer.writeAll(" APP_EXTENSION_SAFE");881 if (hdr.flags & macho.MH_APP_EXTENSION_SAFE != 0) try bw.writeAll(" APP_EXTENSION_SAFE");
875 if (hdr.flags & macho.MH_NLIST_OUTOFSYNC_WITH_DYLDINFO != 0) try writer.writeAll(" NLIST_OUTOFSYNC_WITH_DYLDINFO");882 if (hdr.flags & macho.MH_NLIST_OUTOFSYNC_WITH_DYLDINFO != 0) try bw.writeAll(" NLIST_OUTOFSYNC_WITH_DYLDINFO");
876 }883 }
877884
878 try writer.writeByte('\n');885 try bw.writeByte('\n');
879 }886 }
880887
881 fn dumpLoadCommand(lc: macho.LoadCommandIterator.LoadCommand, index: usize, writer: anytype) !void {888 fn dumpLoadCommand(lc: macho.LoadCommandIterator.LoadCommand, index: usize, bw: *std.io.BufferedWriter) !void {
882 // print header first889 // print header first
883 try writer.print(890 try bw.print(
884 \\LC {d}891 \\LC {d}
885 \\cmd {s}892 \\cmd {s}
886 \\cmdsize {d}893 \\cmdsize {d}
...@@ -889,8 +896,8 @@ const MachODumper = struct {...@@ -889,8 +896,8 @@ const MachODumper = struct {
889 switch (lc.cmd()) {896 switch (lc.cmd()) {
890 .SEGMENT_64 => {897 .SEGMENT_64 => {
891 const seg = lc.cast(macho.segment_command_64).?;898 const seg = lc.cast(macho.segment_command_64).?;
892 try writer.writeByte('\n');899 try bw.writeByte('\n');
893 try writer.print(900 try bw.print(
894 \\segname {s}901 \\segname {s}
895 \\vmaddr {x}902 \\vmaddr {x}
896 \\vmsize {x}903 \\vmsize {x}
...@@ -905,8 +912,8 @@ const MachODumper = struct {...@@ -905,8 +912,8 @@ const MachODumper = struct {
905 });912 });
906913
907 for (lc.getSections()) |sect| {914 for (lc.getSections()) |sect| {
908 try writer.writeByte('\n');915 try bw.writeByte('\n');
909 try writer.print(916 try bw.print(
910 \\sectname {s}917 \\sectname {s}
911 \\addr {x}918 \\addr {x}
912 \\size {x}919 \\size {x}
...@@ -928,8 +935,8 @@ const MachODumper = struct {...@@ -928,8 +935,8 @@ const MachODumper = struct {
928 .REEXPORT_DYLIB,935 .REEXPORT_DYLIB,
929 => {936 => {
930 const dylib = lc.cast(macho.dylib_command).?;937 const dylib = lc.cast(macho.dylib_command).?;
931 try writer.writeByte('\n');938 try bw.writeByte('\n');
932 try writer.print(939 try bw.print(
933 \\name {s}940 \\name {s}
934 \\timestamp {d}941 \\timestamp {d}
935 \\current version {x}942 \\current version {x}
...@@ -944,16 +951,16 @@ const MachODumper = struct {...@@ -944,16 +951,16 @@ const MachODumper = struct {
944951
945 .MAIN => {952 .MAIN => {
946 const main = lc.cast(macho.entry_point_command).?;953 const main = lc.cast(macho.entry_point_command).?;
947 try writer.writeByte('\n');954 try bw.writeByte('\n');
948 try writer.print(955 try bw.print(
949 \\entryoff {x}956 \\entryoff {x}
950 \\stacksize {x}957 \\stacksize {x}
951 , .{ main.entryoff, main.stacksize });958 , .{ main.entryoff, main.stacksize });
952 },959 },
953960
954 .RPATH => {961 .RPATH => {
955 try writer.writeByte('\n');962 try bw.writeByte('\n');
956 try writer.print(963 try bw.print(
957 \\path {s}964 \\path {s}
958 , .{965 , .{
959 lc.getRpathPathName(),966 lc.getRpathPathName(),
...@@ -962,8 +969,8 @@ const MachODumper = struct {...@@ -962,8 +969,8 @@ const MachODumper = struct {
962969
963 .UUID => {970 .UUID => {
964 const uuid = lc.cast(macho.uuid_command).?;971 const uuid = lc.cast(macho.uuid_command).?;
965 try writer.writeByte('\n');972 try bw.writeByte('\n');
966 try writer.print("uuid {x}", .{&uuid.uuid});973 try bw.print("uuid {x}", .{&uuid.uuid});
967 },974 },
968975
969 .DATA_IN_CODE,976 .DATA_IN_CODE,
...@@ -971,8 +978,8 @@ const MachODumper = struct {...@@ -971,8 +978,8 @@ const MachODumper = struct {
971 .CODE_SIGNATURE,978 .CODE_SIGNATURE,
972 => {979 => {
973 const llc = lc.cast(macho.linkedit_data_command).?;980 const llc = lc.cast(macho.linkedit_data_command).?;
974 try writer.writeByte('\n');981 try bw.writeByte('\n');
975 try writer.print(982 try bw.print(
976 \\dataoff {x}983 \\dataoff {x}
977 \\datasize {x}984 \\datasize {x}
978 , .{ llc.dataoff, llc.datasize });985 , .{ llc.dataoff, llc.datasize });
...@@ -980,8 +987,8 @@ const MachODumper = struct {...@@ -980,8 +987,8 @@ const MachODumper = struct {
980987
981 .DYLD_INFO_ONLY => {988 .DYLD_INFO_ONLY => {
982 const dlc = lc.cast(macho.dyld_info_command).?;989 const dlc = lc.cast(macho.dyld_info_command).?;
983 try writer.writeByte('\n');990 try bw.writeByte('\n');
984 try writer.print(991 try bw.print(
985 \\rebaseoff {x}992 \\rebaseoff {x}
986 \\rebasesize {x}993 \\rebasesize {x}
987 \\bindoff {x}994 \\bindoff {x}
...@@ -1008,8 +1015,8 @@ const MachODumper = struct {...@@ -1008,8 +1015,8 @@ const MachODumper = struct {
10081015
1009 .SYMTAB => {1016 .SYMTAB => {
1010 const slc = lc.cast(macho.symtab_command).?;1017 const slc = lc.cast(macho.symtab_command).?;
1011 try writer.writeByte('\n');1018 try bw.writeByte('\n');
1012 try writer.print(1019 try bw.print(
1013 \\symoff {x}1020 \\symoff {x}
1014 \\nsyms {x}1021 \\nsyms {x}
1015 \\stroff {x}1022 \\stroff {x}
...@@ -1024,8 +1031,8 @@ const MachODumper = struct {...@@ -1024,8 +1031,8 @@ const MachODumper = struct {
10241031
1025 .DYSYMTAB => {1032 .DYSYMTAB => {
1026 const dlc = lc.cast(macho.dysymtab_command).?;1033 const dlc = lc.cast(macho.dysymtab_command).?;
1027 try writer.writeByte('\n');1034 try bw.writeByte('\n');
1028 try writer.print(1035 try bw.print(
1029 \\ilocalsym {x}1036 \\ilocalsym {x}
1030 \\nlocalsym {x}1037 \\nlocalsym {x}
1031 \\iextdefsym {x}1038 \\iextdefsym {x}
...@@ -1048,8 +1055,8 @@ const MachODumper = struct {...@@ -1048,8 +1055,8 @@ const MachODumper = struct {
10481055
1049 .BUILD_VERSION => {1056 .BUILD_VERSION => {
1050 const blc = lc.cast(macho.build_version_command).?;1057 const blc = lc.cast(macho.build_version_command).?;
1051 try writer.writeByte('\n');1058 try bw.writeByte('\n');
1052 try writer.print(1059 try bw.print(
1053 \\platform {s}1060 \\platform {s}
1054 \\minos {d}.{d}.{d}1061 \\minos {d}.{d}.{d}
1055 \\sdk {d}.{d}.{d}1062 \\sdk {d}.{d}.{d}
...@@ -1065,12 +1072,12 @@ const MachODumper = struct {...@@ -1065,12 +1072,12 @@ const MachODumper = struct {
1065 blc.ntools,1072 blc.ntools,
1066 });1073 });
1067 for (lc.getBuildVersionTools()) |tool| {1074 for (lc.getBuildVersionTools()) |tool| {
1068 try writer.writeByte('\n');1075 try bw.writeByte('\n');
1069 switch (tool.tool) {1076 switch (tool.tool) {
1070 .CLANG, .SWIFT, .LD, .LLD, .ZIG => try writer.print("tool {s}\n", .{@tagName(tool.tool)}),1077 .CLANG, .SWIFT, .LD, .LLD, .ZIG => try bw.print("tool {s}\n", .{@tagName(tool.tool)}),
1071 else => |x| try writer.print("tool {d}\n", .{@intFromEnum(x)}),1078 else => |x| try bw.print("tool {d}\n", .{@intFromEnum(x)}),
1072 }1079 }
1073 try writer.print(1080 try bw.print(
1074 \\version {d}.{d}.{d}1081 \\version {d}.{d}.{d}
1075 , .{1082 , .{
1076 tool.version >> 16,1083 tool.version >> 16,
...@@ -1086,8 +1093,8 @@ const MachODumper = struct {...@@ -1086,8 +1093,8 @@ const MachODumper = struct {
1086 .VERSION_MIN_TVOS,1093 .VERSION_MIN_TVOS,
1087 => {1094 => {
1088 const vlc = lc.cast(macho.version_min_command).?;1095 const vlc = lc.cast(macho.version_min_command).?;
1089 try writer.writeByte('\n');1096 try bw.writeByte('\n');
1090 try writer.print(1097 try bw.print(
1091 \\version {d}.{d}.{d}1098 \\version {d}.{d}.{d}
1092 \\sdk {d}.{d}.{d}1099 \\sdk {d}.{d}.{d}
1093 , .{1100 , .{
...@@ -1104,8 +1111,8 @@ const MachODumper = struct {...@@ -1104,8 +1111,8 @@ const MachODumper = struct {
1104 }1111 }
1105 }1112 }
11061113
1107 fn dumpSymtab(ctx: ObjectContext, writer: anytype) !void {1114 fn dumpSymtab(ctx: ObjectContext, bw: *std.io.BufferedWriter) !void {
1108 try writer.writeAll(symtab_label ++ "\n");1115 try bw.writeAll(symtab_label ++ "\n");
11091116
1110 for (ctx.symtab.items) |sym| {1117 for (ctx.symtab.items) |sym| {
1111 const sym_name = ctx.getString(sym.n_strx);1118 const sym_name = ctx.getString(sym.n_strx);
...@@ -1120,32 +1127,32 @@ const MachODumper = struct {...@@ -1120,32 +1127,32 @@ const MachODumper = struct {
1120 macho.N_STSYM => "STSYM",1127 macho.N_STSYM => "STSYM",
1121 else => "UNKNOWN STAB",1128 else => "UNKNOWN STAB",
1122 };1129 };
1123 try writer.print("{x}", .{sym.n_value});1130 try bw.print("{x}", .{sym.n_value});
1124 if (sym.n_sect > 0) {1131 if (sym.n_sect > 0) {
1125 const sect = ctx.sections.items[sym.n_sect - 1];1132 const sect = ctx.sections.items[sym.n_sect - 1];
1126 try writer.print(" ({s},{s})", .{ sect.segName(), sect.sectName() });1133 try bw.print(" ({s},{s})", .{ sect.segName(), sect.sectName() });
1127 }1134 }
1128 try writer.print(" {s} (stab) {s}\n", .{ tt, sym_name });1135 try bw.print(" {s} (stab) {s}\n", .{ tt, sym_name });
1129 } else if (sym.sect()) {1136 } else if (sym.sect()) {
1130 const sect = ctx.sections.items[sym.n_sect - 1];1137 const sect = ctx.sections.items[sym.n_sect - 1];
1131 try writer.print("{x} ({s},{s})", .{1138 try bw.print("{x} ({s},{s})", .{
1132 sym.n_value,1139 sym.n_value,
1133 sect.segName(),1140 sect.segName(),
1134 sect.sectName(),1141 sect.sectName(),
1135 });1142 });
1136 if (sym.n_desc & macho.REFERENCED_DYNAMICALLY != 0) try writer.writeAll(" [referenced dynamically]");1143 if (sym.n_desc & macho.REFERENCED_DYNAMICALLY != 0) try bw.writeAll(" [referenced dynamically]");
1137 if (sym.weakDef()) try writer.writeAll(" weak");1144 if (sym.weakDef()) try bw.writeAll(" weak");
1138 if (sym.weakRef()) try writer.writeAll(" weakref");1145 if (sym.weakRef()) try bw.writeAll(" weakref");
1139 if (sym.ext()) {1146 if (sym.ext()) {
1140 if (sym.pext()) try writer.writeAll(" private");1147 if (sym.pext()) try bw.writeAll(" private");
1141 try writer.writeAll(" external");1148 try bw.writeAll(" external");
1142 } else if (sym.pext()) try writer.writeAll(" (was private external)");1149 } else if (sym.pext()) try bw.writeAll(" (was private external)");
1143 try writer.print(" {s}\n", .{sym_name});1150 try bw.print(" {s}\n", .{sym_name});
1144 } else if (sym.tentative()) {1151 } else if (sym.tentative()) {
1145 const alignment = (sym.n_desc >> 8) & 0x0F;1152 const alignment = (sym.n_desc >> 8) & 0x0F;
1146 try writer.print(" 0x{x:0>16} (common) (alignment 2^{d})", .{ sym.n_value, alignment });1153 try bw.print(" 0x{x:0>16} (common) (alignment 2^{d})", .{ sym.n_value, alignment });
1147 if (sym.ext()) try writer.writeAll(" external");1154 if (sym.ext()) try bw.writeAll(" external");
1148 try writer.print(" {s}\n", .{sym_name});1155 try bw.print(" {s}\n", .{sym_name});
1149 } else if (sym.undf()) {1156 } else if (sym.undf()) {
1150 const ordinal = @divFloor(@as(i16, @bitCast(sym.n_desc)), macho.N_SYMBOL_RESOLVER);1157 const ordinal = @divFloor(@as(i16, @bitCast(sym.n_desc)), macho.N_SYMBOL_RESOLVER);
1151 const import_name = blk: {1158 const import_name = blk: {
...@@ -1164,10 +1171,10 @@ const MachODumper = struct {...@@ -1164,10 +1171,10 @@ const MachODumper = struct {
1164 const ext = mem.lastIndexOfScalar(u8, basename, '.') orelse basename.len;1171 const ext = mem.lastIndexOfScalar(u8, basename, '.') orelse basename.len;
1165 break :blk basename[0..ext];1172 break :blk basename[0..ext];
1166 };1173 };
1167 try writer.writeAll("(undefined)");1174 try bw.writeAll("(undefined)");
1168 if (sym.weakRef()) try writer.writeAll(" weakref");1175 if (sym.weakRef()) try bw.writeAll(" weakref");
1169 if (sym.ext()) try writer.writeAll(" external");1176 if (sym.ext()) try bw.writeAll(" external");
1170 try writer.print(" {s} (from {s})\n", .{1177 try bw.print(" {s} (from {s})\n", .{
1171 sym_name,1178 sym_name,
1172 import_name,1179 import_name,
1173 });1180 });
...@@ -1175,8 +1182,8 @@ const MachODumper = struct {...@@ -1175,8 +1182,8 @@ const MachODumper = struct {
1175 }1182 }
1176 }1183 }
11771184
1178 fn dumpIndirectSymtab(ctx: ObjectContext, writer: anytype) !void {1185 fn dumpIndirectSymtab(ctx: ObjectContext, bw: *std.io.BufferedWriter) !void {
1179 try writer.writeAll(indirect_symtab_label ++ "\n");1186 try bw.writeAll(indirect_symtab_label ++ "\n");
11801187
1181 var sects_buffer: [3]macho.section_64 = undefined;1188 var sects_buffer: [3]macho.section_64 = undefined;
1182 const sects = blk: {1189 const sects = blk: {
...@@ -1214,23 +1221,23 @@ const MachODumper = struct {...@@ -1214,23 +1221,23 @@ const MachODumper = struct {
1214 break :blk @sizeOf(u64);1221 break :blk @sizeOf(u64);
1215 };1222 };
12161223
1217 try writer.print("{s},{s}\n", .{ sect.segName(), sect.sectName() });1224 try bw.print("{s},{s}\n", .{ sect.segName(), sect.sectName() });
1218 try writer.print("nentries {d}\n", .{end - start});1225 try bw.print("nentries {d}\n", .{end - start});
1219 for (ctx.indsymtab.items[start..end], 0..) |index, j| {1226 for (ctx.indsymtab.items[start..end], 0..) |index, j| {
1220 const sym = ctx.symtab.items[index];1227 const sym = ctx.symtab.items[index];
1221 const addr = sect.addr + entry_size * j;1228 const addr = sect.addr + entry_size * j;
1222 try writer.print("0x{x} {d} {s}\n", .{ addr, index, ctx.getString(sym.n_strx) });1229 try bw.print("0x{x} {d} {s}\n", .{ addr, index, ctx.getString(sym.n_strx) });
1223 }1230 }
1224 }1231 }
1225 }1232 }
12261233
1227 fn dumpRebaseInfo(ctx: ObjectContext, data: []const u8, writer: anytype) !void {1234 fn dumpRebaseInfo(ctx: ObjectContext, data: []const u8, bw: *std.io.BufferedWriter) !void {
1228 var rebases = std.ArrayList(u64).init(ctx.gpa);1235 var rebases = std.ArrayList(u64).init(ctx.gpa);
1229 defer rebases.deinit();1236 defer rebases.deinit();
1230 try ctx.parseRebaseInfo(data, &rebases);1237 try ctx.parseRebaseInfo(data, &rebases);
1231 mem.sort(u64, rebases.items, {}, std.sort.asc(u64));1238 mem.sort(u64, rebases.items, {}, std.sort.asc(u64));
1232 for (rebases.items) |addr| {1239 for (rebases.items) |addr| {
1233 try writer.print("0x{x}\n", .{addr});1240 try bw.print("0x{x}\n", .{addr});
1234 }1241 }
1235 }1242 }
12361243
...@@ -1323,7 +1330,7 @@ const MachODumper = struct {...@@ -1323,7 +1330,7 @@ const MachODumper = struct {
1323 };1330 };
1324 };1331 };
13251332
1326 fn dumpBindInfo(ctx: ObjectContext, data: []const u8, writer: anytype) !void {1333 fn dumpBindInfo(ctx: ObjectContext, data: []const u8, bw: *std.io.BufferedWriter) !void {
1327 var bindings = std.ArrayList(Binding).init(ctx.gpa);1334 var bindings = std.ArrayList(Binding).init(ctx.gpa);
1328 defer {1335 defer {
1329 for (bindings.items) |*b| {1336 for (bindings.items) |*b| {
...@@ -1334,15 +1341,15 @@ const MachODumper = struct {...@@ -1334,15 +1341,15 @@ const MachODumper = struct {
1334 try ctx.parseBindInfo(data, &bindings);1341 try ctx.parseBindInfo(data, &bindings);
1335 mem.sort(Binding, bindings.items, {}, Binding.lessThan);1342 mem.sort(Binding, bindings.items, {}, Binding.lessThan);
1336 for (bindings.items) |binding| {1343 for (bindings.items) |binding| {
1337 try writer.print("0x{x} [addend: {d}]", .{ binding.address, binding.addend });1344 try bw.print("0x{x} [addend: {d}]", .{ binding.address, binding.addend });
1338 try writer.writeAll(" (");1345 try bw.writeAll(" (");
1339 switch (binding.tag) {1346 switch (binding.tag) {
1340 .self => try writer.writeAll("self"),1347 .self => try bw.writeAll("self"),
1341 .exe => try writer.writeAll("main executable"),1348 .exe => try bw.writeAll("main executable"),
1342 .flat => try writer.writeAll("flat lookup"),1349 .flat => try bw.writeAll("flat lookup"),
1343 .ord => try writer.writeAll(std.fs.path.basename(ctx.imports.items[binding.ordinal - 1])),1350 .ord => try bw.writeAll(std.fs.path.basename(ctx.imports.items[binding.ordinal - 1])),
1344 }1351 }
1345 try writer.print(") {s}\n", .{binding.name});1352 try bw.print(") {s}\n", .{binding.name});
1346 }1353 }
1347 }1354 }
13481355
...@@ -1439,7 +1446,7 @@ const MachODumper = struct {...@@ -1439,7 +1446,7 @@ const MachODumper = struct {
1439 }1446 }
1440 }1447 }
14411448
1442 fn dumpExportsTrie(ctx: ObjectContext, data: []const u8, writer: anytype) !void {1449 fn dumpExportsTrie(ctx: ObjectContext, data: []const u8, bw: *std.io.BufferedWriter) !void {
1443 const seg = ctx.getSegmentByName("__TEXT") orelse return;1450 const seg = ctx.getSegmentByName("__TEXT") orelse return;
14441451
1445 var arena = std.heap.ArenaAllocator.init(ctx.gpa);1452 var arena = std.heap.ArenaAllocator.init(ctx.gpa);
...@@ -1456,23 +1463,23 @@ const MachODumper = struct {...@@ -1456,23 +1463,23 @@ const MachODumper = struct {
1456 .@"export" => {1463 .@"export" => {
1457 const info = exp.data.@"export";1464 const info = exp.data.@"export";
1458 if (info.kind != .regular or info.weak) {1465 if (info.kind != .regular or info.weak) {
1459 try writer.writeByte('[');1466 try bw.writeByte('[');
1460 }1467 }
1461 switch (info.kind) {1468 switch (info.kind) {
1462 .regular => {},1469 .regular => {},
1463 .absolute => try writer.writeAll("ABS, "),1470 .absolute => try bw.writeAll("ABS, "),
1464 .tlv => try writer.writeAll("THREAD_LOCAL, "),1471 .tlv => try bw.writeAll("THREAD_LOCAL, "),
1465 }1472 }
1466 if (info.weak) try writer.writeAll("WEAK");1473 if (info.weak) try bw.writeAll("WEAK");
1467 if (info.kind != .regular or info.weak) {1474 if (info.kind != .regular or info.weak) {
1468 try writer.writeAll("] ");1475 try bw.writeAll("] ");
1469 }1476 }
1470 try writer.print("{x} ", .{seg.vmaddr + info.vmoffset});1477 try bw.print("{x} ", .{seg.vmaddr + info.vmoffset});
1471 },1478 },
1472 else => {},1479 else => {},
1473 }1480 }
14741481
1475 try writer.print("{s}\n", .{exp.name});1482 try bw.print("{s}\n", .{exp.name});
1476 }1483 }
1477 }1484 }
14781485
...@@ -1616,9 +1623,9 @@ const MachODumper = struct {...@@ -1616,9 +1623,9 @@ const MachODumper = struct {
1616 }1623 }
1617 }1624 }
16181625
1619 fn dumpSection(ctx: ObjectContext, sect: macho.section_64, writer: anytype) !void {1626 fn dumpSection(ctx: ObjectContext, sect: macho.section_64, bw: *std.io.BufferedWriter) !void {
1620 const data = ctx.data[sect.offset..][0..sect.size];1627 const data = ctx.data[sect.offset..][0..sect.size];
1621 try writer.print("{s}", .{data});1628 try bw.print("{s}", .{data});
1622 }1629 }
1623 };1630 };
16241631
...@@ -1632,29 +1639,29 @@ const MachODumper = struct {...@@ -1632,29 +1639,29 @@ const MachODumper = struct {
1632 var ctx = ObjectContext{ .gpa = gpa, .data = bytes, .header = hdr };1639 var ctx = ObjectContext{ .gpa = gpa, .data = bytes, .header = hdr };
1633 try ctx.parse();1640 try ctx.parse();
16341641
1635 var output = std.ArrayList(u8).init(gpa);1642 var output: std.io.AllocatingWriter = undefined;
1636 const writer = output.writer();1643 const bw = output.init(gpa);
16371644
1638 switch (check.kind) {1645 switch (check.kind) {
1639 .headers => {1646 .headers => {
1640 try ObjectContext.dumpHeader(ctx.header, writer);1647 try ObjectContext.dumpHeader(ctx.header, bw);
16411648
1642 var it = ctx.getLoadCommandIterator();1649 var it = ctx.getLoadCommandIterator();
1643 var i: usize = 0;1650 var i: usize = 0;
1644 while (it.next()) |cmd| {1651 while (it.next()) |cmd| {
1645 try ObjectContext.dumpLoadCommand(cmd, i, writer);1652 try ObjectContext.dumpLoadCommand(cmd, i, bw);
1646 try writer.writeByte('\n');1653 try bw.writeByte('\n');
16471654
1648 i += 1;1655 i += 1;
1649 }1656 }
1650 },1657 },
16511658
1652 .symtab => if (ctx.symtab.items.len > 0) {1659 .symtab => if (ctx.symtab.items.len > 0) {
1653 try ctx.dumpSymtab(writer);1660 try ctx.dumpSymtab(bw);
1654 } else return step.fail("no symbol table found", .{}),1661 } else return step.fail("no symbol table found", .{}),
16551662
1656 .indirect_symtab => if (ctx.symtab.items.len > 0 and ctx.indsymtab.items.len > 0) {1663 .indirect_symtab => if (ctx.symtab.items.len > 0 and ctx.indsymtab.items.len > 0) {
1657 try ctx.dumpIndirectSymtab(writer);1664 try ctx.dumpIndirectSymtab(bw);
1658 } else return step.fail("no indirect symbol table found", .{}),1665 } else return step.fail("no indirect symbol table found", .{}),
16591666
1660 .dyld_rebase,1667 .dyld_rebase,
...@@ -1669,26 +1676,26 @@ const MachODumper = struct {...@@ -1669,26 +1676,26 @@ const MachODumper = struct {
1669 switch (check.kind) {1676 switch (check.kind) {
1670 .dyld_rebase => if (lc.rebase_size > 0) {1677 .dyld_rebase => if (lc.rebase_size > 0) {
1671 const data = ctx.data[lc.rebase_off..][0..lc.rebase_size];1678 const data = ctx.data[lc.rebase_off..][0..lc.rebase_size];
1672 try writer.writeAll(dyld_rebase_label ++ "\n");1679 try bw.writeAll(dyld_rebase_label ++ "\n");
1673 try ctx.dumpRebaseInfo(data, writer);1680 try ctx.dumpRebaseInfo(data, bw);
1674 } else return step.fail("no rebase data found", .{}),1681 } else return step.fail("no rebase data found", .{}),
16751682
1676 .dyld_bind => if (lc.bind_size > 0) {1683 .dyld_bind => if (lc.bind_size > 0) {
1677 const data = ctx.data[lc.bind_off..][0..lc.bind_size];1684 const data = ctx.data[lc.bind_off..][0..lc.bind_size];
1678 try writer.writeAll(dyld_bind_label ++ "\n");1685 try bw.writeAll(dyld_bind_label ++ "\n");
1679 try ctx.dumpBindInfo(data, writer);1686 try ctx.dumpBindInfo(data, bw);
1680 } else return step.fail("no bind data found", .{}),1687 } else return step.fail("no bind data found", .{}),
16811688
1682 .dyld_weak_bind => if (lc.weak_bind_size > 0) {1689 .dyld_weak_bind => if (lc.weak_bind_size > 0) {
1683 const data = ctx.data[lc.weak_bind_off..][0..lc.weak_bind_size];1690 const data = ctx.data[lc.weak_bind_off..][0..lc.weak_bind_size];
1684 try writer.writeAll(dyld_weak_bind_label ++ "\n");1691 try bw.writeAll(dyld_weak_bind_label ++ "\n");
1685 try ctx.dumpBindInfo(data, writer);1692 try ctx.dumpBindInfo(data, bw);
1686 } else return step.fail("no weak bind data found", .{}),1693 } else return step.fail("no weak bind data found", .{}),
16871694
1688 .dyld_lazy_bind => if (lc.lazy_bind_size > 0) {1695 .dyld_lazy_bind => if (lc.lazy_bind_size > 0) {
1689 const data = ctx.data[lc.lazy_bind_off..][0..lc.lazy_bind_size];1696 const data = ctx.data[lc.lazy_bind_off..][0..lc.lazy_bind_size];
1690 try writer.writeAll(dyld_lazy_bind_label ++ "\n");1697 try bw.writeAll(dyld_lazy_bind_label ++ "\n");
1691 try ctx.dumpBindInfo(data, writer);1698 try ctx.dumpBindInfo(data, bw);
1692 } else return step.fail("no lazy bind data found", .{}),1699 } else return step.fail("no lazy bind data found", .{}),
16931700
1694 else => unreachable,1701 else => unreachable,
...@@ -1700,8 +1707,8 @@ const MachODumper = struct {...@@ -1700,8 +1707,8 @@ const MachODumper = struct {
1700 const lc = cmd.cast(macho.dyld_info_command).?;1707 const lc = cmd.cast(macho.dyld_info_command).?;
1701 if (lc.export_size > 0) {1708 if (lc.export_size > 0) {
1702 const data = ctx.data[lc.export_off..][0..lc.export_size];1709 const data = ctx.data[lc.export_off..][0..lc.export_size];
1703 try writer.writeAll(exports_label ++ "\n");1710 try bw.writeAll(exports_label ++ "\n");
1704 try ctx.dumpExportsTrie(data, writer);1711 try ctx.dumpExportsTrie(data, bw);
1705 break :blk;1712 break :blk;
1706 }1713 }
1707 }1714 }
...@@ -1716,7 +1723,7 @@ const MachODumper = struct {...@@ -1716,7 +1723,7 @@ const MachODumper = struct {
1716 const sectname = name[sep_index + 1 ..];1723 const sectname = name[sep_index + 1 ..];
1717 const sect = ctx.getSectionByName(segname, sectname) orelse1724 const sect = ctx.getSectionByName(segname, sectname) orelse
1718 return step.fail("section '{s}' not found", .{name});1725 return step.fail("section '{s}' not found", .{name});
1719 try ctx.dumpSection(sect, writer);1726 try ctx.dumpSection(sect, bw);
1720 },1727 },
17211728
1722 else => return step.fail("invalid check kind for MachO file format: {s}", .{@tagName(check.kind)}),1729 else => return step.fail("invalid check kind for MachO file format: {s}", .{@tagName(check.kind)}),
...@@ -1850,7 +1857,7 @@ const ElfDumper = struct {...@@ -1850,7 +1857,7 @@ const ElfDumper = struct {
1850 }1857 }
1851 }1858 }
18521859
1853 fn dumpSymtab(ctx: ArchiveContext, writer: anytype) !void {1860 fn dumpSymtab(ctx: ArchiveContext, bw: *std.io.BufferedWriter) !void {
1854 var files = std.AutoHashMap(usize, []const u8).init(ctx.gpa);1861 var files = std.AutoHashMap(usize, []const u8).init(ctx.gpa);
1855 defer files.deinit();1862 defer files.deinit();
1856 try files.ensureUnusedCapacity(@intCast(ctx.objects.items.len));1863 try files.ensureUnusedCapacity(@intCast(ctx.objects.items.len));
...@@ -1875,21 +1882,21 @@ const ElfDumper = struct {...@@ -1875,21 +1882,21 @@ const ElfDumper = struct {
1875 try gop.value_ptr.append(entry.name);1882 try gop.value_ptr.append(entry.name);
1876 }1883 }
18771884
1878 try writer.print("{s}\n", .{archive_symtab_label});1885 try bw.print("{s}\n", .{archive_symtab_label});
1879 for (symbols.keys(), symbols.values()) |off, values| {1886 for (symbols.keys(), symbols.values()) |off, values| {
1880 try writer.print("in object {s}\n", .{files.get(off).?});1887 try bw.print("in object {s}\n", .{files.get(off).?});
1881 for (values.items) |value| {1888 for (values.items) |value| {
1882 try writer.print("{s}\n", .{value});1889 try bw.print("{s}\n", .{value});
1883 }1890 }
1884 }1891 }
1885 }1892 }
18861893
1887 fn dumpObjects(ctx: ArchiveContext, step: *Step, check: Check, writer: anytype) !void {1894 fn dumpObjects(ctx: ArchiveContext, step: *Step, check: Check, bw: *std.io.BufferedWriter) !void {
1888 for (ctx.objects.items) |object| {1895 for (ctx.objects.items) |object| {
1889 try writer.print("object {s}\n", .{object.name});1896 try bw.print("object {s}\n", .{object.name});
1890 const output = try parseAndDumpObject(step, check, ctx.data[object.off..][0..object.len]);1897 const output = try parseAndDumpObject(step, check, ctx.data[object.off..][0..object.len]);
1891 defer ctx.gpa.free(output);1898 defer ctx.gpa.free(output);
1892 try writer.print("{s}\n", .{output});1899 try bw.print("{s}\n", .{output});
1893 }1900 }
1894 }1901 }
18951902
...@@ -1955,32 +1962,32 @@ const ElfDumper = struct {...@@ -1955,32 +1962,32 @@ const ElfDumper = struct {
1955 else => {},1962 else => {},
1956 };1963 };
19571964
1958 var output = std.ArrayList(u8).init(gpa);1965 var output: std.io.AllocatingWriter = undefined;
1959 const writer = output.writer();1966 const bw = output.init(gpa);
19601967
1961 switch (check.kind) {1968 switch (check.kind) {
1962 .headers => {1969 .headers => {
1963 try ctx.dumpHeader(writer);1970 try ctx.dumpHeader(bw);
1964 try ctx.dumpShdrs(writer);1971 try ctx.dumpShdrs(bw);
1965 try ctx.dumpPhdrs(writer);1972 try ctx.dumpPhdrs(bw);
1966 },1973 },
19671974
1968 .symtab => if (ctx.symtab.symbols.len > 0) {1975 .symtab => if (ctx.symtab.symbols.len > 0) {
1969 try ctx.dumpSymtab(.symtab, writer);1976 try ctx.dumpSymtab(.symtab, bw);
1970 } else return step.fail("no symbol table found", .{}),1977 } else return step.fail("no symbol table found", .{}),
19711978
1972 .dynamic_symtab => if (ctx.dysymtab.symbols.len > 0) {1979 .dynamic_symtab => if (ctx.dysymtab.symbols.len > 0) {
1973 try ctx.dumpSymtab(.dysymtab, writer);1980 try ctx.dumpSymtab(.dysymtab, bw);
1974 } else return step.fail("no dynamic symbol table found", .{}),1981 } else return step.fail("no dynamic symbol table found", .{}),
19751982
1976 .dynamic_section => if (ctx.getSectionByName(".dynamic")) |shndx| {1983 .dynamic_section => if (ctx.getSectionByName(".dynamic")) |shndx| {
1977 try ctx.dumpDynamicSection(shndx, writer);1984 try ctx.dumpDynamicSection(shndx, bw);
1978 } else return step.fail("no .dynamic section found", .{}),1985 } else return step.fail("no .dynamic section found", .{}),
19791986
1980 .dump_section => {1987 .dump_section => {
1981 const name = mem.sliceTo(@as([*:0]const u8, @ptrCast(check.data.items.ptr + check.payload.dump_section)), 0);1988 const name = mem.sliceTo(@as([*:0]const u8, @ptrCast(check.data.items.ptr + check.payload.dump_section)), 0);
1982 const shndx = ctx.getSectionByName(name) orelse return step.fail("no '{s}' section found", .{name});1989 const shndx = ctx.getSectionByName(name) orelse return step.fail("no '{s}' section found", .{name});
1983 try ctx.dumpSection(shndx, writer);1990 try ctx.dumpSection(shndx, bw);
1984 },1991 },
19851992
1986 else => return step.fail("invalid check kind for ELF file format: {s}", .{@tagName(check.kind)}),1993 else => return step.fail("invalid check kind for ELF file format: {s}", .{@tagName(check.kind)}),
...@@ -1999,76 +2006,76 @@ const ElfDumper = struct {...@@ -1999,76 +2006,76 @@ const ElfDumper = struct {
1999 symtab: Symtab = .{},2006 symtab: Symtab = .{},
2000 dysymtab: Symtab = .{},2007 dysymtab: Symtab = .{},
20012008
2002 fn dumpHeader(ctx: ObjectContext, writer: anytype) !void {2009 fn dumpHeader(ctx: ObjectContext, bw: *std.io.BufferedWriter) !void {
2003 try writer.writeAll("header\n");2010 try bw.writeAll("header\n");
2004 try writer.print("type {s}\n", .{@tagName(ctx.hdr.e_type)});2011 try bw.print("type {s}\n", .{@tagName(ctx.hdr.e_type)});
2005 try writer.print("entry {x}\n", .{ctx.hdr.e_entry});2012 try bw.print("entry {x}\n", .{ctx.hdr.e_entry});
2006 }2013 }
20072014
2008 fn dumpPhdrs(ctx: ObjectContext, writer: anytype) !void {2015 fn dumpPhdrs(ctx: ObjectContext, bw: *std.io.BufferedWriter) !void {
2009 if (ctx.phdrs.len == 0) return;2016 if (ctx.phdrs.len == 0) return;
20102017
2011 try writer.writeAll("program headers\n");2018 try bw.writeAll("program headers\n");
20122019
2013 for (ctx.phdrs, 0..) |phdr, phndx| {2020 for (ctx.phdrs, 0..) |phdr, phndx| {
2014 try writer.print("phdr {d}\n", .{phndx});2021 try bw.print("phdr {d}\n", .{phndx});
2015 try writer.print("type {s}\n", .{fmtPhType(phdr.p_type)});2022 try bw.print("type {s}\n", .{fmtPhType(phdr.p_type)});
2016 try writer.print("vaddr {x}\n", .{phdr.p_vaddr});2023 try bw.print("vaddr {x}\n", .{phdr.p_vaddr});
2017 try writer.print("paddr {x}\n", .{phdr.p_paddr});2024 try bw.print("paddr {x}\n", .{phdr.p_paddr});
2018 try writer.print("offset {x}\n", .{phdr.p_offset});2025 try bw.print("offset {x}\n", .{phdr.p_offset});
2019 try writer.print("memsz {x}\n", .{phdr.p_memsz});2026 try bw.print("memsz {x}\n", .{phdr.p_memsz});
2020 try writer.print("filesz {x}\n", .{phdr.p_filesz});2027 try bw.print("filesz {x}\n", .{phdr.p_filesz});
2021 try writer.print("align {x}\n", .{phdr.p_align});2028 try bw.print("align {x}\n", .{phdr.p_align});
20222029
2023 {2030 {
2024 const flags = phdr.p_flags;2031 const flags = phdr.p_flags;
2025 try writer.writeAll("flags");2032 try bw.writeAll("flags");
2026 if (flags > 0) try writer.writeByte(' ');2033 if (flags > 0) try bw.writeByte(' ');
2027 if (flags & elf.PF_R != 0) {2034 if (flags & elf.PF_R != 0) {
2028 try writer.writeByte('R');2035 try bw.writeByte('R');
2029 }2036 }
2030 if (flags & elf.PF_W != 0) {2037 if (flags & elf.PF_W != 0) {
2031 try writer.writeByte('W');2038 try bw.writeByte('W');
2032 }2039 }
2033 if (flags & elf.PF_X != 0) {2040 if (flags & elf.PF_X != 0) {
2034 try writer.writeByte('E');2041 try bw.writeByte('E');
2035 }2042 }
2036 if (flags & elf.PF_MASKOS != 0) {2043 if (flags & elf.PF_MASKOS != 0) {
2037 try writer.writeAll("OS");2044 try bw.writeAll("OS");
2038 }2045 }
2039 if (flags & elf.PF_MASKPROC != 0) {2046 if (flags & elf.PF_MASKPROC != 0) {
2040 try writer.writeAll("PROC");2047 try bw.writeAll("PROC");
2041 }2048 }
2042 try writer.writeByte('\n');2049 try bw.writeByte('\n');
2043 }2050 }
2044 }2051 }
2045 }2052 }
20462053
2047 fn dumpShdrs(ctx: ObjectContext, writer: anytype) !void {2054 fn dumpShdrs(ctx: ObjectContext, bw: *std.io.BufferedWriter) !void {
2048 if (ctx.shdrs.len == 0) return;2055 if (ctx.shdrs.len == 0) return;
20492056
2050 try writer.writeAll("section headers\n");2057 try bw.writeAll("section headers\n");
20512058
2052 for (ctx.shdrs, 0..) |shdr, shndx| {2059 for (ctx.shdrs, 0..) |shdr, shndx| {
2053 try writer.print("shdr {d}\n", .{shndx});2060 try bw.print("shdr {d}\n", .{shndx});
2054 try writer.print("name {s}\n", .{ctx.getSectionName(shndx)});2061 try bw.print("name {s}\n", .{ctx.getSectionName(shndx)});
2055 try writer.print("type {s}\n", .{fmtShType(shdr.sh_type)});2062 try bw.print("type {s}\n", .{fmtShType(shdr.sh_type)});
2056 try writer.print("addr {x}\n", .{shdr.sh_addr});2063 try bw.print("addr {x}\n", .{shdr.sh_addr});
2057 try writer.print("offset {x}\n", .{shdr.sh_offset});2064 try bw.print("offset {x}\n", .{shdr.sh_offset});
2058 try writer.print("size {x}\n", .{shdr.sh_size});2065 try bw.print("size {x}\n", .{shdr.sh_size});
2059 try writer.print("addralign {x}\n", .{shdr.sh_addralign});2066 try bw.print("addralign {x}\n", .{shdr.sh_addralign});
2060 // TODO dump formatted sh_flags2067 // TODO dump formatted sh_flags
2061 }2068 }
2062 }2069 }
20632070
2064 fn dumpDynamicSection(ctx: ObjectContext, shndx: usize, writer: anytype) !void {2071 fn dumpDynamicSection(ctx: ObjectContext, shndx: usize, bw: *std.io.BufferedWriter) !void {
2065 const shdr = ctx.shdrs[shndx];2072 const shdr = ctx.shdrs[shndx];
2066 const strtab = ctx.getSectionContents(shdr.sh_link);2073 const strtab = ctx.getSectionContents(shdr.sh_link);
2067 const data = ctx.getSectionContents(shndx);2074 const data = ctx.getSectionContents(shndx);
2068 const nentries = @divExact(data.len, @sizeOf(elf.Elf64_Dyn));2075 const nentries = @divExact(data.len, @sizeOf(elf.Elf64_Dyn));
2069 const entries = @as([*]align(1) const elf.Elf64_Dyn, @ptrCast(data.ptr))[0..nentries];2076 const entries = @as([*]align(1) const elf.Elf64_Dyn, @ptrCast(data.ptr))[0..nentries];
20702077
2071 try writer.writeAll(ElfDumper.dynamic_section_label ++ "\n");2078 try bw.writeAll(ElfDumper.dynamic_section_label ++ "\n");
20722079
2073 for (entries) |entry| {2080 for (entries) |entry| {
2074 const key = @as(u64, @bitCast(entry.d_tag));2081 const key = @as(u64, @bitCast(entry.d_tag));
...@@ -2109,7 +2116,7 @@ const ElfDumper = struct {...@@ -2109,7 +2116,7 @@ const ElfDumper = struct {
2109 elf.DT_NULL => "NULL",2116 elf.DT_NULL => "NULL",
2110 else => "UNKNOWN",2117 else => "UNKNOWN",
2111 };2118 };
2112 try writer.print("{s}", .{key_str});2119 try bw.print("{s}", .{key_str});
21132120
2114 switch (key) {2121 switch (key) {
2115 elf.DT_NEEDED,2122 elf.DT_NEEDED,
...@@ -2118,7 +2125,7 @@ const ElfDumper = struct {...@@ -2118,7 +2125,7 @@ const ElfDumper = struct {
2118 elf.DT_RUNPATH,2125 elf.DT_RUNPATH,
2119 => {2126 => {
2120 const name = getString(strtab, @intCast(value));2127 const name = getString(strtab, @intCast(value));
2121 try writer.print(" {s}", .{name});2128 try bw.print(" {s}", .{name});
2122 },2129 },
21232130
2124 elf.DT_INIT_ARRAY,2131 elf.DT_INIT_ARRAY,
...@@ -2136,7 +2143,7 @@ const ElfDumper = struct {...@@ -2136,7 +2143,7 @@ const ElfDumper = struct {
2136 elf.DT_INIT,2143 elf.DT_INIT,
2137 elf.DT_FINI,2144 elf.DT_FINI,
2138 elf.DT_NULL,2145 elf.DT_NULL,
2139 => try writer.print(" {x}", .{value}),2146 => try bw.print(" {x}", .{value}),
21402147
2141 elf.DT_INIT_ARRAYSZ,2148 elf.DT_INIT_ARRAYSZ,
2142 elf.DT_FINI_ARRAYSZ,2149 elf.DT_FINI_ARRAYSZ,
...@@ -2146,77 +2153,77 @@ const ElfDumper = struct {...@@ -2146,77 +2153,77 @@ const ElfDumper = struct {
2146 elf.DT_RELASZ,2153 elf.DT_RELASZ,
2147 elf.DT_RELAENT,2154 elf.DT_RELAENT,
2148 elf.DT_RELACOUNT,2155 elf.DT_RELACOUNT,
2149 => try writer.print(" {d}", .{value}),2156 => try bw.print(" {d}", .{value}),
21502157
2151 elf.DT_PLTREL => try writer.writeAll(switch (value) {2158 elf.DT_PLTREL => try bw.writeAll(switch (value) {
2152 elf.DT_REL => " REL",2159 elf.DT_REL => " REL",
2153 elf.DT_RELA => " RELA",2160 elf.DT_RELA => " RELA",
2154 else => " UNKNOWN",2161 else => " UNKNOWN",
2155 }),2162 }),
21562163
2157 elf.DT_FLAGS => if (value > 0) {2164 elf.DT_FLAGS => if (value > 0) {
2158 if (value & elf.DF_ORIGIN != 0) try writer.writeAll(" ORIGIN");2165 if (value & elf.DF_ORIGIN != 0) try bw.writeAll(" ORIGIN");
2159 if (value & elf.DF_SYMBOLIC != 0) try writer.writeAll(" SYMBOLIC");2166 if (value & elf.DF_SYMBOLIC != 0) try bw.writeAll(" SYMBOLIC");
2160 if (value & elf.DF_TEXTREL != 0) try writer.writeAll(" TEXTREL");2167 if (value & elf.DF_TEXTREL != 0) try bw.writeAll(" TEXTREL");
2161 if (value & elf.DF_BIND_NOW != 0) try writer.writeAll(" BIND_NOW");2168 if (value & elf.DF_BIND_NOW != 0) try bw.writeAll(" BIND_NOW");
2162 if (value & elf.DF_STATIC_TLS != 0) try writer.writeAll(" STATIC_TLS");2169 if (value & elf.DF_STATIC_TLS != 0) try bw.writeAll(" STATIC_TLS");
2163 },2170 },
21642171
2165 elf.DT_FLAGS_1 => if (value > 0) {2172 elf.DT_FLAGS_1 => if (value > 0) {
2166 if (value & elf.DF_1_NOW != 0) try writer.writeAll(" NOW");2173 if (value & elf.DF_1_NOW != 0) try bw.writeAll(" NOW");
2167 if (value & elf.DF_1_GLOBAL != 0) try writer.writeAll(" GLOBAL");2174 if (value & elf.DF_1_GLOBAL != 0) try bw.writeAll(" GLOBAL");
2168 if (value & elf.DF_1_GROUP != 0) try writer.writeAll(" GROUP");2175 if (value & elf.DF_1_GROUP != 0) try bw.writeAll(" GROUP");
2169 if (value & elf.DF_1_NODELETE != 0) try writer.writeAll(" NODELETE");2176 if (value & elf.DF_1_NODELETE != 0) try bw.writeAll(" NODELETE");
2170 if (value & elf.DF_1_LOADFLTR != 0) try writer.writeAll(" LOADFLTR");2177 if (value & elf.DF_1_LOADFLTR != 0) try bw.writeAll(" LOADFLTR");
2171 if (value & elf.DF_1_INITFIRST != 0) try writer.writeAll(" INITFIRST");2178 if (value & elf.DF_1_INITFIRST != 0) try bw.writeAll(" INITFIRST");
2172 if (value & elf.DF_1_NOOPEN != 0) try writer.writeAll(" NOOPEN");2179 if (value & elf.DF_1_NOOPEN != 0) try bw.writeAll(" NOOPEN");
2173 if (value & elf.DF_1_ORIGIN != 0) try writer.writeAll(" ORIGIN");2180 if (value & elf.DF_1_ORIGIN != 0) try bw.writeAll(" ORIGIN");
2174 if (value & elf.DF_1_DIRECT != 0) try writer.writeAll(" DIRECT");2181 if (value & elf.DF_1_DIRECT != 0) try bw.writeAll(" DIRECT");
2175 if (value & elf.DF_1_TRANS != 0) try writer.writeAll(" TRANS");2182 if (value & elf.DF_1_TRANS != 0) try bw.writeAll(" TRANS");
2176 if (value & elf.DF_1_INTERPOSE != 0) try writer.writeAll(" INTERPOSE");2183 if (value & elf.DF_1_INTERPOSE != 0) try bw.writeAll(" INTERPOSE");
2177 if (value & elf.DF_1_NODEFLIB != 0) try writer.writeAll(" NODEFLIB");2184 if (value & elf.DF_1_NODEFLIB != 0) try bw.writeAll(" NODEFLIB");
2178 if (value & elf.DF_1_NODUMP != 0) try writer.writeAll(" NODUMP");2185 if (value & elf.DF_1_NODUMP != 0) try bw.writeAll(" NODUMP");
2179 if (value & elf.DF_1_CONFALT != 0) try writer.writeAll(" CONFALT");2186 if (value & elf.DF_1_CONFALT != 0) try bw.writeAll(" CONFALT");
2180 if (value & elf.DF_1_ENDFILTEE != 0) try writer.writeAll(" ENDFILTEE");2187 if (value & elf.DF_1_ENDFILTEE != 0) try bw.writeAll(" ENDFILTEE");
2181 if (value & elf.DF_1_DISPRELDNE != 0) try writer.writeAll(" DISPRELDNE");2188 if (value & elf.DF_1_DISPRELDNE != 0) try bw.writeAll(" DISPRELDNE");
2182 if (value & elf.DF_1_DISPRELPND != 0) try writer.writeAll(" DISPRELPND");2189 if (value & elf.DF_1_DISPRELPND != 0) try bw.writeAll(" DISPRELPND");
2183 if (value & elf.DF_1_NODIRECT != 0) try writer.writeAll(" NODIRECT");2190 if (value & elf.DF_1_NODIRECT != 0) try bw.writeAll(" NODIRECT");
2184 if (value & elf.DF_1_IGNMULDEF != 0) try writer.writeAll(" IGNMULDEF");2191 if (value & elf.DF_1_IGNMULDEF != 0) try bw.writeAll(" IGNMULDEF");
2185 if (value & elf.DF_1_NOKSYMS != 0) try writer.writeAll(" NOKSYMS");2192 if (value & elf.DF_1_NOKSYMS != 0) try bw.writeAll(" NOKSYMS");
2186 if (value & elf.DF_1_NOHDR != 0) try writer.writeAll(" NOHDR");2193 if (value & elf.DF_1_NOHDR != 0) try bw.writeAll(" NOHDR");
2187 if (value & elf.DF_1_EDITED != 0) try writer.writeAll(" EDITED");2194 if (value & elf.DF_1_EDITED != 0) try bw.writeAll(" EDITED");
2188 if (value & elf.DF_1_NORELOC != 0) try writer.writeAll(" NORELOC");2195 if (value & elf.DF_1_NORELOC != 0) try bw.writeAll(" NORELOC");
2189 if (value & elf.DF_1_SYMINTPOSE != 0) try writer.writeAll(" SYMINTPOSE");2196 if (value & elf.DF_1_SYMINTPOSE != 0) try bw.writeAll(" SYMINTPOSE");
2190 if (value & elf.DF_1_GLOBAUDIT != 0) try writer.writeAll(" GLOBAUDIT");2197 if (value & elf.DF_1_GLOBAUDIT != 0) try bw.writeAll(" GLOBAUDIT");
2191 if (value & elf.DF_1_SINGLETON != 0) try writer.writeAll(" SINGLETON");2198 if (value & elf.DF_1_SINGLETON != 0) try bw.writeAll(" SINGLETON");
2192 if (value & elf.DF_1_STUB != 0) try writer.writeAll(" STUB");2199 if (value & elf.DF_1_STUB != 0) try bw.writeAll(" STUB");
2193 if (value & elf.DF_1_PIE != 0) try writer.writeAll(" PIE");2200 if (value & elf.DF_1_PIE != 0) try bw.writeAll(" PIE");
2194 },2201 },
21952202
2196 else => try writer.print(" {x}", .{value}),2203 else => try bw.print(" {x}", .{value}),
2197 }2204 }
2198 try writer.writeByte('\n');2205 try bw.writeByte('\n');
2199 }2206 }
2200 }2207 }
22012208
2202 fn dumpSymtab(ctx: ObjectContext, comptime @"type": enum { symtab, dysymtab }, writer: anytype) !void {2209 fn dumpSymtab(ctx: ObjectContext, comptime @"type": enum { symtab, dysymtab }, bw: *std.io.BufferedWriter) !void {
2203 const symtab = switch (@"type") {2210 const symtab = switch (@"type") {
2204 .symtab => ctx.symtab,2211 .symtab => ctx.symtab,
2205 .dysymtab => ctx.dysymtab,2212 .dysymtab => ctx.dysymtab,
2206 };2213 };
22072214
2208 try writer.writeAll(switch (@"type") {2215 try bw.writeAll(switch (@"type") {
2209 .symtab => symtab_label,2216 .symtab => symtab_label,
2210 .dysymtab => dynamic_symtab_label,2217 .dysymtab => dynamic_symtab_label,
2211 } ++ "\n");2218 } ++ "\n");
22122219
2213 for (symtab.symbols, 0..) |sym, index| {2220 for (symtab.symbols, 0..) |sym, index| {
2214 try writer.print("{x} {x}", .{ sym.st_value, sym.st_size });2221 try bw.print("{x} {x}", .{ sym.st_value, sym.st_size });
22152222
2216 {2223 {
2217 if (elf.SHN_LORESERVE <= sym.st_shndx and sym.st_shndx < elf.SHN_HIRESERVE) {2224 if (elf.SHN_LORESERVE <= sym.st_shndx and sym.st_shndx < elf.SHN_HIRESERVE) {
2218 if (elf.SHN_LOPROC <= sym.st_shndx and sym.st_shndx < elf.SHN_HIPROC) {2225 if (elf.SHN_LOPROC <= sym.st_shndx and sym.st_shndx < elf.SHN_HIPROC) {
2219 try writer.print(" LO+{d}", .{sym.st_shndx - elf.SHN_LOPROC});2226 try bw.print(" LO+{d}", .{sym.st_shndx - elf.SHN_LOPROC});
2220 } else {2227 } else {
2221 const sym_ndx = switch (sym.st_shndx) {2228 const sym_ndx = switch (sym.st_shndx) {
2222 elf.SHN_ABS => "ABS",2229 elf.SHN_ABS => "ABS",
...@@ -2224,12 +2231,12 @@ const ElfDumper = struct {...@@ -2224,12 +2231,12 @@ const ElfDumper = struct {
2224 elf.SHN_LIVEPATCH => "LIV",2231 elf.SHN_LIVEPATCH => "LIV",
2225 else => "UNK",2232 else => "UNK",
2226 };2233 };
2227 try writer.print(" {s}", .{sym_ndx});2234 try bw.print(" {s}", .{sym_ndx});
2228 }2235 }
2229 } else if (sym.st_shndx == elf.SHN_UNDEF) {2236 } else if (sym.st_shndx == elf.SHN_UNDEF) {
2230 try writer.writeAll(" UND");2237 try bw.writeAll(" UND");
2231 } else {2238 } else {
2232 try writer.print(" {x}", .{sym.st_shndx});2239 try bw.print(" {x}", .{sym.st_shndx});
2233 }2240 }
2234 }2241 }
22352242
...@@ -2246,12 +2253,12 @@ const ElfDumper = struct {...@@ -2246,12 +2253,12 @@ const ElfDumper = struct {
2246 elf.STT_NUM => "NUM",2253 elf.STT_NUM => "NUM",
2247 elf.STT_GNU_IFUNC => "IFUNC",2254 elf.STT_GNU_IFUNC => "IFUNC",
2248 else => if (elf.STT_LOPROC <= tt and tt < elf.STT_HIPROC) {2255 else => if (elf.STT_LOPROC <= tt and tt < elf.STT_HIPROC) {
2249 break :blk try writer.print(" LOPROC+{d}", .{tt - elf.STT_LOPROC});2256 break :blk try bw.print(" LOPROC+{d}", .{tt - elf.STT_LOPROC});
2250 } else if (elf.STT_LOOS <= tt and tt < elf.STT_HIOS) {2257 } else if (elf.STT_LOOS <= tt and tt < elf.STT_HIOS) {
2251 break :blk try writer.print(" LOOS+{d}", .{tt - elf.STT_LOOS});2258 break :blk try bw.print(" LOOS+{d}", .{tt - elf.STT_LOOS});
2252 } else "UNK",2259 } else "UNK",
2253 };2260 };
2254 try writer.print(" {s}", .{sym_type});2261 try bw.print(" {s}", .{sym_type});
2255 }2262 }
22562263
2257 blk: {2264 blk: {
...@@ -2262,28 +2269,28 @@ const ElfDumper = struct {...@@ -2262,28 +2269,28 @@ const ElfDumper = struct {
2262 elf.STB_WEAK => "WEAK",2269 elf.STB_WEAK => "WEAK",
2263 elf.STB_NUM => "NUM",2270 elf.STB_NUM => "NUM",
2264 else => if (elf.STB_LOPROC <= bind and bind < elf.STB_HIPROC) {2271 else => if (elf.STB_LOPROC <= bind and bind < elf.STB_HIPROC) {
2265 break :blk try writer.print(" LOPROC+{d}", .{bind - elf.STB_LOPROC});2272 break :blk try bw.print(" LOPROC+{d}", .{bind - elf.STB_LOPROC});
2266 } else if (elf.STB_LOOS <= bind and bind < elf.STB_HIOS) {2273 } else if (elf.STB_LOOS <= bind and bind < elf.STB_HIOS) {
2267 break :blk try writer.print(" LOOS+{d}", .{bind - elf.STB_LOOS});2274 break :blk try bw.print(" LOOS+{d}", .{bind - elf.STB_LOOS});
2268 } else "UNKNOWN",2275 } else "UNKNOWN",
2269 };2276 };
2270 try writer.print(" {s}", .{sym_bind});2277 try bw.print(" {s}", .{sym_bind});
2271 }2278 }
22722279
2273 const sym_vis = @as(elf.STV, @enumFromInt(sym.st_other));2280 const sym_vis = @as(elf.STV, @enumFromInt(sym.st_other));
2274 try writer.print(" {s}", .{@tagName(sym_vis)});2281 try bw.print(" {s}", .{@tagName(sym_vis)});
22752282
2276 const sym_name = switch (sym.st_type()) {2283 const sym_name = switch (sym.st_type()) {
2277 elf.STT_SECTION => ctx.getSectionName(sym.st_shndx),2284 elf.STT_SECTION => ctx.getSectionName(sym.st_shndx),
2278 else => symtab.getName(index).?,2285 else => symtab.getName(index).?,
2279 };2286 };
2280 try writer.print(" {s}\n", .{sym_name});2287 try bw.print(" {s}\n", .{sym_name});
2281 }2288 }
2282 }2289 }
22832290
2284 fn dumpSection(ctx: ObjectContext, shndx: usize, writer: anytype) !void {2291 fn dumpSection(ctx: ObjectContext, shndx: usize, bw: *std.io.BufferedWriter) !void {
2285 const data = ctx.getSectionContents(shndx);2292 const data = ctx.getSectionContents(shndx);
2286 try writer.print("{s}", .{data});2293 try bw.print("{s}", .{data});
2287 }2294 }
22882295
2289 inline fn getSectionName(ctx: ObjectContext, shndx: usize) []const u8 {2296 inline fn getSectionName(ctx: ObjectContext, shndx: usize) []const u8 {
...@@ -2333,7 +2340,7 @@ const ElfDumper = struct {...@@ -2333,7 +2340,7 @@ const ElfDumper = struct {
2333 sh_type: u32,2340 sh_type: u32,
2334 comptime unused_fmt_string: []const u8,2341 comptime unused_fmt_string: []const u8,
2335 options: std.fmt.FormatOptions,2342 options: std.fmt.FormatOptions,
2336 writer: anytype,2343 bw: *std.io.BufferedWriter,
2337 ) !void {2344 ) !void {
2338 _ = unused_fmt_string;2345 _ = unused_fmt_string;
2339 _ = options;2346 _ = options;
...@@ -2362,14 +2369,14 @@ const ElfDumper = struct {...@@ -2362,14 +2369,14 @@ const ElfDumper = struct {
2362 elf.SHT_GNU_VERNEED => "VERNEED",2369 elf.SHT_GNU_VERNEED => "VERNEED",
2363 elf.SHT_GNU_VERSYM => "VERSYM",2370 elf.SHT_GNU_VERSYM => "VERSYM",
2364 else => if (elf.SHT_LOOS <= sh_type and sh_type < elf.SHT_HIOS) {2371 else => if (elf.SHT_LOOS <= sh_type and sh_type < elf.SHT_HIOS) {
2365 return try writer.print("LOOS+0x{x}", .{sh_type - elf.SHT_LOOS});2372 return try bw.print("LOOS+0x{x}", .{sh_type - elf.SHT_LOOS});
2366 } else if (elf.SHT_LOPROC <= sh_type and sh_type < elf.SHT_HIPROC) {2373 } else if (elf.SHT_LOPROC <= sh_type and sh_type < elf.SHT_HIPROC) {
2367 return try writer.print("LOPROC+0x{x}", .{sh_type - elf.SHT_LOPROC});2374 return try bw.print("LOPROC+0x{x}", .{sh_type - elf.SHT_LOPROC});
2368 } else if (elf.SHT_LOUSER <= sh_type and sh_type < elf.SHT_HIUSER) {2375 } else if (elf.SHT_LOUSER <= sh_type and sh_type < elf.SHT_HIUSER) {
2369 return try writer.print("LOUSER+0x{x}", .{sh_type - elf.SHT_LOUSER});2376 return try bw.print("LOUSER+0x{x}", .{sh_type - elf.SHT_LOUSER});
2370 } else "UNKNOWN",2377 } else "UNKNOWN",
2371 };2378 };
2372 try writer.writeAll(name);2379 try bw.writeAll(name);
2373 }2380 }
23742381
2375 fn fmtPhType(ph_type: u32) std.fmt.Formatter(formatPhType) {2382 fn fmtPhType(ph_type: u32) std.fmt.Formatter(formatPhType) {
...@@ -2380,7 +2387,7 @@ const ElfDumper = struct {...@@ -2380,7 +2387,7 @@ const ElfDumper = struct {
2380 ph_type: u32,2387 ph_type: u32,
2381 comptime unused_fmt_string: []const u8,2388 comptime unused_fmt_string: []const u8,
2382 options: std.fmt.FormatOptions,2389 options: std.fmt.FormatOptions,
2383 writer: anytype,2390 bw: *std.io.BufferedWriter,
2384 ) !void {2391 ) !void {
2385 _ = unused_fmt_string;2392 _ = unused_fmt_string;
2386 _ = options;2393 _ = options;
...@@ -2398,12 +2405,12 @@ const ElfDumper = struct {...@@ -2398,12 +2405,12 @@ const ElfDumper = struct {
2398 elf.PT_GNU_STACK => "GNU_STACK",2405 elf.PT_GNU_STACK => "GNU_STACK",
2399 elf.PT_GNU_RELRO => "GNU_RELRO",2406 elf.PT_GNU_RELRO => "GNU_RELRO",
2400 else => if (elf.PT_LOOS <= ph_type and ph_type < elf.PT_HIOS) {2407 else => if (elf.PT_LOOS <= ph_type and ph_type < elf.PT_HIOS) {
2401 return try writer.print("LOOS+0x{x}", .{ph_type - elf.PT_LOOS});2408 return try bw.print("LOOS+0x{x}", .{ph_type - elf.PT_LOOS});
2402 } else if (elf.PT_LOPROC <= ph_type and ph_type < elf.PT_HIPROC) {2409 } else if (elf.PT_LOPROC <= ph_type and ph_type < elf.PT_HIPROC) {
2403 return try writer.print("LOPROC+0x{x}", .{ph_type - elf.PT_LOPROC});2410 return try bw.print("LOPROC+0x{x}", .{ph_type - elf.PT_LOPROC});
2404 } else "UNKNOWN",2411 } else "UNKNOWN",
2405 };2412 };
2406 try writer.writeAll(p_type);2413 try bw.writeAll(p_type);
2407 }2414 }
2408};2415};
24092416
...@@ -2463,12 +2470,12 @@ const WasmDumper = struct {...@@ -2463,12 +2470,12 @@ const WasmDumper = struct {
2463 step: *Step,2470 step: *Step,
2464 section: std.wasm.Section,2471 section: std.wasm.Section,
2465 data: []const u8,2472 data: []const u8,
2466 writer: anytype,2473 bw: *std.io.BufferedWriter,
2467 ) !void {2474 ) !void {
2468 var fbs = std.io.fixedBufferStream(data);2475 var fbs = std.io.fixedBufferStream(data);
2469 const reader = fbs.reader();2476 const reader = fbs.reader();
24702477
2471 try writer.print(2478 try bw.print(
2472 \\Section {s}2479 \\Section {s}
2473 \\size {d}2480 \\size {d}
2474 , .{ @tagName(section), data.len });2481 , .{ @tagName(section), data.len });
...@@ -2486,37 +2493,37 @@ const WasmDumper = struct {...@@ -2486,37 +2493,37 @@ const WasmDumper = struct {
2486 .data,2493 .data,
2487 => {2494 => {
2488 const entries = try std.leb.readUleb128(u32, reader);2495 const entries = try std.leb.readUleb128(u32, reader);
2489 try writer.print("\nentries {d}\n", .{entries});2496 try bw.print("\nentries {d}\n", .{entries});
2490 try parseSection(step, section, data[fbs.pos..], entries, writer);2497 try parseSection(step, section, data[fbs.pos..], entries, bw);
2491 },2498 },
2492 .custom => {2499 .custom => {
2493 const name_length = try std.leb.readUleb128(u32, reader);2500 const name_length = try std.leb.readUleb128(u32, reader);
2494 const name = data[fbs.pos..][0..name_length];2501 const name = data[fbs.pos..][0..name_length];
2495 fbs.pos += name_length;2502 fbs.pos += name_length;
2496 try writer.print("\nname {s}\n", .{name});2503 try bw.print("\nname {s}\n", .{name});
24972504
2498 if (mem.eql(u8, name, "name")) {2505 if (mem.eql(u8, name, "name")) {
2499 try parseDumpNames(step, reader, writer, data);2506 try parseDumpNames(step, reader, bw, data);
2500 } else if (mem.eql(u8, name, "producers")) {2507 } else if (mem.eql(u8, name, "producers")) {
2501 try parseDumpProducers(reader, writer, data);2508 try parseDumpProducers(reader, bw, data);
2502 } else if (mem.eql(u8, name, "target_features")) {2509 } else if (mem.eql(u8, name, "target_features")) {
2503 try parseDumpFeatures(reader, writer, data);2510 try parseDumpFeatures(reader, bw, data);
2504 }2511 }
2505 // TODO: Implement parsing and dumping other custom sections (such as relocations)2512 // TODO: Implement parsing and dumping other custom sections (such as relocations)
2506 },2513 },
2507 .start => {2514 .start => {
2508 const start = try std.leb.readUleb128(u32, reader);2515 const start = try std.leb.readUleb128(u32, reader);
2509 try writer.print("\nstart {d}\n", .{start});2516 try bw.print("\nstart {d}\n", .{start});
2510 },2517 },
2511 .data_count => {2518 .data_count => {
2512 const count = try std.leb.readUleb128(u32, reader);2519 const count = try std.leb.readUleb128(u32, reader);
2513 try writer.print("\ncount {d}\n", .{count});2520 try bw.print("\ncount {d}\n", .{count});
2514 },2521 },
2515 else => {}, // skip unknown sections2522 else => {}, // skip unknown sections
2516 }2523 }
2517 }2524 }
25182525
2519 fn parseSection(step: *Step, section: std.wasm.Section, data: []const u8, entries: u32, writer: anytype) !void {2526 fn parseSection(step: *Step, section: std.wasm.Section, data: []const u8, entries: u32, bw: *std.io.BufferedWriter) !void {
2520 var fbs = std.io.fixedBufferStream(data);2527 var fbs = std.io.fixedBufferStream(data);
2521 const reader = fbs.reader();2528 const reader = fbs.reader();
25222529
...@@ -2529,15 +2536,15 @@ const WasmDumper = struct {...@@ -2529,15 +2536,15 @@ const WasmDumper = struct {
2529 return step.fail("expected function type, found byte '{d}'", .{func_type});2536 return step.fail("expected function type, found byte '{d}'", .{func_type});
2530 }2537 }
2531 const params = try std.leb.readUleb128(u32, reader);2538 const params = try std.leb.readUleb128(u32, reader);
2532 try writer.print("params {d}\n", .{params});2539 try bw.print("params {d}\n", .{params});
2533 var index: u32 = 0;2540 var index: u32 = 0;
2534 while (index < params) : (index += 1) {2541 while (index < params) : (index += 1) {
2535 _ = try parseDumpType(step, std.wasm.Valtype, reader, writer);2542 _ = try parseDumpType(step, std.wasm.Valtype, reader, bw);
2536 } else index = 0;2543 } else index = 0;
2537 const returns = try std.leb.readUleb128(u32, reader);2544 const returns = try std.leb.readUleb128(u32, reader);
2538 try writer.print("returns {d}\n", .{returns});2545 try bw.print("returns {d}\n", .{returns});
2539 while (index < returns) : (index += 1) {2546 while (index < returns) : (index += 1) {
2540 _ = try parseDumpType(step, std.wasm.Valtype, reader, writer);2547 _ = try parseDumpType(step, std.wasm.Valtype, reader, bw);
2541 }2548 }
2542 }2549 }
2543 },2550 },
...@@ -2555,26 +2562,26 @@ const WasmDumper = struct {...@@ -2555,26 +2562,26 @@ const WasmDumper = struct {
2555 return step.fail("invalid import kind", .{});2562 return step.fail("invalid import kind", .{});
2556 };2563 };
25572564
2558 try writer.print(2565 try bw.print(
2559 \\module {s}2566 \\module {s}
2560 \\name {s}2567 \\name {s}
2561 \\kind {s}2568 \\kind {s}
2562 , .{ module_name, name, @tagName(kind) });2569 , .{ module_name, name, @tagName(kind) });
2563 try writer.writeByte('\n');2570 try bw.writeByte('\n');
2564 switch (kind) {2571 switch (kind) {
2565 .function => {2572 .function => {
2566 try writer.print("index {d}\n", .{try std.leb.readUleb128(u32, reader)});2573 try bw.print("index {d}\n", .{try std.leb.readUleb128(u32, reader)});
2567 },2574 },
2568 .memory => {2575 .memory => {
2569 try parseDumpLimits(reader, writer);2576 try parseDumpLimits(reader, bw);
2570 },2577 },
2571 .global => {2578 .global => {
2572 _ = try parseDumpType(step, std.wasm.Valtype, reader, writer);2579 _ = try parseDumpType(step, std.wasm.Valtype, reader, bw);
2573 try writer.print("mutable {}\n", .{0x01 == try std.leb.readUleb128(u32, reader)});2580 try bw.print("mutable {}\n", .{0x01 == try std.leb.readUleb128(u32, reader)});
2574 },2581 },
2575 .table => {2582 .table => {
2576 _ = try parseDumpType(step, std.wasm.RefType, reader, writer);2583 _ = try parseDumpType(step, std.wasm.RefType, reader, bw);
2577 try parseDumpLimits(reader, writer);2584 try parseDumpLimits(reader, bw);
2578 },2585 },
2579 }2586 }
2580 }2587 }
...@@ -2582,28 +2589,28 @@ const WasmDumper = struct {...@@ -2582,28 +2589,28 @@ const WasmDumper = struct {
2582 .function => {2589 .function => {
2583 var i: u32 = 0;2590 var i: u32 = 0;
2584 while (i < entries) : (i += 1) {2591 while (i < entries) : (i += 1) {
2585 try writer.print("index {d}\n", .{try std.leb.readUleb128(u32, reader)});2592 try bw.print("index {d}\n", .{try std.leb.readUleb128(u32, reader)});
2586 }2593 }
2587 },2594 },
2588 .table => {2595 .table => {
2589 var i: u32 = 0;2596 var i: u32 = 0;
2590 while (i < entries) : (i += 1) {2597 while (i < entries) : (i += 1) {
2591 _ = try parseDumpType(step, std.wasm.RefType, reader, writer);2598 _ = try parseDumpType(step, std.wasm.RefType, reader, bw);
2592 try parseDumpLimits(reader, writer);2599 try parseDumpLimits(reader, bw);
2593 }2600 }
2594 },2601 },
2595 .memory => {2602 .memory => {
2596 var i: u32 = 0;2603 var i: u32 = 0;
2597 while (i < entries) : (i += 1) {2604 while (i < entries) : (i += 1) {
2598 try parseDumpLimits(reader, writer);2605 try parseDumpLimits(reader, bw);
2599 }2606 }
2600 },2607 },
2601 .global => {2608 .global => {
2602 var i: u32 = 0;2609 var i: u32 = 0;
2603 while (i < entries) : (i += 1) {2610 while (i < entries) : (i += 1) {
2604 _ = try parseDumpType(step, std.wasm.Valtype, reader, writer);2611 _ = try parseDumpType(step, std.wasm.Valtype, reader, bw);
2605 try writer.print("mutable {}\n", .{0x01 == try std.leb.readUleb128(u1, reader)});2612 try bw.print("mutable {}\n", .{0x01 == try std.leb.readUleb128(u1, reader)});
2606 try parseDumpInit(step, reader, writer);2613 try parseDumpInit(step, reader, bw);
2607 }2614 }
2608 },2615 },
2609 .@"export" => {2616 .@"export" => {
...@@ -2617,25 +2624,25 @@ const WasmDumper = struct {...@@ -2617,25 +2624,25 @@ const WasmDumper = struct {
2617 return step.fail("invalid export kind value '{d}'", .{kind_byte});2624 return step.fail("invalid export kind value '{d}'", .{kind_byte});
2618 };2625 };
2619 const index = try std.leb.readUleb128(u32, reader);2626 const index = try std.leb.readUleb128(u32, reader);
2620 try writer.print(2627 try bw.print(
2621 \\name {s}2628 \\name {s}
2622 \\kind {s}2629 \\kind {s}
2623 \\index {d}2630 \\index {d}
2624 , .{ name, @tagName(kind), index });2631 , .{ name, @tagName(kind), index });
2625 try writer.writeByte('\n');2632 try bw.writeByte('\n');
2626 }2633 }
2627 },2634 },
2628 .element => {2635 .element => {
2629 var i: u32 = 0;2636 var i: u32 = 0;
2630 while (i < entries) : (i += 1) {2637 while (i < entries) : (i += 1) {
2631 try writer.print("table index {d}\n", .{try std.leb.readUleb128(u32, reader)});2638 try bw.print("table index {d}\n", .{try std.leb.readUleb128(u32, reader)});
2632 try parseDumpInit(step, reader, writer);2639 try parseDumpInit(step, reader, bw);
26332640
2634 const function_indexes = try std.leb.readUleb128(u32, reader);2641 const function_indexes = try std.leb.readUleb128(u32, reader);
2635 var function_index: u32 = 0;2642 var function_index: u32 = 0;
2636 try writer.print("indexes {d}\n", .{function_indexes});2643 try bw.print("indexes {d}\n", .{function_indexes});
2637 while (function_index < function_indexes) : (function_index += 1) {2644 while (function_index < function_indexes) : (function_index += 1) {
2638 try writer.print("index {d}\n", .{try std.leb.readUleb128(u32, reader)});2645 try bw.print("index {d}\n", .{try std.leb.readUleb128(u32, reader)});
2639 }2646 }
2640 }2647 }
2641 },2648 },
...@@ -2648,13 +2655,13 @@ const WasmDumper = struct {...@@ -2648,13 +2655,13 @@ const WasmDumper = struct {
2648 try std.leb.readUleb128(u32, reader)2655 try std.leb.readUleb128(u32, reader)
2649 else2656 else
2650 0;2657 0;
2651 try writer.print("memory index 0x{x}\n", .{index});2658 try bw.print("memory index 0x{x}\n", .{index});
2652 if (flags == 0) {2659 if (flags == 0) {
2653 try parseDumpInit(step, reader, writer);2660 try parseDumpInit(step, reader, bw);
2654 }2661 }
26552662
2656 const size = try std.leb.readUleb128(u32, reader);2663 const size = try std.leb.readUleb128(u32, reader);
2657 try writer.print("size {d}\n", .{size});2664 try bw.print("size {d}\n", .{size});
2658 try reader.skipBytes(size, .{}); // we do not care about the content of the segments2665 try reader.skipBytes(size, .{}); // we do not care about the content of the segments
2659 }2666 }
2660 },2667 },
...@@ -2662,36 +2669,36 @@ const WasmDumper = struct {...@@ -2662,36 +2669,36 @@ const WasmDumper = struct {
2662 }2669 }
2663 }2670 }
26642671
2665 fn parseDumpType(step: *Step, comptime E: type, reader: anytype, writer: anytype) !E {2672 fn parseDumpType(step: *Step, comptime E: type, reader: anytype, bw: *std.io.BufferedWriter) !E {
2666 const byte = try reader.readByte();2673 const byte = try reader.readByte();
2667 const tag = std.enums.fromInt(E, byte) orelse {2674 const tag = std.enums.fromInt(E, byte) orelse {
2668 return step.fail("invalid wasm type value '{d}'", .{byte});2675 return step.fail("invalid wasm type value '{d}'", .{byte});
2669 };2676 };
2670 try writer.print("type {s}\n", .{@tagName(tag)});2677 try bw.print("type {s}\n", .{@tagName(tag)});
2671 return tag;2678 return tag;
2672 }2679 }
26732680
2674 fn parseDumpLimits(reader: anytype, writer: anytype) !void {2681 fn parseDumpLimits(reader: anytype, bw: *std.io.BufferedWriter) !void {
2675 const flags = try std.leb.readUleb128(u8, reader);2682 const flags = try std.leb.readUleb128(u8, reader);
2676 const min = try std.leb.readUleb128(u32, reader);2683 const min = try std.leb.readUleb128(u32, reader);
26772684
2678 try writer.print("min {x}\n", .{min});2685 try bw.print("min {x}\n", .{min});
2679 if (flags != 0) {2686 if (flags != 0) {
2680 try writer.print("max {x}\n", .{try std.leb.readUleb128(u32, reader)});2687 try bw.print("max {x}\n", .{try std.leb.readUleb128(u32, reader)});
2681 }2688 }
2682 }2689 }
26832690
2684 fn parseDumpInit(step: *Step, reader: anytype, writer: anytype) !void {2691 fn parseDumpInit(step: *Step, reader: anytype, bw: *std.io.BufferedWriter) !void {
2685 const byte = try reader.readByte();2692 const byte = try reader.readByte();
2686 const opcode = std.enums.fromInt(std.wasm.Opcode, byte) orelse {2693 const opcode = std.enums.fromInt(std.wasm.Opcode, byte) orelse {
2687 return step.fail("invalid wasm opcode '{d}'", .{byte});2694 return step.fail("invalid wasm opcode '{d}'", .{byte});
2688 };2695 };
2689 switch (opcode) {2696 switch (opcode) {
2690 .i32_const => try writer.print("i32.const {x}\n", .{try std.leb.readIleb128(i32, reader)}),2697 .i32_const => try bw.print("i32.const {x}\n", .{try std.leb.readIleb128(i32, reader)}),
2691 .i64_const => try writer.print("i64.const {x}\n", .{try std.leb.readIleb128(i64, reader)}),2698 .i64_const => try bw.print("i64.const {x}\n", .{try std.leb.readIleb128(i64, reader)}),
2692 .f32_const => try writer.print("f32.const {x}\n", .{@as(f32, @bitCast(try reader.readInt(u32, .little)))}),2699 .f32_const => try bw.print("f32.const {x}\n", .{@as(f32, @bitCast(try reader.readInt(u32, .little)))}),
2693 .f64_const => try writer.print("f64.const {x}\n", .{@as(f64, @bitCast(try reader.readInt(u64, .little)))}),2700 .f64_const => try bw.print("f64.const {x}\n", .{@as(f64, @bitCast(try reader.readInt(u64, .little)))}),
2694 .global_get => try writer.print("global.get {x}\n", .{try std.leb.readUleb128(u32, reader)}),2701 .global_get => try bw.print("global.get {x}\n", .{try std.leb.readUleb128(u32, reader)}),
2695 else => unreachable,2702 else => unreachable,
2696 }2703 }
2697 const end_opcode = try std.leb.readUleb128(u8, reader);2704 const end_opcode = try std.leb.readUleb128(u8, reader);
...@@ -2701,9 +2708,9 @@ const WasmDumper = struct {...@@ -2701,9 +2708,9 @@ const WasmDumper = struct {
2701 }2708 }
27022709
2703 /// https://webassembly.github.io/spec/core/appendix/custom.html2710 /// https://webassembly.github.io/spec/core/appendix/custom.html
2704 fn parseDumpNames(step: *Step, reader: anytype, writer: anytype, data: []const u8) !void {2711 fn parseDumpNames(step: *Step, reader: anytype, bw: *std.io.BufferedWriter, data: []const u8) !void {
2705 while (reader.context.pos < data.len) {2712 while (reader.context.pos < data.len) {
2706 switch (try parseDumpType(step, std.wasm.NameSubsection, reader, writer)) {2713 switch (try parseDumpType(step, std.wasm.NameSubsection, reader, bw)) {
2707 // The module name subsection ... consists of a single name2714 // The module name subsection ... consists of a single name
2708 // that is assigned to the module itself.2715 // that is assigned to the module itself.
2709 .module => {2716 .module => {
...@@ -2711,7 +2718,7 @@ const WasmDumper = struct {...@@ -2711,7 +2718,7 @@ const WasmDumper = struct {
2711 const name_len = try std.leb.readUleb128(u32, reader);2718 const name_len = try std.leb.readUleb128(u32, reader);
2712 if (size != name_len + 1) return error.BadSubsectionSize;2719 if (size != name_len + 1) return error.BadSubsectionSize;
2713 if (reader.context.pos + name_len > data.len) return error.UnexpectedEndOfStream;2720 if (reader.context.pos + name_len > data.len) return error.UnexpectedEndOfStream;
2714 try writer.print("name {s}\n", .{data[reader.context.pos..][0..name_len]});2721 try bw.print("name {s}\n", .{data[reader.context.pos..][0..name_len]});
2715 reader.context.pos += name_len;2722 reader.context.pos += name_len;
2716 },2723 },
27172724
...@@ -2720,7 +2727,7 @@ const WasmDumper = struct {...@@ -2720,7 +2727,7 @@ const WasmDumper = struct {
2720 .function, .global, .data_segment => {2727 .function, .global, .data_segment => {
2721 const size = try std.leb.readUleb128(u32, reader);2728 const size = try std.leb.readUleb128(u32, reader);
2722 const entries = try std.leb.readUleb128(u32, reader);2729 const entries = try std.leb.readUleb128(u32, reader);
2723 try writer.print(2730 try bw.print(
2724 \\size {d}2731 \\size {d}
2725 \\names {d}2732 \\names {d}
2726 \\2733 \\
...@@ -2732,7 +2739,7 @@ const WasmDumper = struct {...@@ -2732,7 +2739,7 @@ const WasmDumper = struct {
2732 const name = data[reader.context.pos..][0..name_len];2739 const name = data[reader.context.pos..][0..name_len];
2733 reader.context.pos += name.len;2740 reader.context.pos += name.len;
27342741
2735 try writer.print(2742 try bw.print(
2736 \\index {d}2743 \\index {d}
2737 \\name {s}2744 \\name {s}
2738 \\2745 \\
...@@ -2752,9 +2759,9 @@ const WasmDumper = struct {...@@ -2752,9 +2759,9 @@ const WasmDumper = struct {
2752 }2759 }
2753 }2760 }
27542761
2755 fn parseDumpProducers(reader: anytype, writer: anytype, data: []const u8) !void {2762 fn parseDumpProducers(reader: anytype, bw: *std.io.BufferedWriter, data: []const u8) !void {
2756 const field_count = try std.leb.readUleb128(u32, reader);2763 const field_count = try std.leb.readUleb128(u32, reader);
2757 try writer.print("fields {d}\n", .{field_count});2764 try bw.print("fields {d}\n", .{field_count});
2758 var current_field: u32 = 0;2765 var current_field: u32 = 0;
2759 while (current_field < field_count) : (current_field += 1) {2766 while (current_field < field_count) : (current_field += 1) {
2760 const field_name_length = try std.leb.readUleb128(u32, reader);2767 const field_name_length = try std.leb.readUleb128(u32, reader);
...@@ -2762,11 +2769,11 @@ const WasmDumper = struct {...@@ -2762,11 +2769,11 @@ const WasmDumper = struct {
2762 reader.context.pos += field_name_length;2769 reader.context.pos += field_name_length;
27632770
2764 const value_count = try std.leb.readUleb128(u32, reader);2771 const value_count = try std.leb.readUleb128(u32, reader);
2765 try writer.print(2772 try bw.print(
2766 \\field_name {s}2773 \\field_name {s}
2767 \\values {d}2774 \\values {d}
2768 , .{ field_name, value_count });2775 , .{ field_name, value_count });
2769 try writer.writeByte('\n');2776 try bw.writeByte('\n');
2770 var current_value: u32 = 0;2777 var current_value: u32 = 0;
2771 while (current_value < value_count) : (current_value += 1) {2778 while (current_value < value_count) : (current_value += 1) {
2772 const value_length = try std.leb.readUleb128(u32, reader);2779 const value_length = try std.leb.readUleb128(u32, reader);
...@@ -2777,18 +2784,18 @@ const WasmDumper = struct {...@@ -2777,18 +2784,18 @@ const WasmDumper = struct {
2777 const version = data[reader.context.pos..][0..version_length];2784 const version = data[reader.context.pos..][0..version_length];
2778 reader.context.pos += version_length;2785 reader.context.pos += version_length;
27792786
2780 try writer.print(2787 try bw.print(
2781 \\value_name {s}2788 \\value_name {s}
2782 \\version {s}2789 \\version {s}
2783 , .{ value, version });2790 , .{ value, version });
2784 try writer.writeByte('\n');2791 try bw.writeByte('\n');
2785 }2792 }
2786 }2793 }
2787 }2794 }
27882795
2789 fn parseDumpFeatures(reader: anytype, writer: anytype, data: []const u8) !void {2796 fn parseDumpFeatures(reader: anytype, bw: *std.io.BufferedWriter, data: []const u8) !void {
2790 const feature_count = try std.leb.readUleb128(u32, reader);2797 const feature_count = try std.leb.readUleb128(u32, reader);
2791 try writer.print("features {d}\n", .{feature_count});2798 try bw.print("features {d}\n", .{feature_count});
27922799
2793 var index: u32 = 0;2800 var index: u32 = 0;
2794 while (index < feature_count) : (index += 1) {2801 while (index < feature_count) : (index += 1) {
...@@ -2797,7 +2804,7 @@ const WasmDumper = struct {...@@ -2797,7 +2804,7 @@ const WasmDumper = struct {
2797 const feature_name = data[reader.context.pos..][0..name_length];2804 const feature_name = data[reader.context.pos..][0..name_length];
2798 reader.context.pos += name_length;2805 reader.context.pos += name_length;
27992806
2800 try writer.print("{c} {s}\n", .{ prefix_byte, feature_name });2807 try bw.print("{c} {s}\n", .{ prefix_byte, feature_name });
2801 }2808 }
2802 }2809 }
2803};2810};
lib/std/Build/Step/Compile.zig+5-5
...@@ -1769,12 +1769,12 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {...@@ -1769,12 +1769,12 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
1769 for (arg, 0..) |c, arg_idx| {1769 for (arg, 0..) |c, arg_idx| {
1770 if (c == '\\' or c == '"') {1770 if (c == '\\' or c == '"') {
1771 // Slow path for arguments that need to be escaped. We'll need to allocate and copy1771 // Slow path for arguments that need to be escaped. We'll need to allocate and copy
1772 var escaped = try ArrayList(u8).initCapacity(arena, arg.len + 1);1772 var escaped: std.ArrayListUnmanaged(u8) = .empty;
1773 const writer = escaped.writer();1773 try escaped.ensureTotalCapacityPrecise(arena, arg.len + 1);
1774 try writer.writeAll(arg[0..arg_idx]);1774 try escaped.appendSlice(arena, arg[0..arg_idx]);
1775 for (arg[arg_idx..]) |to_escape| {1775 for (arg[arg_idx..]) |to_escape| {
1776 if (to_escape == '\\' or to_escape == '"') try writer.writeByte('\\');1776 if (to_escape == '\\' or to_escape == '"') try escaped.append(arena, '\\');
1777 try writer.writeByte(to_escape);1777 try escaped.append(arena, to_escape);
1778 }1778 }
1779 escaped_args.appendAssumeCapacity(escaped.items);1779 escaped_args.appendAssumeCapacity(escaped.items);
1780 continue :arg_blk;1780 continue :arg_blk;
lib/std/Build/Step/ConfigHeader.zig+3-3
...@@ -569,14 +569,14 @@ fn renderValueC(output: *std.ArrayList(u8), name: []const u8, value: Value) !voi...@@ -569,14 +569,14 @@ fn renderValueC(output: *std.ArrayList(u8), name: []const u8, value: Value) !voi
569 try output.appendSlice(if (b) " 1\n" else " 0\n");569 try output.appendSlice(if (b) " 1\n" else " 0\n");
570 },570 },
571 .int => |i| {571 .int => |i| {
572 try output.writer().print("#define {s} {d}\n", .{ name, i });572 try output.print("#define {s} {d}\n", .{ name, i });
573 },573 },
574 .ident => |ident| {574 .ident => |ident| {
575 try output.writer().print("#define {s} {s}\n", .{ name, ident });575 try output.print("#define {s} {s}\n", .{ name, ident });
576 },576 },
577 .string => |string| {577 .string => |string| {
578 // TODO: use C-specific escaping instead of zig string literals578 // TODO: use C-specific escaping instead of zig string literals
579 try output.writer().print("#define {s} \"{}\"\n", .{ name, std.zig.fmtEscapes(string) });579 try output.print("#define {s} \"{}\"\n", .{ name, std.zig.fmtEscapes(string) });
580 },580 },
581 }581 }
582}582}
lib/std/Build/Step/Options.zig+125-103
...@@ -12,9 +12,9 @@ pub const base_id: Step.Id = .options;...@@ -12,9 +12,9 @@ pub const base_id: Step.Id = .options;
12step: Step,12step: Step,
13generated_file: GeneratedFile,13generated_file: GeneratedFile,
1414
15contents: std.ArrayList(u8),15contents: std.ArrayListUnmanaged(u8),
16args: std.ArrayList(Arg),16args: std.ArrayListUnmanaged(Arg),
17encountered_types: std.StringHashMap(void),17encountered_types: std.StringHashMapUnmanaged(void),
1818
19pub fn create(owner: *std.Build) *Options {19pub fn create(owner: *std.Build) *Options {
20 const options = owner.allocator.create(Options) catch @panic("OOM");20 const options = owner.allocator.create(Options) catch @panic("OOM");
...@@ -26,9 +26,9 @@ pub fn create(owner: *std.Build) *Options {...@@ -26,9 +26,9 @@ pub fn create(owner: *std.Build) *Options {
26 .makeFn = make,26 .makeFn = make,
27 }),27 }),
28 .generated_file = undefined,28 .generated_file = undefined,
29 .contents = std.ArrayList(u8).init(owner.allocator),29 .contents = .empty,
30 .args = std.ArrayList(Arg).init(owner.allocator),30 .args = .empty,
31 .encountered_types = std.StringHashMap(void).init(owner.allocator),31 .encountered_types = .empty,
32 };32 };
33 options.generated_file = .{ .step = &options.step };33 options.generated_file = .{ .step = &options.step };
3434
...@@ -40,110 +40,117 @@ pub fn addOption(options: *Options, comptime T: type, name: []const u8, value: T...@@ -40,110 +40,117 @@ pub fn addOption(options: *Options, comptime T: type, name: []const u8, value: T
40}40}
4141
42fn addOptionFallible(options: *Options, comptime T: type, name: []const u8, value: T) !void {42fn addOptionFallible(options: *Options, comptime T: type, name: []const u8, value: T) !void {
43 const out = options.contents.writer();43 try printType(options, &options.contents, T, value, 0, name);
44 try printType(options, out, T, value, 0, name);
45}44}
4645
47fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent: u8, name: ?[]const u8) !void {46fn printType(
47 options: *Options,
48 out: *std.ArrayListUnmanaged(u8),
49 comptime T: type,
50 value: T,
51 indent: u8,
52 name: ?[]const u8,
53) !void {
54 const gpa = options.step.owner.allocator;
48 switch (T) {55 switch (T) {
49 []const []const u8 => {56 []const []const u8 => {
50 if (name) |payload| {57 if (name) |payload| {
51 try out.print("pub const {}: []const []const u8 = ", .{std.zig.fmtId(payload)});58 try out.print(gpa, "pub const {}: []const []const u8 = ", .{std.zig.fmtId(payload)});
52 }59 }
5360
54 try out.writeAll("&[_][]const u8{\n");61 try out.appendSlice(gpa, "&[_][]const u8{\n");
5562
56 for (value) |slice| {63 for (value) |slice| {
57 try out.writeByteNTimes(' ', indent);64 try out.appendNTimes(gpa, ' ', indent);
58 try out.print(" \"{}\",\n", .{std.zig.fmtEscapes(slice)});65 try out.print(gpa, " \"{}\",\n", .{std.zig.fmtEscapes(slice)});
59 }66 }
6067
61 if (name != null) {68 if (name != null) {
62 try out.writeAll("};\n");69 try out.appendSlice(gpa, "};\n");
63 } else {70 } else {
64 try out.writeAll("},\n");71 try out.appendSlice(gpa, "},\n");
65 }72 }
6673
67 return;74 return;
68 },75 },
69 []const u8 => {76 []const u8 => {
70 if (name) |some| {77 if (name) |some| {
71 try out.print("pub const {}: []const u8 = \"{}\";", .{ std.zig.fmtId(some), std.zig.fmtEscapes(value) });78 try out.print(gpa, "pub const {}: []const u8 = \"{}\";", .{ std.zig.fmtId(some), std.zig.fmtEscapes(value) });
72 } else {79 } else {
73 try out.print("\"{}\",", .{std.zig.fmtEscapes(value)});80 try out.print(gpa, "\"{}\",", .{std.zig.fmtEscapes(value)});
74 }81 }
75 return out.writeAll("\n");82 return out.appendSlice(gpa, "\n");
76 },83 },
77 [:0]const u8 => {84 [:0]const u8 => {
78 if (name) |some| {85 if (name) |some| {
79 try out.print("pub const {}: [:0]const u8 = \"{}\";", .{ std.zig.fmtId(some), std.zig.fmtEscapes(value) });86 try out.print(gpa, "pub const {}: [:0]const u8 = \"{}\";", .{ std.zig.fmtId(some), std.zig.fmtEscapes(value) });
80 } else {87 } else {
81 try out.print("\"{}\",", .{std.zig.fmtEscapes(value)});88 try out.print(gpa, "\"{}\",", .{std.zig.fmtEscapes(value)});
82 }89 }
83 return out.writeAll("\n");90 return out.appendSlice(gpa, "\n");
84 },91 },
85 ?[]const u8 => {92 ?[]const u8 => {
86 if (name) |some| {93 if (name) |some| {
87 try out.print("pub const {}: ?[]const u8 = ", .{std.zig.fmtId(some)});94 try out.print(gpa, "pub const {}: ?[]const u8 = ", .{std.zig.fmtId(some)});
88 }95 }
8996
90 if (value) |payload| {97 if (value) |payload| {
91 try out.print("\"{}\"", .{std.zig.fmtEscapes(payload)});98 try out.print(gpa, "\"{}\"", .{std.zig.fmtEscapes(payload)});
92 } else {99 } else {
93 try out.writeAll("null");100 try out.appendSlice(gpa, "null");
94 }101 }
95102
96 if (name != null) {103 if (name != null) {
97 try out.writeAll(";\n");104 try out.appendSlice(gpa, ";\n");
98 } else {105 } else {
99 try out.writeAll(",\n");106 try out.appendSlice(gpa, ",\n");
100 }107 }
101 return;108 return;
102 },109 },
103 ?[:0]const u8 => {110 ?[:0]const u8 => {
104 if (name) |some| {111 if (name) |some| {
105 try out.print("pub const {}: ?[:0]const u8 = ", .{std.zig.fmtId(some)});112 try out.print(gpa, "pub const {}: ?[:0]const u8 = ", .{std.zig.fmtId(some)});
106 }113 }
107114
108 if (value) |payload| {115 if (value) |payload| {
109 try out.print("\"{}\"", .{std.zig.fmtEscapes(payload)});116 try out.print(gpa, "\"{}\"", .{std.zig.fmtEscapes(payload)});
110 } else {117 } else {
111 try out.writeAll("null");118 try out.appendSlice(gpa, "null");
112 }119 }
113120
114 if (name != null) {121 if (name != null) {
115 try out.writeAll(";\n");122 try out.appendSlice(gpa, ";\n");
116 } else {123 } else {
117 try out.writeAll(",\n");124 try out.appendSlice(gpa, ",\n");
118 }125 }
119 return;126 return;
120 },127 },
121 std.SemanticVersion => {128 std.SemanticVersion => {
122 if (name) |some| {129 if (name) |some| {
123 try out.print("pub const {}: @import(\"std\").SemanticVersion = ", .{std.zig.fmtId(some)});130 try out.print(gpa, "pub const {}: @import(\"std\").SemanticVersion = ", .{std.zig.fmtId(some)});
124 }131 }
125132
126 try out.writeAll(".{\n");133 try out.appendSlice(gpa, ".{\n");
127 try out.writeByteNTimes(' ', indent);134 try out.appendNTimes(gpa, ' ', indent);
128 try out.print(" .major = {d},\n", .{value.major});135 try out.print(gpa, " .major = {d},\n", .{value.major});
129 try out.writeByteNTimes(' ', indent);136 try out.appendNTimes(gpa, ' ', indent);
130 try out.print(" .minor = {d},\n", .{value.minor});137 try out.print(gpa, " .minor = {d},\n", .{value.minor});
131 try out.writeByteNTimes(' ', indent);138 try out.appendNTimes(gpa, ' ', indent);
132 try out.print(" .patch = {d},\n", .{value.patch});139 try out.print(gpa, " .patch = {d},\n", .{value.patch});
133140
134 if (value.pre) |some| {141 if (value.pre) |some| {
135 try out.writeByteNTimes(' ', indent);142 try out.appendNTimes(gpa, ' ', indent);
136 try out.print(" .pre = \"{}\",\n", .{std.zig.fmtEscapes(some)});143 try out.print(gpa, " .pre = \"{}\",\n", .{std.zig.fmtEscapes(some)});
137 }144 }
138 if (value.build) |some| {145 if (value.build) |some| {
139 try out.writeByteNTimes(' ', indent);146 try out.appendNTimes(gpa, ' ', indent);
140 try out.print(" .build = \"{}\",\n", .{std.zig.fmtEscapes(some)});147 try out.print(gpa, " .build = \"{}\",\n", .{std.zig.fmtEscapes(some)});
141 }148 }
142149
143 if (name != null) {150 if (name != null) {
144 try out.writeAll("};\n");151 try out.appendSlice(gpa, "};\n");
145 } else {152 } else {
146 try out.writeAll("},\n");153 try out.appendSlice(gpa, "},\n");
147 }154 }
148 return;155 return;
149 },156 },
...@@ -153,21 +160,21 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent...@@ -153,21 +160,21 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent
153 switch (@typeInfo(T)) {160 switch (@typeInfo(T)) {
154 .array => {161 .array => {
155 if (name) |some| {162 if (name) |some| {
156 try out.print("pub const {}: {s} = ", .{ std.zig.fmtId(some), @typeName(T) });163 try out.print(gpa, "pub const {}: {s} = ", .{ std.zig.fmtId(some), @typeName(T) });
157 }164 }
158165
159 try out.print("{s} {{\n", .{@typeName(T)});166 try out.print(gpa, "{s} {{\n", .{@typeName(T)});
160 for (value) |item| {167 for (value) |item| {
161 try out.writeByteNTimes(' ', indent + 4);168 try out.appendNTimes(gpa, ' ', indent + 4);
162 try printType(options, out, @TypeOf(item), item, indent + 4, null);169 try printType(options, out, @TypeOf(item), item, indent + 4, null);
163 }170 }
164 try out.writeByteNTimes(' ', indent);171 try out.appendNTimes(gpa, ' ', indent);
165 try out.writeAll("}");172 try out.appendSlice(gpa, "}");
166173
167 if (name != null) {174 if (name != null) {
168 try out.writeAll(";\n");175 try out.appendSlice(gpa, ";\n");
169 } else {176 } else {
170 try out.writeAll(",\n");177 try out.appendSlice(gpa, ",\n");
171 }178 }
172 return;179 return;
173 },180 },
...@@ -177,27 +184,27 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent...@@ -177,27 +184,27 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent
177 }184 }
178185
179 if (name) |some| {186 if (name) |some| {
180 try out.print("pub const {}: {s} = ", .{ std.zig.fmtId(some), @typeName(T) });187 try out.print(gpa, "pub const {}: {s} = ", .{ std.zig.fmtId(some), @typeName(T) });
181 }188 }
182189
183 try out.print("&[_]{s} {{\n", .{@typeName(p.child)});190 try out.print(gpa, "&[_]{s} {{\n", .{@typeName(p.child)});
184 for (value) |item| {191 for (value) |item| {
185 try out.writeByteNTimes(' ', indent + 4);192 try out.appendNTimes(gpa, ' ', indent + 4);
186 try printType(options, out, @TypeOf(item), item, indent + 4, null);193 try printType(options, out, @TypeOf(item), item, indent + 4, null);
187 }194 }
188 try out.writeByteNTimes(' ', indent);195 try out.appendNTimes(gpa, ' ', indent);
189 try out.writeAll("}");196 try out.appendSlice(gpa, "}");
190197
191 if (name != null) {198 if (name != null) {
192 try out.writeAll(";\n");199 try out.appendSlice(gpa, ";\n");
193 } else {200 } else {
194 try out.writeAll(",\n");201 try out.appendSlice(gpa, ",\n");
195 }202 }
196 return;203 return;
197 },204 },
198 .optional => {205 .optional => {
199 if (name) |some| {206 if (name) |some| {
200 try out.print("pub const {}: {s} = ", .{ std.zig.fmtId(some), @typeName(T) });207 try out.print(gpa, "pub const {}: {s} = ", .{ std.zig.fmtId(some), @typeName(T) });
201 }208 }
202209
203 if (value) |inner| {210 if (value) |inner| {
...@@ -206,13 +213,13 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent...@@ -206,13 +213,13 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent
206 _ = options.contents.pop();213 _ = options.contents.pop();
207 _ = options.contents.pop();214 _ = options.contents.pop();
208 } else {215 } else {
209 try out.writeAll("null");216 try out.appendSlice(gpa, "null");
210 }217 }
211218
212 if (name != null) {219 if (name != null) {
213 try out.writeAll(";\n");220 try out.appendSlice(gpa, ";\n");
214 } else {221 } else {
215 try out.writeAll(",\n");222 try out.appendSlice(gpa, ",\n");
216 }223 }
217 return;224 return;
218 },225 },
...@@ -224,9 +231,9 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent...@@ -224,9 +231,9 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent
224 .null,231 .null,
225 => {232 => {
226 if (name) |some| {233 if (name) |some| {
227 try out.print("pub const {}: {s} = {any};\n", .{ std.zig.fmtId(some), @typeName(T), value });234 try out.print(gpa, "pub const {}: {s} = {any};\n", .{ std.zig.fmtId(some), @typeName(T), value });
228 } else {235 } else {
229 try out.print("{any},\n", .{value});236 try out.print(gpa, "{any},\n", .{value});
230 }237 }
231 return;238 return;
232 },239 },
...@@ -234,7 +241,7 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent...@@ -234,7 +241,7 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent
234 try printEnum(options, out, T, info, indent);241 try printEnum(options, out, T, info, indent);
235242
236 if (name) |some| {243 if (name) |some| {
237 try out.print("pub const {}: {} = .{p_};\n", .{244 try out.print(gpa, "pub const {}: {} = .{p_};\n", .{
238 std.zig.fmtId(some),245 std.zig.fmtId(some),
239 std.zig.fmtId(@typeName(T)),246 std.zig.fmtId(@typeName(T)),
240 std.zig.fmtId(@tagName(value)),247 std.zig.fmtId(@tagName(value)),
...@@ -246,7 +253,7 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent...@@ -246,7 +253,7 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent
246 try printStruct(options, out, T, info, indent);253 try printStruct(options, out, T, info, indent);
247254
248 if (name) |some| {255 if (name) |some| {
249 try out.print("pub const {}: {} = ", .{256 try out.print(gpa, "pub const {}: {} = ", .{
250 std.zig.fmtId(some),257 std.zig.fmtId(some),
251 std.zig.fmtId(@typeName(T)),258 std.zig.fmtId(@typeName(T)),
252 });259 });
...@@ -258,7 +265,7 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent...@@ -258,7 +265,7 @@ fn printType(options: *Options, out: anytype, comptime T: type, value: T, indent
258 }265 }
259}266}
260267
261fn printUserDefinedType(options: *Options, out: anytype, comptime T: type, indent: u8) !void {268fn printUserDefinedType(options: *Options, out: *std.ArrayListUnmanaged(u8), comptime T: type, indent: u8) !void {
262 switch (@typeInfo(T)) {269 switch (@typeInfo(T)) {
263 .@"enum" => |info| {270 .@"enum" => |info| {
264 return try printEnum(options, out, T, info, indent);271 return try printEnum(options, out, T, info, indent);
...@@ -270,94 +277,109 @@ fn printUserDefinedType(options: *Options, out: anytype, comptime T: type, inden...@@ -270,94 +277,109 @@ fn printUserDefinedType(options: *Options, out: anytype, comptime T: type, inden
270 }277 }
271}278}
272279
273fn printEnum(options: *Options, out: anytype, comptime T: type, comptime val: std.builtin.Type.Enum, indent: u8) !void {280fn printEnum(
274 const gop = try options.encountered_types.getOrPut(@typeName(T));281 options: *Options,
282 out: *std.ArrayListUnmanaged(u8),
283 comptime T: type,
284 comptime val: std.builtin.Type.Enum,
285 indent: u8,
286) !void {
287 const gpa = options.step.owner.allocator;
288 const gop = try options.encountered_types.getOrPut(gpa, @typeName(T));
275 if (gop.found_existing) return;289 if (gop.found_existing) return;
276290
277 try out.writeByteNTimes(' ', indent);291 try out.appendNTimes(gpa, ' ', indent);
278 try out.print("pub const {} = enum ({s}) {{\n", .{ std.zig.fmtId(@typeName(T)), @typeName(val.tag_type) });292 try out.print(gpa, "pub const {} = enum ({s}) {{\n", .{ std.zig.fmtId(@typeName(T)), @typeName(val.tag_type) });
279293
280 inline for (val.fields) |field| {294 inline for (val.fields) |field| {
281 try out.writeByteNTimes(' ', indent);295 try out.appendNTimes(gpa, ' ', indent);
282 try out.print(" {p} = {d},\n", .{ std.zig.fmtId(field.name), field.value });296 try out.print(gpa, " {p} = {d},\n", .{ std.zig.fmtId(field.name), field.value });
283 }297 }
284298
285 if (!val.is_exhaustive) {299 if (!val.is_exhaustive) {
286 try out.writeByteNTimes(' ', indent);300 try out.appendNTimes(gpa, ' ', indent);
287 try out.writeAll(" _,\n");301 try out.appendSlice(gpa, " _,\n");
288 }302 }
289303
290 try out.writeByteNTimes(' ', indent);304 try out.appendNTimes(gpa, ' ', indent);
291 try out.writeAll("};\n");305 try out.appendSlice(gpa, "};\n");
292}306}
293307
294fn printStruct(options: *Options, out: anytype, comptime T: type, comptime val: std.builtin.Type.Struct, indent: u8) !void {308fn printStruct(options: *Options, out: *std.ArrayListUnmanaged(u8), comptime T: type, comptime val: std.builtin.Type.Struct, indent: u8) !void {
295 const gop = try options.encountered_types.getOrPut(@typeName(T));309 const gpa = options.step.owner.allocator;
310 const gop = try options.encountered_types.getOrPut(gpa, @typeName(T));
296 if (gop.found_existing) return;311 if (gop.found_existing) return;
297312
298 try out.writeByteNTimes(' ', indent);313 try out.appendNTimes(gpa, ' ', indent);
299 try out.print("pub const {} = ", .{std.zig.fmtId(@typeName(T))});314 try out.print(gpa, "pub const {} = ", .{std.zig.fmtId(@typeName(T))});
300315
301 switch (val.layout) {316 switch (val.layout) {
302 .@"extern" => try out.writeAll("extern struct"),317 .@"extern" => try out.appendSlice(gpa, "extern struct"),
303 .@"packed" => try out.writeAll("packed struct"),318 .@"packed" => try out.appendSlice(gpa, "packed struct"),
304 else => try out.writeAll("struct"),319 else => try out.appendSlice(gpa, "struct"),
305 }320 }
306321
307 try out.writeAll(" {\n");322 try out.appendSlice(gpa, " {\n");
308323
309 inline for (val.fields) |field| {324 inline for (val.fields) |field| {
310 try out.writeByteNTimes(' ', indent);325 try out.appendNTimes(gpa, ' ', indent);
311326
312 const type_name = @typeName(field.type);327 const type_name = @typeName(field.type);
313328
314 // If the type name doesn't contains a '.' the type is from zig builtins.329 // If the type name doesn't contains a '.' the type is from zig builtins.
315 if (std.mem.containsAtLeast(u8, type_name, 1, ".")) {330 if (std.mem.containsAtLeast(u8, type_name, 1, ".")) {
316 try out.print(" {p_}: {}", .{ std.zig.fmtId(field.name), std.zig.fmtId(type_name) });331 try out.print(gpa, " {p_}: {}", .{ std.zig.fmtId(field.name), std.zig.fmtId(type_name) });
317 } else {332 } else {
318 try out.print(" {p_}: {s}", .{ std.zig.fmtId(field.name), type_name });333 try out.print(gpa, " {p_}: {s}", .{ std.zig.fmtId(field.name), type_name });
319 }334 }
320335
321 if (field.defaultValue()) |default_value| {336 if (field.defaultValue()) |default_value| {
322 try out.writeAll(" = ");337 try out.appendSlice(gpa, " = ");
323 switch (@typeInfo(@TypeOf(default_value))) {338 switch (@typeInfo(@TypeOf(default_value))) {
324 .@"enum" => try out.print(".{s},\n", .{@tagName(default_value)}),339 .@"enum" => try out.print(gpa, ".{s},\n", .{@tagName(default_value)}),
325 .@"struct" => |info| {340 .@"struct" => |info| {
326 try printStructValue(options, out, info, default_value, indent + 4);341 try printStructValue(options, out, info, default_value, indent + 4);
327 },342 },
328 else => try printType(options, out, @TypeOf(default_value), default_value, indent, null),343 else => try printType(options, out, @TypeOf(default_value), default_value, indent, null),
329 }344 }
330 } else {345 } else {
331 try out.writeAll(",\n");346 try out.appendSlice(gpa, ",\n");
332 }347 }
333 }348 }
334349
335 // TODO: write declarations350 // TODO: write declarations
336351
337 try out.writeByteNTimes(' ', indent);352 try out.appendNTimes(gpa, ' ', indent);
338 try out.writeAll("};\n");353 try out.appendSlice(gpa, "};\n");
339354
340 inline for (val.fields) |field| {355 inline for (val.fields) |field| {
341 try printUserDefinedType(options, out, field.type, 0);356 try printUserDefinedType(options, out, field.type, 0);
342 }357 }
343}358}
344359
345fn printStructValue(options: *Options, out: anytype, comptime struct_val: std.builtin.Type.Struct, val: anytype, indent: u8) !void {360fn printStructValue(
346 try out.writeAll(".{\n");361 options: *Options,
362 out: *std.ArrayListUnmanaged(u8),
363 comptime struct_val: std.builtin.Type.Struct,
364 val: anytype,
365 indent: u8,
366) !void {
367 const gpa = options.step.owner.allocator;
368 try out.appendSlice(gpa, ".{\n");
347369
348 if (struct_val.is_tuple) {370 if (struct_val.is_tuple) {
349 inline for (struct_val.fields) |field| {371 inline for (struct_val.fields) |field| {
350 try out.writeByteNTimes(' ', indent);372 try out.appendNTimes(gpa, ' ', indent);
351 try printType(options, out, @TypeOf(@field(val, field.name)), @field(val, field.name), indent, null);373 try printType(options, out, @TypeOf(@field(val, field.name)), @field(val, field.name), indent, null);
352 }374 }
353 } else {375 } else {
354 inline for (struct_val.fields) |field| {376 inline for (struct_val.fields) |field| {
355 try out.writeByteNTimes(' ', indent);377 try out.appendNTimes(gpa, ' ', indent);
356 try out.print(" .{p_} = ", .{std.zig.fmtId(field.name)});378 try out.print(gpa, " .{p_} = ", .{std.zig.fmtId(field.name)});
357379
358 const field_name = @field(val, field.name);380 const field_name = @field(val, field.name);
359 switch (@typeInfo(@TypeOf(field_name))) {381 switch (@typeInfo(@TypeOf(field_name))) {
360 .@"enum" => try out.print(".{s},\n", .{@tagName(field_name)}),382 .@"enum" => try out.print(gpa, ".{s},\n", .{@tagName(field_name)}),
361 .@"struct" => |struct_info| {383 .@"struct" => |struct_info| {
362 try printStructValue(options, out, struct_info, field_name, indent + 4);384 try printStructValue(options, out, struct_info, field_name, indent + 4);
363 },385 },
...@@ -367,10 +389,10 @@ fn printStructValue(options: *Options, out: anytype, comptime struct_val: std.bu...@@ -367,10 +389,10 @@ fn printStructValue(options: *Options, out: anytype, comptime struct_val: std.bu
367 }389 }
368390
369 if (indent == 0) {391 if (indent == 0) {
370 try out.writeAll("};\n");392 try out.appendSlice(gpa, "};\n");
371 } else {393 } else {
372 try out.writeByteNTimes(' ', indent);394 try out.appendNTimes(gpa, ' ', indent);
373 try out.writeAll("},\n");395 try out.appendSlice(gpa, "},\n");
374 }396 }
375}397}
376398
lib/std/Target/Query.zig+20-21
...@@ -394,25 +394,24 @@ pub fn canDetectLibC(self: Query) bool {...@@ -394,25 +394,24 @@ pub fn canDetectLibC(self: Query) bool {
394394
395/// Formats a version with the patch component omitted if it is zero,395/// Formats a version with the patch component omitted if it is zero,
396/// unlike SemanticVersion.format which formats all its version components regardless.396/// unlike SemanticVersion.format which formats all its version components regardless.
397fn formatVersion(version: SemanticVersion, writer: anytype) !void {397fn formatVersion(version: SemanticVersion, gpa: Allocator, list: *std.ArrayListUnmanaged(u8)) !void {
398 if (version.patch == 0) {398 if (version.patch == 0) {
399 try writer.print("{d}.{d}", .{ version.major, version.minor });399 try list.print(gpa, "{d}.{d}", .{ version.major, version.minor });
400 } else {400 } else {
401 try writer.print("{d}.{d}.{d}", .{ version.major, version.minor, version.patch });401 try list.print(gpa, "{d}.{d}.{d}", .{ version.major, version.minor, version.patch });
402 }402 }
403}403}
404404
405pub fn zigTriple(self: Query, allocator: Allocator) Allocator.Error![]u8 {405pub fn zigTriple(self: Query, gpa: Allocator) Allocator.Error![]u8 {
406 if (self.isNativeTriple())406 if (self.isNativeTriple()) return gpa.dupe(u8, "native");
407 return allocator.dupe(u8, "native");
408407
409 const arch_name = if (self.cpu_arch) |arch| @tagName(arch) else "native";408 const arch_name = if (self.cpu_arch) |arch| @tagName(arch) else "native";
410 const os_name = if (self.os_tag) |os_tag| @tagName(os_tag) else "native";409 const os_name = if (self.os_tag) |os_tag| @tagName(os_tag) else "native";
411410
412 var result = std.ArrayList(u8).init(allocator);411 var result: std.ArrayListUnmanaged(u8) = .empty;
413 defer result.deinit();412 defer result.deinit(gpa);
414413
415 try result.writer().print("{s}-{s}", .{ arch_name, os_name });414 try result.print(gpa, "{s}-{s}", .{ arch_name, os_name });
416415
417 // The zig target syntax does not allow specifying a max os version with no min, so416 // The zig target syntax does not allow specifying a max os version with no min, so
418 // if either are present, we need the min.417 // if either are present, we need the min.
...@@ -420,11 +419,11 @@ pub fn zigTriple(self: Query, allocator: Allocator) Allocator.Error![]u8 {...@@ -420,11 +419,11 @@ pub fn zigTriple(self: Query, allocator: Allocator) Allocator.Error![]u8 {
420 switch (min) {419 switch (min) {
421 .none => {},420 .none => {},
422 .semver => |v| {421 .semver => |v| {
423 try result.writer().writeAll(".");422 try result.appendSlice(gpa, ".");
424 try formatVersion(v, result.writer());423 try formatVersion(v, gpa, &result);
425 },424 },
426 .windows => |v| {425 .windows => |v| {
427 try result.writer().print("{s}", .{v});426 try result.print(gpa, "{s}", .{v});
428 },427 },
429 }428 }
430 }429 }
...@@ -432,39 +431,39 @@ pub fn zigTriple(self: Query, allocator: Allocator) Allocator.Error![]u8 {...@@ -432,39 +431,39 @@ pub fn zigTriple(self: Query, allocator: Allocator) Allocator.Error![]u8 {
432 switch (max) {431 switch (max) {
433 .none => {},432 .none => {},
434 .semver => |v| {433 .semver => |v| {
435 try result.writer().writeAll("...");434 try result.appendSlice(gpa, "...");
436 try formatVersion(v, result.writer());435 try formatVersion(v, gpa, &result);
437 },436 },
438 .windows => |v| {437 .windows => |v| {
439 // This is counting on a custom format() function defined on `WindowsVersion`438 // This is counting on a custom format() function defined on `WindowsVersion`
440 // to add a prefix '.' and make there be a total of three dots.439 // to add a prefix '.' and make there be a total of three dots.
441 try result.writer().print("..{s}", .{v});440 try result.print(gpa, "..{s}", .{v});
442 },441 },
443 }442 }
444 }443 }
445444
446 if (self.glibc_version) |v| {445 if (self.glibc_version) |v| {
447 const name = if (self.abi) |abi| @tagName(abi) else "gnu";446 const name = if (self.abi) |abi| @tagName(abi) else "gnu";
448 try result.ensureUnusedCapacity(name.len + 2);447 try result.ensureUnusedCapacity(gpa, name.len + 2);
449 result.appendAssumeCapacity('-');448 result.appendAssumeCapacity('-');
450 result.appendSliceAssumeCapacity(name);449 result.appendSliceAssumeCapacity(name);
451 result.appendAssumeCapacity('.');450 result.appendAssumeCapacity('.');
452 try formatVersion(v, result.writer());451 try formatVersion(v, gpa, &result);
453 } else if (self.android_api_level) |lvl| {452 } else if (self.android_api_level) |lvl| {
454 const name = if (self.abi) |abi| @tagName(abi) else "android";453 const name = if (self.abi) |abi| @tagName(abi) else "android";
455 try result.ensureUnusedCapacity(name.len + 2);454 try result.ensureUnusedCapacity(gpa, name.len + 2);
456 result.appendAssumeCapacity('-');455 result.appendAssumeCapacity('-');
457 result.appendSliceAssumeCapacity(name);456 result.appendSliceAssumeCapacity(name);
458 result.appendAssumeCapacity('.');457 result.appendAssumeCapacity('.');
459 try result.writer().print("{d}", .{lvl});458 try result.print(gpa, "{d}", .{lvl});
460 } else if (self.abi) |abi| {459 } else if (self.abi) |abi| {
461 const name = @tagName(abi);460 const name = @tagName(abi);
462 try result.ensureUnusedCapacity(name.len + 1);461 try result.ensureUnusedCapacity(gpa, name.len + 1);
463 result.appendAssumeCapacity('-');462 result.appendAssumeCapacity('-');
464 result.appendSliceAssumeCapacity(name);463 result.appendSliceAssumeCapacity(name);
465 }464 }
466465
467 return result.toOwnedSlice();466 return result.toOwnedSlice(gpa);
468}467}
469468
470/// Renders the query into a textual representation that can be parsed via the469/// Renders the query into a textual representation that can be parsed via the
lib/std/io/AllocatingWriter.zig+6
...@@ -77,6 +77,12 @@ pub fn toArrayList(aw: *AllocatingWriter) std.ArrayListUnmanaged(u8) {...@@ -77,6 +77,12 @@ pub fn toArrayList(aw: *AllocatingWriter) std.ArrayListUnmanaged(u8) {
77 return result;77 return result;
78}78}
7979
80pub fn toOwnedSlice(aw: *AllocatingWriter) error{OutOfMemory}![]u8 {
81 const gpa = aw.allocator;
82 var list = toArrayList(aw);
83 return list.toOwnedSlice(gpa);
84}
85
80fn setArrayList(aw: *AllocatingWriter, list: std.ArrayListUnmanaged(u8)) void {86fn setArrayList(aw: *AllocatingWriter, list: std.ArrayListUnmanaged(u8)) void {
81 aw.written = list.items;87 aw.written = list.items;
82 aw.buffered_writer.buffer = list.unusedCapacitySlice();88 aw.buffered_writer.buffer = list.unusedCapacitySlice();