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