Subversion Repositories HelenOS-historic

Rev

Rev 631 | Rev 673 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 631 Rev 635
Line 70... Line 70...
70
    .func = cmd_add_breakpoint,
70
    .func = cmd_add_breakpoint,
71
    .argc = 1,
71
    .argc = 1,
72
    .argv = &add_argv
72
    .argv = &add_argv
73
};
73
};
74
 
74
 
-
 
75
static cmd_arg_t adde_argv[] = {
-
 
76
    { .type = ARG_TYPE_INT },
-
 
77
    { .type = ARG_TYPE_INT }
-
 
78
};
-
 
79
static cmd_info_t addbkpte_info = {
-
 
80
    .name = "addbkpte",
-
 
81
    .description = "addebkpte <&symbol> <&func> - new bkpoint. Call func(or Nothing if 0).",
-
 
82
    .func = cmd_add_breakpoint,
-
 
83
    .argc = 2,
-
 
84
    .argv = adde_argv
-
 
85
};
-
 
86
 
-
 
87
static struct {
-
 
88
    __u32 andmask;
-
 
89
    __u32 value;
-
 
90
}jmpinstr[] = {
-
 
91
    {0xf3ff0000, 0x41000000}, /* BCzF */
-
 
92
    {0xf3ff0000, 0x41020000}, /* BCzFL */
-
 
93
    {0xf3ff0000, 0x41010000}, /* BCzT */
-
 
94
    {0xf3ff0000, 0x41030000}, /* BCzTL */
-
 
95
    {0xfc000000, 0x10000000}, /* BEQ */
-
 
96
    {0xfc000000, 0x50000000}, /* BEQL */
-
 
97
    {0xfc1f0000, 0x04010000}, /* BEQL */
-
 
98
    {0xfc1f0000, 0x04110000}, /* BGEZAL */
-
 
99
    {0xfc1f0000, 0x04130000}, /* BGEZALL */
-
 
100
    {0xfc1f0000, 0x04030000}, /* BGEZL */
-
 
101
    {0xfc1f0000, 0x1c000000}, /* BGTZ */
-
 
102
    {0xfc1f0000, 0x5c000000}, /* BGTZL */
-
 
103
    {0xfc1f0000, 0x18000000}, /* BLEZ */
-
 
104
    {0xfc1f0000, 0x58000000}, /* BLEZL */
-
 
105
    {0xfc1f0000, 0x04000000}, /* BLTZ */
-
 
106
    {0xfc1f0000, 0x04100000}, /* BLTZAL */
-
 
107
    {0xfc1f0000, 0x04120000}, /* BLTZALL */
-
 
108
    {0xfc1f0000, 0x04020000}, /* BLTZL */
-
 
109
    {0xfc000000, 0x14000000}, /* BNE */
-
 
110
    {0xfc000000, 0x54000000}, /* BNEL */
-
 
111
    {0xfc000000, 0x08000000}, /* J */
-
 
112
    {0xfc000000, 0x0c000000}, /* JAL */
-
 
113
    {0xfc1f07ff, 0x00000009}, /* JALR */
-
 
114
    {0,0} /* EndOfTable */
-
 
115
};
-
 
116
 
-
 
117
/** Test, if the given instruction is a jump or branch instruction
-
 
118
 *
-
 
119
 * @param instr Instruction code
-
 
120
 * @return true - it is jump instruction, false otherwise
-
 
121
 */
-
 
122
static bool is_jump(__native instr)
-
 
123
{
-
 
124
    int i;
-
 
125
 
-
 
126
    for (i=0;jmpinstr[i].andmask;i++) {
-
 
127
        if ((instr & jmpinstr[i].andmask) == jmpinstr[i].value)
-
 
128
            return true;
-
 
129
    }
-
 
130
 
-
 
131
    return false;
-
 
132
}
-
 
133
 
75
/** Add new breakpoint to table */
134
/** Add new breakpoint to table */
76
int cmd_add_breakpoint(cmd_arg_t *argv)
135
int cmd_add_breakpoint(cmd_arg_t *argv)
77
{
136
{
78
    bpinfo_t *cur = NULL;
137
    bpinfo_t *cur = NULL;
79
    ipl_t ipl;
138
    ipl_t ipl;
Line 114... Line 173...
114
    }
173
    }
