]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/gdbserver/hostio.c
Normalize includes to use common/
[thirdparty/binutils-gdb.git] / gdb / gdbserver / hostio.c
1 /* Host file transfer support for gdbserver.
2 Copyright (C) 2007-2019 Free Software Foundation, Inc.
3
4 Contributed by CodeSourcery.
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20
21 #include "server.h"
22 #include "gdb/fileio.h"
23 #include "hostio.h"
24
25 #include <fcntl.h>
26 #include <limits.h>
27 #include <unistd.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include "common/fileio.h"
31
32 extern int remote_debug;
33
34 struct fd_list
35 {
36 int fd;
37 struct fd_list *next;
38 };
39
40 static struct fd_list *open_fds;
41
42 static int
43 safe_fromhex (char a, int *nibble)
44 {
45 if (a >= '0' && a <= '9')
46 *nibble = a - '0';
47 else if (a >= 'a' && a <= 'f')
48 *nibble = a - 'a' + 10;
49 else if (a >= 'A' && a <= 'F')
50 *nibble = a - 'A' + 10;
51 else
52 return -1;
53
54 return 0;
55 }
56
57 /* Filenames are hex encoded, so the maximum we can handle is half the
58 packet buffer size. Cap to PATH_MAX, if it is shorter. */
59 #if !defined (PATH_MAX) || (PATH_MAX > (PBUFSIZ / 2 + 1))
60 # define HOSTIO_PATH_MAX (PBUFSIZ / 2 + 1)
61 #else
62 # define HOSTIO_PATH_MAX PATH_MAX
63 #endif
64
65 static int
66 require_filename (char **pp, char *filename)
67 {
68 int count;
69 char *p;
70
71 p = *pp;
72 count = 0;
73
74 while (*p && *p != ',')
75 {
76 int nib1, nib2;
77
78 /* Don't allow overflow. */
79 if (count >= HOSTIO_PATH_MAX - 1)
80 return -1;
81
82 if (safe_fromhex (p[0], &nib1)
83 || safe_fromhex (p[1], &nib2))
84 return -1;
85
86 filename[count++] = nib1 * 16 + nib2;
87 p += 2;
88 }
89
90 filename[count] = '\0';
91 *pp = p;
92 return 0;
93 }
94
95 static int
96 require_int (char **pp, int *value)
97 {
98 char *p;
99 int count, firstdigit;
100
101 p = *pp;
102 *value = 0;
103 count = 0;
104 firstdigit = -1;
105
106 while (*p && *p != ',')
107 {
108 int nib;
109
110 if (safe_fromhex (p[0], &nib))
111 return -1;
112
113 if (firstdigit == -1)
114 firstdigit = nib;
115
116 /* Don't allow overflow. */
117 if (count >= 8 || (count == 7 && firstdigit >= 0x8))
118 return -1;
119
120 *value = *value * 16 + nib;
121 p++;
122 count++;
123 }
124
125 *pp = p;
126 return 0;
127 }
128
129 static int
130 require_data (char *p, int p_len, char **data, int *data_len)
131 {
132 int input_index, output_index, escaped;
133
134 *data = (char *) xmalloc (p_len);
135
136 output_index = 0;
137 escaped = 0;
138 for (input_index = 0; input_index < p_len; input_index++)
139 {
140 char b = p[input_index];
141
142 if (escaped)
143 {
144 (*data)[output_index++] = b ^ 0x20;
145 escaped = 0;
146 }
147 else if (b == '}')
148 escaped = 1;
149 else
150 (*data)[output_index++] = b;
151 }
152
153 if (escaped)
154 {
155 free (*data);
156 return -1;
157 }
158
159 *data_len = output_index;
160 return 0;
161 }
162
163 static int
164 require_comma (char **pp)
165 {
166 if (**pp == ',')
167 {
168 (*pp)++;
169 return 0;
170 }
171 else
172 return -1;
173 }
174
175 static int
176 require_end (char *p)
177 {
178 if (*p == '\0')
179 return 0;
180 else
181 return -1;
182 }
183
184 static int
185 require_valid_fd (int fd)
186 {
187 struct fd_list *fd_ptr;
188
189 for (fd_ptr = open_fds; fd_ptr != NULL; fd_ptr = fd_ptr->next)
190 if (fd_ptr->fd == fd)
191 return 0;
192
193 return -1;
194 }
195
196 /* Fill in own_buf with the last hostio error packet, however it
197 suitable for the target. */
198 static void
199 hostio_error (char *own_buf)
200 {
201 the_target->hostio_last_error (own_buf);
202 }
203
204 static void
205 hostio_packet_error (char *own_buf)
206 {
207 sprintf (own_buf, "F-1,%x", FILEIO_EINVAL);
208 }
209
210 static void
211 hostio_reply (char *own_buf, int result)
212 {
213 sprintf (own_buf, "F%x", result);
214 }
215
216 static int
217 hostio_reply_with_data (char *own_buf, char *buffer, int len,
218 int *new_packet_len)
219 {
220 int input_index, output_index, out_maxlen;
221
222 sprintf (own_buf, "F%x;", len);
223 output_index = strlen (own_buf);
224
225 out_maxlen = PBUFSIZ;
226
227 for (input_index = 0; input_index < len; input_index++)
228 {
229 char b = buffer[input_index];
230
231 if (b == '$' || b == '#' || b == '}' || b == '*')
232 {
233 /* These must be escaped. */
234 if (output_index + 2 > out_maxlen)
235 break;
236 own_buf[output_index++] = '}';
237 own_buf[output_index++] = b ^ 0x20;
238 }
239 else
240 {
241 if (output_index + 1 > out_maxlen)
242 break;
243 own_buf[output_index++] = b;
244 }
245 }
246
247 *new_packet_len = output_index;
248 return input_index;
249 }
250
251 /* Process ID of inferior whose filesystem hostio functions
252 that take FILENAME arguments will use. Zero means to use
253 our own filesystem. */
254
255 static int hostio_fs_pid;
256
257 /* See hostio.h. */
258
259 void
260 hostio_handle_new_gdb_connection (void)
261 {
262 hostio_fs_pid = 0;
263 }
264
265 /* Handle a "vFile:setfs:" packet. */
266
267 static void
268 handle_setfs (char *own_buf)
269 {
270 char *p;
271 int pid;
272
273 /* If the target doesn't have any of the in-filesystem-of methods
274 then there's no point in GDB sending "vFile:setfs:" packets. We
275 reply with an empty packet (i.e. we pretend we don't understand
276 "vFile:setfs:") and that should stop GDB sending any more. */
277 if (the_target->multifs_open == NULL
278 && the_target->multifs_unlink == NULL
279 && the_target->multifs_readlink == NULL)
280 {
281 own_buf[0] = '\0';
282 return;
283 }
284
285 p = own_buf + strlen ("vFile:setfs:");
286
287 if (require_int (&p, &pid)
288 || pid < 0
289 || require_end (p))
290 {
291 hostio_packet_error (own_buf);
292 return;
293 }
294
295 hostio_fs_pid = pid;
296
297 hostio_reply (own_buf, 0);
298 }
299
300 static void
301 handle_open (char *own_buf)
302 {
303 char filename[HOSTIO_PATH_MAX];
304 char *p;
305 int fileio_flags, fileio_mode, flags, fd;
306 mode_t mode;
307 struct fd_list *new_fd;
308
309 p = own_buf + strlen ("vFile:open:");
310
311 if (require_filename (&p, filename)
312 || require_comma (&p)
313 || require_int (&p, &fileio_flags)
314 || require_comma (&p)
315 || require_int (&p, &fileio_mode)
316 || require_end (p)
317 || fileio_to_host_openflags (fileio_flags, &flags)
318 || fileio_to_host_mode (fileio_mode, &mode))
319 {
320 hostio_packet_error (own_buf);
321 return;
322 }
323
324 /* We do not need to convert MODE, since the fileio protocol
325 uses the standard values. */
326 if (hostio_fs_pid != 0 && the_target->multifs_open != NULL)
327 fd = the_target->multifs_open (hostio_fs_pid, filename,
328 flags, mode);
329 else
330 fd = open (filename, flags, mode);
331
332 if (fd == -1)
333 {
334 hostio_error (own_buf);
335 return;
336 }
337
338 /* Record the new file descriptor. */
339 new_fd = XNEW (struct fd_list);
340 new_fd->fd = fd;
341 new_fd->next = open_fds;
342 open_fds = new_fd;
343
344 hostio_reply (own_buf, fd);
345 }
346
347 static void
348 handle_pread (char *own_buf, int *new_packet_len)
349 {
350 int fd, ret, len, offset, bytes_sent;
351 char *p, *data;
352 static int max_reply_size = -1;
353
354 p = own_buf + strlen ("vFile:pread:");
355
356 if (require_int (&p, &fd)
357 || require_comma (&p)
358 || require_valid_fd (fd)
359 || require_int (&p, &len)
360 || require_comma (&p)
361 || require_int (&p, &offset)
362 || require_end (p))
363 {
364 hostio_packet_error (own_buf);
365 return;
366 }
367
368 /* Do not attempt to read more than the maximum number of bytes
369 hostio_reply_with_data can fit in a packet. We may still read
370 too much because of escaping, but this is handled below. */
371 if (max_reply_size == -1)
372 {
373 sprintf (own_buf, "F%x;", PBUFSIZ);
374 max_reply_size = PBUFSIZ - strlen (own_buf);
375 }
376 if (len > max_reply_size)
377 len = max_reply_size;
378
379 data = (char *) xmalloc (len);
380 #ifdef HAVE_PREAD
381 ret = pread (fd, data, len, offset);
382 #else
383 ret = -1;
384 #endif
385 /* If we have no pread or it failed for this file, use lseek/read. */
386 if (ret == -1)
387 {
388 ret = lseek (fd, offset, SEEK_SET);
389 if (ret != -1)
390 ret = read (fd, data, len);
391 }
392
393 if (ret == -1)
394 {
395 hostio_error (own_buf);
396 free (data);
397 return;
398 }
399
400 bytes_sent = hostio_reply_with_data (own_buf, data, ret, new_packet_len);
401
402 /* If we were using read, and the data did not all fit in the reply,
403 we would have to back up using lseek here. With pread it does
404 not matter. But we still have a problem; the return value in the
405 packet might be wrong, so we must fix it. This time it will
406 definitely fit. */
407 if (bytes_sent < ret)
408 bytes_sent = hostio_reply_with_data (own_buf, data, bytes_sent,
409 new_packet_len);
410
411 free (data);
412 }
413
414 static void
415 handle_pwrite (char *own_buf, int packet_len)
416 {
417 int fd, ret, len, offset;
418 char *p, *data;
419
420 p = own_buf + strlen ("vFile:pwrite:");
421
422 if (require_int (&p, &fd)
423 || require_comma (&p)
424 || require_valid_fd (fd)
425 || require_int (&p, &offset)
426 || require_comma (&p)
427 || require_data (p, packet_len - (p - own_buf), &data, &len))
428 {
429 hostio_packet_error (own_buf);
430 return;
431 }
432
433 #ifdef HAVE_PWRITE
434 ret = pwrite (fd, data, len, offset);
435 #else
436 ret = -1;
437 #endif
438 /* If we have no pwrite or it failed for this file, use lseek/write. */
439 if (ret == -1)
440 {
441 ret = lseek (fd, offset, SEEK_SET);
442 if (ret != -1)
443 ret = write (fd, data, len);
444 }
445
446 if (ret == -1)
447 {
448 hostio_error (own_buf);
449 free (data);
450 return;
451 }
452
453 hostio_reply (own_buf, ret);
454 free (data);
455 }
456
457 static void
458 handle_fstat (char *own_buf, int *new_packet_len)
459 {
460 int fd, bytes_sent;
461 char *p;
462 struct stat st;
463 struct fio_stat fst;
464
465 p = own_buf + strlen ("vFile:fstat:");
466
467 if (require_int (&p, &fd)
468 || require_valid_fd (fd)
469 || require_end (p))
470 {
471 hostio_packet_error (own_buf);
472 return;
473 }
474
475 if (fstat (fd, &st) == -1)
476 {
477 hostio_error (own_buf);
478 return;
479 }
480
481 host_to_fileio_stat (&st, &fst);
482
483 bytes_sent = hostio_reply_with_data (own_buf,
484 (char *) &fst, sizeof (fst),
485 new_packet_len);
486
487 /* If the response does not fit into a single packet, do not attempt
488 to return a partial response, but simply fail. */
489 if (bytes_sent < sizeof (fst))
490 write_enn (own_buf);
491 }
492
493 static void
494 handle_close (char *own_buf)
495 {
496 int fd, ret;
497 char *p;
498 struct fd_list **open_fd_p, *old_fd;
499
500 p = own_buf + strlen ("vFile:close:");
501
502 if (require_int (&p, &fd)
503 || require_valid_fd (fd)
504 || require_end (p))
505 {
506 hostio_packet_error (own_buf);
507 return;
508 }
509
510 ret = close (fd);
511
512 if (ret == -1)
513 {
514 hostio_error (own_buf);
515 return;
516 }
517
518 open_fd_p = &open_fds;
519 /* We know that fd is in the list, thanks to require_valid_fd. */
520 while ((*open_fd_p)->fd != fd)
521 open_fd_p = &(*open_fd_p)->next;
522
523 old_fd = *open_fd_p;
524 *open_fd_p = (*open_fd_p)->next;
525 free (old_fd);
526
527 hostio_reply (own_buf, ret);
528 }
529
530 static void
531 handle_unlink (char *own_buf)
532 {
533 char filename[HOSTIO_PATH_MAX];
534 char *p;
535 int ret;
536
537 p = own_buf + strlen ("vFile:unlink:");
538
539 if (require_filename (&p, filename)
540 || require_end (p))
541 {
542 hostio_packet_error (own_buf);
543 return;
544 }
545
546 if (hostio_fs_pid != 0 && the_target->multifs_unlink != NULL)
547 ret = the_target->multifs_unlink (hostio_fs_pid, filename);
548 else
549 ret = unlink (filename);
550
551 if (ret == -1)
552 {
553 hostio_error (own_buf);
554 return;
555 }
556
557 hostio_reply (own_buf, ret);
558 }
559
560 static void
561 handle_readlink (char *own_buf, int *new_packet_len)
562 {
563 char filename[HOSTIO_PATH_MAX], linkname[HOSTIO_PATH_MAX];
564 char *p;
565 int ret, bytes_sent;
566
567 p = own_buf + strlen ("vFile:readlink:");
568
569 if (require_filename (&p, filename)
570 || require_end (p))
571 {
572 hostio_packet_error (own_buf);
573 return;
574 }
575
576 if (hostio_fs_pid != 0 && the_target->multifs_readlink != NULL)
577 ret = the_target->multifs_readlink (hostio_fs_pid, filename,
578 linkname,
579 sizeof (linkname) - 1);
580 else
581 ret = readlink (filename, linkname, sizeof (linkname) - 1);
582
583 if (ret == -1)
584 {
585 hostio_error (own_buf);
586 return;
587 }
588
589 bytes_sent = hostio_reply_with_data (own_buf, linkname, ret, new_packet_len);
590
591 /* If the response does not fit into a single packet, do not attempt
592 to return a partial response, but simply fail. */
593 if (bytes_sent < ret)
594 sprintf (own_buf, "F-1,%x", FILEIO_ENAMETOOLONG);
595 }
596
597 /* Handle all the 'F' file transfer packets. */
598
599 int
600 handle_vFile (char *own_buf, int packet_len, int *new_packet_len)
601 {
602 if (startswith (own_buf, "vFile:open:"))
603 handle_open (own_buf);
604 else if (startswith (own_buf, "vFile:pread:"))
605 handle_pread (own_buf, new_packet_len);
606 else if (startswith (own_buf, "vFile:pwrite:"))
607 handle_pwrite (own_buf, packet_len);
608 else if (startswith (own_buf, "vFile:fstat:"))
609 handle_fstat (own_buf, new_packet_len);
610 else if (startswith (own_buf, "vFile:close:"))
611 handle_close (own_buf);
612 else if (startswith (own_buf, "vFile:unlink:"))
613 handle_unlink (own_buf);
614 else if (startswith (own_buf, "vFile:readlink:"))
615 handle_readlink (own_buf, new_packet_len);
616 else if (startswith (own_buf, "vFile:setfs:"))
617 handle_setfs (own_buf);
618 else
619 return 0;
620
621 return 1;
622 }