Subversion Repositories HelenOS

Rev

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

Rev 3012 Rev 3093
Line 32... Line 32...
32
/** @file
32
/** @file
33
 */
33
 */
34
 
34
 
35
#include <stdio.h>
35
#include <stdio.h>
36
#include <stdlib.h>
36
#include <stdlib.h>
-
 
37
#include <assert.h>
37
#include <sys/types.h>
38
#include <sys/types.h>
38
#include <udebug.h>
39
#include <udebug.h>
39
 
40
 
40
#include "../../../cons.h"
41
#include "../../../cons.h"
41
#include "../../../main.h"
42
#include "../../../main.h"
Line 46... Line 47...
46
 
47
 
47
static istate_t istate;
48
static istate_t istate;
48
 
49
 
49
int arch_breakpoint_set(breakpoint_t *b)
50
int arch_breakpoint_set(breakpoint_t *b)
50
{
51
{
51
    uint32_t brkp;
-
 
52
    int rc;
-
 
53
 
-
 
54
    rc = udebug_mem_read(app_phone, &b->arch.back, b->addr,
-
 
55
        sizeof(b->arch.back));
-
 
56
    if (rc < 0) return rc;
-
 
57
 
-
 
58
    cons_printf("udebug_mem_read() -> %d\n", rc);
-
 
59
    brkp = OPCODE_BREAK;
-
 
60
    rc = udebug_mem_write(app_phone, &brkp, b->addr, sizeof(brkp));
52
    return bstore_push(&b->arch.bs, b->addr, OPCODE_BREAK);
61
    cons_printf("udebug_mem_write() -> %d\n", rc);
-
 
62
    if (rc < 0) return rc;
-
 
63
 
-
 
64
    return 0;
-
 
65
}
53
}
66
 
54
 
67
int arch_breakpoint_remove(breakpoint_t *b)
55
int arch_breakpoint_remove(breakpoint_t *b)
68
{
56
{
69
    int rc;
-
 
70
 
-
 
71
    if (b->active) {
-
 
72
        rc = udebug_mem_write(app_phone, &b->arch.back, b->addr + 4, 4);
57
    return bstore_pop(&b->arch.bs);
73
        if (rc < 0) {
-
 
74
            cons_printf("error writing memory\n");
-
 
75
            return rc;
-
 
76
        }
-
 
77
        active_bkpt = NULL;
-
 
78
    } else {
-
 
79
            rc = udebug_mem_write(app_phone, &b->arch.back, b->addr, 4);
-
 
80
        if (rc < 0) {
-
 
81
            cons_printf("error writing memory\n");
-
 
82
            return rc;
-
 
83
        }
-
 
84
    }
-
 
85
 
-
 
86
    return 0;
-
 
87
 
-
 
88
}
58
}
89
 
59
 
