/
debug_gdb.c
765 lines (745 loc) · 18.3 KB
/
debug_gdb.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
/* radare - LGPL - Copyright 2009-2016 - pancake, defragger */
#include <r_asm.h>
#include <r_debug.h>
#include <libgdbr.h>
#include <gdbclient/commands.h>
typedef struct {
libgdbr_t desc;
} RIOGdb;
#define UNKNOWN -1
#define UNSUPPORTED 0
#define SUPPORTED 1
static libgdbr_t *desc = NULL;
static ut8* reg_buf = NULL;
static int buf_size = 0;
static int support_sw_bp = UNKNOWN;
static int support_hw_bp = UNKNOWN;
static int r_debug_gdb_attach(RDebug *dbg, int pid);
static void check_connection (RDebug *dbg) {
if (!desc) {
r_debug_gdb_attach (dbg, -1);
}
}
static int r_debug_gdb_step(RDebug *dbg) {
check_connection (dbg);
gdbr_step (desc, -1); // TODO handle thread specific step?
return true;
}
static int r_debug_gdb_reg_read(RDebug *dbg, int type, ut8 *buf, int size) {
int copy_size;
int buflen = 0;
check_connection (dbg);
gdbr_read_registers (desc);
if (!desc) {
return -1;
}
// read the len of the current area
free (r_reg_get_bytes (dbg->reg, type, &buflen));
if (size < desc->data_len) {
eprintf ("r_debug_gdb_reg_read: small buffer %d vs %d\n",
(int)size, (int)desc->data_len);
// return -1;
}
copy_size = R_MIN (desc->data_len, size);
buflen = R_MAX (desc->data_len, buflen);
if (reg_buf) {
// if (buf_size < copy_size) { //desc->data_len) {
if (buflen > buf_size) { //copy_size) {
ut8* new_buf = realloc (reg_buf, buflen);
if (!new_buf) {
return -1;
}
reg_buf = new_buf;
buf_size = buflen;
}
} else {
reg_buf = calloc (buflen, 1);
if (!reg_buf) {
return -1;
}
buf_size = buflen;
}
memset ((void*)(volatile void*)buf, 0, size);
memcpy ((void*)(volatile void*)buf, desc->data, R_MIN (copy_size, size));
memset ((void*)(volatile void*)reg_buf, 0, buflen);
memcpy ((void*)(volatile void*)reg_buf, desc->data, copy_size);
#if 0
int i;
//for(i=0;i<168;i++) {
for(i=0;i<copy_size;i++) {
if (!(i%16)) printf ("\n0x%08x ", i);
printf ("%02x ", buf[i]); //(ut8)desc->data[i]);
}
printf("\n");
#endif
return desc->data_len;
}
static RList *r_debug_gdb_map_get(RDebug* dbg) { //TODO
check_connection (dbg);
//TODO
return NULL;
}
static int r_debug_gdb_reg_write(RDebug *dbg, int type, const ut8 *buf, int size) {
check_connection (dbg);
if (!reg_buf) {
// we cannot write registers before we once read them
return -1;
}
int buflen = 0;
int bits = dbg->anal->bits;
const char *pcname = r_reg_get_name (dbg->anal->reg, R_REG_NAME_PC);
RRegItem *reg = r_reg_get (dbg->anal->reg, pcname, 0);
if (reg) {
if (dbg->anal->bits != reg->size)
bits = reg->size;
}
free (r_reg_get_bytes (dbg->reg, type, &buflen));
// some implementations of the gdb protocol are acting weird.
// so winedbg is not able to write registers through the <G> packet
// and also it does not return the whole gdb register profile after
// calling <g>
// so this workaround resizes the small register profile buffer
// to the whole set and fills the rest with 0
if (buf_size < buflen) {
ut8* new_buf = realloc (reg_buf, buflen * sizeof (ut8));
if (!new_buf) {
return -1;
}
reg_buf = new_buf;
memset (new_buf + buf_size, 0, buflen - buf_size);
}
RRegItem* current = NULL;
for (;;) {
current = r_reg_next_diff (dbg->reg, type, reg_buf, buflen, current, bits);
if (!current) break;
ut64 val = r_reg_get_value (dbg->reg, current);
int bytes = bits / 8;
gdbr_write_reg (desc, current->name, (char*)&val, bytes);
}
return true;
}
static int r_debug_gdb_continue(RDebug *dbg, int pid, int tid, int sig) {
check_connection (dbg);
gdbr_continue (desc, -1);
return true;
}
static int r_debug_gdb_wait(RDebug *dbg, int pid) {
check_connection (dbg);
/* do nothing */
return true;
}
static int r_debug_gdb_attach(RDebug *dbg, int pid) {
RIODesc *d = dbg->iob.io->desc;
// TODO: the core must update the dbg.swstep config var when this var is changed
dbg->swstep = false;
//eprintf ("XWJSTEP TOFALSE\n");
if (d && d->plugin && d->plugin->name && d->data) {
if (!strcmp ("gdb", d->plugin->name)) {
RIOGdb *g = d->data;
support_sw_bp = UNKNOWN;
support_hw_bp = UNKNOWN;
int arch = r_sys_arch_id (dbg->arch);
int bits = dbg->anal->bits;
desc = &g->desc;
switch (arch) {
case R_SYS_ARCH_X86:
if (bits == 16 || bits == 32) {
gdbr_set_architecture (desc, "x86", 32);
} else if (bits == 64) {
gdbr_set_architecture (desc, "x86", 64);
} else {
eprintf ("Not supported register %s %d profile\n", dbg->arch, bits);
return false;
}
break;
case R_SYS_ARCH_SH:
// TODO
break;
case R_SYS_ARCH_ARM:
if (bits == 16 || bits == 32) {
gdbr_set_architecture (desc, "arm", 32);
} else if (bits == 64) {
gdbr_set_architecture (desc, "arm", 64);
} else {
eprintf ("Not supported register %s %d profile\n", dbg->arch, bits);
return false;
}
break;
case R_SYS_ARCH_LM32:
if (bits == 32) {
gdbr_set_architecture(desc, "lm32", 32);
} else {
eprintf ("Not supported register %s %d profile\n", dbg->arch, bits);
return false;
}
break;
case R_SYS_ARCH_MIPS:
if (bits == 32 || bits == 64) {
gdbr_set_architecture (desc, "mips", bits);
} else {
eprintf ("Not supported register %s %d profile\n", dbg->arch, bits);
return false;
}
break;
case R_SYS_ARCH_AVR:
gdbr_set_architecture (desc, "avr", 16);
break;
}
} else {
eprintf ("ERROR: Underlaying IO descriptor is not a GDB one..\n");
}
}
return true;
}
static int r_debug_gdb_detach(RDebug *dbg, int pid) {
return gdbr_detach_pid (desc, pid);
}
static const char *r_debug_gdb_reg_profile(RDebug *dbg) {
int arch = r_sys_arch_id (dbg->arch);
int bits = dbg->anal->bits;
check_connection (dbg);
switch (arch) {
case R_SYS_ARCH_X86:
if (bits == 16 || bits == 32) {
return strdup (
"=PC eip\n"
"=SP esp\n"
"=BP ebp\n"
"=A0 eax\n"
"=A1 ebx\n"
"=A2 ecx\n"
"=A3 edi\n"
"=SN oeax\n"
"gpr eax .32 0 0\n"
"gpr ecx .32 4 0\n"
"gpr edx .32 8 0\n"
"gpr ebx .32 12 0\n"
"gpr esp .32 16 0\n"
"gpr ebp .32 20 0\n"
"gpr esi .32 24 0\n"
"gpr edi .32 28 0\n"
"gpr eip .32 32 0\n"
"gpr eflags .32 36 0\n"
"seg cs .32 40 0\n"
"seg ss .32 44 0\n"
"seg ds .32 48 0\n"
"seg es .32 52 0\n"
"seg fs .32 56 0\n"
"seg gs .32 60 0\n"
"gpr st0 .80 64 0\n"
"gpr st1 .80 74 0\n"
"gpr st2 .80 84 0\n"
"gpr st3 .80 94 0\n"
"gpr st4 .80 104 0\n"
"gpr st5 .80 114 0\n"
"gpr st6 .80 124 0\n"
"gpr st7 .80 134 0\n"
"gpr fctrl .32 144 0\n"
"gpr fstat .32 148 0\n"
"gpr ftag .32 152 0\n"
"gpr fiseg .32 156 0\n"
"gpr fioff .32 160 0\n"
"gpr foseg .32 164 0\n"
"gpr fooff .32 168 0\n"
"gpr fop .32 172 0\n"
/* Commented until the long registers will be implemented
"gpr xmm0 .128 176 0\n"
"gpr xmm1 .128 192 0\n"
"gpr xmm2 .128 208 0\n"
"gpr xmm3 .128 224 0\n"
"gpr xmm4 .128 240 0\n"
"gpr xmm5 .128 256 0\n"
"gpr xmm6 .128 272 0\n"
"gpr xmm7 .128 288 0\n"
"gpr mxcsr .32 304 0\n"
*/
);
} else if (dbg->anal->bits == 64) {
return strdup (
"=PC rip\n"
"=SP rsp\n"
"=BP rbp\n"
"=A0 rax\n"
"=A1 rbx\n"
"=A2 rcx\n"
"=A3 rdx\n"
"=SN orax\n"
"gpr fake .64 795 0\n"
"gpr rax .64 0 0\n"
"gpr rbx .64 8 0\n"
"gpr rcx .64 16 0\n"
"gpr rdx .64 24 0\n"
"gpr rsi .64 32 0\n"
"gpr rdi .64 40 0\n"
"gpr rbp .64 48 0\n"
"gpr rsp .64 56 0\n"
"gpr r8 .64 64 0\n"
"gpr r9 .64 72 0\n"
"gpr r10 .64 80 0\n"
"gpr r11 .64 88 0\n"
"gpr r12 .64 96 0\n"
"gpr r13 .64 104 0\n"
"gpr r14 .64 112 0\n"
"gpr r15 .64 120 0\n"
"gpr rip .64 128 0\n"
"gpr eflags .32 136 0\n"
"seg cs .32 140 0\n"
"seg ss .32 144 0\n"
"seg ds .32 148 0\n"
"seg es .32 152 0\n"
"seg fs .32 156 0\n"
"seg gs .32 160 0\n"
"gpr st0 .80 164 0\n"
"gpr st1 .80 174 0\n"
"gpr st2 .80 184 0\n"
"gpr st3 .80 194 0\n"
"gpr st4 .80 204 0\n"
"gpr st5 .80 214 0\n"
"gpr st6 .80 224 0\n"
"gpr st7 .80 234 0\n"
"gpr fctrl .32 244 0\n"
"gpr fstat .32 248 0\n"
"gpr ftag .32 252 0\n"
"gpr fiseg .32 256 0\n"
"gpr fioff .32 260 0\n"
"gpr foseg .32 264 0\n"
"gpr fooff .32 268 0\n"
"gpr fop .32 272 0\n"
/* Commented until the long registers will be implemented
"gpr xmm0 .128 276 0\n"
"gpr xmm1 .128 292 0\n"
"gpr xmm2 .128 308 0\n"
"gpr xmm3 .128 324 0\n"
"gpr xmm4 .128 340 0\n"
"gpr xmm5 .128 356 0\n"
"gpr xmm6 .128 372 0\n"
"gpr xmm7 .128 388 0\n"
"gpr xmm8 .128 404 0\n"
"gpr xmm9 .128 420 0\n"
"gpr xmm10 .128 436 0\n"
"gpr xmm11 .128 452 0\n"
"gpr xmm12 .128 468 0\n"
"gpr xmm13 .128 484 0\n"
"gpr xmm14 .128 500 0\n"
"gpr xmm15 .128 516 0\n"
"gpr mxcsr .32 532 0\n"
*/
);
} else {
return strdup (
"=PC eip\n"
"=SP esp\n"
"=BP ebp\n"
"=A0 eax\n"
"=A1 ebx\n"
"=A2 ecx\n"
"=A3 edi\n"
"gpr eax .32 0 0\n"
"gpr ecx .32 4 0\n"
"gpr edx .32 8 0\n"
"gpr ebx .32 12 0\n"
"gpr esp .32 16 0\n"
"gpr ebp .32 20 0\n"
"gpr esi .32 24 0\n"
"gpr edi .32 28 0\n"
"gpr eip .32 32 0\n"
"gpr eflags .32 36 0\n"
"seg cs .32 40 0\n"
"seg ss .32 44 0\n"
"seg ds .32 48 0\n"
"seg es .32 52 0\n"
"seg fs .32 56 0\n"
"seg gs .32 60 0\n"
);
}
break;
case R_SYS_ARCH_ARM:
if (bits == 64) {
return strdup (
"=PC pc\n"
"=SP sp\n"
"=A0 r0\n"
"=A1 r1\n"
"=A2 r2\n"
"=A3 r3\n"
"gpr x0 .64 0 0\n"
"gpr x1 .64 8 0\n"
"gpr x2 .64 16 0\n"
"gpr x3 .64 24 0\n"
"gpr x4 .64 32 0\n"
"gpr x5 .64 40 0\n"
"gpr x6 .64 48 0\n"
"gpr x7 .64 56 0\n"
"gpr x8 .64 64 0\n"
"gpr x9 .64 72 0\n"
"gpr x10 .64 80 0\n"
"gpr x11 .64 88 0\n"
"gpr x12 .64 96 0\n"
"gpr x13 .64 104 0\n"
"gpr x14 .64 112 0\n"
"gpr x15 .64 120 0\n"
"gpr x16 .64 128 0\n"
"gpr x17 .64 136 0\n"
"gpr x18 .64 144 0\n"
"gpr x19 .64 152 0\n"
"gpr x20 .64 160 0\n"
"gpr x21 .64 168 0\n"
"gpr x22 .64 176 0\n"
"gpr x23 .64 184 0\n"
"gpr x24 .64 192 0\n"
"gpr x25 .64 200 0\n"
"gpr x26 .64 208 0\n"
"gpr x27 .64 216 0\n"
"gpr x28 .64 224 0\n"
"gpr x29 .64 232 0\n"
"gpr x30 .64 240 0\n"
"gpr sp .64 248 0\n"
"gpr pc .64 256 0\n"
"gpr pstate .64 264 0\n"
);
} else {
return strdup (
#if 0
"=PC r15\n"
"=SP r14\n" // XXX
"=A0 r0\n"
"=A1 r1\n"
"=A2 r2\n"
"=A3 r3\n"
"gpr lr .32 56 0\n" // r14
"gpr pc .32 60 0\n" // r15
"gpr r0 .32 0 0\n"
"gpr r1 .32 4 0\n"
"gpr r2 .32 8 0\n"
"gpr r3 .32 12 0\n"
"gpr r4 .32 16 0\n"
"gpr r5 .32 20 0\n"
"gpr r6 .32 24 0\n"
"gpr r7 .32 28 0\n"
"gpr r8 .32 32 0\n"
"gpr r9 .32 36 0\n"
"gpr r10 .32 40 0\n"
"gpr r11 .32 44 0\n"
"gpr r12 .32 48 0\n"
"gpr r13 .32 52 0\n"
"gpr r14 .32 56 0\n"
"gpr r15 .32 60 0\n"
"gpr f0 .96 64 0\n"
"gpr f1 .96 76 0\n"
"gpr f2 .96 88 0\n"
"gpr f3 .96 100 0\n"
"gpr f4 .96 112 0\n"
"gpr f5 .96 124 0\n"
"gpr f6 .96 136 0\n"
"gpr f7 .96 148 0\n"
"gpr fps .96 160 0\n"
"gpr cpsr .32 172 0\n"
#else
"=PC r15\n"
"=SP r14\n" // XXX
"=A0 r0\n"
"=A1 r1\n"
"=A2 r2\n"
"=A3 r3\n"
"gpr r0 .32 0 0\n"
"gpr r1 .32 4 0\n"
"gpr r2 .32 8 0\n"
"gpr r3 .32 12 0\n"
"gpr r4 .32 16 0\n"
"gpr r5 .32 20 0\n"
"gpr r6 .32 24 0\n"
"gpr r7 .32 28 0\n"
"gpr r8 .32 32 0\n"
"gpr r9 .32 36 0\n"
"gpr r10 .32 40 0\n"
"gpr r11 .32 44 0\n"
"gpr r12 .32 48 0\n"
"gpr sp .32 52 0\n" // r13
"gpr lr .32 56 0\n" // r14
"gpr pc .32 60 0\n" // r15
"gpr r13 .32 52 0\n"
"gpr r14 .32 56 0\n"
"gpr r15 .32 60 0\n"
"gpr cpsr .96 64 0\n"
"mmx d0 .64 68 0\n" // neon
"mmx d1 .64 76 0\n" // neon
"mmx d2 .64 84 0\n" // neon
"mmx d3 .64 92 0\n" // neon
"mmx d4 .64 100 0\n" // neon
"mmx d5 .64 108 0\n" // neon
"mmx d6 .64 116 0\n" // neon
"mmx d7 .64 124 0\n" // neon
"mmx d8 .64 132 0\n" // neon
"mmx d9 .64 140 0\n" // neon
"mmx d10 .64 148 0\n" // neon
"mmx d11 .64 156 0\n" // neon
"mmx d12 .64 164 0\n" // neon
"mmx d13 .64 172 0\n" // neon
"mmx d14 .64 180 0\n" // neon
"mmx d15 .64 188 0\n" // neon
"mmx d16 .64 196 0\n" // neon
"mmx d17 .64 204 0\n" // neon
"mmx d18 .64 212 0\n" // neon
"mmx d19 .64 220 0\n" // neon
"mmx d20 .64 228 0\n" // neon
"mmx d21 .64 236 0\n" // neon
"mmx d22 .64 244 0\n" // neon
"mmx d23 .64 252 0\n" // neon
"mmx d24 .64 260 0\n" // neon
"mmx d25 .64 268 0\n" // neon
"mmx d26 .64 276 0\n" // neon
"mmx d27 .64 284 0\n" // neon
"mmx d28 .64 292 0\n" // neon
"mmx d29 .64 300 0\n" // neon
"mmx d30 .64 308 0\n" // neon
"mmx d31 .64 316 0\n" // neon
"mmx fpscr .32 324 0\n" // neon
#endif
);
}
case R_SYS_ARCH_SH:
return strdup (
"=PC pc\n"
"=SP r15\n"
"=BP r14\n"
"gpr r0 .32 0 0\n"
"gpr r1 .32 4 0\n"
"gpr r2 .32 8 0\n"
"gpr r3 .32 12 0\n"
"gpr r4 .32 16 0\n"
"gpr r5 .32 20 0\n"
"gpr r6 .32 24 0\n"
"gpr r7 .32 28 0\n"
"gpr r8 .32 32 0\n"
"gpr r9 .32 36 0\n"
"gpr r10 .32 40 0\n"
"gpr r11 .32 44 0\n"
"gpr r12 .32 48 0\n"
"gpr r13 .32 52 0\n"
"gpr r14 .32 56 0\n"
"gpr r15 .32 60 0\n"
"gpr pc .32 64 0\n"
"gpr pr .32 68 0\n"
"gpr sr .32 72 0\n"
"gpr gbr .32 76 0\n"
"gpr mach .32 80 0\n"
"gpr macl .32 84 0\n"
);
case R_SYS_ARCH_LM32:
return strdup (
"=PC PC\n"
"=SP sp\n"
"=BP gp\n"
"gpr r0 .32 0 0\n"
"gpr r1 .32 4 0\n"
"gpr r2 .32 8 0\n"
"gpr r3 .32 12 0\n"
"gpr r4 .32 16 0\n"
"gpr r5 .32 20 0\n"
"gpr r6 .32 24 0\n"
"gpr r7 .32 28 0\n"
"gpr r8 .32 32 0\n"
"gpr r9 .32 36 0\n"
"gpr r10 .32 40 0\n"
"gpr r11 .32 44 0\n"
"gpr r12 .32 48 0\n"
"gpr r13 .32 52 0\n"
"gpr r14 .32 56 0\n"
"gpr r15 .32 60 0\n"
"gpr r16 .32 64 0\n"
"gpr r17 .32 68 0\n"
"gpr r18 .32 72 0\n"
"gpr r19 .32 76 0\n"
"gpr r20 .32 80 0\n"
"gpr r21 .32 84 0\n"
"gpr r22 .32 88 0\n"
"gpr r23 .32 92 0\n"
"gpr r24 .32 96 0\n"
"gpr r25 .32 100 0\n"
"gpr gp .32 104 0\n"
"gpr fp .32 108 0\n"
"gpr sp .32 112 0\n"
"gpr ra .32 116 0\n"
"gpr ea .32 120 0\n"
"gpr ba .32 124 0\n"
"gpr PC .32 128 0\n"
"gpr EID .32 132 0\n"
"gpr EBA .32 136 0\n"
"gpr DEBA .32 140 0\n"
"gpr IE .32 144 0\n"
"gpr IM .32 148 0\n"
"gpr IP .32 152 0\n"
);
case R_SYS_ARCH_MIPS:
return strdup (
"=PC pc\n"
"=SP sp\n"
"=BP gp\n"
"gpr zero .32 0 0\n"
"gpr at .32 4 0\n"
"gpr v0 .32 8 0\n"
"gpr v1 .32 12 0\n"
"gpr a0 .32 16 0\n"
"gpr a1 .32 20 0\n"
"gpr a2 .32 24 0\n"
"gpr a3 .32 28 0\n"
"gpr t0 .32 32 0\n"
"gpr t1 .32 36 0\n"
"gpr t2 .32 40 0\n"
"gpr t3 .32 44 0\n"
"gpr t4 .32 48 0\n"
"gpr t5 .32 52 0\n"
"gpr t6 .32 56 0\n"
"gpr t7 .32 60 0\n"
"gpr s0 .32 64 0\n"
"gpr s1 .32 68 0\n"
"gpr s2 .32 72 0\n"
"gpr s3 .32 76 0\n"
"gpr s4 .32 80 0\n"
"gpr s5 .32 84 0\n"
"gpr s6 .32 88 0\n"
"gpr s7 .32 92 0\n"
"gpr t8 .32 96 0\n"
"gpr t9 .32 100 0\n"
"gpr k0 .32 104 0\n"
"gpr k1 .32 108 0\n"
"gpr gp .32 112 0\n"
"gpr sp .32 116 0\n"
"gpr s8 .32 120 0\n"
"gpr ra .32 124 0\n"
"gpr sr .32 128 0\n"
"gpr lo .32 132 0\n"
"gpr hi .32 134 0\n"
"gpr bad .32 140 0\n"
"gpr cause .32 144 0\n"
"gpr pc .32 148 0\n"
"gpr f0 .32 152 0\n"
"gpr f1 .32 156 0\n"
"gpr f2 .32 160 0\n"
"gpr f3 .32 164 0\n"
"gpr f4 .32 168 0\n"
"gpr f5 .32 172 0\n"
"gpr f6 .32 176 0\n"
"gpr f7 .32 180 0\n"
"gpr f8 .32 184 0\n"
"gpr f9 .32 188 0\n"
"gpr f10 .32 192 0\n"
"gpr f11 .32 196 0\n"
"gpr f12 .32 200 0\n"
"gpr f13 .32 204 0\n"
"gpr f14 .32 208 0\n"
"gpr f15 .32 212 0\n"
"gpr f16 .32 216 0\n"
"gpr f17 .32 220 0\n"
"gpr f18 .32 224 0\n"
"gpr f19 .32 228 0\n"
"gpr f20 .32 232 0\n"
"gpr f21 .32 236 0\n"
"gpr f22 .32 240 0\n"
"gpr f23 .32 244 0\n"
"gpr f24 .32 248 0\n"
"gpr f25 .32 252 0\n"
"gpr f26 .32 256 0\n"
"gpr f27 .32 260 0\n"
"gpr f28 .32 264 0\n"
"gpr f29 .32 268 0\n"
"gpr f30 .32 272 0\n"
"gpr f31 .32 276 0\n"
"gpr fsr .32 280 0\n"
"gpr fir .32 284 0\n"
"gpr unknw .32 288 0\n" //Not documented what this part of the register packet is
);
case R_SYS_ARCH_AVR:
return strdup (
"=PC pc\n"
"=SP sp\n"
"gpr r0 .8 0 0\n"
"gpr r1 .8 1 0\n"
"gpr r2 .8 2 0\n"
"gpr r3 .8 3 0\n"
"gpr r4 .8 4 0\n"
"gpr r5 .8 5 0\n"
"gpr r6 .8 6 0\n"
"gpr r7 .8 7 0\n"
"gpr r8 .8 8 0\n"
"gpr r9 .8 9 0\n"
"gpr r10 .8 10 0\n"
"gpr r11 .8 11 0\n"
"gpr r12 .8 12 0\n"
"gpr r13 .8 13 0\n"
"gpr r14 .8 14 0\n"
"gpr r15 .8 15 0\n"
"gpr r16 .8 16 0\n"
"gpr r17 .8 17 0\n"
"gpr r18 .8 18 0\n"
"gpr r19 .8 19 0\n"
"gpr r20 .8 20 0\n"
"gpr r21 .8 21 0\n"
"gpr r22 .8 22 0\n"
"gpr r23 .8 23 0\n"
"gpr r24 .8 24 0\n"
"gpr r25 .8 25 0\n"
"gpr r26 .8 26 0\n"
"gpr r27 .8 27 0\n"
"gpr r28 .8 28 0\n"
"gpr r29 .8 29 0\n"
"gpr r30 .8 30 0\n"
"gpr r31 .8 31 0\n"
"gpr sreg .8 32 0\n"
"gpr sp .16 33 0\n"
"gpr pc2 .32 34 0\n"
"gpr pc .32 35 0\n"
/* "gpr pc .32 39 0\n" */
);
}
return NULL;
}
static int r_debug_gdb_breakpoint (RBreakpointItem *bp, int set, void *user) {
int ret;
if (!bp) return false;
// TODO handle rwx and conditions
if (set)
ret = bp->hw?
gdbr_set_hwbp (desc, bp->addr, ""):
gdbr_set_bp (desc, bp->addr, "");
else
ret = bp->hw?
gdbr_remove_hwbp (desc, bp->addr):
gdbr_remove_bp (desc, bp->addr);
return !ret;
}
static bool r_debug_gdb_kill(RDebug *dbg, int pid, int tid, int sig) {
// TODO kill based on pid and signal
if (sig != 0) {
return gdbr_kill (desc);
}
return true;
}
RDebugPlugin r_debug_plugin_gdb = {
.name = "gdb",
/* TODO: Add support for more architectures here */
.license = "LGPL3",
.arch = "x86,arm,sh,mips,avr,lm32",
.bits = R_SYS_BITS_16 | R_SYS_BITS_32 | R_SYS_BITS_64,
.step = r_debug_gdb_step,
.cont = r_debug_gdb_continue,
.attach = &r_debug_gdb_attach,
.detach = &r_debug_gdb_detach,
.canstep = 1,
.wait = &r_debug_gdb_wait,
.map_get = r_debug_gdb_map_get,
.breakpoint = &r_debug_gdb_breakpoint,
.reg_read = &r_debug_gdb_reg_read,
.reg_write = &r_debug_gdb_reg_write,
.reg_profile = (void *)r_debug_gdb_reg_profile,
.kill = &r_debug_gdb_kill,
//.bp_write = &r_debug_gdb_bp_write,
//.bp_read = &r_debug_gdb_bp_read,
};
#ifndef CORELIB
struct r_lib_struct_t radare_plugin = {
.type = R_LIB_TYPE_DBG,
.data = &r_debug_plugin_gdb,
.version = R2_VERSION
};
#endif