| ... | @@ -198,49 +198,46 @@ pub fn writeStackTrace(stack_trace: *const builtin.StackTrace, out_stream: var, | ... | @@ -198,49 +198,46 @@ pub fn writeStackTrace(stack_trace: *const builtin.StackTrace, out_stream: var, |
| 198 | } | 198 | } |
| 199 | } | 199 | } |
| 200 | | 200 | |
| 201 | pub inline fn getReturnAddress(frame_count: usize) usize { | 201 | pub const StackIterator = struct { |
| 202 | var fp = @ptrToInt(@frameAddress()); | 202 | first_addr: ?usize, |
| 203 | var i: usize = 0; | 203 | debug_info: *DebugInfo, |
| 204 | while (fp != 0 and i < frame_count) { | 204 | fp: usize, |
| 205 | fp = @intToPtr(*const usize, fp).*; | 205 | |
| 206 | i += 1; | 206 | pub fn init(debug_info: *DebugInfo, first_addr: ?usize) StackIterator { |
| | 207 | return StackIterator{ |
| | 208 | .debug_info = debug_info, |
| | 209 | .first_addr = first_addr, |
| | 210 | .fp = @ptrToInt(@frameAddress()), |
| | 211 | }; |
| 207 | } | 212 | } |
| 208 | return @intToPtr(*const usize, fp + @sizeOf(usize)).*; | 213 | |
| 209 | } | 214 | fn next(self: *StackIterator) ?usize { |
| | 215 | if (self.fp == 0) return null; |
| | 216 | self.fp = @intToPtr(*const usize, self.fp).*; |
| | 217 | if (self.fp == 0) return null; |
| | 218 | |
| | 219 | if (self.first_addr) |addr| { |
| | 220 | while (self.fp != 0) : (self.fp = @intToPtr(*const usize, self.fp).*) { |
| | 221 | const return_address = @intToPtr(*const usize, self.fp + @sizeOf(usize)).*; |
| | 222 | if (addr == return_address) { |
| | 223 | self.first_addr = null; |
| | 224 | return return_address; |
| | 225 | } |
| | 226 | } |
| | 227 | } |
| | 228 | |
| | 229 | const return_address = @intToPtr(*const usize, self.fp + @sizeOf(usize)).*; |
| | 230 | return return_address; |
| | 231 | } |
| | 232 | }; |
| 210 | | 233 | |
| 211 | pub fn writeCurrentStackTrace(out_stream: var, debug_info: *DebugInfo, tty_color: bool, start_addr: ?usize) !void { | 234 | pub fn writeCurrentStackTrace(out_stream: var, debug_info: *DebugInfo, tty_color: bool, start_addr: ?usize) !void { |
| 212 | switch (builtin.os) { | 235 | switch (builtin.os) { |
| 213 | builtin.Os.windows => return writeCurrentStackTraceWindows(out_stream, debug_info, tty_color, start_addr), | 236 | builtin.Os.windows => return writeCurrentStackTraceWindows(out_stream, debug_info, tty_color, start_addr), |
| 214 | else => {}, | 237 | else => {}, |
| 215 | } | 238 | } |
| 216 | const AddressState = union(enum) { | 239 | var it = StackIterator.init(debug_info, start_addr); |
| 217 | NotLookingForStartAddress, | 240 | while (it.next()) |return_address| { |
| 218 | LookingForStartAddress: usize, | | |
| 219 | }; | | |
| 220 | // TODO: I want to express like this: | | |
| 221 | //var addr_state = if (start_addr) |addr| AddressState { .LookingForStartAddress = addr } | | |
| 222 | // else AddressState.NotLookingForStartAddress; | | |
| 223 | var addr_state: AddressState = undefined; | | |
| 224 | if (start_addr) |addr| { | | |
| 225 | addr_state = AddressState{ .LookingForStartAddress = addr }; | | |
| 226 | } else { | | |
| 227 | addr_state = AddressState.NotLookingForStartAddress; | | |
| 228 | } | | |
| 229 | | | |
| 230 | var fp = @ptrToInt(@frameAddress()); | | |
| 231 | while (fp != 0) : (fp = @intToPtr(*const usize, fp).*) { | | |
| 232 | const return_address = @intToPtr(*const usize, fp + @sizeOf(usize)).*; | | |
| 233 | | | |
| 234 | switch (addr_state) { | | |
| 235 | AddressState.NotLookingForStartAddress => {}, | | |
| 236 | AddressState.LookingForStartAddress => |addr| { | | |
| 237 | if (return_address == addr) { | | |
| 238 | addr_state = AddressState.NotLookingForStartAddress; | | |
| 239 | } else { | | |
| 240 | continue; | | |
| 241 | } | | |
| 242 | }, | | |
| 243 | } | | |
| 244 | try printSourceAtAddress(debug_info, out_stream, return_address, tty_color); | 241 | try printSourceAtAddress(debug_info, out_stream, return_address, tty_color); |
| 245 | } | 242 | } |
| 246 | } | 243 | } |