| ... | ... | @@ -9,6 +9,7 @@ const macho = std.macho; |
| 9 | 9 | const ArrayList = std.ArrayList; |
| 10 | 10 | const builtin = @import("builtin"); |
| 11 | 11 | |
| 12 | pub var stack_trace_start_address: ?usize = null; |
| 12 | 13 | pub const FailingAllocator = @import("failing_allocator.zig").FailingAllocator; |
| 13 | 14 | |
| 14 | 15 | /// Tries to write to stderr, unbuffered, and ignores any error returned. |
| ... | ... | @@ -51,8 +52,7 @@ pub fn dumpCurrentStackTrace() void { |
| 51 | 52 | stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", @errorName(err)) catch return; |
| 52 | 53 | return; |
| 53 | 54 | }; |
| 54 | | defer debug_info.close(); |
| 55 | | writeCurrentStackTrace(stderr, global_allocator, debug_info, stderr_file.isTty(), 1) catch |err| { |
| 55 | writeCurrentStackTrace(stderr, global_allocator, debug_info, stderr_file.isTty()) catch |err| { |
| 56 | 56 | stderr.print("Unable to dump stack trace: {}\n", @errorName(err)) catch return; |
| 57 | 57 | return; |
| 58 | 58 | }; |
| ... | ... | @@ -65,7 +65,6 @@ pub fn dumpStackTrace(stack_trace: &const builtin.StackTrace) void { |
| 65 | 65 | stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", @errorName(err)) catch return; |
| 66 | 66 | return; |
| 67 | 67 | }; |
| 68 | | defer debug_info.close(); |
| 69 | 68 | writeStackTrace(stack_trace, stderr, global_allocator, debug_info, stderr_file.isTty()) catch |err| { |
| 70 | 69 | stderr.print("Unable to dump stack trace: {}\n", @errorName(err)) catch return; |
| 71 | 70 | return; |
| ... | ... | @@ -162,18 +161,38 @@ pub fn writeStackTrace(stack_trace: &const builtin.StackTrace, out_stream: var, |
| 162 | 161 | } |
| 163 | 162 | |
| 164 | 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 | 181 | var fp = @ptrToInt(@frameAddress()); |
| 170 | 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 | 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 | 196 | try printSourceAtAddress(debug_info, out_stream, return_address); |
| 178 | 197 | } |
| 179 | 198 | } |