| ... | @@ -248,56 +248,63 @@ const ComputeCompareExpected = struct { | ... | @@ -248,56 +248,63 @@ const ComputeCompareExpected = struct { |
| 248 | const Check = struct { | 248 | const 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), |
| 253 | | 254 | |
| 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 | } |
| 262 | | 264 | |
| 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 | } |
| 270 | | 272 | |
| 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 | } |
| 277 | | 280 | |
| 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 | } |
| 284 | | 288 | |
| 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 | } |
| 291 | | 296 | |
| 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 | } |
| 298 | | 304 | |
| 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 | } |
| 812 | | 819 | |
| 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 | }; |
| 833 | | 840 | |
| 834 | try writer.print( | 841 | try bw.print( |
| 835 | \\header | 842 | \\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 | }); |
| 847 | | 854 | |
| 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 | } |
| 877 | | 884 | |
| 878 | try writer.writeByte('\n'); | 885 | try bw.writeByte('\n'); |
| 879 | } | 886 | } |
| 880 | | 887 | |
| 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 first | 889 | // 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 | }); |
| 906 | | 913 | |
| 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 { |
| 944 | | 951 | |
| 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 | }, |
| 953 | | 960 | |
| 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 { |
| 962 | | 969 | |
| 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 | }, |
| 968 | | 975 | |
| 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 { |
| 980 | | 987 | |
| 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 { |
| 1008 | | 1015 | |
| 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 { |
| 1024 | | 1031 | |
| 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 { |
| 1048 | | 1055 | |
| 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 | } |
| 1106 | | 1113 | |
| 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"); |
| 1109 | | 1116 | |
| 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 | } |
| 1177 | | 1184 | |
| 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"); |
| 1180 | | 1187 | |
| 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 | }; |
| 1216 | | 1223 | |
| 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 | } |
| 1226 | | 1233 | |
| 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 | } |
| 1236 | | 1243 | |
| ... | @@ -1323,7 +1330,7 @@ const MachODumper = struct { | ... | @@ -1323,7 +1330,7 @@ const MachODumper = struct { |
| 1323 | }; | 1330 | }; |
| 1324 | }; | 1331 | }; |
| 1325 | | 1332 | |
| 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 | } |
| 1348 | | 1355 | |
| ... | @@ -1439,7 +1446,7 @@ const MachODumper = struct { | ... | @@ -1439,7 +1446,7 @@ const MachODumper = struct { |
| 1439 | } | 1446 | } |
| 1440 | } | 1447 | } |
| 1441 | | 1448 | |
| 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; |
| 1444 | | 1451 | |
| 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 | } |
| 1474 | | 1481 | |
| 1475 | try writer.print("{s}\n", .{exp.name}); | 1482 | try bw.print("{s}\n", .{exp.name}); |
| 1476 | } | 1483 | } |
| 1477 | } | 1484 | } |
| 1478 | | 1485 | |
| ... | @@ -1616,9 +1623,9 @@ const MachODumper = struct { | ... | @@ -1616,9 +1623,9 @@ const MachODumper = struct { |
| 1616 | } | 1623 | } |
| 1617 | } | 1624 | } |
| 1618 | | 1625 | |
| 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 | }; |
| 1624 | | 1631 | |
| ... | @@ -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(); |
| 1634 | | 1641 | |
| 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); |
| 1637 | | 1644 | |
| 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); |
| 1641 | | 1648 | |
| 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'); |
| 1647 | | 1654 | |
| 1648 | i += 1; | 1655 | i += 1; |
| 1649 | } | 1656 | } |
| 1650 | }, | 1657 | }, |
| 1651 | | 1658 | |
| 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", .{}), |
| 1655 | | 1662 | |
| 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", .{}), |
| 1659 | | 1666 | |
| 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", .{}), |
| 1675 | | 1682 | |
| 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", .{}), |
| 1681 | | 1688 | |
| 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", .{}), |
| 1687 | | 1694 | |
| 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", .{}), |
| 1693 | | 1700 | |
| 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) orelse | 1724 | 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 | }, |
| 1721 | | 1728 | |
| 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 | } |
| 1852 | | 1859 | |
| 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 | } |
| 1877 | | 1884 | |
| 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 | } |
| 1886 | | 1893 | |
| 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 | } |
| 1895 | | 1902 | |
| ... | @@ -1955,32 +1962,32 @@ const ElfDumper = struct { | ... | @@ -1955,32 +1962,32 @@ const ElfDumper = struct { |
| 1955 | else => {}, | 1962 | else => {}, |
| 1956 | }; | 1963 | }; |
| 1957 | | 1964 | |
| 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); |
| 1960 | | 1967 | |
| 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 | }, |
| 1967 | | 1974 | |
| 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", .{}), |
| 1971 | | 1978 | |
| 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", .{}), |
| 1975 | | 1982 | |
| 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", .{}), |
| 1979 | | 1986 | |
| 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 | }, |
| 1985 | | 1992 | |
| 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 = .{}, |
| 2001 | | 2008 | |
| 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 | } |
| 2007 | | 2014 | |
| 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; |
| 2010 | | 2017 | |
| 2011 | try writer.writeAll("program headers\n"); | 2018 | try bw.writeAll("program headers\n"); |
| 2012 | | 2019 | |
| 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}); |
| 2022 | | 2029 | |
| 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 | } |
| 2046 | | 2053 | |
| 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; |
| 2049 | | 2056 | |
| 2050 | try writer.writeAll("section headers\n"); | 2057 | try bw.writeAll("section headers\n"); |
| 2051 | | 2058 | |
| 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_flags | 2067 | // TODO dump formatted sh_flags |
| 2061 | } | 2068 | } |
| 2062 | } | 2069 | } |
| 2063 | | 2070 | |
| 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]; |
| 2070 | | 2077 | |
| 2071 | try writer.writeAll(ElfDumper.dynamic_section_label ++ "\n"); | 2078 | try bw.writeAll(ElfDumper.dynamic_section_label ++ "\n"); |
| 2072 | | 2079 | |
| 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}); |
| 2113 | | 2120 | |
| 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 | }, |
| 2123 | | 2130 | |
| 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}), |
| 2140 | | 2147 | |
| 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}), |
| 2150 | | 2157 | |
| 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 | }), |
| 2156 | | 2163 | |
| 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 | }, |
| 2164 | | 2171 | |
| 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 | }, |
| 2195 | | 2202 | |
| 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 | } |
| 2201 | | 2208 | |
| 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 | }; |
| 2207 | | 2214 | |
| 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"); |
| 2212 | | 2219 | |
| 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 }); |
| 2215 | | 2222 | |
| 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 | } |
| 2235 | | 2242 | |
| ... | @@ -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 | } |
| 2256 | | 2263 | |
| 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 | } |
| 2272 | | 2279 | |
| 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)}); |
| 2275 | | 2282 | |
| 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 | } |
| 2283 | | 2290 | |
| 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 | } |
| 2288 | | 2295 | |
| 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 | } |
| 2374 | | 2381 | |
| 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 | }; |
| 2409 | | 2416 | |
| ... | @@ -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(); |
| 2470 | | 2477 | |
| 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}); |
| 2497 | | 2504 | |
| 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 sections | 2522 | else => {}, // skip unknown sections |
| 2516 | } | 2523 | } |
| 2517 | } | 2524 | } |
| 2518 | | 2525 | |
| 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(); |
| 2522 | | 2529 | |
| ... | @@ -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 | }; |
| 2557 | | 2564 | |
| 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); |
| 2633 | | 2640 | |
| 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 | else | 2656 | 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 | } |
| 2655 | | 2662 | |
| 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 segments | 2665 | 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 | } |
| 2664 | | 2671 | |
| 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 | } |
| 2673 | | 2680 | |
| 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); |
| 2677 | | 2684 | |
| 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 | } |
| 2683 | | 2690 | |
| 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 | } |
| 2702 | | 2709 | |
| 2703 | /// https://webassembly.github.io/spec/core/appendix/custom.html | 2710 | /// 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 name | 2714 | // 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 | }, |
| 2717 | | 2724 | |
| ... | @@ -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; |
| 2734 | | 2741 | |
| 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 | } |
| 2754 | | 2761 | |
| 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; |
| 2763 | | 2770 | |
| 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; |
| 2779 | | 2786 | |
| 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 | } |
| 2788 | | 2795 | |
| 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}); |
| 2792 | | 2799 | |
| 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; |
| 2799 | | 2806 | |
| 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 | }; |