90
void arch_event_breakpoint(thash_t thread_hash)
60
static void _ev_breakpoint(thash_t thread_hash)
91
{
61
{
92
    breakpoint_t *b;
62
    breakpoint_t *b;
93
    dthread_t *dt;
63
    dthread_t *dt;
94
    int rc;
64
    int rc;
95
    uint32_t epc;
65
    uint32_t epc;
Line 104... Line 74...
104
    cons_printf("udebug_regs_read -> %d\n", rc);
74
    cons_printf("udebug_regs_read -> %d\n", rc);
105
    epc = istate_get_pc(&istate);
75
    epc = istate_get_pc(&istate);
106
    cons_printf("EPC was 0x%08x\n", epc);
76
    cons_printf("EPC was 0x%08x\n", epc);
107
    brk_addr = epc;
77
    brk_addr = epc;
108
 
78
 
109
    b = breakpoint_find_by_addr(brk_addr);
-
 
110
    if (b != NULL) {
-
 
111
        cons_printf("move breakpoint\b");
-
 
112
            rc = udebug_mem_write(app_phone, &b->arch.back, brk_addr, 4);
-
 
113
        rc = udebug_mem_read(app_phone, &b->arch.back, brk_addr + 4, 4);
-
 
114
            rc = udebug_mem_write(app_phone, &brkp, brk_addr + 4, 4);
-
 
115
        active_bkpt = b;
-
 
116
        b->active = true;
-
 
117
 
-
 
118
        cons_printf("breakpoint_hit...\n");
-
 
119
        breakpoint_hit(b);
79
    dt = dthread_get();
120
        cons_printf("end_hit...\n");
-
 
121
        return;
-
 
122
    }
-
 
123
 
80
 
-
 
81
    if (active_bkpt != NULL) {
124
    b = breakpoint_find_by_addr(brk_addr - 4);
82
        assert(active_bkpt->arch.bs.address == brk_addr);
-
 
83
 
125
    if (b != NULL && b->active) {
84
        /* A breakpoint-clearing BRK has been hit */
126
        cons_printf("restoring breakpoint %d\n", b->id);
85
        cons_printf("restoring breakpoint %d\n", b->id);
127
            rc = udebug_mem_write(app_phone, &b->arch.back, brk_addr, 4);
86
        rc = bstore_pop(&b->arch.bs);
-
 
87
        if (rc != 0) return;
128
        rc = udebug_mem_read(app_phone, &b->arch.back, brk_addr - 4, 4);
88
        rc = bstore_push(&b->arch.bs, brk_addr - 4, OPCODE_BREAK);
129
            rc = udebug_mem_write(app_phone, &brkp, brk_addr - 4, 4);
89
        if (rc != 0) return;
130
        active_bkpt = NULL;
90
        active_bkpt = NULL;
131
       
-
 
132
        if (dt->arch.singlestep) {
-
 
133
            singlestep_hit();
-
 
134
 
-
 
135
            rc = udebug_mem_read(app_phone, &dt->arch.sstep_back, brk_addr + 4, 4);
-
 
136
            rc = udebug_mem_write(app_phone, &brkp, brk_addr + 4, 4);
-
 
137
        }
-
 
138
        return;
91
        return;
139
    }
92
    }
140
 
93
 
-
 
94
    b = breakpoint_find_by_addr(brk_addr);
-
 
95
    if (b == NULL) {
-
 
96
        cons_printf("Unrecognized breakpoint at 0x%lx\n", brk_addr);
-
 
97
    }
-
 
98
 
-
 
99
    /* A breakpoint has been hit */
-
 
100
    cons_printf("breakpoint_hit...\n");
-
 
101
    breakpoint_hit(b);
-
 
102
 
-
 
103
    /* While in breakpoint_hit(), singlestep was activated */
-
 
104
    if (dt->arch.singlestep) return;
-
 
105
 
-
 
106
    cons_printf("move breakpoint\b");
-
 
107
    rc = bstore_pop(&b->arch.bs);
-
 
108
    if (rc != 0) return;
-
 
109
 
-
 
110
    /*
-
 
111
     * There could be another breakpoint at brk_addr + 4,
-
 
112
     * but that's okay. We'll pop the active breakpoint bs
-
 
113
     * before doing anything else.
-
 
114
     */
-
 
115
    rc = bstore_push(&b->arch.bs, brk_addr + 4, OPCODE_BREAK);
-
 
116
    if (rc != 0) return;
-
 
117
 
-
 
118
    active_bkpt = b;
-
 
119
    b->active = true;
-
 
120
 
-
 
121
    cons_printf("end_hit...\n");
-
 
122
}
-
 
123
 
-
 
124
 
-
 
125
static void _ev_singlestep(thash_t thread_hash)
-
 
126
{
-
 
127
    dthread_t *dt;
-
 
128
    int rc;
-
 
129
    uint32_t epc;
-
 
130
    int brk_addr;
-
 
131
    uint32_t brkp;
-
 
132
 
141
    dt = dthread_get();
133
    dt = dthread_get();
142
 
134
 
143
    if (dt->arch.singlestep) {
135
    assert(active_bkpt == NULL);
144
        cons_printf("advance singlestep\n");
136
    assert(dt->arch.singlestep);
145
            rc = udebug_mem_write(app_phone, &dt->arch.sstep_back, brk_addr, 4);
-
 
146
        rc = udebug_mem_read(app_phone, &dt->arch.sstep_back, brk_addr + 4, 4);
137
    brkp = OPCODE_BREAK;
-
 
138
 
147
            rc = udebug_mem_write(app_phone, &brkp, brk_addr + 4, 4);
139
    cons_printf("arch_event_breakpoint\n");
148
 
140
 
-
 
141
    rc = udebug_regs_read(app_phone, thread_hash, &istate);
-
 
142
    cons_printf("udebug_regs_read -> %d\n", rc);
149
        singlestep_hit();
143
    epc = istate_get_pc(&istate);
-
 
144
    cons_printf("EPC was 0x%08x\n", epc);
-
 
145
    brk_addr = epc;
150
 
146
 
-
 
147
    if (dt->arch.cur.valid) {
-
 
148
        cons_printf("restore breakpoint BRK\n");
151
        return;
149
        rc = bstore_pop(&dt->arch.cur);
152
    }
150
    }
153
 
151
 
154
    cons_printf("Unrecognized breakpoint at 0x%lx\n", brk_addr);
152
    cons_printf("clear singlestep BRK\n");
-
 
153
    rc = bstore_pop(&dt->arch.next);
-
 
154
 
-
 
155
    dt->arch.singlestep = false;
-
 
156
 
-
 
157
    singlestep_hit();
-
 
158
}
-
 
159
 
-
 
160
 
-
 
161
void arch_event_breakpoint(thash_t thread_hash)
-
 
162
{
-
 
163
    dthread_t *dt;
-
 
164
 
-
 
165
    dt = dthread_get();
-
 
166
    if (dt->arch.singlestep) {
-
 
167
        _ev_singlestep(thread_hash);
-
 
168
    } else {
-
 
169
        _ev_breakpoint(thread_hash);
-
 
170
    }
155
}
171
}
156
 
