Changes in kernel/arch/mips32/src/debugger.c [da1bafb:556f9892] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/mips32/src/debugger.c
rda1bafb r556f9892 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 132 * @return true - it is jump instruction, false otherwise 134 133 * 135 134 */ 136 135 static bool is_jump(unative_t instr) 137 136 { 138 unsignedint i;139 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 interrupts_restore(ipl); 166 167 return 0; 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))) {168 } else if (breakpoints[i].address == (uintptr_t)argv->intval + 169 sizeof(unative_t) || breakpoints[i].address == 170 (uintptr_t)argv->intval - sizeof(unative_t)) { 170 171 printf("Adjacent breakpoints not supported, conflict " 171 172 "with %d.\n", i); 172 irq_spinlock_unlock(&bkpoint_lock, true); 173 spinlock_unlock(&bkpoint_lock); 174 interrupts_restore(ipl); 173 175 return 0; 174 176 } 175 177 176 178 } 177 178 bpinfo_t *cur = NULL; 179 180 for (i = 0; i < BKPOINTS_MAX; i++) { 179 180 for (i = 0; i < BKPOINTS_MAX; i++) 181 181 if (!breakpoints[i].address) { 182 182 cur = &breakpoints[i]; 183 183 break; 184 184 } 185 }186 187 185 if (!cur) { 188 186 printf("Too many breakpoints.\n"); 189 irq_spinlock_unlock(&bkpoint_lock, true); 187 spinlock_unlock(&bkpoint_lock); 188 interrupts_restore(ipl); 190 189 return 0; 191 190 } 192 193 printf("Adding breakpoint on address %p\n", argv->intval);194 195 191 cur->address = (uintptr_t) argv->intval; 196 cur->instruction = ((unative_t *) cur->address)[0]; 197 cur->nextinstruction = ((unative_t *) cur->address)[1]; 192 printf("Adding breakpoint on address: %p\n", argv->intval); 193 cur->instruction = ((unative_t *)cur->address)[0]; 194 cur->nextinstruction = ((unative_t *)cur->address)[1]; 198 195 if (argv == &add_argv) { 199 196 cur->flags = 0; 200 } else { 197 } else { /* We are add extended */ 201 198 cur->flags = BKPOINT_FUNCCALL; 202 199 cur->bkfunc = (void (*)(void *, istate_t *)) argv[1].intval; 203 200 } 204 205 201 if (is_jump(cur->instruction)) 206 202 cur->flags |= BKPOINT_ONESHOT; 207 208 203 cur->counter = 0; 209 204 210 205 /* Set breakpoint */ 211 *((unative_t *) 206 *((unative_t *)cur->address) = 0x0d; 212 207 smc_coherence(cur->address); 213 214 irq_spinlock_unlock(&bkpoint_lock, true); 215 208 209 spinlock_unlock(&bkpoint_lock); 210 interrupts_restore(ipl); 211 216 212 return 1; 217 213 } 218 214 219 /** Remove breakpoint from table 220 * 221 */ 215 /** Remove breakpoint from table */ 222 216 int cmd_del_breakpoint(cmd_arg_t *argv) 223 217 { 218 bpinfo_t *cur; 219 ipl_t ipl; 220 224 221 if (argv->intval > BKPOINTS_MAX) { 225 222 printf("Invalid breakpoint number.\n"); 226 223 return 0; 227 224 } 228 229 irq_spinlock_lock(&bkpoint_lock, true);230 231 bpinfo_t *cur = &breakpoints[argv->intval];225 ipl = interrupts_disable(); 226 spinlock_lock(&bkpoint_lock); 227 228 cur = &breakpoints[argv->intval]; 232 229 if (!cur->address) { 233 230 printf("Breakpoint does not exist.\n"); 234 irq_spinlock_unlock(&bkpoint_lock, true); 231 spinlock_unlock(&bkpoint_lock); 232 interrupts_restore(ipl); 235 233 return 0; 236 234 } 237 238 235 if ((cur->flags & BKPOINT_INPROG) && (cur->flags & BKPOINT_ONESHOT)) { 239 236 printf("Cannot remove one-shot breakpoint in-progress\n"); 240 irq_spinlock_unlock(&bkpoint_lock, true); 237 spinlock_unlock(&bkpoint_lock); 238 interrupts_restore(ipl); 241 239 return 0; 242 240 } 243 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]); 248 241 ((uint32_t *)cur->address)[0] = cur->instruction; 242 smc_coherence(((uint32_t *)cur->address)[0]); 243 ((uint32_t *)cur->address)[1] = cur->nextinstruction; 244 smc_coherence(((uint32_t *)cur->address)[1]); 245 249 246 cur->address = NULL; 250 251 irq_spinlock_unlock(&bkpoint_lock, true); 247 248 spinlock_unlock(&bkpoint_lock); 249 interrupts_restore(ipl); 252 250 return 1; 253 251 } 254 252 255 /** Print table of active breakpoints 256 * 257 */ 253 /** Print table of active breakpoints */ 258 254 int cmd_print_breakpoints(cmd_arg_t *argv) 259 255 { … … 280 276 } 281 277 282 #endif /* CONFIG_KCONSOLE */ 283 284 /** Initialize debugger 285 * 286 */ 278 #endif 279 280 /** Initialize debugger */ 287 281 void debugger_init() 288 282 { 289 unsignedint i;290 283 int i; 284 291 285 for (i = 0; i < BKPOINTS_MAX; i++) 292 286 breakpoints[i].address = NULL; 293 287 294 288 #ifdef CONFIG_KCONSOLE 295 289 cmd_initialize(&bkpts_info); 296 290 if (!cmd_register(&bkpts_info)) 297 291 printf("Cannot register command %s\n", bkpts_info.name); 298 292 299 293 cmd_initialize(&delbkpt_info); 300 294 if (!cmd_register(&delbkpt_info)) 301 295 printf("Cannot register command %s\n", delbkpt_info.name); 302 296 303 297 cmd_initialize(&addbkpt_info); 304 298 if (!cmd_register(&addbkpt_info)) 305 299 printf("Cannot register command %s\n", addbkpt_info.name); 306 300 307 301 cmd_initialize(&addbkpte_info); 308 302 if (!cmd_register(&addbkpte_info)) 309 303 printf("Cannot register command %s\n", addbkpte_info.name); 310 #endif /* CONFIG_KCONSOLE */304 #endif 311 305 } 312 306 313 307 /** Handle breakpoint 314 308 * 315 * Find breakpoint in breakpoint table. 309 * Find breakpoint in breakpoint table. 316 310 * If found, call kconsole, set break on next instruction and reexecute. 317 311 * If we are on "next instruction", set it back on the first and reexecute. 318 312 * If breakpoint not found in breakpoint table, call kconsole and start 319 313 * next instruction. 320 *321 314 */ 322 315 void debugger_bpoint(istate_t *istate) 323 316 { 317 bpinfo_t *cur = NULL; 318 uintptr_t fireaddr = istate->epc; 319 int i; 320 324 321 /* test branch delay slot */ 325 322 if (cp0_cause_read() & 0x80000000) 326 323 panic("Breakpoint in branch delay slot not supported."); 327 328 irq_spinlock_lock(&bkpoint_lock, false); 329 330 bpinfo_t *cur = NULL; 331 uintptr_t fireaddr = istate->epc; 332 unsigned int i; 333 324 325 spinlock_lock(&bkpoint_lock); 334 326 for (i = 0; i < BKPOINTS_MAX; i++) { 335 327 /* Normal breakpoint */ 336 if ( (fireaddr == breakpoints[i].address)&&337 (!(breakpoints[i].flags & BKPOINT_REINST))) {328 if (fireaddr == breakpoints[i].address && 329 !(breakpoints[i].flags & BKPOINT_REINST)) { 338 330 cur = &breakpoints[i]; 339 331 break; 340 332 } 341 342 333 /* Reinst only breakpoint */ 343 334 if ((breakpoints[i].flags & BKPOINT_REINST) && … … 347 338 } 348 339 } 349 350 340 if (cur) { 351 341 if (cur->flags & BKPOINT_REINST) { 352 342 /* Set breakpoint on first instruction */ 353 ((uint32_t *) 343 ((uint32_t *)cur->address)[0] = 0x0d; 354 344 smc_coherence(((uint32_t *)cur->address)[0]); 355 356 345 /* Return back the second */ 357 ((uint32_t *) cur->address)[1] = cur->nextinstruction; 358 smc_coherence(((uint32_t *) cur->address)[1]); 359 346 ((uint32_t *)cur->address)[1] = cur->nextinstruction; 347 smc_coherence(((uint32_t *)cur->address)[1]); 360 348 cur->flags &= ~BKPOINT_REINST; 361 irq_spinlock_unlock(&bkpoint_lock, false);349 spinlock_unlock(&bkpoint_lock); 362 350 return; 363 } 364 351 } 365 352 if (cur->flags & BKPOINT_INPROG) 366 353 printf("Warning: breakpoint recursion\n"); 367 354 368 355 if (!(cur->flags & BKPOINT_FUNCCALL)) { 369 printf("***Breakpoint % u: %p in %s.\n", i, fireaddr,370 symtab_fmt_name_lookup( fireaddr));371 } 372 356 printf("***Breakpoint %d: %p in %s.\n", i, fireaddr, 357 symtab_fmt_name_lookup(istate->epc)); 358 } 359 373 360 /* Return first instruction back */ 374 361 ((uint32_t *)cur->address)[0] = cur->instruction; … … 384 371 printf("***Breakpoint %d: %p in %s.\n", i, fireaddr, 385 372 symtab_fmt_name_lookup(fireaddr)); 386 373 387 374 /* Move on to next instruction */ 388 375 istate->epc += 4; 389 376 } 390 391 377 if (cur) 392 378 cur->counter++; 393 394 379 if (cur && (cur->flags & BKPOINT_FUNCCALL)) { 395 380 /* Allow zero bkfunc, just for counting */ … … 398 383 } else { 399 384 #ifdef CONFIG_KCONSOLE 400 /* 401 * This disables all other processors - we are not SMP, 385 /* This disables all other processors - we are not SMP, 402 386 * actually this gets us to cpu_halt, if scheduler() is run 403 387 * - we generally do not want scheduler to be run from debug, 404 388 * so this is a good idea 405 */ 389 */ 406 390 atomic_set(&haltstate, 1); 407 irq_spinlock_unlock(&bkpoint_lock, false);391 spinlock_unlock(&bkpoint_lock); 408 392 409 393 kconsole("debug", "Debug console ready.\n", false); 410 394 411 irq_spinlock_lock(&bkpoint_lock, false);395 spinlock_lock(&bkpoint_lock); 412 396 atomic_set(&haltstate, 0); 413 397 #endif 414 398 } 415 416 if ((cur) && (cur->address == fireaddr) 417 && ((cur->flags & BKPOINT_INPROG))) { 399 if (cur && cur->address == fireaddr && (cur->flags & BKPOINT_INPROG)) { 418 400 /* Remove one-shot breakpoint */ 419 401 if ((cur->flags & BKPOINT_ONESHOT)) 420 402 cur->address = NULL; 421 422 403 /* Remove in-progress flag */ 423 404 cur->flags &= ~BKPOINT_INPROG; 424 } 425 426 irq_spinlock_unlock(&bkpoint_lock, false); 405 } 406 spinlock_unlock(&bkpoint_lock); 427 407 } 428 408
Note:
See TracChangeset
for help on using the changeset viewer.