115
    cur->address = (__address) argv->intval;
174
    cur->address = (__address) argv->intval;
116
    printf("Adding breakpoint on address: %p\n", argv->intval);
175
    printf("Adding breakpoint on address: %p\n", argv->intval);
117
    cur->instruction = ((__native *)cur->address)[0];
176
    cur->instruction = ((__native *)cur->address)[0];
118
    cur->nextinstruction = ((__native *)cur->address)[1];
177
    cur->nextinstruction = ((__native *)cur->address)[1];
-
 
178
    if (argv == &add_argv) {
-
 
179
        cur->flags = 0;
-
 
180
    } else { /* We are add extended */
-
 
181
        cur->flags = BKPOINT_FUNCCALL;
-
 
182
        cur->bkfunc =   (void (*)(void *, struct exception_regdump *)) argv[1].intval;
-
 
183
    }
-
 
184
    if (is_jump(cur->instruction))
-
 
185
        cur->flags |= BKPOINT_ONESHOT;
119
    cur->executing = false;
186
    cur->counter = 0;
120
 
187
 
121
    /* Set breakpoint */
188
    /* Set breakpoint */
122
    *((__native *)cur->address) = 0x0d;
189
    *((__native *)cur->address) = 0x0d;
123
 
190
 
124
    spinlock_unlock(&bkpoint_lock);
191
    spinlock_unlock(&bkpoint_lock);
125
    interrupts_restore(ipl);
192
    interrupts_restore(ipl);
126
 
193
 
127
    return 1;
194
    return 1;
128
}
195
}
129
 
196
 
-
 
197
 
-
 
198
 
130
/** Remove breakpoint from table */
199
/** Remove breakpoint from table */
131
int cmd_del_breakpoint(cmd_arg_t *argv)
200
int cmd_del_breakpoint(cmd_arg_t *argv)
132
{
201
{
133
    bpinfo_t *cur;
202
    bpinfo_t *cur;
134
    ipl_t ipl;
203
    ipl_t ipl;
Line 145... Line 214...
145
        printf("Breakpoint does not exist.\n");
214
        printf("Breakpoint does not exist.\n");
146
        spinlock_unlock(&bkpoint_lock);
215
        spinlock_unlock(&bkpoint_lock);
147
        interrupts_restore(ipl);
216
        interrupts_restore(ipl);
148
        return 0;
217
        return 0;
149
    }
218
    }
-
 
219
    if ((cur->flags & BKPOINT_INPROG) && (cur->flags & BKPOINT_ONESHOT)) {
-
 
220
        printf("Cannot remove one-shot breakpoint in-progress\n");
-
 
221
        spinlock_unlock(&bkpoint_lock);
-
 
222
        interrupts_restore(ipl);
-
 
223
        return 0;
150
   
224
    }
151
    ((__u32 *)cur->address)[0] = cur->instruction;
225
    ((__u32 *)cur->address)[0] = cur->instruction;
152
    ((__u32 *)cur->address)[1] = cur->nextinstruction;
226
    ((__u32 *)cur->address)[1] = cur->nextinstruction;
153
 
227
 
154
    cur->address = NULL;
228
    cur->address = NULL;
155
 
229
 
Line 168... Line 242...
168
    for (i=0; i < BKPOINTS_MAX; i++)
242
    for (i=0; i < BKPOINTS_MAX; i++)
169
        if (breakpoints[i].address) {
243
        if (breakpoints[i].address) {
170
            symbol = get_symtab_entry(breakpoints[i].address);
244
            symbol = get_symtab_entry(breakpoints[i].address);
171
            printf("%d. 0x%p in %s\n",i,
245
            printf("%d. 0x%p in %s\n",i,
172
                   breakpoints[i].address, symbol);
246
                   breakpoints[i].address, symbol);
-
 
247
            printf("     Count(%d) ", breakpoints[i].counter);
-
 
248
            if (breakpoints[i].flags & BKPOINT_INPROG)
-
 
249
                printf("INPROG ");
-
 
250
            if (breakpoints[i].flags & BKPOINT_ONESHOT)
-
 
251
                printf("ONESHOT ");
-
 
252
            if (breakpoints[i].flags & BKPOINT_FUNCCALL)
-
 
253
                printf("FUNCCALL ");
-
 
254
            printf("\n");
173
        }
255
        }