172
 
157
void arch_event_trap(dthread_t *dt)
173
void arch_event_trap(dthread_t *dt)
158
{
174
{
159
    /* Unused */
175
    /* Unused */
160
    (void)dt;
176
    (void)dt;
161
}
177
}
162
 
178
 
163
void arch_dump_regs(thash_t thash)
179
void arch_dump_regs(thash_t thash)
164
{
180
{
-
 
181
    /* TODO */
165
}
182
}
166
 
183
 
167
void arch_set_singlestep(dthread_t *dt, int enable)
184
void arch_singlestep(dthread_t *dt)
168
{
185
{
169
    int rc;
186
    int rc;
170
    uint32_t epc;
187
    uint32_t epc;
171
    uint32_t brk;
188
    breakpoint_t *b;
172
    breakpoint_t *b1, *b2;
189
    uint32_t old_instr;
173
 
190
 
174
    brk = OPCODE_BREAK;
191
    assert(active_bkpt == NULL);
-
 
192
    assert(dt->arch.singlestep == false);
175
 
193
 
176
    cons_printf("arch_set_singlestep(dt, %d)\n", enable);
194
    cons_printf("arch_singlestep(dt)\n");
177
    rc = udebug_regs_read(app_phone, dt->hash, &istate);
195
    rc = udebug_regs_read(app_phone, dt->hash, &istate);
178
    cons_printf("udebug_regs_read -> %d\n", rc);
196
    cons_printf("udebug_regs_read -> %d\n", rc);
179
    epc = istate_get_pc(&istate);
197
    epc = istate_get_pc(&istate);
180
    cons_printf("EPC was 0x%08x\n", epc);
198
    cons_printf("EPC was 0x%08x\n", epc);
181
 
199
 
182
    b1 = breakpoint_find_by_addr(epc - 4);
200
    cons_printf("initial set singlestep\n");
183
    b2 = breakpoint_find_by_addr(epc);
201
    b = breakpoint_find_by_addr(epc);
184
 
-
 
185
    if (enable && !dt->arch.singlestep) {
-
 
186
        if (b1 && b1->active) {
202
    if (b != NULL) {
187
            dt->arch.sstep_back = b1->arch.back;
203
        /* Cover breakpoint with old instruction */
188
        } else if (b2) {
-
 
189
            dt->arch.sstep_back = b2->arch.back;
204
        old_instr = b->arch.bs.value;
190
        } else {
-
 
191
            cons_printf("initial set singlestep\b");
-
 
192
            rc = udebug_mem_read(app_phone, &dt->arch.sstep_back, epc + 4, 4);
205
        rc = bstore_push(&dt->arch.cur, epc, old_instr);
193
            rc = udebug_mem_write(app_phone, &brk, epc + 4, 4);
-
 
194
            if (rc < 0) { cons_printf("error writing mem\n"); return; }
-
 
195
        }
-
 
196
    } else if (!enable && dt->arch.singlestep) {
-
 
197
        if ((b1 && b1->active) || b2) {
206
        if (rc < 0) return;
198
            /* Do not remove BRK instruction */
-
 
199
        } else  {
-
 
200
            cons_printf("remove singlestep\b");
-
 
201
            rc = udebug_mem_write(app_phone, &dt->arch.sstep_back, epc + 4, 4);
-
 
202
        }
-
 
203
    }
207
    }
-
 
208
 
-
 
209
    /* Cover next instruction with BREAK */
-
 
210
    rc = bstore_push(&dt->arch.next, epc + 4, OPCODE_BREAK);
-
 
211
    if (rc < 0) return;
-
 
212
 
204
    dt->arch.singlestep = enable;
213
    dt->arch.singlestep = true;
-
 
214
    dthread_resume(dt);
205
}
215
}
206
 
216
 
207
/** @}
217
/** @}
208
 */
218
 */