| ... | ... | @@ -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 { |
| 202 | | var fp = @ptrToInt(@frameAddress()); |
| 203 | | var i: usize = 0; |
| 204 | | while (fp != 0 and i < frame_count) { |
| 205 | | fp = @intToPtr(*const usize, fp).*; |
| 206 | | i += 1; |
| 201 | pub const StackIterator = struct { |
| 202 | first_addr: ?usize, |
| 203 | debug_info: *DebugInfo, |
| 204 | fp: usize, |
| 205 | |
| 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)).*; |
| 209 | | } |
| 213 | |
| 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 | 234 | pub fn writeCurrentStackTrace(out_stream: var, debug_info: *DebugInfo, tty_color: bool, start_addr: ?usize) !void { |
| 212 | 235 | switch (builtin.os) { |
| 213 | 236 | builtin.Os.windows => return writeCurrentStackTraceWindows(out_stream, debug_info, tty_color, start_addr), |
| 214 | 237 | else => {}, |
| 215 | 238 | } |
| 216 | | const AddressState = union(enum) { |
| 217 | | NotLookingForStartAddress, |
| 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 | | } |
| 239 | var it = StackIterator.init(debug_info, start_addr); |
| 240 | while (it.next()) |return_address| { |
| 244 | 241 | try printSourceAtAddress(debug_info, out_stream, return_address, tty_color); |
| 245 | 242 | } |
| 246 | 243 | } |