| ... | @@ -9,6 +9,7 @@ const macho = std.macho; | ... | @@ -9,6 +9,7 @@ const macho = std.macho; |
| 9 | const ArrayList = std.ArrayList; | 9 | const ArrayList = std.ArrayList; |
| 10 | const builtin = @import("builtin"); | 10 | const builtin = @import("builtin"); |
| 11 | | 11 | |
| | 12 | pub var stack_trace_start_address: ?usize = null; |
| 12 | pub const FailingAllocator = @import("failing_allocator.zig").FailingAllocator; | 13 | pub const FailingAllocator = @import("failing_allocator.zig").FailingAllocator; |
| 13 | | 14 | |
| 14 | /// Tries to write to stderr, unbuffered, and ignores any error returned. | 15 | /// Tries to write to stderr, unbuffered, and ignores any error returned. |
| ... | @@ -51,8 +52,7 @@ pub fn dumpCurrentStackTrace() void { | ... | @@ -51,8 +52,7 @@ pub fn dumpCurrentStackTrace() void { |
| 51 | stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", @errorName(err)) catch return; | 52 | stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", @errorName(err)) catch return; |
| 52 | return; | 53 | return; |
| 53 | }; | 54 | }; |
| 54 | defer debug_info.close(); | 55 | writeCurrentStackTrace(stderr, global_allocator, debug_info, stderr_file.isTty()) catch |err| { |
| 55 | writeCurrentStackTrace(stderr, global_allocator, debug_info, stderr_file.isTty(), 1) catch |err| { | | |
| 56 | stderr.print("Unable to dump stack trace: {}\n", @errorName(err)) catch return; | 56 | stderr.print("Unable to dump stack trace: {}\n", @errorName(err)) catch return; |
| 57 | return; | 57 | return; |
| 58 | }; | 58 | }; |
| ... | @@ -65,7 +65,6 @@ pub fn dumpStackTrace(stack_trace: &const builtin.StackTrace) void { | ... | @@ -65,7 +65,6 @@ pub fn dumpStackTrace(stack_trace: &const builtin.StackTrace) void { |
| 65 | stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", @errorName(err)) catch return; | 65 | stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", @errorName(err)) catch return; |
| 66 | return; | 66 | return; |
| 67 | }; | 67 | }; |
| 68 | defer debug_info.close(); | | |
| 69 | writeStackTrace(stack_trace, stderr, global_allocator, debug_info, stderr_file.isTty()) catch |err| { | 68 | writeStackTrace(stack_trace, stderr, global_allocator, debug_info, stderr_file.isTty()) catch |err| { |
| 70 | stderr.print("Unable to dump stack trace: {}\n", @errorName(err)) catch return; | 69 | stderr.print("Unable to dump stack trace: {}\n", @errorName(err)) catch return; |
| 71 | return; | 70 | return; |
| ... | @@ -162,18 +161,38 @@ pub fn writeStackTrace(stack_trace: &const builtin.StackTrace, out_stream: var, | ... | @@ -162,18 +161,38 @@ pub fn writeStackTrace(stack_trace: &const builtin.StackTrace, out_stream: var, |
| 162 | } | 161 | } |
| 163 | | 162 | |
| 164 | pub fn writeCurrentStackTrace(out_stream: var, allocator: &mem.Allocator, | 163 | pub fn writeCurrentStackTrace(out_stream: var, allocator: &mem.Allocator, |
| 165 | debug_info: &ElfStackTrace, tty_color: bool, ignore_frame_count: usize) !void | 164 | debug_info: &ElfStackTrace, tty_color: bool) !void |
| 166 | { | 165 | { |
| 167 | var ignored_count: usize = 0; | 166 | const AddressState = union(enum) { |
| | 167 | NotLookingForStartAddress, |
| | 168 | LookingForStartAddress: usize, |
| | 169 | FoundStartAddress, |
| | 170 | }; |
| | 171 | // TODO: I want to express like this: |
| | 172 | //var addr_state = if (stack_trace_start_address) |addr| AddressState { .LookingForStartAddress = addr } |
| | 173 | // else AddressState.NotLookingForStartAddress; |
| | 174 | var addr_state: AddressState = undefined; |
| | 175 | if (stack_trace_start_address) |addr| { |
| | 176 | addr_state = AddressState { .LookingForStartAddress = addr }; |
| | 177 | } else { |
| | 178 | addr_state = AddressState.NotLookingForStartAddress; |
| | 179 | } |
| 168 | | 180 | |
| 169 | var fp = @ptrToInt(@frameAddress()); | 181 | var fp = @ptrToInt(@frameAddress()); |
| 170 | while (fp != 0) : (fp = *@intToPtr(&const usize, fp)) { | 182 | while (fp != 0) : (fp = *@intToPtr(&const usize, fp)) { |
| 171 | if (ignored_count < ignore_frame_count) { | | |
| 172 | ignored_count += 1; | | |
| 173 | continue; | | |
| 174 | } | | |
| 175 | | | |
| 176 | const return_address = *@intToPtr(&const usize, fp + @sizeOf(usize)); | 183 | const return_address = *@intToPtr(&const usize, fp + @sizeOf(usize)); |
| | 184 | |
| | 185 | switch (addr_state) { |
| | 186 | AddressState.NotLookingForStartAddress => continue, |
| | 187 | AddressState.LookingForStartAddress => |addr| { |
| | 188 | if (return_address == addr) { |
| | 189 | addr_state = AddressState.FoundStartAddress; |
| | 190 | } else { |
| | 191 | continue; |
| | 192 | } |
| | 193 | }, |
| | 194 | AddressState.FoundStartAddress => {}, |
| | 195 | } |
| 177 | try printSourceAtAddress(debug_info, out_stream, return_address); | 196 | try printSourceAtAddress(debug_info, out_stream, return_address); |
| 178 | } | 197 | } |
| 179 | } | 198 | } |