aboutsummaryrefslogtreecommitdiff
path: root/bfd/srec.c
diff options
context:
space:
mode:
authorKen Raeburn <raeburn@cygnus>1995-01-12 21:37:32 +0000
committerKen Raeburn <raeburn@cygnus>1995-01-12 21:37:32 +0000
commit7f4c005d31f2c970f59c93eae2eb1c2489ec6281 (patch)
tree06e3faa2cf12e27fb28a6bc1a0d42ec44f224e65 /bfd/srec.c
parent89f7a04c0bc9aaa52d961b366601f67b0a091781 (diff)
downloadgdb-7f4c005d31f2c970f59c93eae2eb1c2489ec6281.zip
gdb-7f4c005d31f2c970f59c93eae2eb1c2489ec6281.tar.gz
gdb-7f4c005d31f2c970f59c93eae2eb1c2489ec6281.tar.bz2
* srec.c, tekhex.c: Include libiberty.h. Delete static array hex_value and
replace references to it with references to hex_init, hex_p, and hex_value. * tekhex.c (digs): Now const.
Diffstat (limited to 'bfd/srec.c')
-rw-r--r--bfd/srec.c883
1 files changed, 554 insertions, 329 deletions
diff --git a/bfd/srec.c b/bfd/srec.c
index f3612df..3ec152f 100644
--- a/bfd/srec.c
+++ b/bfd/srec.c
@@ -106,10 +106,20 @@ DESCRIPTION
#include "bfd.h"
#include "sysdep.h"
#include "libbfd.h"
+#include "libiberty.h"
+
+static void srec_init PARAMS ((void));
+static boolean srec_mkobject PARAMS ((bfd *));
+static int srec_get_byte PARAMS ((bfd *, boolean *));
+static void srec_bad_byte PARAMS ((bfd *, unsigned int, int, boolean));
+static boolean srec_scan PARAMS ((bfd *));
+static const bfd_target *srec_object_p PARAMS ((bfd *));
+static const bfd_target *symbolsrec_object_p PARAMS ((bfd *));
+static boolean srec_read_section PARAMS ((bfd *, asection *, bfd_byte *));
static boolean srec_write_record PARAMS ((bfd *, int, bfd_vma,
- const unsigned char *,
- const unsigned char *));
+ const bfd_byte *,
+ const bfd_byte *));
static boolean srec_write_header PARAMS ((bfd *));
static boolean srec_write_symbols PARAMS ((bfd *));
@@ -117,18 +127,13 @@ static boolean srec_write_symbols PARAMS ((bfd *));
static CONST char digs[] = "0123456789ABCDEF";
-/* Table that gets filled in with numbers corresponding to hex chars. */
-
-static char hex_value[256];
-
-#define NOT_HEX 20
-#define NIBBLE(x) hex_value[(unsigned char)(x)]
+#define NIBBLE(x) hex_value(x)
#define HEX(buffer) ((NIBBLE((buffer)[0])<<4) + NIBBLE((buffer)[1]))
#define TOHEX(d, x, ch) \
d[1] = digs[(x) & 0xf]; \
d[0] = digs[((x)>>4)&0xf]; \
ch += ((x) & 0xff);
-#define ISHEX(x) (hex_value[(unsigned char)(x)] != NOT_HEX)
+#define ISHEX(x) hex_p(x)
/* Initialize by filling in the hex conversion array. */
@@ -141,57 +146,49 @@ srec_init ()
if (inited == false)
{
inited = true;
-
- for (i = 0; i < sizeof (hex_value); i++)
- {
- hex_value[i] = NOT_HEX;
- }
- for (i = 0; i < 10; i++)
- {
- hex_value[i + '0'] = i;
- }
- for (i = 0; i < 6; i++)
- {
- hex_value[i + 'a'] = i + 10;
- hex_value[i + 'A'] = i + 10;
- }
+ hex_init ();
}
}
-
/* The maximum number of bytes on a line is FF */
#define MAXCHUNK 0xff
/* The number of bytes we fit onto a line on output */
#define CHUNK 21
-/* We cannot output our srecords as we see them, we have to glue them
- together, this is done in this structure : */
+/* When writing an S-record file, the S-records can not be output as
+ they are seen. This structure is used to hold them in memory. */
struct srec_data_list_struct
{
- unsigned char *data;
+ struct srec_data_list_struct *next;
+ bfd_byte *data;
bfd_vma where;
bfd_size_type size;
- struct srec_data_list_struct *next;
+};
+typedef struct srec_data_list_struct srec_data_list_type;
+/* When scanning the S-record file, a linked list of srec_symbol
+ structures is built to represent the symbol table (if there is
+ one). */
+
+struct srec_symbol
+{
+ struct srec_symbol *next;
+ const char *name;
+ bfd_vma val;
};
-typedef struct srec_data_list_struct srec_data_list_type;
+/* The S-record tdata information. */
typedef struct srec_data_struct
{
srec_data_list_type *head;
srec_data_list_type *tail;
unsigned int type;
-
- int done_symbol_read;
- int count;
- asymbol *symbols;
- char *strings;
- int symbol_idx;
- int string_size;
- int string_idx;
+ struct srec_symbol *symbols;
+ struct srec_symbol *symtail;
+ asymbol *csymbols;
}
tdata_type;
@@ -199,323 +196,393 @@ static boolean srec_write_section PARAMS ((bfd *, tdata_type *,
srec_data_list_type *));
static boolean srec_write_terminator PARAMS ((bfd *, tdata_type *));
-/*
- called once per input S-Record, used to work out vma and size of data.
- */
-
-static bfd_vma low, high;
+/* Set up the S-record tdata information. */
-/*ARGSUSED*/
-static void
-size_symbols (abfd, buf, len, val)
+static boolean
+srec_mkobject (abfd)
bfd *abfd;
- char *buf;
- int len;
- int val;
{
- abfd->symcount++;
- abfd->tdata.srec_data->string_size += len + 1;
-}
+ srec_init ();
-static void
-fillup_symbols (abfd, buf, len, val)
- bfd *abfd;
- char *buf;
- int len;
- int val;
-{
- if (!abfd->tdata.srec_data->done_symbol_read)
+ if (abfd->tdata.srec_data == NULL)
{
- asymbol *p;
- if (abfd->tdata.srec_data->symbols == 0)
+ tdata_type *tdata = (tdata_type *) bfd_alloc (abfd, sizeof (tdata_type));
+ if (tdata == NULL)
{
- abfd->tdata.srec_data->symbols = (asymbol *) bfd_alloc (abfd, abfd->symcount * sizeof (asymbol));
- abfd->tdata.srec_data->strings = (char *) bfd_alloc (abfd, abfd->tdata.srec_data->string_size);
- if (!abfd->tdata.srec_data->symbols || !abfd->tdata.srec_data->strings)
- {
- bfd_set_error (bfd_error_no_memory);
- abort (); /* FIXME */
- }
- abfd->tdata.srec_data->symbol_idx = 0;
- abfd->tdata.srec_data->string_idx = 0;
+ bfd_set_error (bfd_error_no_memory);
+ return false;
}
-
- p = abfd->tdata.srec_data->symbols + abfd->tdata.srec_data->symbol_idx++;
- p->the_bfd = abfd;
- p->name = abfd->tdata.srec_data->strings + abfd->tdata.srec_data->string_idx;
- memcpy ((char *) (p->name), buf, len + 1);
- abfd->tdata.srec_data->string_idx += len + 1;
- p->value = val;
- p->flags = BSF_EXPORT | BSF_GLOBAL;
- p->section = bfd_abs_section_ptr;
- p->udata.p = NULL;
+ abfd->tdata.srec_data = tdata;
+ tdata->type = 1;
+ tdata->head = NULL;
+ tdata->tail = NULL;
+ tdata->symbols = NULL;
+ tdata->symtail = NULL;
+ tdata->csymbols = NULL;
}
-}
-/*ARGSUSED*/
-static void
-size_srec (abfd, section, address, raw, length)
- bfd *abfd;
- asection *section;
- bfd_vma address;
- bfd_byte *raw;
- unsigned int length;
-{
- if (address < low)
- low = address;
- if (address + length > high)
- high = address + length - 1;
-}
+ return true;
+}
-/*
- called once per input S-Record, copies data from input into bfd_alloc'd area
- */
+/* Read a byte from an S record file. Set *ERRORPTR if an error
+ occurred. Return EOF on error or end of file. */
-/*ARGSUSED*/
-static void
-fillup (abfd, section, address, raw, length)
+static int
+srec_get_byte (abfd, errorptr)
bfd *abfd;
- asection *section;
- bfd_vma address;
- bfd_byte *raw;
- unsigned int length;
+ boolean *errorptr;
{
- unsigned int i;
- bfd_byte *dst =
- (bfd_byte *) (section->used_by_bfd) + address - section->vma;
- /* length -1 because we don't read in the checksum */
- for (i = 0; i < length - 1; i++)
+ bfd_byte c;
+
+ if (bfd_read (&c, 1, 1, abfd) != 1)
{
- *dst = HEX (raw);
- dst++;
- raw += 2;
+ if (bfd_get_error () != bfd_error_file_truncated)
+ *errorptr = true;
+ return EOF;
}
+
+ return (int) (c & 0xff);
}
-/* Pass over an S-Record file, calling one of the above functions on each
- record. */
+/* Report a problem in an S record file. FIXME: This probably should
+ not call fprintf, but we really do need some mechanism for printing
+ error messages. */
-static int
-white (x)
- char x;
-{
- return (x == ' ' || x == '\t' || x == '\n' || x == '\r');
-}
-static int
-skipwhite (src, abfd)
- char *src;
+static void
+srec_bad_byte (abfd, lineno, c, error)
bfd *abfd;
+ unsigned int lineno;
+ int c;
+ boolean error;
{
- int eof = 0;
- while (white (*src) && !eof)
+ if (c == EOF)
{
- eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1);
+ if (! error)
+ bfd_set_error (bfd_error_file_truncated);
+ }
+ else
+ {
+ char buf[10];
+
+ if (! isprint (c))
+ sprintf (buf, "\\%03o", (unsigned int) c);
+ else
+ {
+ buf[0] = c;
+ buf[1] = '\0';
+ }
+ fprintf (stderr, "%s:%d: Unexpected character `%s' in S-record file\n",
+ bfd_get_filename (abfd), lineno, buf);
+ bfd_set_error (bfd_error_bad_value);
}
- return eof;
}
+/* Add a new symbol found in an S-record file. */
+
static boolean
-srec_mkobject (abfd)
+srec_new_symbol (abfd, name, val)
bfd *abfd;
+ const char *name;
+ bfd_vma val;
{
- if (abfd->tdata.srec_data == 0)
+ struct srec_symbol *n;
+
+ n = (struct srec_symbol *) bfd_alloc (abfd, sizeof (struct srec_symbol));
+ if (n == NULL)
{
- tdata_type *tdata = (tdata_type *) bfd_alloc (abfd, sizeof (tdata_type));
- if (!tdata)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
- abfd->tdata.srec_data = tdata;
- tdata->type = 1;
- tdata->head = NULL;
- tdata->tail = NULL;
+ bfd_set_error (bfd_error_no_memory);
+ return false;
}
- return true;
+ n->name = name;
+ n->val = val;
+
+ if (abfd->tdata.srec_data->symbols == NULL)
+ abfd->tdata.srec_data->symbols = n;
+ else
+ abfd->tdata.srec_data->symtail->next = n;
+ abfd->tdata.srec_data->symtail = n;
+ n->next = NULL;
+
+ ++abfd->symcount;
+
+ return true;
}
-static void
-pass_over (abfd, func, symbolfunc, section)
+/* Read the S record file and turn it into sections. We create a new
+ section for each contiguous set of bytes. */
+
+static boolean
+srec_scan (abfd)
bfd *abfd;
- void (*func) ();
- void (*symbolfunc) ();
- asection *section;
{
- unsigned int bytes_on_line;
- boolean eof = false;
+ int c;
+ unsigned int lineno = 1;
+ boolean error = false;
+ bfd_byte *buf = NULL;
+ size_t bufsize = 0;
+ asection *sec = NULL;
- srec_mkobject (abfd);
- /* To the front of the file */
if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
- abort ();
- while (eof == false)
+ goto error_return;
+
+ while ((c = srec_get_byte (abfd, &error)) != EOF)
{
- char buffer[MAXCHUNK];
- char *src = buffer;
- char type;
- bfd_vma address = 0;
-
- /* Find first 'S' or $ */
- eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1);
- switch (*src)
+ /* We only build sections from contiguous S-records, so if this
+ is not an S-record, then stop building a section. */
+ if (c != 'S' && c != '\r' && c != '\n')
+ sec = NULL;
+
+ switch (c)
{
default:
- if (eof)
- return;
+ srec_bad_byte (abfd, lineno, c, error);
+ goto error_return;
+
+ case '\n':
+ ++lineno;
+ break;
+
+ case '\r':
break;
case '$':
- /* Inside a symbol definition - just ignore the module name */
- while (*src != '\n' && !eof)
+ /* Starting a module name, which we ignore. */
+ while ((c = srec_get_byte (abfd, &error)) != '\n'
+ && c != EOF)
+ ;
+ if (c == EOF)
{
- eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1);
+ srec_bad_byte (abfd, lineno, c, error);
+ goto error_return;
}
+
+ ++lineno;
+
break;
case ' ':
- /* spaces - maybe just before a symbol */
- while (*src != '\n' && *src != '\r' && white (*src))
- {
- eof = skipwhite (src, abfd);
+ {
+ char *symname;
+ bfd_vma symval;
+
+ /* Starting a symbol definition. */
+ while ((c = srec_get_byte (abfd, &error)) != EOF
+ && (c == ' ' || c == '\t'))
+ ;
+ if (c == EOF)
+ {
+ srec_bad_byte (abfd, lineno, c, error);
+ goto error_return;
+ }
+ obstack_1grow (&abfd->memory, c);
+ while ((c = srec_get_byte (abfd, &error)) != EOF
+ && ! isspace (c))
+ obstack_1grow (&abfd->memory, c);
+ if (c == EOF)
{
- int val = 0;
- int slen = 0;
- char symbol[MAXCHUNK];
+ srec_bad_byte (abfd, lineno, c, error);
+ goto error_return;
+ }
- /* get the symbol part */
- while (!eof && !white (*src) && slen < MAXCHUNK)
- {
- symbol[slen++] = *src;
- eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1);
- }
- symbol[slen] = 0;
- eof = skipwhite (src, abfd);
- /* skip the $ for the hex value */
- if (*src == '$')
- {
- eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1);
- }
+ symname = obstack_finish (&abfd->memory);
+ if (symname == NULL)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ goto error_return;
+ }
+
+ while ((c = srec_get_byte (abfd, &error)) != EOF
+ && (c == ' ' || c == '\t'))
+ ;
+ if (c == EOF)
+ {
+ srec_bad_byte (abfd, lineno, c, error);
+ goto error_return;
+ }
- /* Scan off the hex number */
- while (isxdigit (*src))
+ /* Skip a dollar sign before the hex value. */
+ if (c == '$')
+ {
+ c = srec_get_byte (abfd, &error);
+ if (c == EOF)
{
- val *= 16;
- if (isdigit (*src))
- val += *src - '0';
- else if (isupper (*src))
- {
- val += *src - 'A' + 10;
- }
- else
- {
- val += *src - 'a' + 10;
- }
- eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1);
+ srec_bad_byte (abfd, lineno, c, error);
+ goto error_return;
}
- symbolfunc (abfd, symbol, slen, val);
}
- }
+
+ symval = 0;
+ while (ISHEX (c))
+ {
+ symval <<= 4;
+ symval += NIBBLE (c);
+ c = srec_get_byte (abfd, &error);
+ }
+
+ if (c == EOF || ! isspace (c))
+ {
+ srec_bad_byte (abfd, lineno, c, error);
+ goto error_return;
+ }
+
+ if (! srec_new_symbol (abfd, symname, symval))
+ goto error_return;
+
+ if (c == '\n')
+ ++lineno;
+
+ }
break;
+
case 'S':
- src++;
+ {
+ file_ptr pos;
+ char hdr[3];
+ unsigned int bytes;
+ bfd_vma address;
+ bfd_byte *data;
- /* Fetch the type and the length */
- if (bfd_read (src, 1, 3, abfd) != 3)
- abort (); /* FIXME */
+ /* Starting an S-record. */
- type = *src++;
+ pos = bfd_tell (abfd) - 1;
- if (!ISHEX (src[0]) || !ISHEX (src[1]))
- break;
+ if (bfd_read (hdr, 1, 3, abfd) != 3)
+ goto error_return;
- bytes_on_line = HEX (src);
+ if (! ISHEX (hdr[1]) || ! ISHEX (hdr[2]))
+ {
+ if (! ISHEX (hdr[1]))
+ c = hdr[1];
+ else
+ c = hdr[2];
+ srec_bad_byte (abfd, lineno, c, error);
+ goto error_return;
+ }
- if (bytes_on_line > MAXCHUNK / 2)
- break;
- src += 2;
+ bytes = HEX (hdr + 1);
+ if (bytes * 2 > bufsize)
+ {
+ if (buf != NULL)
+ free (buf);
+ buf = (bfd_byte *) malloc (bytes * 2);
+ if (buf == NULL)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ goto error_return;
+ }
+ bufsize = bytes * 2;
+ }
- if (bfd_read (src, 1, bytes_on_line * 2, abfd) != bytes_on_line * 2)
- abort (); /* FIXME */
+ if (bfd_read (buf, 1, bytes * 2, abfd) != bytes * 2)
+ goto error_return;
- switch (type)
- {
- case '0':
- case '5':
- /* Prologue - ignore */
- break;
- case '3':
- address = HEX (src);
- src += 2;
- bytes_on_line--;
-
- case '2':
- address = HEX (src) | (address << 8);
- src += 2;
- bytes_on_line--;
- case '1':
- address = HEX (src) | (address << 8);
- src += 2;
- address = HEX (src) | (address << 8);
- src += 2;
- bytes_on_line -= 2;
- func (abfd, section, address, src, bytes_on_line);
- break;
-
- case '7':
- address = HEX (src);
- src += 2;
- bytes_on_line--;
- case '8':
- address = HEX (src) | (address << 8);
- src += 2;
- bytes_on_line--;
- case '9':
- address = HEX (src) | (address << 8);
- src += 2;
- address = HEX (src) | (address << 8);
- src += 2;
- bytes_on_line -= 2;
- abfd->start_address = address;
- return;
-
- default:
- return;
- }
+ /* Ignore the checksum byte. */
+ --bytes;
+
+ address = 0;
+ data = buf;
+ switch (hdr[0])
+ {
+ case '0':
+ case '5':
+ /* Prologue--ignore the file name, but stop building a
+ section at this point. */
+ sec = NULL;
+ break;
+
+ case '3':
+ address = HEX (data);
+ data += 2;
+ --bytes;
+ /* Fall through. */
+ case '2':
+ address = (address << 8) | HEX (data);
+ data += 2;
+ --bytes;
+ /* Fall through. */
+ case '1':
+ address = (address << 8) | HEX (data);
+ data += 2;
+ address = (address << 8) | HEX (data);
+ data += 2;
+ bytes -= 2;
+
+ if (sec != NULL
+ && sec->vma + sec->_raw_size == address)
+ {
+ /* This data goes at the end of the section we are
+ currently building. */
+ sec->_raw_size += bytes;
+ }
+ else
+ {
+ char secbuf[20];
+ char *secname;
+
+ sprintf (secbuf, ".sec%d", bfd_count_sections (abfd) + 1);
+ secname = (char *) bfd_alloc (abfd, strlen (secbuf) + 1);
+ strcpy (secname, secbuf);
+ sec = bfd_make_section (abfd, secname);
+ if (sec == NULL)
+ goto error_return;
+ sec->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
+ sec->vma = address;
+ sec->_raw_size = bytes;
+ sec->filepos = pos;
+ }
+
+ break;
+
+ case '7':
+ address = HEX (data);
+ data += 2;
+ /* Fall through. */
+ case '8':
+ address = (address << 8) | HEX (data);
+ data += 2;
+ /* Fall through. */
+ case '9':
+ address = (address << 8) | HEX (data);
+ data += 2;
+ address = (address << 8) | HEX (data);
+ data += 2;
+
+ /* This is a termination record. */
+ abfd->start_address = address;
+
+ if (buf != NULL)
+ free (buf);
+
+ return true;
+ }
+ }
+ break;
}
}
-}
+ if (error)
+ goto error_return;
-static const bfd_target *
-object_p (abfd)
- bfd *abfd;
-{
- asection *section;
- /* We create one section called .text for all the contents,
- and allocate enough room for the entire file. */
-
- section = bfd_make_section (abfd, ".text");
- section->_raw_size = 0;
- section->vma = 0xffffffff;
- low = 0xffffffff;
- high = 0;
- pass_over (abfd, size_srec, size_symbols, section);
- section->_raw_size = high - low;
- section->vma = low;
- section->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
-
- if (abfd->symcount)
- abfd->flags |= HAS_SYMS;
- return abfd->xvec;
+ if (buf != NULL)
+ free (buf);
+
+ return true;
+
+ error_return:
+ if (buf != NULL)
+ free (buf);
+ return false;
}
+/* Check whether an existing file is an S-record file. */
+
static const bfd_target *
srec_object_p (abfd)
bfd *abfd;
{
- char b[4];
+ bfd_byte b[4];
srec_init ();
@@ -524,33 +591,166 @@ srec_object_p (abfd)
return NULL;
if (b[0] != 'S' || !ISHEX (b[1]) || !ISHEX (b[2]) || !ISHEX (b[3]))
- return (const bfd_target *) NULL;
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
- /* We create one section called .text for all the contents,
- and allocate enough room for the entire file. */
+ if (! srec_mkobject (abfd)
+ || ! srec_scan (abfd))
+ return NULL;
- return object_p (abfd);
+ return abfd->xvec;
}
+/* Check whether an existing file is an S-record file with symbols. */
static const bfd_target *
symbolsrec_object_p (abfd)
bfd *abfd;
{
- char b[4];
+ char b[2];
srec_init ();
if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
- || bfd_read (b, 1, 4, abfd) != 4)
+ || bfd_read (b, 1, 2, abfd) != 2)
return NULL;
if (b[0] != '$' || b[1] != '$')
- return (const bfd_target *) NULL;
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
- return object_p (abfd);
+ if (! srec_mkobject (abfd)
+ || ! srec_scan (abfd))
+ return NULL;
+
+ return abfd->xvec;
}
+/* Read in the contents of a section in an S-record file. */
+
+static boolean
+srec_read_section (abfd, section, contents)
+ bfd *abfd;
+ asection *section;
+ bfd_byte *contents;
+{
+ int c;
+ bfd_size_type sofar = 0;
+ boolean error = false;
+ bfd_byte *buf = NULL;
+ size_t bufsize = 0;
+
+ if (bfd_seek (abfd, section->filepos, SEEK_SET) != 0)
+ goto error_return;
+
+ while ((c = srec_get_byte (abfd, &error)) != EOF)
+ {
+ bfd_byte hdr[3];
+ unsigned int bytes;
+ bfd_vma address;
+ bfd_byte *data;
+
+ if (c == '\r' || c == '\n')
+ continue;
+
+ /* This is called after srec_scan has already been called, so we
+ ought to know the exact format. */
+ BFD_ASSERT (c == 'S');
+
+ if (bfd_read (hdr, 1, 3, abfd) != 3)
+ goto error_return;
+
+ BFD_ASSERT (ISHEX (hdr[1]) && ISHEX (hdr[2]));
+
+ bytes = HEX (hdr + 1);
+
+ if (bytes * 2 > bufsize)
+ {
+ if (buf != NULL)
+ free (buf);
+ buf = (bfd_byte *) malloc (bytes * 2);
+ if (buf == NULL)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ goto error_return;
+ }
+ bufsize = bytes * 2;
+ }
+
+ if (bfd_read (buf, 1, bytes * 2, abfd) != bytes * 2)
+ goto error_return;
+
+ address = 0;
+ data = buf;
+ switch (hdr[0])
+ {
+ default:
+ BFD_ASSERT (sofar == section->_raw_size);
+ if (buf != NULL)
+ free (buf);
+ return true;
+
+ case '3':
+ address = HEX (data);
+ data += 2;
+ --bytes;
+ /* Fall through. */
+ case '2':
+ address = (address << 8) | HEX (data);
+ data += 2;
+ --bytes;
+ /* Fall through. */
+ case '1':
+ address = (address << 8) | HEX (data);
+ data += 2;
+ address = (address << 8) | HEX (data);
+ data += 2;
+ bytes -= 2;
+
+ if (address != section->vma + sofar)
+ {
+ /* We've come to the end of this section. */
+ BFD_ASSERT (sofar == section->_raw_size);
+ if (buf != NULL)
+ free (buf);
+ return true;
+ }
+
+ /* Don't consider checksum. */
+ --bytes;
+
+ while (bytes-- != 0)
+ {
+ contents[sofar] = HEX (data);
+ data += 2;
+ ++sofar;
+ }
+
+ break;
+ }
+ }
+
+ if (error)
+ goto error_return;
+
+ BFD_ASSERT (sofar == section->_raw_size);
+
+ if (buf != NULL)
+ free (buf);
+
+ return true;
+
+ error_return:
+ if (buf != NULL)
+ free (buf);
+ return false;
+}
+
+/* Get the contents of a section in an S-record file. */
static boolean
srec_get_section_contents (abfd, section, location, offset, count)
@@ -560,35 +760,25 @@ srec_get_section_contents (abfd, section, location, offset, count)
file_ptr offset;
bfd_size_type count;
{
- if (section->used_by_bfd == (PTR) NULL)
+ if (section->used_by_bfd == NULL)
{
- section->used_by_bfd = (PTR) bfd_alloc (abfd, section->_raw_size);
- if (!section->used_by_bfd)
+ section->used_by_bfd = bfd_alloc (abfd, section->_raw_size);
+ if (section->used_by_bfd == NULL
+ && section->_raw_size != 0)
{
bfd_set_error (bfd_error_no_memory);
return false;
}
- pass_over (abfd, fillup, fillup_symbols, section);
+ if (! srec_read_section (abfd, section, section->used_by_bfd))
+ return false;
}
- memcpy ((PTR) location,
- (PTR) ((char *) (section->used_by_bfd) + offset),
- count);
- return true;
-}
+ memcpy (location, (bfd_byte *) section->used_by_bfd + offset, count);
-
-boolean
-srec_set_arch_mach (abfd, arch, machine)
- bfd *abfd;
- enum bfd_architecture arch;
- unsigned long machine;
-{
- return bfd_default_set_arch_mach (abfd, arch, machine);
+ return true;
}
-
/* we have to save up all the Srecords for a splurge before output,
also remember */
@@ -614,7 +804,7 @@ srec_set_section_contents (abfd, section, location, offset, bytes_to_do)
if ((section->flags & SEC_ALLOC)
&& (section->flags & SEC_LOAD))
{
- unsigned char *data = (unsigned char *) bfd_alloc (abfd, bytes_to_do);
+ bfd_byte *data = (bfd_byte *) bfd_alloc (abfd, bytes_to_do);
if (data == NULL)
{
bfd_set_error (bfd_error_no_memory);
@@ -675,17 +865,15 @@ srec_write_record (abfd, type, address, data, end)
bfd *abfd;
int type;
bfd_vma address;
- const unsigned char *data;
- const unsigned char *end;
+ const bfd_byte *data;
+ const bfd_byte *end;
{
char buffer[MAXCHUNK];
-
unsigned int check_sum = 0;
- CONST unsigned char *src = data;
+ CONST bfd_byte *src = data;
char *dst = buffer;
char *length;
-
*dst++ = 'S';
*dst++ = '0' + type;
@@ -738,8 +926,8 @@ static boolean
srec_write_header (abfd)
bfd *abfd;
{
- unsigned char buffer[MAXCHUNK];
- unsigned char *dst = buffer;
+ bfd_byte buffer[MAXCHUNK];
+ bfd_byte *dst = buffer;
unsigned int i;
/* I'll put an arbitary 40 char limit on header size */
@@ -757,7 +945,7 @@ srec_write_section (abfd, tdata, list)
srec_data_list_type *list;
{
unsigned int bytes_written = 0;
- unsigned char *location = list->data;
+ bfd_byte *location = list->data;
while (bytes_written < list->size)
{
@@ -791,7 +979,7 @@ srec_write_terminator (abfd, tdata)
bfd *abfd;
tdata_type *tdata;
{
- unsigned char buffer[2];
+ bfd_byte buffer[2];
return srec_write_record (abfd, 10 - tdata->type,
abfd->start_address, buffer, buffer);
@@ -930,29 +1118,58 @@ srec_make_empty_symbol (abfd)
return new;
}
+/* Return the amount of memory needed to read the symbol table. */
+
static long
srec_get_symtab_upper_bound (abfd)
bfd *abfd;
{
- /* Read in all the info */
- if (! srec_get_section_contents (abfd, abfd->sections, 0, 0, 0))
- return -1;
- return (bfd_get_symcount (abfd) + 1) * (sizeof (asymbol *));
+ return (bfd_get_symcount (abfd) + 1) * sizeof (asymbol *);
}
+/* Return the symbol table. */
+
static long
srec_get_symtab (abfd, alocation)
bfd *abfd;
asymbol **alocation;
{
- int lim = abfd->symcount;
- int i;
- for (i = 0; i < lim; i++)
+ unsigned int symcount = bfd_get_symcount (abfd);
+ asymbol *csymbols;
+ unsigned int i;
+
+ csymbols = abfd->tdata.srec_data->csymbols;
+ if (csymbols == NULL)
{
- alocation[i] = abfd->tdata.srec_data->symbols + i;
+ asymbol *c;
+ struct srec_symbol *s;
+
+ csymbols = (asymbol *) bfd_alloc (abfd, symcount * sizeof (asymbol));
+ if (csymbols == NULL && symcount != 0)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return false;
+ }
+ abfd->tdata.srec_data->csymbols = csymbols;
+
+ for (s = abfd->tdata.srec_data->symbols, c = csymbols;
+ s != NULL;
+ s = s->next, ++c)
+ {
+ c->the_bfd = abfd;
+ c->name = s->name;
+ c->value = s->val;
+ c->flags = BSF_GLOBAL;
+ c->section = bfd_abs_section_ptr;
+ c->udata.p = NULL;
+ }
}
- alocation[i] = 0;
- return lim;
+
+ for (i = 0; i < symcount; i++)
+ *alocation++ = csymbols++;
+ *alocation = NULL;
+
+ return symcount;
}
/*ARGSUSED*/
@@ -997,6 +1214,14 @@ srec_print_symbol (ignore_abfd, afile, symbol, how)
#define srec_find_nearest_line _bfd_nosymbols_find_nearest_line
#define srec_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
+#define srec_get_reloc_upper_bound \
+ ((long (*) PARAMS ((bfd *, asection *))) bfd_0l)
+#define srec_canonicalize_reloc \
+ ((long (*) PARAMS ((bfd *, asection *, arelent **, asymbol **))) bfd_0l)
+#define srec_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
+
+#define srec_set_arch_mach bfd_default_set_arch_mach
+
#define srec_bfd_get_relocated_section_contents \
bfd_generic_get_relocated_section_contents
#define srec_bfd_relax_section bfd_generic_relax_section
@@ -1050,7 +1275,7 @@ const bfd_target srec_vec =
BFD_JUMP_TABLE_CORE (_bfd_nocore),
BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
BFD_JUMP_TABLE_SYMBOLS (srec),
- BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
+ BFD_JUMP_TABLE_RELOCS (srec),
BFD_JUMP_TABLE_WRITE (srec),
BFD_JUMP_TABLE_LINK (srec),
BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
@@ -1106,7 +1331,7 @@ const bfd_target symbolsrec_vec =
BFD_JUMP_TABLE_CORE (_bfd_nocore),
BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
BFD_JUMP_TABLE_SYMBOLS (srec),
- BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
+ BFD_JUMP_TABLE_RELOCS (srec),
BFD_JUMP_TABLE_WRITE (srec),
BFD_JUMP_TABLE_LINK (srec),
BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),