Changes in kernel/arch/mips32/src/debugger.c [96b02eb9:e16e0d59] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/mips32/src/debugger.c
r96b02eb9 re16e0d59 46 46 47 47 bpinfo_t breakpoints[BKPOINTS_MAX]; 48 IRQ_SPINLOCK_STATIC_INITIALIZE(bkpoint_lock);48 SPINLOCK_INITIALIZE(bkpoint_lock); 49 49 50 50 #ifdef CONFIG_KCONSOLE 51 51 52 static int cmd_print_breakpoints(cmd_arg_t *); 53 static int cmd_del_breakpoint(cmd_arg_t *); 54 static int cmd_add_breakpoint(cmd_arg_t *); 55 52 static int cmd_print_breakpoints(cmd_arg_t *argv); 56 53 static cmd_info_t bkpts_info = { 57 54 .name = "bkpts", … … 61 58 }; 62 59 60 static int cmd_del_breakpoint(cmd_arg_t *argv); 63 61 static cmd_arg_t del_argv = { 64 62 .type = ARG_TYPE_INT 65 63 }; 66 67 64 static cmd_info_t delbkpt_info = { 68 65 .name = "delbkpt", 69 .description = " Delete breakpoint.",66 .description = "delbkpt <number> - Delete breakpoint.", 70 67 .func = cmd_del_breakpoint, 71 68 .argc = 1, … … 73 70 }; 74 71 72 static int cmd_add_breakpoint(cmd_arg_t *argv); 75 73 static cmd_arg_t add_argv = { 76 74 .type = ARG_TYPE_INT 77 75 }; 78 79 76 static cmd_info_t addbkpt_info = { 80 77 .name = "addbkpt", 81 .description = "Add bkpoint (break on J/Branch insts unsupported).", 78 .description = "addbkpt <&symbol> - new bkpoint. Break on J/Branch " 79 "insts unsupported.", 82 80 .func = cmd_add_breakpoint, 83 81 .argc = 1, … … 91 89 static cmd_info_t addbkpte_info = { 92 90 .name = "addbkpte", 93 .description = "Add bkpoint with a trigger function.", 91 .description = "addebkpte <&symbol> <&func> - new bkpoint. Call " 92 "func(or Nothing if 0).", 94 93 .func = cmd_add_breakpoint, 95 94 .argc = 2, … … 101 100 uint32_t value; 102 101 } jmpinstr[] = { 103 {0xf3ff0000, 0x41000000}, /* BCzF */ 104 {0xf3ff0000, 0x41020000}, /* BCzFL */ 105 {0xf3ff0000, 0x41010000}, /* BCzT */ 106 {0xf3ff0000, 0x41030000}, /* BCzTL */ 107 {0xfc000000, 0x10000000}, /* BEQ */ 108 {0xfc000000, 0x50000000}, /* BEQL */ 109 {0xfc1f0000, 0x04010000}, /* BEQL */ 110 {0xfc1f0000, 0x04110000}, /* BGEZAL */ 111 {0xfc1f0000, 0x04130000}, /* BGEZALL */ 112 {0xfc1f0000, 0x04030000}, /* BGEZL */ 113 {0xfc1f0000, 0x1c000000}, /* BGTZ */ 114 {0xfc1f0000, 0x5c000000}, /* BGTZL */ 115 {0xfc1f0000, 0x18000000}, /* BLEZ */ 116 {0xfc1f0000, 0x58000000}, /* BLEZL */ 117 {0xfc1f0000, 0x04000000}, /* BLTZ */ 118 {0xfc1f0000, 0x04100000}, /* BLTZAL */ 119 {0xfc1f0000, 0x04120000}, /* BLTZALL */ 120 {0xfc1f0000, 0x04020000}, /* BLTZL */ 121 {0xfc000000, 0x14000000}, /* BNE */ 122 {0xfc000000, 0x54000000}, /* BNEL */ 123 {0xfc000000, 0x08000000}, /* J */ 124 {0xfc000000, 0x0c000000}, /* JAL */ 125 {0xfc1f07ff, 0x00000009}, /* JALR */ 126 {0, 0} /* end of table */ 127 }; 102 {0xf3ff0000, 0x41000000}, /* BCzF */ 103 {0xf3ff0000, 0x41020000}, /* BCzFL */ 104 {0xf3ff0000, 0x41010000}, /* BCzT */ 105 {0xf3ff0000, 0x41030000}, /* BCzTL */ 106 {0xfc000000, 0x10000000}, /* BEQ */ 107 {0xfc000000, 0x50000000}, /* BEQL */ 108 {0xfc1f0000, 0x04010000}, /* BEQL */ 109 {0xfc1f0000, 0x04110000}, /* BGEZAL */ 110 {0xfc1f0000, 0x04130000}, /* BGEZALL */ 111 {0xfc1f0000, 0x04030000}, /* BGEZL */ 112 {0xfc1f0000, 0x1c000000}, /* BGTZ */ 113 {0xfc1f0000, 0x5c000000}, /* BGTZL */ 114 {0xfc1f0000, 0x18000000}, /* BLEZ */ 115 {0xfc1f0000, 0x58000000}, /* BLEZL */ 116 {0xfc1f0000, 0x04000000}, /* BLTZ */ 117 {0xfc1f0000, 0x04100000}, /* BLTZAL */ 118 {0xfc1f0000, 0x04120000}, /* BLTZALL */ 119 {0xfc1f0000, 0x04020000}, /* BLTZL */ 120 {0xfc000000, 0x14000000}, /* BNE */ 121 {0xfc000000, 0x54000000}, /* BNEL */ 122 {0xfc000000, 0x08000000}, /* J */ 123 {0xfc000000, 0x0c000000}, /* JAL */ 124 {0xfc1f07ff, 0x00000009}, /* JALR */ 125 {0, 0} /* EndOfTable */ 126 }; 127 128 128 129 129 /** Test, if the given instruction is a jump or branch instruction 130 130 * 131 131 * @param instr Instruction code 132 * 133 * @return true if it is jump instruction, false otherwise 134 * 135 */ 136 bool is_jump(sysarg_t instr) 137 { 138 unsigned int i; 139 132 * @return true - it is jump instruction, false otherwise 133 * 134 */ 135 static bool is_jump(unative_t instr) 136 { 137 int i; 138 140 139 for (i = 0; jmpinstr[i].andmask; i++) { 141 140 if ((instr & jmpinstr[i].andmask) == jmpinstr[i].value) 142 141 return true; 143 142 } 144 143 145 144 return false; 146 145 } 147 146 148 /** Add new breakpoint to table 149 * 150 */ 147 /** Add new breakpoint to table */ 151 148 int cmd_add_breakpoint(cmd_arg_t *argv) 152 149 { 150 bpinfo_t *cur = NULL; 151 ipl_t ipl; 152 int i; 153 153 154 if (argv->intval & 0x3) { 154 155 printf("Not aligned instruction, forgot to use &symbol?\n"); 155 156 return 1; 156 157 } 157 158 irq_spinlock_lock(&bkpoint_lock, true);159 158 ipl = interrupts_disable(); 159 spinlock_lock(&bkpoint_lock); 160 160 161 /* Check, that the breakpoints do not conflict */ 161 unsigned int i;162 162 for (i = 0; i < BKPOINTS_MAX; i++) { 163 if (breakpoints[i].address == (uintptr_t) 163 if (breakpoints[i].address == (uintptr_t)argv->intval) { 164 164 printf("Duplicate breakpoint %d.\n", i); 165 irq_spinlock_unlock(&bkpoint_lock, true);165 spinlock_unlock(&bkpoint_lock); 166 166 return 0; 167 } else if ( (breakpoints[i].address == (uintptr_t)argv->intval +168 sizeof( sysarg_t)) || (breakpoints[i].address ==169 (uintptr_t) argv->intval - sizeof(sysarg_t))) {167 } else if (breakpoints[i].address == (uintptr_t)argv->intval + 168 sizeof(unative_t) || breakpoints[i].address == 169 (uintptr_t)argv->intval - sizeof(unative_t)) { 170 170 printf("Adjacent breakpoints not supported, conflict " 171 171 "with %d.\n", i); 172 irq_spinlock_unlock(&bkpoint_lock, true);172 spinlock_unlock(&bkpoint_lock); 173 173 return 0; 174 174 } 175 175 176 176 } 177 178 bpinfo_t *cur = NULL; 179 180 for (i = 0; i < BKPOINTS_MAX; i++) { 177 178 for (i = 0; i < BKPOINTS_MAX; i++) 181 179 if (!breakpoints[i].address) { 182 180 cur = &breakpoints[i]; 183 181 break; 184 182 } 185 }186 187 183 if (!cur) { 188 184 printf("Too many breakpoints.\n"); 189 irq_spinlock_unlock(&bkpoint_lock, true); 185 spinlock_unlock(&bkpoint_lock); 186 interrupts_restore(ipl); 190 187 return 0; 191 188 } 192 193 printf("Adding breakpoint on address %p\n", (void *) argv->intval);194 195 189 cur->address = (uintptr_t) argv->intval; 196 cur->instruction = ((sysarg_t *) cur->address)[0]; 197 cur->nextinstruction = ((sysarg_t *) cur->address)[1]; 190 printf("Adding breakpoint on address: %p\n", argv->intval); 191 cur->instruction = ((unative_t *)cur->address)[0]; 192 cur->nextinstruction = ((unative_t *)cur->address)[1]; 198 193 if (argv == &add_argv) { 199 194 cur->flags = 0; 200 } else { 195 } else { /* We are add extended */ 201 196 cur->flags = BKPOINT_FUNCCALL; 202 197 cur->bkfunc = (void (*)(void *, istate_t *)) argv[1].intval; 203 198 } 204 205 199 if (is_jump(cur->instruction)) 206 200 cur->flags |= BKPOINT_ONESHOT; 207 208 201 cur->counter = 0; 209 202 210 203 /* Set breakpoint */ 211 *(( sysarg_t *)cur->address) = 0x0d;204 *((unative_t *)cur->address) = 0x0d; 212 205 smc_coherence(cur->address); 213 214 irq_spinlock_unlock(&bkpoint_lock, true); 215 206 207 spinlock_unlock(&bkpoint_lock); 208 interrupts_restore(ipl); 209 216 210 return 1; 217 211 } 218 212 219 /** Remove breakpoint from table 220 * 221 */ 213 /** Remove breakpoint from table */ 222 214 int cmd_del_breakpoint(cmd_arg_t *argv) 223 215 { 216 bpinfo_t *cur; 217 ipl_t ipl; 218 224 219 if (argv->intval > BKPOINTS_MAX) { 225 220 printf("Invalid breakpoint number.\n"); 226 221 return 0; 227 222 } 228 229 irq_spinlock_lock(&bkpoint_lock, true);230 231 bpinfo_t *cur = &breakpoints[argv->intval];223 ipl = interrupts_disable(); 224 spinlock_lock(&bkpoint_lock); 225 226 cur = &breakpoints[argv->intval]; 232 227 if (!cur->address) { 233 228 printf("Breakpoint does not exist.\n"); 234 irq_spinlock_unlock(&bkpoint_lock, true); 229 spinlock_unlock(&bkpoint_lock); 230 interrupts_restore(ipl); 235 231 return 0; 236 232 } 237 238 233 if ((cur->flags & BKPOINT_INPROG) && (cur->flags & BKPOINT_ONESHOT)) { 239 234 printf("Cannot remove one-shot breakpoint in-progress\n"); 240 irq_spinlock_unlock(&bkpoint_lock, true); 235 spinlock_unlock(&bkpoint_lock); 236 interrupts_restore(ipl); 241 237 return 0; 242 238 } 239 ((uint32_t *)cur->address)[0] = cur->instruction; 240 smc_coherence(((uint32_t *)cur->address)[0]); 241 ((uint32_t *)cur->address)[1] = cur->nextinstruction; 242 smc_coherence(((uint32_t *)cur->address)[1]); 243 244 cur->address = NULL; 245 246 spinlock_unlock(&bkpoint_lock); 247 interrupts_restore(ipl); 248 return 1; 249 } 250 251 /** Print table of active breakpoints */ 252 int cmd_print_breakpoints(cmd_arg_t *argv) 253 { 254 unsigned int i; 255 char *symbol; 243 256 244 ((uint32_t *) cur->address)[0] = cur->instruction; 245 smc_coherence(((uint32_t *) cur->address)[0]); 246 ((uint32_t *) cur->address)[1] = cur->nextinstruction; 247 smc_coherence(((uint32_t *) cur->address)[1]); 257 printf("# Count Address INPROG ONESHOT FUNCCALL In symbol\n"); 258 printf("-- ----- ---------- ------ ------- -------- ---------\n"); 248 259 249 cur->address = (uintptr_t) NULL; 250 251 irq_spinlock_unlock(&bkpoint_lock, true); 252 return 1; 253 } 254 255 /** Print table of active breakpoints 256 * 257 */ 258 int cmd_print_breakpoints(cmd_arg_t *argv) 259 { 260 unsigned int i; 261 262 printf("[nr] [count] [address ] [inprog] [oneshot] [funccall] [in symbol\n"); 263 264 for (i = 0; i < BKPOINTS_MAX; i++) { 260 for (i = 0; i < BKPOINTS_MAX; i++) 265 261 if (breakpoints[i].address) { 266 const char *symbol = symtab_fmt_name_lookup(262 symbol = symtab_fmt_name_lookup( 267 263 breakpoints[i].address); 268 269 printf("%- 4u %7zu %p %-8s %-9s %-10s %s\n", i,270 breakpoints[i].counter, (void *)breakpoints[i].address,264 265 printf("%-2u %-5d %#10zx %-6s %-7s %-8s %s\n", i, 266 breakpoints[i].counter, breakpoints[i].address, 271 267 ((breakpoints[i].flags & BKPOINT_INPROG) ? "true" : 272 268 "false"), ((breakpoints[i].flags & BKPOINT_ONESHOT) … … 274 270 BKPOINT_FUNCCALL) ? "true" : "false"), symbol); 275 271 } 276 }277 278 272 return 1; 279 273 } 280 274 281 #endif /* CONFIG_KCONSOLE */ 282 283 /** Initialize debugger 284 * 285 */ 275 #endif 276 277 /** Initialize debugger */ 286 278 void debugger_init() 287 279 { 288 unsignedint i;289 280 int i; 281 290 282 for (i = 0; i < BKPOINTS_MAX; i++) 291 breakpoints[i].address = (uintptr_t)NULL;292 283 breakpoints[i].address = NULL; 284 293 285 #ifdef CONFIG_KCONSOLE 294 286 cmd_initialize(&bkpts_info); 295 287 if (!cmd_register(&bkpts_info)) 296 288 printf("Cannot register command %s\n", bkpts_info.name); 297 289 298 290 cmd_initialize(&delbkpt_info); 299 291 if (!cmd_register(&delbkpt_info)) 300 292 printf("Cannot register command %s\n", delbkpt_info.name); 301 293 302 294 cmd_initialize(&addbkpt_info); 303 295 if (!cmd_register(&addbkpt_info)) 304 296 printf("Cannot register command %s\n", addbkpt_info.name); 305 297 306 298 cmd_initialize(&addbkpte_info); 307 299 if (!cmd_register(&addbkpte_info)) 308 300 printf("Cannot register command %s\n", addbkpte_info.name); 309 #endif /* CONFIG_KCONSOLE */301 #endif 310 302 } 311 303 312 304 /** Handle breakpoint 313 305 * 314 * Find breakpoint in breakpoint table. 306 * Find breakpoint in breakpoint table. 315 307 * If found, call kconsole, set break on next instruction and reexecute. 316 308 * If we are on "next instruction", set it back on the first and reexecute. 317 309 * If breakpoint not found in breakpoint table, call kconsole and start 318 310 * next instruction. 319 *320 311 */ 321 312 void debugger_bpoint(istate_t *istate) 322 313 { 314 bpinfo_t *cur = NULL; 315 uintptr_t fireaddr = istate->epc; 316 int i; 317 323 318 /* test branch delay slot */ 324 319 if (cp0_cause_read() & 0x80000000) 325 320 panic("Breakpoint in branch delay slot not supported."); 326 327 irq_spinlock_lock(&bkpoint_lock, false); 328 329 bpinfo_t *cur = NULL; 330 uintptr_t fireaddr = istate->epc; 331 unsigned int i; 332 321 322 spinlock_lock(&bkpoint_lock); 333 323 for (i = 0; i < BKPOINTS_MAX; i++) { 334 324 /* Normal breakpoint */ 335 if ( (fireaddr == breakpoints[i].address)&&336 (!(breakpoints[i].flags & BKPOINT_REINST))) {325 if (fireaddr == breakpoints[i].address && 326 !(breakpoints[i].flags & BKPOINT_REINST)) { 337 327 cur = &breakpoints[i]; 338 328 break; 339 329 } 340 341 330 /* Reinst only breakpoint */ 342 331 if ((breakpoints[i].flags & BKPOINT_REINST) && 343 (fireaddr == breakpoints[i].address + sizeof( sysarg_t))) {332 (fireaddr == breakpoints[i].address + sizeof(unative_t))) { 344 333 cur = &breakpoints[i]; 345 334 break; 346 335 } 347 336 } 348 349 337 if (cur) { 350 338 if (cur->flags & BKPOINT_REINST) { 351 339 /* Set breakpoint on first instruction */ 352 ((uint32_t *) 340 ((uint32_t *)cur->address)[0] = 0x0d; 353 341 smc_coherence(((uint32_t *)cur->address)[0]); 354 355 342 /* Return back the second */ 356 ((uint32_t *) cur->address)[1] = cur->nextinstruction; 357 smc_coherence(((uint32_t *) cur->address)[1]); 358 343 ((uint32_t *)cur->address)[1] = cur->nextinstruction; 344 smc_coherence(((uint32_t *)cur->address)[1]); 359 345 cur->flags &= ~BKPOINT_REINST; 360 irq_spinlock_unlock(&bkpoint_lock, false);346 spinlock_unlock(&bkpoint_lock); 361 347 return; 362 } 363 348 } 364 349 if (cur->flags & BKPOINT_INPROG) 365 350 printf("Warning: breakpoint recursion\n"); 366 351 367 352 if (!(cur->flags & BKPOINT_FUNCCALL)) { 368 printf("***Breakpoint %u: %p in %s.\n", i, 369 (void *) fireaddr, 370 symtab_fmt_name_lookup(fireaddr)); 371 } 372 353 printf("***Breakpoint %d: %p in %s.\n", i, fireaddr, 354 symtab_fmt_name_lookup(istate->epc)); 355 } 356 373 357 /* Return first instruction back */ 374 358 ((uint32_t *)cur->address)[0] = cur->instruction; … … 382 366 cur->flags |= BKPOINT_INPROG; 383 367 } else { 384 printf("***Breakpoint %d: %p in %s.\n", i, 385 (void *) fireaddr, 368 printf("***Breakpoint %d: %p in %s.\n", i, fireaddr, 386 369 symtab_fmt_name_lookup(fireaddr)); 387 370 388 371 /* Move on to next instruction */ 389 372 istate->epc += 4; 390 373 } 391 392 374 if (cur) 393 375 cur->counter++; 394 395 376 if (cur && (cur->flags & BKPOINT_FUNCCALL)) { 396 377 /* Allow zero bkfunc, just for counting */ … … 399 380 } else { 400 381 #ifdef CONFIG_KCONSOLE 401 /* 402 * This disables all other processors - we are not SMP, 382 /* This disables all other processors - we are not SMP, 403 383 * actually this gets us to cpu_halt, if scheduler() is run 404 384 * - we generally do not want scheduler to be run from debug, 405 385 * so this is a good idea 406 */ 386 */ 407 387 atomic_set(&haltstate, 1); 408 irq_spinlock_unlock(&bkpoint_lock, false);388 spinlock_unlock(&bkpoint_lock); 409 389 410 390 kconsole("debug", "Debug console ready.\n", false); 411 391 412 irq_spinlock_lock(&bkpoint_lock, false);392 spinlock_lock(&bkpoint_lock); 413 393 atomic_set(&haltstate, 0); 414 394 #endif 415 395 } 416 417 if ((cur) && (cur->address == fireaddr) 418 && ((cur->flags & BKPOINT_INPROG))) { 396 if (cur && cur->address == fireaddr && (cur->flags & BKPOINT_INPROG)) { 419 397 /* Remove one-shot breakpoint */ 420 398 if ((cur->flags & BKPOINT_ONESHOT)) 421 cur->address = (uintptr_t) NULL; 422 399 cur->address = NULL; 423 400 /* Remove in-progress flag */ 424 401 cur->flags &= ~BKPOINT_INPROG; 425 } 426 427 irq_spinlock_unlock(&bkpoint_lock, false); 402 } 403 spinlock_unlock(&bkpoint_lock); 428 404 } 429 405
Note:
See TracChangeset
for help on using the changeset viewer.