174
    return 1;
256
    return 1;
175
}
257
}
176
 
258
 
177
/** Initialize debugger */
259
/** Initialize debugger */
Line 191... Line 273...
191
        panic("could not register command %s\n", delbkpt_info.name);
273
        panic("could not register command %s\n", delbkpt_info.name);
192
 
274
 
193
    cmd_initialize(&addbkpt_info);
275
    cmd_initialize(&addbkpt_info);
194
    if (!cmd_register(&addbkpt_info))
276
    if (!cmd_register(&addbkpt_info))
195
        panic("could not register command %s\n", addbkpt_info.name);
277
        panic("could not register command %s\n", addbkpt_info.name);
-
 
278
 
-
 
279
    cmd_initialize(&addbkpte_info);
-
 
280
    if (!cmd_register(&addbkpte_info))
-
 
281
        panic("could not register command %s\n", addbkpte_info.name);
196
}
282
}
197
 
283
 
198
/** Handle breakpoint
284
/** Handle breakpoint
199
 *
285
 *
200
 * Find breakpoint in breakpoint table.
286
 * Find breakpoint in breakpoint table.
Line 203... Line 289...
203
 * If breakpoint not found in breakpoint table, call kconsole and start
289
 * If breakpoint not found in breakpoint table, call kconsole and start
204
 * next instruction.
290
 * next instruction.
205
 */
291
 */
