GDBserver
|
00001 /* Host file transfer support for gdbserver. 00002 Copyright (C) 2007-2013 Free Software Foundation, Inc. 00003 00004 Contributed by CodeSourcery. 00005 00006 This file is part of GDB. 00007 00008 This program is free software; you can redistribute it and/or modify 00009 it under the terms of the GNU General Public License as published by 00010 the Free Software Foundation; either version 3 of the License, or 00011 (at your option) any later version. 00012 00013 This program is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 GNU General Public License for more details. 00017 00018 You should have received a copy of the GNU General Public License 00019 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00020 00021 #include "server.h" 00022 #include "gdb/fileio.h" 00023 #include "hostio.h" 00024 00025 #include <fcntl.h> 00026 #include <limits.h> 00027 #include <unistd.h> 00028 00029 extern int remote_debug; 00030 00031 struct fd_list 00032 { 00033 int fd; 00034 struct fd_list *next; 00035 }; 00036 00037 static struct fd_list *open_fds; 00038 00039 static int 00040 safe_fromhex (char a, int *nibble) 00041 { 00042 if (a >= '0' && a <= '9') 00043 *nibble = a - '0'; 00044 else if (a >= 'a' && a <= 'f') 00045 *nibble = a - 'a' + 10; 00046 else if (a >= 'A' && a <= 'F') 00047 *nibble = a - 'A' + 10; 00048 else 00049 return -1; 00050 00051 return 0; 00052 } 00053 00054 /* Filenames are hex encoded, so the maximum we can handle is half the 00055 packet buffer size. Cap to PATH_MAX, if it is shorter. */ 00056 #if !defined (PATH_MAX) || (PATH_MAX > (PBUFSIZ / 2 + 1)) 00057 # define HOSTIO_PATH_MAX (PBUFSIZ / 2 + 1) 00058 #else 00059 # define HOSTIO_PATH_MAX PATH_MAX 00060 #endif 00061 00062 static int 00063 require_filename (char **pp, char *filename) 00064 { 00065 int count; 00066 char *p; 00067 00068 p = *pp; 00069 count = 0; 00070 00071 while (*p && *p != ',') 00072 { 00073 int nib1, nib2; 00074 00075 /* Don't allow overflow. */ 00076 if (count >= HOSTIO_PATH_MAX - 1) 00077 return -1; 00078 00079 if (safe_fromhex (p[0], &nib1) 00080 || safe_fromhex (p[1], &nib2)) 00081 return -1; 00082 00083 filename[count++] = nib1 * 16 + nib2; 00084 p += 2; 00085 } 00086 00087 filename[count] = '\0'; 00088 *pp = p; 00089 return 0; 00090 } 00091 00092 static int 00093 require_int (char **pp, int *value) 00094 { 00095 char *p; 00096 int count; 00097 00098 p = *pp; 00099 *value = 0; 00100 count = 0; 00101 00102 while (*p && *p != ',') 00103 { 00104 int nib; 00105 00106 /* Don't allow overflow. */ 00107 if (count >= 7) 00108 return -1; 00109 00110 if (safe_fromhex (p[0], &nib)) 00111 return -1; 00112 *value = *value * 16 + nib; 00113 p++; 00114 count++; 00115 } 00116 00117 *pp = p; 00118 return 0; 00119 } 00120 00121 static int 00122 require_data (char *p, int p_len, char **data, int *data_len) 00123 { 00124 int input_index, output_index, escaped; 00125 00126 *data = xmalloc (p_len); 00127 00128 output_index = 0; 00129 escaped = 0; 00130 for (input_index = 0; input_index < p_len; input_index++) 00131 { 00132 char b = p[input_index]; 00133 00134 if (escaped) 00135 { 00136 (*data)[output_index++] = b ^ 0x20; 00137 escaped = 0; 00138 } 00139 else if (b == '}') 00140 escaped = 1; 00141 else 00142 (*data)[output_index++] = b; 00143 } 00144 00145 if (escaped) 00146 { 00147 free (*data); 00148 return -1; 00149 } 00150 00151 *data_len = output_index; 00152 return 0; 00153 } 00154 00155 static int 00156 require_comma (char **pp) 00157 { 00158 if (**pp == ',') 00159 { 00160 (*pp)++; 00161 return 0; 00162 } 00163 else 00164 return -1; 00165 } 00166 00167 static int 00168 require_end (char *p) 00169 { 00170 if (*p == '\0') 00171 return 0; 00172 else 00173 return -1; 00174 } 00175 00176 static int 00177 require_valid_fd (int fd) 00178 { 00179 struct fd_list *fd_ptr; 00180 00181 for (fd_ptr = open_fds; fd_ptr != NULL; fd_ptr = fd_ptr->next) 00182 if (fd_ptr->fd == fd) 00183 return 0; 00184 00185 return -1; 00186 } 00187 00188 /* Fill in own_buf with the last hostio error packet, however it 00189 suitable for the target. */ 00190 static void 00191 hostio_error (char *own_buf) 00192 { 00193 the_target->hostio_last_error (own_buf); 00194 } 00195 00196 static void 00197 hostio_packet_error (char *own_buf) 00198 { 00199 sprintf (own_buf, "F-1,%x", FILEIO_EINVAL); 00200 } 00201 00202 static void 00203 hostio_reply (char *own_buf, int result) 00204 { 00205 sprintf (own_buf, "F%x", result); 00206 } 00207 00208 static int 00209 hostio_reply_with_data (char *own_buf, char *buffer, int len, 00210 int *new_packet_len) 00211 { 00212 int input_index, output_index, out_maxlen; 00213 00214 sprintf (own_buf, "F%x;", len); 00215 output_index = strlen (own_buf); 00216 00217 out_maxlen = PBUFSIZ; 00218 00219 for (input_index = 0; input_index < len; input_index++) 00220 { 00221 char b = buffer[input_index]; 00222 00223 if (b == '$' || b == '#' || b == '}' || b == '*') 00224 { 00225 /* These must be escaped. */ 00226 if (output_index + 2 > out_maxlen) 00227 break; 00228 own_buf[output_index++] = '}'; 00229 own_buf[output_index++] = b ^ 0x20; 00230 } 00231 else 00232 { 00233 if (output_index + 1 > out_maxlen) 00234 break; 00235 own_buf[output_index++] = b; 00236 } 00237 } 00238 00239 *new_packet_len = output_index; 00240 return input_index; 00241 } 00242 00243 static int 00244 fileio_open_flags_to_host (int fileio_open_flags, int *open_flags_p) 00245 { 00246 int open_flags = 0; 00247 00248 if (fileio_open_flags & ~FILEIO_O_SUPPORTED) 00249 return -1; 00250 00251 if (fileio_open_flags & FILEIO_O_CREAT) 00252 open_flags |= O_CREAT; 00253 if (fileio_open_flags & FILEIO_O_EXCL) 00254 open_flags |= O_EXCL; 00255 if (fileio_open_flags & FILEIO_O_TRUNC) 00256 open_flags |= O_TRUNC; 00257 if (fileio_open_flags & FILEIO_O_APPEND) 00258 open_flags |= O_APPEND; 00259 if (fileio_open_flags & FILEIO_O_RDONLY) 00260 open_flags |= O_RDONLY; 00261 if (fileio_open_flags & FILEIO_O_WRONLY) 00262 open_flags |= O_WRONLY; 00263 if (fileio_open_flags & FILEIO_O_RDWR) 00264 open_flags |= O_RDWR; 00265 /* On systems supporting binary and text mode, always open files in 00266 binary mode. */ 00267 #ifdef O_BINARY 00268 open_flags |= O_BINARY; 00269 #endif 00270 00271 *open_flags_p = open_flags; 00272 return 0; 00273 } 00274 00275 static void 00276 handle_open (char *own_buf) 00277 { 00278 char filename[HOSTIO_PATH_MAX]; 00279 char *p; 00280 int fileio_flags, mode, flags, fd; 00281 struct fd_list *new_fd; 00282 00283 p = own_buf + strlen ("vFile:open:"); 00284 00285 if (require_filename (&p, filename) 00286 || require_comma (&p) 00287 || require_int (&p, &fileio_flags) 00288 || require_comma (&p) 00289 || require_int (&p, &mode) 00290 || require_end (p) 00291 || fileio_open_flags_to_host (fileio_flags, &flags)) 00292 { 00293 hostio_packet_error (own_buf); 00294 return; 00295 } 00296 00297 /* We do not need to convert MODE, since the fileio protocol 00298 uses the standard values. */ 00299 fd = open (filename, flags, mode); 00300 00301 if (fd == -1) 00302 { 00303 hostio_error (own_buf); 00304 return; 00305 } 00306 00307 /* Record the new file descriptor. */ 00308 new_fd = xmalloc (sizeof (struct fd_list)); 00309 new_fd->fd = fd; 00310 new_fd->next = open_fds; 00311 open_fds = new_fd; 00312 00313 hostio_reply (own_buf, fd); 00314 } 00315 00316 static void 00317 handle_pread (char *own_buf, int *new_packet_len) 00318 { 00319 int fd, ret, len, offset, bytes_sent; 00320 char *p, *data; 00321 00322 p = own_buf + strlen ("vFile:pread:"); 00323 00324 if (require_int (&p, &fd) 00325 || require_comma (&p) 00326 || require_valid_fd (fd) 00327 || require_int (&p, &len) 00328 || require_comma (&p) 00329 || require_int (&p, &offset) 00330 || require_end (p)) 00331 { 00332 hostio_packet_error (own_buf); 00333 return; 00334 } 00335 00336 data = xmalloc (len); 00337 #ifdef HAVE_PREAD 00338 ret = pread (fd, data, len, offset); 00339 #else 00340 ret = -1; 00341 #endif 00342 /* If we have no pread or it failed for this file, use lseek/read. */ 00343 if (ret == -1) 00344 { 00345 ret = lseek (fd, offset, SEEK_SET); 00346 if (ret != -1) 00347 ret = read (fd, data, len); 00348 } 00349 00350 if (ret == -1) 00351 { 00352 hostio_error (own_buf); 00353 free (data); 00354 return; 00355 } 00356 00357 bytes_sent = hostio_reply_with_data (own_buf, data, ret, new_packet_len); 00358 00359 /* If we were using read, and the data did not all fit in the reply, 00360 we would have to back up using lseek here. With pread it does 00361 not matter. But we still have a problem; the return value in the 00362 packet might be wrong, so we must fix it. This time it will 00363 definitely fit. */ 00364 if (bytes_sent < ret) 00365 bytes_sent = hostio_reply_with_data (own_buf, data, bytes_sent, 00366 new_packet_len); 00367 00368 free (data); 00369 } 00370 00371 static void 00372 handle_pwrite (char *own_buf, int packet_len) 00373 { 00374 int fd, ret, len, offset; 00375 char *p, *data; 00376 00377 p = own_buf + strlen ("vFile:pwrite:"); 00378 00379 if (require_int (&p, &fd) 00380 || require_comma (&p) 00381 || require_valid_fd (fd) 00382 || require_int (&p, &offset) 00383 || require_comma (&p) 00384 || require_data (p, packet_len - (p - own_buf), &data, &len)) 00385 { 00386 hostio_packet_error (own_buf); 00387 return; 00388 } 00389 00390 #ifdef HAVE_PWRITE 00391 ret = pwrite (fd, data, len, offset); 00392 #else 00393 ret = -1; 00394 #endif 00395 /* If we have no pwrite or it failed for this file, use lseek/write. */ 00396 if (ret == -1) 00397 { 00398 ret = lseek (fd, offset, SEEK_SET); 00399 if (ret != -1) 00400 ret = write (fd, data, len); 00401 } 00402 00403 if (ret == -1) 00404 { 00405 hostio_error (own_buf); 00406 free (data); 00407 return; 00408 } 00409 00410 hostio_reply (own_buf, ret); 00411 free (data); 00412 } 00413 00414 static void 00415 handle_close (char *own_buf) 00416 { 00417 int fd, ret; 00418 char *p; 00419 struct fd_list **open_fd_p, *old_fd; 00420 00421 p = own_buf + strlen ("vFile:close:"); 00422 00423 if (require_int (&p, &fd) 00424 || require_valid_fd (fd) 00425 || require_end (p)) 00426 { 00427 hostio_packet_error (own_buf); 00428 return; 00429 } 00430 00431 ret = close (fd); 00432 00433 if (ret == -1) 00434 { 00435 hostio_error (own_buf); 00436 return; 00437 } 00438 00439 open_fd_p = &open_fds; 00440 /* We know that fd is in the list, thanks to require_valid_fd. */ 00441 while ((*open_fd_p)->fd != fd) 00442 open_fd_p = &(*open_fd_p)->next; 00443 00444 old_fd = *open_fd_p; 00445 *open_fd_p = (*open_fd_p)->next; 00446 free (old_fd); 00447 00448 hostio_reply (own_buf, ret); 00449 } 00450 00451 static void 00452 handle_unlink (char *own_buf) 00453 { 00454 char filename[HOSTIO_PATH_MAX]; 00455 char *p; 00456 int ret; 00457 00458 p = own_buf + strlen ("vFile:unlink:"); 00459 00460 if (require_filename (&p, filename) 00461 || require_end (p)) 00462 { 00463 hostio_packet_error (own_buf); 00464 return; 00465 } 00466 00467 ret = unlink (filename); 00468 00469 if (ret == -1) 00470 { 00471 hostio_error (own_buf); 00472 return; 00473 } 00474 00475 hostio_reply (own_buf, ret); 00476 } 00477 00478 static void 00479 handle_readlink (char *own_buf, int *new_packet_len) 00480 { 00481 #if defined (HAVE_READLINK) 00482 char filename[HOSTIO_PATH_MAX], linkname[HOSTIO_PATH_MAX]; 00483 char *p; 00484 int ret, bytes_sent; 00485 00486 p = own_buf + strlen ("vFile:readlink:"); 00487 00488 if (require_filename (&p, filename) 00489 || require_end (p)) 00490 { 00491 hostio_packet_error (own_buf); 00492 return; 00493 } 00494 00495 ret = readlink (filename, linkname, sizeof (linkname) - 1); 00496 if (ret == -1) 00497 { 00498 hostio_error (own_buf); 00499 return; 00500 } 00501 00502 bytes_sent = hostio_reply_with_data (own_buf, linkname, ret, new_packet_len); 00503 00504 /* If the response does not fit into a single packet, do not attempt 00505 to return a partial response, but simply fail. */ 00506 if (bytes_sent < ret) 00507 sprintf (own_buf, "F-1,%x", FILEIO_ENAMETOOLONG); 00508 #else /* ! HAVE_READLINK */ 00509 sprintf (own_buf, "F-1,%x", FILEIO_ENOSYS); 00510 #endif 00511 } 00512 00513 /* Handle all the 'F' file transfer packets. */ 00514 00515 int 00516 handle_vFile (char *own_buf, int packet_len, int *new_packet_len) 00517 { 00518 if (strncmp (own_buf, "vFile:open:", 11) == 0) 00519 handle_open (own_buf); 00520 else if (strncmp (own_buf, "vFile:pread:", 11) == 0) 00521 handle_pread (own_buf, new_packet_len); 00522 else if (strncmp (own_buf, "vFile:pwrite:", 12) == 0) 00523 handle_pwrite (own_buf, packet_len); 00524 else if (strncmp (own_buf, "vFile:close:", 12) == 0) 00525 handle_close (own_buf); 00526 else if (strncmp (own_buf, "vFile:unlink:", 13) == 0) 00527 handle_unlink (own_buf); 00528 else if (strncmp (own_buf, "vFile:readlink:", 15) == 0) 00529 handle_readlink (own_buf, new_packet_len); 00530 else 00531 return 0; 00532 00533 return 1; 00534 }