ef30a029cc11b34dd0a4d756510f78a6c0ef5969
[fw/stlink] / src / gdb-server.c
1 /* -*- tab-width:8 -*- */
2
3 /*
4  Copyright (C)  2011 Peter Zotov <whitequark@whitequark.org>
5  Use of this source code is governed by a BSD-style
6  license that can be found in the LICENSE file.
7 */
8
9 #include <stdio.h>
10 #include <string.h>
11 #include <stdlib.h>
12 #include <unistd.h>
13 #include <sys/types.h>
14 #include <sys/socket.h>
15 #include <netinet/in.h>
16 #include <arpa/inet.h>
17 #include "gdb-remote.h"
18 #include "stlink-hw.h"
19
20 static const char hex[] = "0123456789abcdef";
21
22 int serve(struct stlink* sl, int port);
23
24 int main(int argc, char** argv) {
25         if(argc != 3) {
26                 fprintf(stderr, "Usage: %s <port> /dev/sgX\n", argv[0]);
27                 return 1;
28         }
29
30         struct stlink *sl = stlink_quirk_open(argv[2], 0);
31         if (sl == NULL)
32                 return 1;
33
34         if(stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE)
35                 stlink_enter_swd_mode(sl);
36
37         stlink_core_id(sl);
38         printf("Debugging ARM core %08x.\n", sl->core_id);
39
40         int port = atoi(argv[1]);
41
42         while(serve(sl, port) == 0);
43
44         stlink_close(sl);
45
46         return 0;
47 }
48
49 int serve(struct stlink* sl, int port) {
50         int sock = socket(AF_INET, SOCK_STREAM, 0);
51         if(sock < 0) {
52                 perror("socket");
53                 return 1;
54         }
55
56         unsigned int val = 1;
57         setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
58
59         struct sockaddr_in serv_addr = {0};
60         serv_addr.sin_family = AF_INET;
61         serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
62         serv_addr.sin_port = htons(port);
63
64         if(bind(sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
65                 perror("bind");
66                 return 1;
67         }
68
69         if(listen(sock, 5) < 0) {
70                 perror("listen");
71                 return 1;
72         }
73
74         stlink_force_debug(sl);
75         stlink_reset(sl);
76
77         printf("Listening at *:%d...\n", port);
78
79         int client = accept(sock, NULL, NULL);
80         if(client < 0) {
81                 perror("accept");
82                 return 1;
83         }
84
85         close(sock);
86
87         printf("GDB connected.\n");
88
89         while(1) {
90                 char* packet;
91
92                 int status = gdb_recv_packet(client, &packet);
93                 if(status < 0) {
94                         fprintf(stderr, "cannot recv: %d\n", status);
95                         return 1;
96                 }
97
98                 #ifdef DEBUG
99                 printf("recv: %s\n", packet);
100                 #endif
101
102                 char* reply = NULL;
103
104                 switch(packet[0]) {
105                 case 'c':
106                         stlink_run(sl);
107
108                         printf("Core running, waiting for interrupt.\n");
109
110                         int status = gdb_wait_for_interrupt(client);
111                         if(status < 0) {
112                                 fprintf(stderr, "cannot wait for int: %d\n", status);
113                                 return 1;
114                         }
115
116                         stlink_force_debug(sl);
117
118                         reply = strdup("S05"); // TRAP
119                         break;
120
121                 case 's':
122                         stlink_step(sl);
123
124                         reply = strdup("S05"); // TRAP
125                         break;
126
127                 case '?':
128                         reply = strdup("S05"); // TRAP
129                         break;
130
131                 case 'g':
132                         stlink_read_all_regs(sl);
133
134                         reply = calloc(8 * 16 + 1, 1);
135                         for(int i = 0; i < 16; i++)
136                                 sprintf(&reply[i * 8], "%08x", htonl(sl->reg.r[i]));
137
138                         break;
139
140                 case 'p': {
141                         unsigned id = strtoul(&packet[1], NULL, 16), reg = 0xDEADDEAD;
142
143                         if(id < 16) {
144                                 stlink_read_reg(sl, id);
145                                 reg = htonl(sl->reg.r[id]);
146                         } else if(id == 0x19) {
147                                 stlink_read_reg(sl, 16);
148                                 reg = htonl(sl->reg.xpsr);
149                         } else {
150                                 reply = strdup("E00");
151                         }
152
153                         reply = calloc(8 + 1, 1);
154                         sprintf(reply, "%08x", reg);
155
156                         break;
157                 }
158
159                 case 'P': {
160                         char* s_reg = &packet[1];
161                         char* s_value = strstr(&packet[1], "=") + 1;
162
163                         unsigned reg   = strtoul(s_reg,   NULL, 16);
164                         unsigned value = strtoul(s_value, NULL, 16);
165
166                         if(reg < 16) {
167                                 stlink_write_reg(sl, ntohl(value), reg);
168                         } else if(reg == 0x19) {
169                                 stlink_write_reg(sl, ntohl(value), 16);
170                         } else {
171                                 reply = strdup("E00");
172                         }
173
174                         if(!reply) {
175                                 reply = strdup("OK");
176                         }
177
178                         break;
179                 }
180
181                 case 'G':
182                         for(int i = 0; i < 16; i++) {
183                                 char str[9] = {0};
184                                 strncpy(str, &packet[1 + i * 8], 8);
185                                 uint32_t reg = strtoul(str, NULL, 16);
186                                 stlink_write_reg(sl, ntohl(reg), i);
187                         }
188
189                         reply = strdup("OK");
190                         break;
191
192                 case 'm': {
193                         char* s_start = &packet[1];
194                         char* s_count = strstr(&packet[1], ",") + 1;
195
196                         stm32_addr_t start = strtoul(s_start, NULL, 16);
197                         unsigned     count = strtoul(s_count, NULL, 16);
198
199                         unsigned adj_start = start % 4;
200
201                         stlink_read_mem32(sl, start - adj_start, (count % 4 == 0) ?
202                                                 count : count + 4 - (count % 4));
203
204                         reply = calloc(count * 2 + 1, 1);
205                         for(int i = 0; i < count; i++) {
206                                 reply[i * 2 + 0] = hex[sl->q_buf[i + adj_start] >> 4];
207                                 reply[i * 2 + 1] = hex[sl->q_buf[i + adj_start] & 0xf];
208                         }
209
210                         break;
211                 }
212
213                 case 'M': {
214                         char* s_start = &packet[1];
215                         char* s_count = strstr(&packet[1], ",") + 1;
216                         char* hexdata = strstr(packet, ":") + 1;
217
218                         stm32_addr_t start = strtoul(s_start, NULL, 16);
219                         unsigned     count = strtoul(s_count, NULL, 16);
220
221                         for(int i = 0; i < count; i ++) {
222                                 char hex[3] = { hexdata[i*2], hexdata[i*2+1], 0 };
223                                 uint8_t byte = strtoul(hex, NULL, 16);
224                                 sl->q_buf[i] = byte;
225                         }
226
227                         if((count % 4) == 0 && (start % 4) == 0) {
228                                 stlink_write_mem32(sl, start, count);
229                         } else {
230                                 stlink_write_mem8(sl, start, count);
231                         }
232
233                         reply = strdup("OK");
234
235                         break;
236                 }
237
238                 case 'k': {
239                         // After this function will be entered afterwards, the
240                         // chip will be reset anyway. So this is a no-op.
241
242                         close(client);
243                         return 0;
244                 }
245
246                 default:
247                         reply = strdup("");
248                 }
249
250                 if(reply) {
251                         #ifdef DEBUG
252                         printf("send: %s\n", reply);
253                         #endif
254
255                         int result = gdb_send_packet(client, reply);
256                         if(result != 0) {
257                                 fprintf(stderr, "cannot send: %d\n", result);
258                                 return 1;
259                         }
260
261                         free(reply);
262                 }
263
264                 free(packet);
265         }
266
267         return 0;
268 }