206
void debugger_bpoint(struct exception_regdump *pstate)
292
void debugger_bpoint(struct exception_regdump *pstate)
207
{
293
{
208
    char *symbol;
-
 
209
    bpinfo_t *cur = NULL;
294
    bpinfo_t *cur = NULL;
-
 
295
    __address fireaddr = pstate->epc;
210
    int i;
296
    int i;
211
 
297
 
212
    symbol = get_symtab_entry(pstate->epc);
-
 
213
   
-
 
214
 
-
 
215
    /* test branch delay slot */
298
    /* test branch delay slot */
216
    if (cp0_cause_read() & 0x80000000)
299
    if (cp0_cause_read() & 0x80000000)
217
        panic("Breakpoint in branch delay slot not supported.\n");
300
        panic("Breakpoint in branch delay slot not supported.\n");
218
 
301
 
219
    spinlock_lock(&bkpoint_lock);
302
    spinlock_lock(&bkpoint_lock);
220
    for (i=0; i<BKPOINTS_MAX; i++) {
303
    for (i=0; i<BKPOINTS_MAX; i++) {
221
        if (pstate->epc == breakpoints[i].address || \
304
        /* Normal breakpoint */
222
            (pstate->epc == breakpoints[i].address+sizeof(__native) &&\
305
        if (fireaddr == breakpoints[i].address \
223
             breakpoints[i].executing))
306
            && !(breakpoints[i].flags & BKPOINT_REINST)) {
224
            cur = &breakpoints[i];
307
            cur = &breakpoints[i];
225
        break;
308
            break;
-
 
309
        }
-
 
310
        /* Reinst only breakpoint */
-
 
311
        if ((breakpoints[i].flags & BKPOINT_REINST) \
-
 
312
            && (fireaddr ==breakpoints[i].address+sizeof(__native))) {
-
 
313
            cur = &breakpoints[i];
-
 
314
            break;
226
 
315
        }
227
    }
316
    }
228
    if (cur) {
317
    if (cur) {
229
        if ((cur->executing && pstate->epc==cur->address) ||
-
 
230
            (!cur->executing && pstate->epc==cur->address+sizeof(__native)))
-
 
231
            panic("Weird breakpoint state.\n");
-
 
232
        if (!cur->executing) {
318
        if (cur->flags & BKPOINT_REINST) {
233
            printf("***Breakpoint %d: 0x%p in %s.\n", i,
-
 
234
                   pstate->epc,symbol);
-
 
235
            /* Return first instruction back */
-
 
236
            ((__u32 *)cur->address)[0] = cur->instruction;
-
 
237
            /* Set Breakpoint on second */
-
 
238
            ((__u32 *)cur->address)[1] = 0x0d;
-
 
239
            cur->executing = true;
-
 
240
        } else {
-
 
241
            /* Set breakpoint on first instruction */
319
            /* Set breakpoint on first instruction */
242
            ((__u32 *)cur->address)[0] = 0x0d;
320
            ((__u32 *)cur->address)[0] = 0x0d;
243
            /* Return back the second */
321
            /* Return back the second */
244
            ((__u32 *)cur->address)[1] = cur->nextinstruction;
322
            ((__u32 *)cur->address)[1] = cur->nextinstruction;
245
            cur->executing = false;
323
            cur->flags &= ~BKPOINT_REINST;
246
            spinlock_unlock(&bkpoint_lock);
324
            spinlock_unlock(&bkpoint_lock);
247
            return;
325
            return;
248
        }
326
        }
-
 
327
        if (cur->flags & BKPOINT_INPROG)
-
 
328
            printf("Warning: breakpoint recursion\n");
-
 
329
       
-
 
330
        if (!(cur->flags & BKPOINT_FUNCCALL))
-
 
331
            printf("***Breakpoint %d: 0x%p in %s.\n", i,
-
 
332
                   fireaddr, get_symtab_entry(pstate->epc));
-
 
333
 
-
 
334
        /* Return first instruction back */
-
 
335
        ((__u32 *)cur->address)[0] = cur->instruction;
-
 
336
 
-
 
337
        if (! (cur->flags & BKPOINT_ONESHOT)) {
-
 
338
            /* Set Breakpoint on next instruction */
-
 
339
            ((__u32 *)cur->address)[1] = 0x0d;
-
 
340
            cur->flags |= BKPOINT_REINST;
-
 
341
        }
-
 
342
        cur->flags |= BKPOINT_INPROG;
249
    } else {
343
    } else {
250
        printf("***Breakpoint 0x%p in %s.\n", pstate->epc, symbol);
344
        printf("***Breakpoint 0x%p in %s.\n", fireaddr,
-
 
345
               get_symtab_entry(fireaddr));
251
        /* Move on to next instruction */
346
        /* Move on to next instruction */
252
        pstate->epc += 4;
347
        pstate->epc += 4;
253
    }
348
    }
-
 
349
   
-
 
350
    cur->counter++;
-
 
351
    if (cur && (cur->flags & BKPOINT_FUNCCALL)) {
-
 
352
        /* Allow zero bkfunc, just for counting */
-
 
353
        if (cur->bkfunc)
-
 
354
            cur->bkfunc(cur, pstate);
-
 
355
    } else {
-
 
356
        printf("***Type 'exit' to exit kconsole.\n");
-
 
357
        /* This disables all other processors - we are not SMP,
-
 
358
         * actually this gets us to cpu_halt, if scheduler() is run
-
 
359
         * - we generally do not want scheduler to be run from debug,
-
 
360
         *   so this is a good idea
-
 
361
         */
-
 
362
        atomic_set(&haltstate,1);
254
    spinlock_unlock(&bkpoint_lock);
363
        spinlock_unlock(&bkpoint_lock);
255
 
364
 
-
 
365
        kconsole("debug");
-
 
366
 
-
 
367
        spinlock_lock(&bkpoint_lock);
-
 
368
        atomic_set(&haltstate,0);
256
           
369
    }
-
 
370
 
257
    printf("***Type 'exit' to exit kconsole.\n");
371
    if (cur && cur->address == fireaddr && (cur->flags & BKPOINT_INPROG)) {
258
    /* Umm..we should rather set some 'debugstate' here */
372
        /* Remove one-shot breakpoint */
-
 
373
        if ((cur->flags & BKPOINT_ONESHOT))
259
    atomic_set(&haltstate,1);
374
            cur->address = NULL;
260
    kconsole("debug");
375
        /* Remove in-progress flag */
-
 
376
        cur->flags &= ~BKPOINT_INPROG;
-
 
377
    }
261
    atomic_set(&haltstate,0);
378
    spinlock_unlock(&bkpoint_lock);
262
}
379
}