summaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
Diffstat (limited to 'gdb')
-rw-r--r--gdb/Makefile65
-rw-r--r--gdb/SOURCES3
-rw-r--r--gdb/arm-stub.c574
-rw-r--r--gdb/linker.cfg64
4 files changed, 704 insertions, 2 deletions
diff --git a/gdb/Makefile b/gdb/Makefile
index 61f4cb838d..fa94eac9b1 100644
--- a/gdb/Makefile
+++ b/gdb/Makefile
@@ -7,6 +7,67 @@
7# $Id$ 7# $Id$
8# 8#
9 9
10ifeq ($(ARCHOS),ifp7xx)
11
12INCLUDES= -I$(FIRMDIR)/include -I$(FIRMDIR)/export -I. -I$(OBJDIR) \
13 -I$(BUILDDIR)
14
15DEPFILE = $(OBJDIR)/dep-stub
16LDS := linker.cfg
17
18SRC := $(shell cat SOURCES | $(CC) -DMEMORYSIZE=$(MEMORYSIZE) $(INCLUDES) $(TARGET) $(DEFINES) -E -P -include "config.h" - )
19DIRS = .
20
21ifdef APPEXTRA
22 DIRS += $(subst :, ,$(APPEXTRA))
23 INCLUDES += $(patsubst %,-I%,$(subst :, ,$(APPEXTRA)))
24endif
25
26ifndef VERSION
27VERSION=$(shell date +%y%m%d-%H%M)
28endif
29
30CFLAGS = $(GCCOPTS) $(INCLUDES) $(TARGET) $(DEFINES) \
31 -DAPPSVERSION=\"$(VERSION)\" $(EXTRA_DEFINES) -DMEM=${MEMORYSIZE}
32
33OBJS := $(SRC:%.c=$(OBJDIR)/%.o)
34SOURCES = $(SRC)
35LINKFILE = $(OBJDIR)/linkage.lds
36
37LIBROCKBOX = $(BUILDDIR)/librockbox.a
38
39all: $(BUILDDIR)/$(BINARY) $(FLASHFILE)
40
41dep: $(DEPFILE)
42
43$(LINKFILE): $(LDS)
44 @echo "Build LDS file"
45 @cat $< | $(CC) -DMEMORYSIZE=$(MEMORYSIZE) $(INCLUDES) $(TARGET) $(DEFINES) -E -P $(ROMBUILD) - >$@
46
47$(OBJDIR)/stub.elf : $(OBJS) $(LINKFILE) $(DEPFILE) $(LIBROCKBOX)
48 @echo "LD stub.elf"
49 @$(CC) $(GCCOPTS) -Os -nostdlib -o $@ $(OBJS) -L$(BUILDDIR) -L$(BUILDDIR)/firmware -lrockbox -lgcc -T$(LINKFILE) -Wl,-Map,$(OBJDIR)/stub.map
50
51$(OBJDIR)/stub.bin : $(OBJDIR)/stub.elf
52 @echo "OBJCOPY $<"
53 @$(OC) -O binary $< $@
54
55$(BUILDDIR)/$(BINARY) : $(OBJDIR)/stub.bin
56 @echo "Build stub file"
57 $(MKFIRMWARE) $< $@
58
59include $(TOOLSDIR)/make.inc
60
61clean:
62 @echo "cleaning stub"
63 @-rm -f $(OBJS) $(BUILDDIR)/$(BINARY) \
64 $(OBJDIR)/stub.bin $(OBJDIR)/stub.elf $(OBJDIR)/*.map \
65 $(LINKFILE) $(DEPFILE)
66
67-include $(DEPFILE)
68
69else # not ifp7xx
70
10ifdef RECORDER 71ifdef RECORDER
11EXTRA = -DRECORDER 72EXTRA = -DRECORDER
12EXT = ajz 73EXT = ajz
@@ -38,6 +99,8 @@ $(TARGET).elf: $(OBJS)
38clean: 99clean:
39 rm $(OBJS) $(TARGET).map $(TARGET).elf $(TARGET).out $(TARGET).mod $(TARGET).ajz 100 rm $(OBJS) $(TARGET).map $(TARGET).elf $(TARGET).out $(TARGET).mod $(TARGET).ajz
40 101
41start.o: start.S 102start.o: start.s
42sh-stub.o: sh-stub.c 103sh-stub.o: sh-stub.c
43setjmp.o: setjmp.S 104setjmp.o: setjmp.S
105
106endif
diff --git a/gdb/SOURCES b/gdb/SOURCES
new file mode 100644
index 0000000000..9668d12dc8
--- /dev/null
+++ b/gdb/SOURCES
@@ -0,0 +1,3 @@
1#ifdef CPU_ARM
2arm-stub.c
3#endif
diff --git a/gdb/arm-stub.c b/gdb/arm-stub.c
new file mode 100644
index 0000000000..68b24a7457
--- /dev/null
+++ b/gdb/arm-stub.c
@@ -0,0 +1,574 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 by Tomasz Malesinski
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include <stdbool.h>
21#include <string.h>
22#include "usb_serial.h"
23#include "sscanf.h"
24
25#define BUFMAX 1024
26
27#define VEC_UND 1
28#define VEC_SWI 2
29#define VEC_PABT 3
30#define VEC_DABT 4
31
32static char packet_buf[BUFMAX];
33static char reply_buf[BUFMAX];
34
35static const char hexchars[] = "0123456789abcdef";
36static int gdb_exception_no, gdb_mem_access;
37static unsigned long registers[17];
38
39static inline bool isxdigit(char c)
40{
41 return ((c >= '0') && (c <= '9'))
42 || ((c >= 'a') && (c <= 'f')) || ((c >= 'A') && (c <= 'F'));
43}
44
45static int hex(char ch) {
46 if ((ch >= 'a') && (ch <= 'f'))
47 return ch - 'a' + 10;
48 if ((ch >= '0') && (ch <= '9'))
49 return ch - '0';
50 if ((ch >= 'A') && (ch <= 'F'))
51 return ch - 'A' + 10;
52 return -1;
53}
54
55static void hex_byte(char *s, int byte) {
56 s[0] = hexchars[(byte >> 4) & 0xf];
57 s[1] = hexchars[byte & 0xf];
58}
59
60static void hex_word(char *s, unsigned long val) {
61 int i;
62 for (i = 0; i < 4; i++)
63 hex_byte(s + i * 2, (val >> (i * 8)) & 0xff);
64}
65
66static void hex_string(char *d, char *s) {
67 while (*s) {
68 hex_byte(d, *s++);
69 d += 2;
70 }
71 *d = 0;
72}
73
74static int get_hex_byte(char *s) {
75 return (hex(s[0]) << 4) + hex(s[1]);
76}
77
78static unsigned long get_hex_word(char *s) {
79 int i;
80 unsigned long r = 0;
81 for (i = 3; i >= 0; i--)
82 r = (r << 8) + get_hex_byte(s + i * 2);
83 return r;
84}
85
86static void reply_error(int n, char *reply) {
87 reply[0] = 'E';
88 hex_byte(reply + 1, n);
89 reply[3] = 0;
90}
91
92static void reply_signal(int n, char *reply) {
93 int signal;
94 reply[0] = 'S';
95 switch (n)
96 {
97 case VEC_UND:
98 signal = 4;
99 break;
100 case VEC_PABT:
101 case VEC_DABT:
102 signal = 7;
103 break;
104 default:
105 signal = 5;
106 break;
107 }
108 hex_byte(reply + 1, signal);
109 reply[3] = 0;
110}
111
112static void reply_ok(char *reply) {
113 strcpy(reply, "OK");
114}
115
116static void serial_write(unsigned char *buf, int len) {
117 int i;
118 for (i = 0; i < len; i++)
119 usb_serial_put_byte(buf[i]);
120}
121
122static void get_packet(char *buf, int len) {
123 int count, checksum;
124 int ch;
125
126 while (1) {
127 do {
128 ch = usb_serial_get_byte();
129 } while (ch != '$');
130
131 checksum = 0;
132 count = 0;
133 while (count < len) {
134 ch = usb_serial_get_byte();
135 if (ch == '$') {
136 checksum = 0;
137 count = 0;
138 } else if (ch == '#')
139 break;
140 else {
141 checksum += ch;
142 buf[count] = ch;
143 count++;
144 }
145 }
146 buf[count] = 0;
147
148 if (ch == '#') {
149 int rchksum;
150
151 ch = usb_serial_get_byte();
152 rchksum = hex(ch) << 4;
153 ch = usb_serial_get_byte();
154 rchksum += hex(ch);
155
156 if ((checksum & 0xff) != rchksum)
157 usb_serial_put_byte('-');
158 else {
159 usb_serial_put_byte('+');
160 return;
161 }
162 }
163 }
164}
165
166static void put_packet(char *buf) {
167 int i, checksum;
168 int ch;
169 char tmp[3];
170
171 do {
172 usb_serial_put_byte('$');
173
174 checksum = 0;
175 for (i = 0; buf[i]; i++)
176 checksum += buf[i];
177
178 serial_write(buf, i);
179
180 tmp[0] = '#';
181 hex_byte(tmp + 1, checksum & 0xff);
182 serial_write(tmp, 3);
183
184 ch = usb_serial_get_byte();
185
186 } while (ch != '+');
187}
188
189static inline unsigned long get_general_reg(int n)
190{
191 return registers[n + 1];
192}
193
194static inline void set_general_reg(int n, unsigned long v)
195{
196 registers[n + 1] = v;
197}
198
199static inline unsigned long get_cpsr(void)
200{
201 return registers[0];
202}
203
204static inline void set_cpsr(unsigned long v)
205{
206 registers[0] = v;
207}
208
209static void g_reply(char *buf) {
210 int i;
211 char *p;
212
213 p = buf;
214 for (i = 0; i < 16; i++) {
215 hex_word(p, get_general_reg(i));
216 p += 8;
217 }
218
219 for (i = 0; i < 8; i++) {
220 memset(p, '0', 16);
221 p += 16;
222 }
223
224 hex_word(p, 0);
225 p += 8;
226 hex_word(p, get_cpsr());
227 p[8] = 0;
228}
229
230static void cmd_get_register(char *args, char *reply) {
231 int r;
232
233 if (sscanf(args, "%x", &r) != 1) {
234 reply_error(0, reply);
235 return;
236 }
237
238 if (r >= 0 && r < 16) {
239 hex_word(reply, get_general_reg(r));
240 reply[8] = 0;
241 } else if (r == 25) {
242 hex_word(reply, get_cpsr());
243 reply[8] = 0;
244 } else {
245 hex_word(reply, 0);
246 reply[8] = 0;
247 }
248}
249
250static void cmd_set_register(char *args, char *reply) {
251 int r, p;
252 unsigned long v;
253
254 p = -1;
255 sscanf(args, "%x=%n", &r, &p);
256 if (p == -1) {
257 reply_error(0, reply);
258 return;
259 }
260
261 v = get_hex_word(args + p);
262 if (r >= 0 && r < 16)
263 set_general_reg(r, v);
264 else if (r == 25)
265 set_cpsr(v);
266 reply_ok(reply);
267}
268
269static void cmd_set_registers(char *args, char *reply) {
270 char *p;
271 int i, len;
272
273 len = strlen(args);
274
275 p = args;
276 for (i = 0; i < 16 && len >= (i + 1) * 8; i++) {
277 set_general_reg(i, get_hex_word(p));
278 p += 8;
279 }
280
281 if (len >= 16 * 8 + 8 * 16 + 2 * 8)
282 {
283 p += 8 * 16 + 8;
284 set_cpsr(get_hex_word(p));
285 }
286
287 reply_ok(reply);
288}
289
290static void cmd_get_memory(char *args, char *reply) {
291 unsigned long addr, len, i;
292
293 if (sscanf(args, "%lx,%lx", &addr, &len) != 2) {
294 reply_error(0, reply);
295 return;
296 }
297
298 if (len > (BUFMAX - 16) / 2) {
299 reply_error(1, reply);
300 return;
301 }
302
303 gdb_mem_access = 1;
304 for (i = 0; i < len; i++)
305 hex_byte(reply + i * 2, *((unsigned char *)(addr + i)));
306 gdb_mem_access = 0;
307
308 reply[len * 2] = 0;
309}
310
311static void cmd_put_memory(char *args, char *reply) {
312 unsigned long addr, len, i;
313 int pos;
314
315 pos = -1;
316 sscanf(args, "%lx,%lx:%n", &addr, &len, &pos);
317 if (pos == -1) {
318 reply_error(0, reply);
319 return;
320 }
321
322 gdb_mem_access = 1;
323 for (i = 0; i < len; i++)
324 *((unsigned char *)(addr + i)) = get_hex_byte(args + pos + i * 2);
325 gdb_mem_access = 0;
326
327 reply_ok(reply);
328}
329
330static void parse_continue_args(char *args) {
331 int sig;
332 unsigned long addr;
333
334 if (sscanf(args, "%x;%lx", &sig, &addr) == 2) {
335 set_general_reg(15, addr);
336 } else if (sscanf(args, "%lx", &addr) == 1) {
337 set_general_reg(15, addr);
338 }
339}
340
341static void cmd_go(char *args) {
342 parse_continue_args(args);
343
344 asm volatile(
345 " mov r1, %0\n"
346 " ldr r12, [r1], #4\n"
347 " mov r0, r12\n"
348 " and r0, r0, #0x1f\n"
349 " cmp r0, #0x10\n"
350 " bne 1f\n"
351 " ldr r14, [r1, #60]\n"
352 " msr spsr_fsxc, r12\n"
353 " ldmia r1, {r0-r14}^\n"
354 " movs r15, r14\n"
355 "1:\n"
356 " msr cpsr_fsxc, r12\n"
357 " ldmia r1, {r0-r15}\n"
358 : : "r" (registers));
359}
360
361static void remote_cmd(char *cmd, char *reply) {
362 (void)cmd;
363 hex_string(reply, "Unrecognized command\n");
364}
365
366static void cmd_query(char *args, char *reply) {
367 if (!strncmp(args, "Rcmd,", 5)) {
368 unsigned i = 0;
369 char *s = args + 5;
370 char cmd[200];
371 while (isxdigit(s[0]) && isxdigit(s[1]) && i < sizeof(cmd) - 1) {
372 cmd[i++] = get_hex_byte(s);
373 s += 2;
374 }
375 cmd[i] = 0;
376 remote_cmd(cmd, reply);
377 } else
378 reply[0] = 0;
379}
380
381void gdb_loop(void) {
382 int no_reply;
383
384 gdb_mem_access = 0;
385
386 while (1) {
387 get_packet(packet_buf, sizeof(packet_buf) - 1);
388
389 no_reply = 0;
390 switch (packet_buf[0]) {
391 case '?':
392 reply_signal(gdb_exception_no, reply_buf);
393 break;
394
395 case 'p':
396 cmd_get_register(packet_buf + 1, reply_buf);
397 break;
398
399 case 'P':
400 cmd_set_register(packet_buf + 1, reply_buf);
401 break;
402
403 case 'g':
404 g_reply(reply_buf);
405 break;
406
407 case 'G':
408 cmd_set_registers(packet_buf + 1, reply_buf);
409 break;
410
411 case 'm':
412 cmd_get_memory(packet_buf + 1, reply_buf);
413 break;
414
415 case 'M':
416 cmd_put_memory(packet_buf + 1, reply_buf);
417 break;
418
419 case 'q':
420 cmd_query(packet_buf + 1, reply_buf);
421 break;
422
423 case 'c':
424 cmd_go(packet_buf + 1);
425 reply_error(1, reply_buf);
426 break;
427
428/* case 's': */
429/* cmd_go(packet_buf + 1); */
430/* break; */
431
432 default:
433 reply_buf[0] = 0;
434 }
435
436 if (!no_reply)
437 put_packet(reply_buf);
438 }
439}
440
441extern void *vectors[];
442
443static void gdb_set_vector(int n, void *p)
444{
445 vectors[n] = p;
446}
447
448void gdb_und_exc(void);
449void gdb_swi_exc(void);
450void gdb_pabt_exc(void);
451void gdb_dabt_exc(void);
452
453static void gdb_set_vectors(void)
454{
455 gdb_set_vector(VEC_UND, gdb_und_exc);
456 gdb_set_vector(VEC_SWI, gdb_swi_exc);
457 gdb_set_vector(VEC_PABT, gdb_pabt_exc);
458 gdb_set_vector(VEC_DABT, gdb_dabt_exc);
459}
460
461void gdb_loop_from_exc(void)
462{
463 if (gdb_mem_access)
464 reply_error(1, reply_buf);
465 else
466 reply_signal(gdb_exception_no, reply_buf);
467 put_packet(reply_buf);
468 gdb_loop();
469}
470
471#define GPIO3_CLR (*(volatile unsigned long *)0x800030d8)
472
473#define IRQ_REG(reg) (*(volatile unsigned long *)(0x80300000 + (reg)))
474
475static inline unsigned long irq_read(int reg)
476{
477 unsigned long v, v2;
478 do
479 {
480 v = IRQ_REG(reg);
481 v2 = IRQ_REG(reg);
482 } while (v != v2);
483 return v;
484}
485
486#define IRQ_WRITE_WAIT(reg, val, cond) \
487 do { unsigned long v, v2; \
488 do { \
489 IRQ_REG(reg) = (val); \
490 v = IRQ_REG(reg); \
491 v2 = IRQ_REG(reg); \
492 } while ((v != v2) || !(cond)); \
493 } while (0);
494
495static void system_init(void)
496{
497 int i;
498
499 /* turn off watchdog */
500 (*(volatile unsigned long *)0x80002804) = 0;
501
502 for (i = 0; i < 0x1c; i++)
503 {
504 IRQ_WRITE_WAIT(0x404 + i * 4, 0x1e000001, (v & 0x3010f) == 1);
505 IRQ_WRITE_WAIT(0x404 + i * 4, 0x4000000, (v & 0x10000) == 0);
506 IRQ_WRITE_WAIT(0x404 + i * 4, 0x10000001, (v & 0xf) == 1);
507 }
508
509 GPIO3_CLR = 1;
510}
511
512void main(void)
513{
514 system_init();
515 usb_serial_init();
516 gdb_exception_no = VEC_SWI;
517 gdb_set_vectors();
518 gdb_loop();
519}
520
521#define str(s) #s
522#define xstr(s) str(s)
523
524asm (".text\n"
525 "gdb_und_exc:\n"
526 " ldr sp, =_stub_stack\n"
527 " sub r14, r14, #4\n"
528 " stmfd sp!, {r0-r3, r12, r14}\n"
529 " mov r0, #" xstr(VEC_UND) "\n"
530 " b gdb_handle_exception\n"
531 "gdb_swi_exc:\n"
532 " ldr sp, =_stub_stack\n"
533 " stmfd sp!, {r0-r3, r12, r14}\n"
534 " mov r0, #" xstr(VEC_SWI) "\n"
535 " b gdb_handle_exception\n"
536 "gdb_pabt_exc:\n"
537 " ldr sp, =_stub_stack\n"
538 " stmfd sp!, {r0-r3, r12, r14}\n"
539 " mov r0, #" xstr(VEC_PABT) "\n"
540 " b gdb_handle_exception\n"
541 "gdb_dabt_exc:\n"
542 " ldr sp, =_stub_stack\n"
543 " sub r14, r14, #4\n"
544 " stmfd sp!, {r0-r3, r12, r14}\n"
545 " ldr r0, =gdb_mem_access\n"
546 " ldr r0, [r0]\n"
547 " tst r0, r0\n"
548 " bne gdb_data_abort\n"
549 " mov r0, #" xstr(VEC_DABT) "\n"
550 " b gdb_handle_exception\n"
551 "gdb_handle_exception:\n"
552 " ldr r1, =gdb_exception_no\n"
553 " str r0, [r1]\n"
554 " ldr r0, =registers\n"
555 " mrs r12, spsr\n"
556 " str r12, [r0], #4\n"
557 " ldmfd sp!, {r2, r3}\n"
558 " stmia r0!, {r2, r3}\n"
559 " ldmfd sp!, {r2, r3, r12, r14}\n"
560 " str r14, [r0, #52]\n"
561 " stmia r0!, {r2-r12}\n"
562 " mrs r1, spsr\n"
563 " and r2, r1, #0x1f\n"
564 " cmp r2, #0x10\n"
565 " bne 1f\n"
566 " stmia r0, {r13, r14}^\n"
567 " b gdb_data_abort\n"
568 "1:\n"
569 " msr cpsr_c, r1\n"
570 " stmia r0, {r13, r14}\n"
571 "gdb_data_abort:\n"
572 " msr cpsr_c, #0xd3\n"
573 " ldr sp, =_stub_stack\n"
574 " b gdb_loop_from_exc\n");
diff --git a/gdb/linker.cfg b/gdb/linker.cfg
index 5d5334b92f..2cc6a0e9b4 100644
--- a/gdb/linker.cfg
+++ b/gdb/linker.cfg
@@ -1,5 +1,65 @@
1#include "config.h"
2
3#ifdef CPU_ARM
4ENTRY(start)
5STARTUP(crt0.o)
6OUTPUT_FORMAT(elf32-littlearm)
7#else
1ENTRY(_start) 8ENTRY(_start)
2OUTPUT_FORMAT(elf32-sh) 9OUTPUT_FORMAT(elf32-sh)
10#endif
11
12#ifdef IRIVER_IFP7XX_SERIES
13MEMORY
14{
15 IRAM : ORIGIN = 0, LENGTH = 0x10000
16 DRAM : ORIGIN = 0x24000000, LENGTH = 0x8000
17}
18
19SECTIONS
20{
21 .text :
22 {
23 *(.init*)
24 *(.text)
25 *(.text*)
26 *(.rodata)
27 *(.rodata*)
28 *(.glue_7)
29 *(.glue_7t)
30 } >DRAM
31
32 .data :
33 {
34 *(.data)
35 } >DRAM
36
37 .vectors :
38 {
39 _vectorsstart = .;
40 *(.vectors)
41 _vectorsend = .;
42 } >IRAM AT>DRAM
43 _vectorscopy = LOADADDR(.vectors);
44
45 .stack (NOLOAD) :
46 {
47 stackbegin = .;
48 . += 0x400;
49 _stub_stack = .;
50 . += 0x200;
51 stackend = .;
52 } >DRAM
53
54 .bss (NOLOAD) :
55 {
56 _edata = .;
57 *(.bss)
58 _end = .;
59 } >DRAM
60}
61#else
62
3SECTIONS 63SECTIONS
4{ 64{
5 .vectors 0x09000000 : 65 .vectors 0x09000000 :
@@ -25,4 +85,6 @@ SECTIONS
25 { 85 {
26 LONG(0); 86 LONG(0);
27 } 87 }
28 } 88}
89
90#endif