| ... | @@ -246,10 +246,14 @@ pub fn dumpHexFallible(bytes: []const u8) !void { | ... | @@ -246,10 +246,14 @@ pub fn dumpHexFallible(bytes: []const u8) !void { |
| 246 | const stderr = std.io.getStdErr(); | 246 | const stderr = std.io.getStdErr(); |
| 247 | const ttyconf = std.io.tty.detectConfig(stderr); | 247 | const ttyconf = std.io.tty.detectConfig(stderr); |
| 248 | const writer = stderr.writer(); | 248 | const writer = stderr.writer(); |
| | 249 | try dumpHexInternal(bytes, ttyconf, writer); |
| | 250 | } |
| | 251 | |
| | 252 | fn dumpHexInternal(bytes: []const u8, ttyconf: std.io.tty.Config, writer: anytype) !void { |
| 249 | var chunks = mem.window(u8, bytes, 16, 16); | 253 | var chunks = mem.window(u8, bytes, 16, 16); |
| 250 | while (chunks.next()) |window| { | 254 | while (chunks.next()) |window| { |
| 251 | // 1. Print the address. | 255 | // 1. Print the address. |
| 252 | const address = (@intFromPtr(bytes.ptr) + 0x10 * (chunks.index orelse 0) / 16) - 0x10; | 256 | const address = (@intFromPtr(bytes.ptr) + 0x10 * (std.math.divCeil(usize, chunks.index orelse bytes.len, 16) catch unreachable)) - 0x10; |
| 253 | try ttyconf.setColor(writer, .dim); | 257 | try ttyconf.setColor(writer, .dim); |
| 254 | // We print the address in lowercase and the bytes in uppercase hexadecimal to distinguish them more. | 258 | // We print the address in lowercase and the bytes in uppercase hexadecimal to distinguish them more. |
| 255 | // Also, make sure all lines are aligned by padding the address. | 259 | // Also, make sure all lines are aligned by padding the address. |
| ... | @@ -294,6 +298,24 @@ pub fn dumpHexFallible(bytes: []const u8) !void { | ... | @@ -294,6 +298,24 @@ pub fn dumpHexFallible(bytes: []const u8) !void { |
| 294 | } | 298 | } |
| 295 | } | 299 | } |
| 296 | | 300 | |
| | 301 | test dumpHexInternal { |
| | 302 | const bytes: []const u8 = &.{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x01, 0x12, 0x13 }; |
| | 303 | var output = std.ArrayList(u8).init(std.testing.allocator); |
| | 304 | defer output.deinit(); |
| | 305 | try dumpHexInternal(bytes, .no_color, output.writer()); |
| | 306 | const expected = try std.fmt.allocPrint(std.testing.allocator, |
| | 307 | \\{x:0>[2]} 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF .."3DUfw........ |
| | 308 | \\{x:0>[2]} 01 12 13 ... |
| | 309 | \\ |
| | 310 | , .{ |
| | 311 | @intFromPtr(bytes.ptr), |
| | 312 | @intFromPtr(bytes.ptr) + 16, |
| | 313 | @sizeOf(usize) * 2, |
| | 314 | }); |
| | 315 | defer std.testing.allocator.free(expected); |
| | 316 | try std.testing.expectEqualStrings(expected, output.items); |
| | 317 | } |
| | 318 | |
| 297 | /// Tries to print the current stack trace to stderr, unbuffered, and ignores any error returned. | 319 | /// Tries to print the current stack trace to stderr, unbuffered, and ignores any error returned. |
| 298 | /// TODO multithreaded awareness | 320 | /// TODO multithreaded awareness |
| 299 | pub fn dumpCurrentStackTrace(start_addr: ?usize) void { | 321 | pub fn dumpCurrentStackTrace(start_addr: ?usize) void { |