Subversion Repositories HelenOS

Rev

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

Rev 3093 Rev 3099
Line 34... Line 34...
34
 
34
 
35
#include <stdio.h>
35
#include <stdio.h>
36
#include <stdlib.h>
36
#include <stdlib.h>
37
#include <assert.h>
37
#include <assert.h>
38
#include <sys/types.h>
38
#include <sys/types.h>
-
 
39
#include <errno.h>
39
#include <udebug.h>
40
#include <udebug.h>
40
 
41
 
41
#include "../../../cons.h"
42
#include "../../../cons.h"
42
#include "../../../main.h"
43
#include "../../../main.h"
43
#include "../../../breakpoint.h"
44
#include "../../../breakpoint.h"
Line 45... Line 46...
45
 
46
 
46
#define OPCODE_BREAK        0x0000000d
47
#define OPCODE_BREAK        0x0000000d
47
 
48
 
48
static istate_t istate;
49
static istate_t istate;
49
 
50
 
-
 
51
typedef enum {
-
 
52
    OP_J,
-
 
53
    OP_JAL,
-
 
54
    OP_JALR,
-
 
55
    OP_JR
-
 
56
} op_t;
-
 
57
 
-
 
58
typedef struct {
-
 
59
    uint32_t mask;
-
 
60
    uint32_t value;
-
 
61
    op_t op;
-
 
62
} instr_desc_t;
-
 
63
 
-
 
64
static instr_desc_t decoding_table[] = {
-
 
65
    { 0xfc000000, 0x08000000, OP_J },
-
 
66
    { 0xfc000000, 0x0c000000, OP_JAL },
-
 
67
    { 0xfc1f07ff, 0x00000009, OP_JALR },
-
 
68
    { 0xfc1fffff, 0x00000008, OP_JR },
-
 
69
    { 0, 0, -1 }
-
 
70
};
-
 
71
 
50
int arch_breakpoint_set(breakpoint_t *b)
72
int arch_breakpoint_set(breakpoint_t *b)
51
{
73
{
52
    return bstore_push(&b->arch.bs, b->addr, OPCODE_BREAK);
74
    return bstore_push(&b->arch.bs, b->addr, OPCODE_BREAK);
53
}
75
}
54
 
76
 
55
int arch_breakpoint_remove(breakpoint_t *b)
77
int arch_breakpoint_remove(breakpoint_t *b)
56
{
78
{
57
    return bstore_pop(&b->arch.bs);
79
    return bstore_pop(&b->arch.bs);
58
}
80
}
59
 
81
 
-
 
82
static int islot_read(uintptr_t addr, uint32_t *instr)
-
 
83
{
-
 
84
    int rc;
-
 
85
 
-
 
86
    rc = udebug_mem_read(app_phone, instr, addr, sizeof(uint32_t));
-
 
87
    if (rc != EOK) {
-
 
88
        cons_printf("Error reading memory address 0x%zx\n", addr);
-
 
89
    }
-
 
90
 
-
 
91
    return rc;
-
 
92
}
-
 
93
 
-
 
94
static op_t instr_decode(uint32_t instr)
-
 
95
{
-
 
96
    instr_desc_t *idesc;
-
 
97
 
-
 
98
    idesc = &decoding_table[0];
-
 
99
    while (idesc->op >= 0) {
-
 
100
        if ((instr & idesc->mask) == idesc->value)
-
 
101
            return idesc->op;
-
 
102
        ++idesc;
-
 
103
    }
-
 
104
 
-
 
105
    return -1;
-
 
106
}
-
 
107
 
-
 
108
static int get_reg(int reg_no, uint32_t *value)
-
 
109
{
-
 
110
    int rc;
-
 
111
 
-
 
112
    cons_printf("get_reg...\n");
-
 
113
 
-
 
114
    if (reg_no == 0) {
-
 
115
        *value = 0;
-
 
116
        return 0;
-
 
117
    }
-
 
118
 
-
 
119
    /* FIXME: ugly */
-
 
120
    *value = ((uint32_t *)&istate)[reg_no - 1];
-
 
121
    printf("get_reg ok (0x%08x)\n", *value);
-
 
122
 
-
 
123
    return 0;
-
 
124
}
-
 
125
 
-
 
126
/** Get address of the instruction that will be executed after the current one.
-
 
127
 *
-
 
128
 * Assumptions: addr == PC, *addr is not covered by a BREAK.
-
 
129
 *
-
 
130
 * @param addr  Address of an instruction.
-
 
131
 * @return  Address of the instruction that will be executed afterwards.
-
 
132
 */
-
 
133
static int get_next_addr(uintptr_t addr, uintptr_t *next_addr)
-
 
134
{
-
 
135
    /* TODO: J[AL]R, branches and delay slots */
-
 
136
    uint32_t instr;
-
 
137
    op_t op;
-
 
138
    int rc;
-
 
139
 
-
 
140
    rc = islot_read(addr, &instr);
-
 
141
    if (rc != 0) return rc;
-
 
142
 
-
 
143
    op = instr_decode(instr);
-
 
144
 
-
 
145
    switch (op) {
-
 
146
    case OP_J:
-
 
147
    case OP_JAL:
-
 
148
        *next_addr =
-
 
149
            ((addr + 4) & 0xf0000000) |
-
 
150
            ((instr & 0x03ffffff) << 2);
-
 
151
        break;
-
 
152
    case OP_JR:
-
 
153
    case OP_JALR:
-
 
154
        rc = get_reg((instr >> 21) & 0x1f, next_addr);
-
 
155
        break;
-
 
156
    default:
-
 
157
        /* Regular instruction */  
-
 
158
        *next_addr = addr + 4;
-
 
159
        break;
-
 
160
    }
-
 
161
 
-
 
162
    return 0;  
-
 
163
}
-
 
