| 264 | } |
| 265 | |
| 266 | static int |
| 267 | db_backtrace(struct thread *td, struct trapframe *tf, struct amd64_frame *frame, |
| 268 | db_addr_t pc, register_t sp, int count) |
| 269 | { |
| 270 | struct amd64_frame *actframe; |
| 271 | const char *name; |
| 272 | db_expr_t offset; |
| 273 | c_db_sym_t sym; |
| 274 | boolean_t first; |
| 275 | |
| 276 | if (count == -1) |
| 277 | count = 1024; |
| 278 | |
| 279 | first = TRUE; |
| 280 | while (count-- && !db_pager_quit) { |
| 281 | sym = db_search_symbol(pc, DB_STGY_ANY, &offset); |
| 282 | db_symbol_values(sym, &name, NULL); |
| 283 | |
| 284 | /* |
| 285 | * Attempt to determine a (possibly fake) frame that gives |
| 286 | * the caller's pc. It may differ from `frame' if the |
| 287 | * current function never sets up a standard frame or hasn't |
| 288 | * set one up yet or has just discarded one. The last two |
| 289 | * cases can be guessed fairly reliably for code generated |
| 290 | * by gcc. The first case is too much trouble to handle in |
| 291 | * general because the amount of junk on the stack depends |
| 292 | * on the pc (the special handling of "calltrap", etc. in |
| 293 | * db_nextframe() works because the `next' pc is special). |
| 294 | */ |
| 295 | actframe = frame; |
| 296 | if (first) { |
| 297 | first = FALSE; |
| 298 | if (sym == C_DB_SYM_NULL && sp != 0) { |
| 299 | /* |
| 300 | * If a symbol couldn't be found, we've probably |
| 301 | * jumped to a bogus location, so try and use |
| 302 | * the return address to find our caller. |
| 303 | */ |
| 304 | db_print_stack_entry(name, pc, NULL); |
| 305 | pc = db_get_value(sp, 8, FALSE); |
| 306 | if (db_search_symbol(pc, DB_STGY_PROC, |
| 307 | &offset) == C_DB_SYM_NULL) |
| 308 | break; |
| 309 | continue; |
| 310 | } else if (tf != NULL) { |
| 311 | int instr; |
| 312 | |
| 313 | instr = db_get_value(pc, 4, FALSE); |
| 314 | if ((instr & 0xffffffff) == 0xe5894855) { |
| 315 | /* pushq %rbp; movq %rsp, %rbp */ |
| 316 | actframe = (void *)(tf->tf_rsp - 8); |
| 317 | } else if ((instr & 0xffffff) == 0xe58948) { |
| 318 | /* movq %rsp, %rbp */ |
| 319 | actframe = (void *)tf->tf_rsp; |
| 320 | if (tf->tf_rbp == 0) { |
| 321 | /* Fake frame better. */ |
| 322 | frame = actframe; |
| 323 | } |
no test coverage detected