GDB (API)
|
00001 /* S-record download support for GDB, the GNU debugger. 00002 Copyright (C) 1995-2013 Free Software Foundation, Inc. 00003 00004 This file is part of GDB. 00005 00006 This program is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation; either version 3 of the License, or 00009 (at your option) any later version. 00010 00011 This program is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00018 00019 #include "defs.h" 00020 #include "serial.h" 00021 #include "srec.h" 00022 #include <sys/time.h> 00023 #include <time.h> 00024 #include "gdb_assert.h" 00025 #include "gdb_string.h" 00026 #include "gdb_bfd.h" 00027 00028 extern int remote_debug; 00029 00030 static int make_srec (char *srec, CORE_ADDR targ_addr, bfd * abfd, 00031 asection * sect, int sectoff, int *maxrecsize, 00032 int flags); 00033 00034 /* Download an executable by converting it to S records. DESC is a 00035 `struct serial *' to send the data to. FILE is the name of the 00036 file to be loaded. LOAD_OFFSET is the offset into memory to load 00037 data into. It is usually specified by the user and is useful with 00038 the a.out file format. MAXRECSIZE is the length in chars of the 00039 largest S-record the host can accomodate. This is measured from 00040 the starting `S' to the last char of the checksum. FLAGS is 00041 various random flags, and HASHMARK is non-zero to cause a `#' to be 00042 printed out for each record loaded. WAITACK, if non-NULL, is a 00043 function that waits for an acknowledgement after each S-record, and 00044 returns non-zero if the ack is read correctly. */ 00045 00046 void 00047 load_srec (struct serial *desc, const char *file, bfd_vma load_offset, 00048 int maxrecsize, 00049 int flags, int hashmark, int (*waitack) (void)) 00050 { 00051 bfd *abfd; 00052 asection *s; 00053 char *srec; 00054 int i; 00055 int reclen; 00056 struct timeval start_time, end_time; 00057 unsigned long data_count = 0; 00058 struct cleanup *cleanup; 00059 00060 srec = (char *) alloca (maxrecsize + 1); 00061 00062 abfd = gdb_bfd_open (file, NULL, -1); 00063 if (!abfd) 00064 { 00065 printf_filtered (_("Unable to open file %s\n"), file); 00066 return; 00067 } 00068 00069 cleanup = make_cleanup_bfd_unref (abfd); 00070 if (bfd_check_format (abfd, bfd_object) == 0) 00071 { 00072 printf_filtered (_("File is not an object file\n")); 00073 do_cleanups (cleanup); 00074 return; 00075 } 00076 00077 gettimeofday (&start_time, NULL); 00078 00079 /* Write a type 0 header record. no data for a type 0, and there 00080 is no data, so len is 0. */ 00081 00082 reclen = maxrecsize; 00083 make_srec (srec, 0, NULL, (asection *) 1, 0, &reclen, flags); 00084 if (remote_debug) 00085 { 00086 srec[reclen] = '\0'; 00087 puts_debug ("sent -->", srec, "<--"); 00088 } 00089 serial_write (desc, srec, reclen); 00090 00091 for (s = abfd->sections; s; s = s->next) 00092 if (s->flags & SEC_LOAD) 00093 { 00094 int numbytes; 00095 00096 bfd_vma addr = bfd_get_section_vma (abfd, s) + load_offset; 00097 bfd_size_type size = bfd_get_section_size (s); 00098 char *section_name = (char *) bfd_get_section_name (abfd, s); 00099 /* Both GDB and BFD have mechanisms for printing addresses. 00100 In the below, GDB's is used so that the address is 00101 consistent with the rest of GDB. BFD's printf_vma() could 00102 have also been used. cagney 1999-09-01 */ 00103 printf_filtered ("%s\t: %s .. %s ", 00104 section_name, 00105 paddress (target_gdbarch (), addr), 00106 paddress (target_gdbarch (), addr + size)); 00107 gdb_flush (gdb_stdout); 00108 00109 data_count += size; 00110 00111 for (i = 0; i < size; i += numbytes) 00112 { 00113 reclen = maxrecsize; 00114 numbytes = make_srec (srec, (CORE_ADDR) (addr + i), abfd, s, 00115 i, &reclen, flags); 00116 00117 if (remote_debug) 00118 { 00119 srec[reclen] = '\0'; 00120 puts_debug ("sent -->", srec, "<--"); 00121 } 00122 00123 /* Repeatedly send the S-record until a good 00124 acknowledgement is sent back. */ 00125 do 00126 { 00127 serial_write (desc, srec, reclen); 00128 if (deprecated_ui_load_progress_hook) 00129 if (deprecated_ui_load_progress_hook (section_name, 00130 (unsigned long) i)) 00131 error (_("Canceled the download")); 00132 } 00133 while (waitack != NULL && !waitack ()); 00134 00135 if (hashmark) 00136 { 00137 putchar_unfiltered ('#'); 00138 gdb_flush (gdb_stdout); 00139 } 00140 } /* Per-packet (or S-record) loop. */ 00141 00142 if (deprecated_ui_load_progress_hook) 00143 if (deprecated_ui_load_progress_hook (section_name, 00144 (unsigned long) i)) 00145 error (_("Canceled the download")); 00146 putchar_unfiltered ('\n'); 00147 } 00148 00149 if (hashmark) 00150 putchar_unfiltered ('\n'); 00151 00152 gettimeofday (&end_time, NULL); 00153 00154 /* Write a terminator record. */ 00155 00156 reclen = maxrecsize; 00157 make_srec (srec, abfd->start_address, NULL, NULL, 0, &reclen, flags); 00158 00159 if (remote_debug) 00160 { 00161 srec[reclen] = '\0'; 00162 puts_debug ("sent -->", srec, "<--"); 00163 } 00164 00165 serial_write (desc, srec, reclen); 00166 00167 /* Some monitors need these to wake up properly. (Which ones? -sts) */ 00168 serial_write (desc, "\r\r", 2); 00169 if (remote_debug) 00170 puts_debug ("sent -->", "\r\r", "<---"); 00171 00172 serial_flush_input (desc); 00173 00174 print_transfer_performance (gdb_stdout, data_count, 0, 00175 &start_time, &end_time); 00176 do_cleanups (cleanup); 00177 } 00178 00179 /* 00180 * make_srec -- make an srecord. This writes each line, one at a 00181 * time, each with it's own header and trailer line. 00182 * An srecord looks like this: 00183 * 00184 * byte count-+ address 00185 * start ---+ | | data +- checksum 00186 * | | | | 00187 * S01000006F6B692D746573742E73726563E4 00188 * S315000448600000000000000000FC00005900000000E9 00189 * S31A0004000023C1400037DE00F023604000377B009020825000348D 00190 * S30B0004485A0000000000004E 00191 * S70500040000F6 00192 * 00193 * S<type><length><address><data><checksum> 00194 * 00195 * Where 00196 * - length 00197 * is the number of bytes following upto the checksum. Note 00198 * that this is not the number of chars following, since it 00199 * takes two chars to represent a byte. 00200 * - type 00201 * is one of: 00202 * 0) header record 00203 * 1) two byte address data record 00204 * 2) three byte address data record 00205 * 3) four byte address data record 00206 * 7) four byte address termination record 00207 * 8) three byte address termination record 00208 * 9) two byte address termination record 00209 * 00210 * - address 00211 * is the start address of the data following, or in the case of 00212 * a termination record, the start address of the image 00213 * - data 00214 * is the data. 00215 * - checksum 00216 * is the sum of all the raw byte data in the record, from the length 00217 * upwards, modulo 256 and subtracted from 255. 00218 * 00219 * This routine returns the length of the S-record. 00220 * 00221 */ 00222 00223 static int 00224 make_srec (char *srec, CORE_ADDR targ_addr, bfd *abfd, asection *sect, 00225 int sectoff, int *maxrecsize, int flags) 00226 { 00227 unsigned char checksum; 00228 int tmp; 00229 static const char hextab[] = "0123456789ABCDEF"; 00230 static const char data_code_table[] = "123"; 00231 static const char term_code_table[] = "987"; 00232 static const char header_code_table[] = "000"; 00233 char const *code_table; 00234 int addr_size; 00235 int payload_size; 00236 char *binbuf; 00237 char *p; 00238 00239 if (sect) 00240 { 00241 tmp = flags; /* Data or header record */ 00242 code_table = abfd ? data_code_table : header_code_table; 00243 binbuf = alloca (*maxrecsize / 2); 00244 } 00245 else 00246 { 00247 tmp = flags >> SREC_TERM_SHIFT; /* Term record */ 00248 code_table = term_code_table; 00249 binbuf = NULL; 00250 } 00251 00252 if ((tmp & SREC_2_BYTE_ADDR) && (targ_addr <= 0xffff)) 00253 addr_size = 2; 00254 else if ((tmp & SREC_3_BYTE_ADDR) && (targ_addr <= 0xffffff)) 00255 addr_size = 3; 00256 else if (tmp & SREC_4_BYTE_ADDR) 00257 addr_size = 4; 00258 else 00259 internal_error (__FILE__, __LINE__, 00260 _("make_srec: Bad address (%s), or bad flags (0x%x)."), 00261 paddress (target_gdbarch (), targ_addr), flags); 00262 00263 /* Now that we know the address size, we can figure out how much 00264 data this record can hold. */ 00265 00266 if (sect && abfd) 00267 { 00268 payload_size = (*maxrecsize - (1 + 1 + 2 + addr_size * 2 + 2)) / 2; 00269 payload_size = min (payload_size, bfd_get_section_size (sect) - sectoff); 00270 00271 bfd_get_section_contents (abfd, sect, binbuf, sectoff, payload_size); 00272 } 00273 else 00274 payload_size = 0; /* Term or header packets have no payload. */ 00275 00276 /* Output the header. */ 00277 snprintf (srec, (*maxrecsize) + 1, "S%c%02X%0*X", 00278 code_table[addr_size - 2], 00279 addr_size + payload_size + 1, 00280 addr_size * 2, (int) targ_addr); 00281 00282 /* Note that the checksum is calculated on the raw data, not the 00283 hexified data. It includes the length, address and the data 00284 portions of the packet. */ 00285 00286 checksum = 0; 00287 00288 checksum += (payload_size + addr_size + 1 /* Packet length */ 00289 + (targ_addr & 0xff) /* Address... */ 00290 + ((targ_addr >> 8) & 0xff) 00291 + ((targ_addr >> 16) & 0xff) 00292 + ((targ_addr >> 24) & 0xff)); 00293 00294 /* NOTE: cagney/2003-08-10: The equation is old. Check that the 00295 recent snprintf changes match that equation. */ 00296 gdb_assert (strlen (srec) == 1 + 1 + 2 + addr_size * 2); 00297 p = srec + 1 + 1 + 2 + addr_size * 2; 00298 00299 /* Build the Srecord. */ 00300 for (tmp = 0; tmp < payload_size; tmp++) 00301 { 00302 unsigned char k; 00303 00304 k = binbuf[tmp]; 00305 *p++ = hextab[k >> 4]; 00306 *p++ = hextab[k & 0xf]; 00307 checksum += k; 00308 } 00309 00310 checksum = ~checksum; 00311 00312 *p++ = hextab[checksum >> 4]; 00313 *p++ = hextab[checksum & 0xf]; 00314 *p++ = '\r'; 00315 00316 *maxrecsize = p - srec; 00317 return payload_size; 00318 }