164
 
60
static void _ev_breakpoint(thash_t thread_hash)
165
static void _ev_breakpoint(thash_t thread_hash)
61
{
166
{
62
    breakpoint_t *b;
167
    breakpoint_t *b;
63
    dthread_t *dt;
168
    dthread_t *dt;
64
    int rc;
169
    int rc;
65
    uint32_t epc;
170
    uint32_t epc;
66
    int brk_addr;
171
    uintptr_t brk_addr;
-
 
172
    uintptr_t next_addr;
67
    uint32_t brkp;
173
    uint32_t brkp;
68
 
174
 
69
    brkp = OPCODE_BREAK;
175
    brkp = OPCODE_BREAK;
70
 
176
 
71
    cons_printf("arch_event_breakpoint\n");
177
    cons_printf("arch_event_breakpoint\n");
Line 78... Line 184...
78
 
184
 
79
    dt = dthread_get();
185
    dt = dthread_get();
80
 
186
 
81
    if (active_bkpt != NULL) {
187
    if (active_bkpt != NULL) {
82
        assert(active_bkpt->arch.bs.address == brk_addr);
188
        assert(active_bkpt->arch.bs.address == brk_addr);
-
 
189
        b = active_bkpt;
83
 
190
 
84
        /* A breakpoint-clearing BRK has been hit */
191
        /* A breakpoint-clearing BRK has been hit */
85
        cons_printf("restoring breakpoint %d\n", b->id);
192
        cons_printf("restoring breakpoint %d\n", b->id);
86
        rc = bstore_pop(&b->arch.bs);
193
        rc = bstore_pop(&b->arch.bs);
87
        if (rc != 0) return;
194
        if (rc != 0) return;
88
        rc = bstore_push(&b->arch.bs, brk_addr - 4, OPCODE_BREAK);
195
        rc = bstore_push(&b->arch.bs, b->addr, OPCODE_BREAK);
89
        if (rc != 0) return;
196
        if (rc != 0) return;
90
        active_bkpt = NULL;
197
        active_bkpt = NULL;
91
        return;
198
        return;
92
    }
199
    }
93
 
200
 
Line 105... Line 212...
105
 
212
 
106
    cons_printf("move breakpoint\b");
213
    cons_printf("move breakpoint\b");
107
    rc = bstore_pop(&b->arch.bs);
214
    rc = bstore_pop(&b->arch.bs);
108
    if (rc != 0) return;
215
    if (rc != 0) return;
109
 
216
 
-
 
217
    rc = get_next_addr(brk_addr, &next_addr);
-
 
218
    if (rc != 0) return;
-
 
219
 
110
    /*
220
    /*
111
     * There could be another breakpoint at brk_addr + 4,
221
     * There could be another breakpoint at next_addr,
112
     * but that's okay. We'll pop the active breakpoint bs
222
     * but that's okay. We'll pop the active breakpoint bs
113
     * before doing anything else.
223
     * before doing anything else.
114
     */
224
     */
115
    rc = bstore_push(&b->arch.bs, brk_addr + 4, OPCODE_BREAK);
225
    rc = bstore_push(&b->arch.bs, next_addr, OPCODE_BREAK);
116
    if (rc != 0) return;
226
    if (rc != 0) return;
117
 
227
 
118
    active_bkpt = b;
228
    active_bkpt = b;
119
    b->active = true;
229
    b->active = true;
120
 
230
 
Line 185... Line 295...
185
{
295
{
186
    int rc;
296
    int rc;
187
    uint32_t epc;
297
    uint32_t epc;
188
    breakpoint_t *b;
298
    breakpoint_t *b;
189
    uint32_t old_instr;
299
    uint32_t old_instr;
-
 
300
    uintptr_t next_addr;
190
 
301
 
191
    assert(active_bkpt == NULL);
302
    assert(active_bkpt == NULL);
192
    assert(dt->arch.singlestep == false);
303
    assert(dt->arch.singlestep == false);
193
 
304
 
194
    cons_printf("arch_singlestep(dt)\n");
305
    cons_printf("arch_singlestep(dt)\n");
Line 204... Line 315...
204
        old_instr = b->arch.bs.value;
315
        old_instr = b->arch.bs.value;
205
        rc = bstore_push(&dt->arch.cur, epc, old_instr);
316
        rc = bstore_push(&dt->arch.cur, epc, old_instr);
206
        if (rc < 0) return;
317
        if (rc < 0) return;
207
    }
318
    }
208
 
319
 
-
 
320
    rc = get_next_addr(epc, &next_addr);
-
 
321
    if (rc != 0) return;
-
 
322
 
209
    /* Cover next instruction with BREAK */
323
    /* Cover next instruction with BREAK */
210
    rc = bstore_push(&dt->arch.next, epc + 4, OPCODE_BREAK);
324
    rc = bstore_push(&dt->arch.next, next_addr, OPCODE_BREAK);
211
    if (rc < 0) return;
325
    if (rc != 0) return;
212
 
326
 
213
    dt->arch.singlestep = true;
327
    dt->arch.singlestep = true;
214
    dthread_resume(dt);
328
    dthread_resume(dt);
215
}
329
}
216
 
330