Home | History | Annotate | Line # | Download | only in bfd
verilog.c revision 1.9
      1  1.1  christos /* BFD back-end for verilog hex memory dump files.
      2  1.9  christos    Copyright (C) 2009-2020 Free Software Foundation, Inc.
      3  1.1  christos    Written by Anthony Green <green (at) moxielogic.com>
      4  1.1  christos 
      5  1.1  christos    This file is part of BFD, the Binary File Descriptor library.
      6  1.1  christos 
      7  1.1  christos    This program is free software; you can redistribute it and/or modify
      8  1.1  christos    it under the terms of the GNU General Public License as published by
      9  1.1  christos    the Free Software Foundation; either version 3 of the License, or
     10  1.1  christos    (at your option) any later version.
     11  1.1  christos 
     12  1.1  christos    This program is distributed in the hope that it will be useful,
     13  1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15  1.1  christos    GNU General Public License for more details.
     16  1.1  christos 
     17  1.1  christos    You should have received a copy of the GNU General Public License
     18  1.1  christos    along with this program; if not, write to the Free Software
     19  1.1  christos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     20  1.1  christos    MA 02110-1301, USA.  */
     21  1.1  christos 
     22  1.1  christos 
     23  1.1  christos /* SUBSECTION
     24  1.1  christos 	Verilog hex memory file handling
     25  1.1  christos 
     26  1.1  christos    DESCRIPTION
     27  1.1  christos 
     28  1.1  christos 	Verilog hex memory files cannot hold anything but addresses
     29  1.1  christos 	and data, so that's all that we implement.
     30  1.1  christos 
     31  1.1  christos 	The syntax of the text file is described in the IEEE standard
     32  1.1  christos 	for Verilog.  Briefly, the file contains two types of tokens:
     33  1.1  christos 	data and optional addresses.  The tokens are separated by
     34  1.1  christos 	whitespace and comments.  Comments may be single line or
     35  1.1  christos 	multiline, using syntax similar to C++.  Addresses are
     36  1.1  christos 	specified by a leading "at" character (@) and are always
     37  1.1  christos 	hexadecimal strings.  Data and addresses may contain
     38  1.1  christos 	underscore (_) characters.
     39  1.1  christos 
     40  1.1  christos 	If no address is specified, the data is assumed to start at
     41  1.1  christos 	address 0.  Similarly, if data exists before the first
     42  1.1  christos 	specified address, then that data is assumed to start at
     43  1.1  christos 	address 0.
     44  1.1  christos 
     45  1.1  christos 
     46  1.1  christos    EXAMPLE
     47  1.1  christos 	@1000
     48  1.8  christos 	01 ae 3f 45 12
     49  1.1  christos 
     50  1.1  christos    DESCRIPTION
     51  1.1  christos 	@1000 specifies the starting address for the memory data.
     52  1.1  christos 	The following characters describe the 5 bytes at 0x1000.  */
     53  1.1  christos 
     54  1.1  christos 
     55  1.1  christos #include "sysdep.h"
     56  1.1  christos #include "bfd.h"
     57  1.1  christos #include "libbfd.h"
     58  1.1  christos #include "libiberty.h"
     59  1.1  christos #include "safe-ctype.h"
     60  1.1  christos 
     61  1.9  christos /* Modified by obcopy.c
     62  1.9  christos    Data width in bytes.  */
     63  1.9  christos unsigned int VerilogDataWidth = 1;
     64  1.9  christos 
     65  1.1  christos /* Macros for converting between hex and binary.  */
     66  1.1  christos 
     67  1.1  christos static const char digs[] = "0123456789ABCDEF";
     68  1.1  christos 
     69  1.9  christos #define NIBBLE(x)    hex_value (x)
     70  1.9  christos #define HEX(buffer) ((NIBBLE ((buffer)[0]) << 4) + NIBBLE ((buffer)[1]))
     71  1.1  christos #define TOHEX(d, x) \
     72  1.1  christos 	d[1] = digs[(x) & 0xf]; \
     73  1.1  christos 	d[0] = digs[((x) >> 4) & 0xf];
     74  1.1  christos 
     75  1.1  christos /* When writing a verilog memory dump file, we write them in the order
     76  1.1  christos    in which they appear in memory. This structure is used to hold them
     77  1.1  christos    in memory.  */
     78  1.1  christos 
     79  1.1  christos struct verilog_data_list_struct
     80  1.1  christos {
     81  1.1  christos   struct verilog_data_list_struct *next;
     82  1.1  christos   bfd_byte * data;
     83  1.1  christos   bfd_vma where;
     84  1.1  christos   bfd_size_type size;
     85  1.1  christos };
     86  1.1  christos 
     87  1.1  christos typedef struct verilog_data_list_struct verilog_data_list_type;
     88  1.1  christos 
     89  1.1  christos /* The verilog tdata information.  */
     90  1.1  christos 
     91  1.1  christos typedef struct verilog_data_struct
     92  1.1  christos {
     93  1.1  christos   verilog_data_list_type *head;
     94  1.1  christos   verilog_data_list_type *tail;
     95  1.1  christos }
     96  1.1  christos tdata_type;
     97  1.1  christos 
     98  1.1  christos static bfd_boolean
     99  1.1  christos verilog_set_arch_mach (bfd *abfd, enum bfd_architecture arch, unsigned long mach)
    100  1.1  christos {
    101  1.1  christos   if (arch != bfd_arch_unknown)
    102  1.1  christos     return bfd_default_set_arch_mach (abfd, arch, mach);
    103  1.1  christos 
    104  1.1  christos   abfd->arch_info = & bfd_default_arch_struct;
    105  1.1  christos   return TRUE;
    106  1.1  christos }
    107  1.1  christos 
    108  1.1  christos /* We have to save up all the outpu for a splurge before output.  */
    109  1.1  christos 
    110  1.1  christos static bfd_boolean
    111  1.1  christos verilog_set_section_contents (bfd *abfd,
    112  1.1  christos 			      sec_ptr section,
    113  1.1  christos 			      const void * location,
    114  1.1  christos 			      file_ptr offset,
    115  1.1  christos 			      bfd_size_type bytes_to_do)
    116  1.1  christos {
    117  1.1  christos   tdata_type *tdata = abfd->tdata.verilog_data;
    118  1.1  christos   verilog_data_list_type *entry;
    119  1.1  christos 
    120  1.1  christos   entry = (verilog_data_list_type *) bfd_alloc (abfd, sizeof (* entry));
    121  1.1  christos   if (entry == NULL)
    122  1.1  christos     return FALSE;
    123  1.1  christos 
    124  1.1  christos   if (bytes_to_do
    125  1.1  christos       && (section->flags & SEC_ALLOC)
    126  1.1  christos       && (section->flags & SEC_LOAD))
    127  1.1  christos     {
    128  1.1  christos       bfd_byte *data;
    129  1.1  christos 
    130  1.1  christos       data = (bfd_byte *) bfd_alloc (abfd, bytes_to_do);
    131  1.1  christos       if (data == NULL)
    132  1.1  christos 	return FALSE;
    133  1.1  christos       memcpy ((void *) data, location, (size_t) bytes_to_do);
    134  1.1  christos 
    135  1.1  christos       entry->data = data;
    136  1.1  christos       entry->where = section->lma + offset;
    137  1.1  christos       entry->size = bytes_to_do;
    138  1.1  christos 
    139  1.1  christos       /* Sort the records by address.  Optimize for the common case of
    140  1.1  christos 	 adding a record to the end of the list.  */
    141  1.1  christos       if (tdata->tail != NULL
    142  1.1  christos 	  && entry->where >= tdata->tail->where)
    143  1.1  christos 	{
    144  1.1  christos 	  tdata->tail->next = entry;
    145  1.1  christos 	  entry->next = NULL;
    146  1.1  christos 	  tdata->tail = entry;
    147  1.1  christos 	}
    148  1.1  christos       else
    149  1.1  christos 	{
    150  1.1  christos 	  verilog_data_list_type **look;
    151  1.1  christos 
    152  1.1  christos 	  for (look = &tdata->head;
    153  1.1  christos 	       *look != NULL && (*look)->where < entry->where;
    154  1.1  christos 	       look = &(*look)->next)
    155  1.1  christos 	    ;
    156  1.1  christos 	  entry->next = *look;
    157  1.1  christos 	  *look = entry;
    158  1.1  christos 	  if (entry->next == NULL)
    159  1.1  christos 	    tdata->tail = entry;
    160  1.1  christos 	}
    161  1.1  christos     }
    162  1.1  christos   return TRUE;
    163  1.1  christos }
    164  1.1  christos 
    165  1.1  christos static bfd_boolean
    166  1.1  christos verilog_write_address (bfd *abfd, bfd_vma address)
    167  1.1  christos {
    168  1.1  christos   char buffer[12];
    169  1.1  christos   char *dst = buffer;
    170  1.1  christos   bfd_size_type wrlen;
    171  1.1  christos 
    172  1.1  christos   /* Write the address.  */
    173  1.1  christos   *dst++ = '@';
    174  1.1  christos   TOHEX (dst, (address >> 24));
    175  1.1  christos   dst += 2;
    176  1.1  christos   TOHEX (dst, (address >> 16));
    177  1.1  christos   dst += 2;
    178  1.1  christos   TOHEX (dst, (address >> 8));
    179  1.1  christos   dst += 2;
    180  1.1  christos   TOHEX (dst, (address));
    181  1.1  christos   dst += 2;
    182  1.1  christos   *dst++ = '\r';
    183  1.1  christos   *dst++ = '\n';
    184  1.1  christos   wrlen = dst - buffer;
    185  1.1  christos 
    186  1.1  christos   return bfd_bwrite ((void *) buffer, wrlen, abfd) == wrlen;
    187  1.1  christos }
    188  1.1  christos 
    189  1.1  christos /* Write a record of type, of the supplied number of bytes. The
    190  1.9  christos    supplied bytes and length don't have a checksum.  That's worked
    191  1.9  christos    out here.  */
    192  1.1  christos 
    193  1.1  christos static bfd_boolean
    194  1.1  christos verilog_write_record (bfd *abfd,
    195  1.1  christos 		      const bfd_byte *data,
    196  1.1  christos 		      const bfd_byte *end)
    197  1.1  christos {
    198  1.9  christos   char buffer[52];
    199  1.1  christos   const bfd_byte *src = data;
    200  1.1  christos   char *dst = buffer;
    201  1.1  christos   bfd_size_type wrlen;
    202  1.1  christos 
    203  1.9  christos   /* Paranoia - check that we will not overflow "buffer".  */
    204  1.9  christos   if (((end - data) * 2) /* Number of hex characters we want to emit.  */
    205  1.9  christos       + ((end - data) / VerilogDataWidth) /* Number of spaces we want to emit.  */
    206  1.9  christos       + 2 /* The carriage return & line feed characters.  */
    207  1.9  christos       > (long) sizeof (buffer))
    208  1.1  christos     {
    209  1.9  christos       /* FIXME: Should we generate an error message ?  */
    210  1.9  christos       return FALSE;
    211  1.9  christos     }
    212  1.9  christos 
    213  1.9  christos   /* Write the data.
    214  1.9  christos      FIXME: Under some circumstances we can emit a space at the end of
    215  1.9  christos      the line.  This is not really necessary, but catching these cases
    216  1.9  christos      would make the code more complicated.  */
    217  1.9  christos   if (VerilogDataWidth == 1)
    218  1.9  christos     {
    219  1.9  christos       for (src = data; src < end;)
    220  1.9  christos 	{
    221  1.9  christos 	  TOHEX (dst, *src);
    222  1.9  christos 	  dst += 2;
    223  1.9  christos 	  src ++;
    224  1.9  christos 	  if (src < end)
    225  1.9  christos 	    *dst++ = ' ';
    226  1.9  christos 	}
    227  1.1  christos     }
    228  1.9  christos   else if (bfd_little_endian (abfd))
    229  1.9  christos     {
    230  1.9  christos       /* If the input byte stream contains:
    231  1.9  christos 	   05 04 03 02 01 00
    232  1.9  christos 	 and VerilogDataWidth is 4 then we want to emit:
    233  1.9  christos            02030405 0001  */
    234  1.9  christos       int i;
    235  1.9  christos 
    236  1.9  christos       for (src = data; src < (end - VerilogDataWidth); src += VerilogDataWidth)
    237  1.9  christos 	{
    238  1.9  christos 	  for (i = VerilogDataWidth - 1; i >= 0; i--)
    239  1.9  christos 	    {
    240  1.9  christos 	      TOHEX (dst, src[i]);
    241  1.9  christos 	      dst += 2;
    242  1.9  christos 	    }
    243  1.9  christos 	  *dst++ = ' ';
    244  1.9  christos 	}
    245  1.9  christos 
    246  1.9  christos       /* Emit any remaining bytes.  Be careful not to read beyond "end".  */
    247  1.9  christos       while (end > src)
    248  1.9  christos 	{
    249  1.9  christos 	  -- end;
    250  1.9  christos 	  TOHEX (dst, *end);
    251  1.9  christos 	  dst += 2;
    252  1.9  christos 	}
    253  1.9  christos     }
    254  1.9  christos   else
    255  1.9  christos     {
    256  1.9  christos       for (src = data; src < end;)
    257  1.9  christos 	{
    258  1.9  christos 	  TOHEX (dst, *src);
    259  1.9  christos 	  dst += 2;
    260  1.9  christos 	  ++ src;
    261  1.9  christos 	  if ((src - data) % VerilogDataWidth == 0)
    262  1.9  christos 	    *dst++ = ' ';
    263  1.9  christos 	}
    264  1.9  christos     }
    265  1.9  christos 
    266  1.1  christos   *dst++ = '\r';
    267  1.1  christos   *dst++ = '\n';
    268  1.1  christos   wrlen = dst - buffer;
    269  1.1  christos 
    270  1.1  christos   return bfd_bwrite ((void *) buffer, wrlen, abfd) == wrlen;
    271  1.1  christos }
    272  1.1  christos 
    273  1.1  christos static bfd_boolean
    274  1.1  christos verilog_write_section (bfd *abfd,
    275  1.1  christos 		       tdata_type *tdata ATTRIBUTE_UNUSED,
    276  1.1  christos 		       verilog_data_list_type *list)
    277  1.1  christos {
    278  1.1  christos   unsigned int octets_written = 0;
    279  1.1  christos   bfd_byte *location = list->data;
    280  1.1  christos 
    281  1.1  christos   verilog_write_address (abfd, list->where);
    282  1.1  christos   while (octets_written < list->size)
    283  1.1  christos     {
    284  1.1  christos       unsigned int octets_this_chunk = list->size - octets_written;
    285  1.1  christos 
    286  1.1  christos       if (octets_this_chunk > 16)
    287  1.1  christos 	octets_this_chunk = 16;
    288  1.1  christos 
    289  1.1  christos       if (! verilog_write_record (abfd,
    290  1.1  christos 				  location,
    291  1.1  christos 				  location + octets_this_chunk))
    292  1.1  christos 	return FALSE;
    293  1.1  christos 
    294  1.1  christos       octets_written += octets_this_chunk;
    295  1.1  christos       location += octets_this_chunk;
    296  1.1  christos     }
    297  1.1  christos 
    298  1.1  christos   return TRUE;
    299  1.1  christos }
    300  1.1  christos 
    301  1.1  christos static bfd_boolean
    302  1.1  christos verilog_write_object_contents (bfd *abfd)
    303  1.1  christos {
    304  1.1  christos   tdata_type *tdata = abfd->tdata.verilog_data;
    305  1.1  christos   verilog_data_list_type *list;
    306  1.1  christos 
    307  1.1  christos   /* Now wander though all the sections provided and output them.  */
    308  1.1  christos   list = tdata->head;
    309  1.1  christos 
    310  1.1  christos   while (list != (verilog_data_list_type *) NULL)
    311  1.1  christos     {
    312  1.1  christos       if (! verilog_write_section (abfd, tdata, list))
    313  1.1  christos 	return FALSE;
    314  1.1  christos       list = list->next;
    315  1.1  christos     }
    316  1.1  christos   return TRUE;
    317  1.1  christos }
    318  1.1  christos 
    319  1.1  christos /* Initialize by filling in the hex conversion array.  */
    320  1.1  christos 
    321  1.1  christos static void
    322  1.1  christos verilog_init (void)
    323  1.1  christos {
    324  1.1  christos   static bfd_boolean inited = FALSE;
    325  1.1  christos 
    326  1.1  christos   if (! inited)
    327  1.1  christos     {
    328  1.1  christos       inited = TRUE;
    329  1.1  christos       hex_init ();
    330  1.1  christos     }
    331  1.1  christos }
    332  1.1  christos 
    333  1.1  christos /* Set up the verilog tdata information.  */
    334  1.1  christos 
    335  1.1  christos static bfd_boolean
    336  1.1  christos verilog_mkobject (bfd *abfd)
    337  1.1  christos {
    338  1.1  christos   tdata_type *tdata;
    339  1.1  christos 
    340  1.1  christos   verilog_init ();
    341  1.1  christos 
    342  1.1  christos   tdata = (tdata_type *) bfd_alloc (abfd, sizeof (tdata_type));
    343  1.1  christos   if (tdata == NULL)
    344  1.1  christos     return FALSE;
    345  1.1  christos 
    346  1.1  christos   abfd->tdata.verilog_data = tdata;
    347  1.1  christos   tdata->head = NULL;
    348  1.1  christos   tdata->tail = NULL;
    349  1.1  christos 
    350  1.1  christos   return TRUE;
    351  1.1  christos }
    352  1.1  christos 
    353  1.8  christos #define verilog_close_and_cleanup		     _bfd_generic_close_and_cleanup
    354  1.8  christos #define verilog_bfd_free_cached_info		     _bfd_generic_bfd_free_cached_info
    355  1.8  christos #define verilog_new_section_hook		     _bfd_generic_new_section_hook
    356  1.8  christos #define verilog_bfd_is_target_special_symbol	     _bfd_bool_bfd_asymbol_false
    357  1.8  christos #define verilog_bfd_is_local_label_name		     bfd_generic_is_local_label_name
    358  1.8  christos #define verilog_get_lineno			     _bfd_nosymbols_get_lineno
    359  1.8  christos #define verilog_find_nearest_line		     _bfd_nosymbols_find_nearest_line
    360  1.8  christos #define verilog_find_inliner_info		     _bfd_nosymbols_find_inliner_info
    361  1.8  christos #define verilog_make_empty_symbol		     _bfd_generic_make_empty_symbol
    362  1.8  christos #define verilog_bfd_make_debug_symbol		     _bfd_nosymbols_bfd_make_debug_symbol
    363  1.8  christos #define verilog_read_minisymbols		     _bfd_generic_read_minisymbols
    364  1.8  christos #define verilog_minisymbol_to_symbol		     _bfd_generic_minisymbol_to_symbol
    365  1.8  christos #define verilog_get_section_contents_in_window	     _bfd_generic_get_section_contents_in_window
    366  1.1  christos #define verilog_bfd_get_relocated_section_contents   bfd_generic_get_relocated_section_contents
    367  1.8  christos #define verilog_bfd_relax_section		     bfd_generic_relax_section
    368  1.8  christos #define verilog_bfd_gc_sections			     bfd_generic_gc_sections
    369  1.8  christos #define verilog_bfd_merge_sections		     bfd_generic_merge_sections
    370  1.8  christos #define verilog_bfd_is_group_section		     bfd_generic_is_group_section
    371  1.9  christos #define verilog_bfd_group_name			     bfd_generic_group_name
    372  1.8  christos #define verilog_bfd_discard_group		     bfd_generic_discard_group
    373  1.8  christos #define verilog_section_already_linked		     _bfd_generic_section_already_linked
    374  1.8  christos #define verilog_bfd_link_hash_table_create	     _bfd_generic_link_hash_table_create
    375  1.8  christos #define verilog_bfd_link_add_symbols		     _bfd_generic_link_add_symbols
    376  1.8  christos #define verilog_bfd_link_just_syms		     _bfd_generic_link_just_syms
    377  1.8  christos #define verilog_bfd_final_link			     _bfd_generic_final_link
    378  1.8  christos #define verilog_bfd_link_split_section		     _bfd_generic_link_split_section
    379  1.1  christos 
    380  1.1  christos const bfd_target verilog_vec =
    381  1.1  christos {
    382  1.1  christos   "verilog",			/* Name.  */
    383  1.1  christos   bfd_target_verilog_flavour,
    384  1.1  christos   BFD_ENDIAN_UNKNOWN,		/* Target byte order.  */
    385  1.1  christos   BFD_ENDIAN_UNKNOWN,		/* Target headers byte order.  */
    386  1.1  christos   (HAS_RELOC | EXEC_P |		/* Object flags.  */
    387  1.1  christos    HAS_LINENO | HAS_DEBUG |
    388  1.1  christos    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
    389  1.1  christos   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
    390  1.1  christos    | SEC_ALLOC | SEC_LOAD | SEC_RELOC),	/* Section flags.  */
    391  1.1  christos   0,				/* Leading underscore.  */
    392  1.1  christos   ' ',				/* AR_pad_char.  */
    393  1.1  christos   16,				/* AR_max_namelen.  */
    394  1.1  christos   0,				/* match priority.  */
    395  1.1  christos   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
    396  1.1  christos   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
    397  1.1  christos   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Data.  */
    398  1.1  christos   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
    399  1.1  christos   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
    400  1.1  christos   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Hdrs.  */
    401  1.1  christos 
    402  1.1  christos   {
    403  1.1  christos     _bfd_dummy_target,
    404  1.1  christos     _bfd_dummy_target,
    405  1.1  christos     _bfd_dummy_target,
    406  1.1  christos     _bfd_dummy_target,
    407  1.1  christos   },
    408  1.1  christos   {
    409  1.8  christos     _bfd_bool_bfd_false_error,
    410  1.1  christos     verilog_mkobject,
    411  1.8  christos     _bfd_bool_bfd_false_error,
    412  1.8  christos     _bfd_bool_bfd_false_error,
    413  1.1  christos   },
    414  1.1  christos   {				/* bfd_write_contents.  */
    415  1.8  christos     _bfd_bool_bfd_false_error,
    416  1.1  christos     verilog_write_object_contents,
    417  1.8  christos     _bfd_bool_bfd_false_error,
    418  1.8  christos     _bfd_bool_bfd_false_error,
    419  1.1  christos   },
    420  1.1  christos 
    421  1.1  christos   BFD_JUMP_TABLE_GENERIC (_bfd_generic),
    422  1.1  christos   BFD_JUMP_TABLE_COPY (_bfd_generic),
    423  1.1  christos   BFD_JUMP_TABLE_CORE (_bfd_nocore),
    424  1.1  christos   BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
    425  1.1  christos   BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
    426  1.1  christos   BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
    427  1.1  christos   BFD_JUMP_TABLE_WRITE (verilog),
    428  1.1  christos   BFD_JUMP_TABLE_LINK (_bfd_nolink),
    429  1.1  christos   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
    430  1.1  christos 
    431  1.1  christos   NULL,
    432  1.1  christos 
    433  1.1  christos   NULL
    434  1.1  christos };
    435