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