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