Home | History | Annotate | Line # | Download | only in bfd
verilog.c revision 1.8
      1  1.1  christos /* BFD back-end for verilog hex memory dump files.
      2  1.8  christos    Copyright (C) 2009-2019 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.1  christos /* Macros for converting between hex and binary.  */
     62  1.1  christos 
     63  1.1  christos static const char digs[] = "0123456789ABCDEF";
     64  1.1  christos 
     65  1.1  christos #define NIBBLE(x)    hex_value(x)
     66  1.1  christos #define HEX(buffer) ((NIBBLE ((buffer)[0])<<4) + NIBBLE ((buffer)[1]))
     67  1.1  christos #define TOHEX(d, x) \
     68  1.1  christos 	d[1] = digs[(x) & 0xf]; \
     69  1.1  christos 	d[0] = digs[((x) >> 4) & 0xf];
     70  1.1  christos 
     71  1.1  christos /* When writing a verilog memory dump file, we write them in the order
     72  1.1  christos    in which they appear in memory. This structure is used to hold them
     73  1.1  christos    in memory.  */
     74  1.1  christos 
     75  1.1  christos struct verilog_data_list_struct
     76  1.1  christos {
     77  1.1  christos   struct verilog_data_list_struct *next;
     78  1.1  christos   bfd_byte * data;
     79  1.1  christos   bfd_vma where;
     80  1.1  christos   bfd_size_type size;
     81  1.1  christos };
     82  1.1  christos 
     83  1.1  christos typedef struct verilog_data_list_struct verilog_data_list_type;
     84  1.1  christos 
     85  1.1  christos /* The verilog tdata information.  */
     86  1.1  christos 
     87  1.1  christos typedef struct verilog_data_struct
     88  1.1  christos {
     89  1.1  christos   verilog_data_list_type *head;
     90  1.1  christos   verilog_data_list_type *tail;
     91  1.1  christos }
     92  1.1  christos tdata_type;
     93  1.1  christos 
     94  1.1  christos static bfd_boolean
     95  1.1  christos verilog_set_arch_mach (bfd *abfd, enum bfd_architecture arch, unsigned long mach)
     96  1.1  christos {
     97  1.1  christos   if (arch != bfd_arch_unknown)
     98  1.1  christos     return bfd_default_set_arch_mach (abfd, arch, mach);
     99  1.1  christos 
    100  1.1  christos   abfd->arch_info = & bfd_default_arch_struct;
    101  1.1  christos   return TRUE;
    102  1.1  christos }
    103  1.1  christos 
    104  1.1  christos /* We have to save up all the outpu for a splurge before output.  */
    105  1.1  christos 
    106  1.1  christos static bfd_boolean
    107  1.1  christos verilog_set_section_contents (bfd *abfd,
    108  1.1  christos 			      sec_ptr section,
    109  1.1  christos 			      const void * location,
    110  1.1  christos 			      file_ptr offset,
    111  1.1  christos 			      bfd_size_type bytes_to_do)
    112  1.1  christos {
    113  1.1  christos   tdata_type *tdata = abfd->tdata.verilog_data;
    114  1.1  christos   verilog_data_list_type *entry;
    115  1.1  christos 
    116  1.1  christos   entry = (verilog_data_list_type *) bfd_alloc (abfd, sizeof (* entry));
    117  1.1  christos   if (entry == NULL)
    118  1.1  christos     return FALSE;
    119  1.1  christos 
    120  1.1  christos   if (bytes_to_do
    121  1.1  christos       && (section->flags & SEC_ALLOC)
    122  1.1  christos       && (section->flags & SEC_LOAD))
    123  1.1  christos     {
    124  1.1  christos       bfd_byte *data;
    125  1.1  christos 
    126  1.1  christos       data = (bfd_byte *) bfd_alloc (abfd, bytes_to_do);
    127  1.1  christos       if (data == NULL)
    128  1.1  christos 	return FALSE;
    129  1.1  christos       memcpy ((void *) data, location, (size_t) bytes_to_do);
    130  1.1  christos 
    131  1.1  christos       entry->data = data;
    132  1.1  christos       entry->where = section->lma + offset;
    133  1.1  christos       entry->size = bytes_to_do;
    134  1.1  christos 
    135  1.1  christos       /* Sort the records by address.  Optimize for the common case of
    136  1.1  christos 	 adding a record to the end of the list.  */
    137  1.1  christos       if (tdata->tail != NULL
    138  1.1  christos 	  && entry->where >= tdata->tail->where)
    139  1.1  christos 	{
    140  1.1  christos 	  tdata->tail->next = entry;
    141  1.1  christos 	  entry->next = NULL;
    142  1.1  christos 	  tdata->tail = entry;
    143  1.1  christos 	}
    144  1.1  christos       else
    145  1.1  christos 	{
    146  1.1  christos 	  verilog_data_list_type **look;
    147  1.1  christos 
    148  1.1  christos 	  for (look = &tdata->head;
    149  1.1  christos 	       *look != NULL && (*look)->where < entry->where;
    150  1.1  christos 	       look = &(*look)->next)
    151  1.1  christos 	    ;
    152  1.1  christos 	  entry->next = *look;
    153  1.1  christos 	  *look = entry;
    154  1.1  christos 	  if (entry->next == NULL)
    155  1.1  christos 	    tdata->tail = entry;
    156  1.1  christos 	}
    157  1.1  christos     }
    158  1.1  christos   return TRUE;
    159  1.1  christos }
    160  1.1  christos 
    161  1.1  christos static bfd_boolean
    162  1.1  christos verilog_write_address (bfd *abfd, bfd_vma address)
    163  1.1  christos {
    164  1.1  christos   char buffer[12];
    165  1.1  christos   char *dst = buffer;
    166  1.1  christos   bfd_size_type wrlen;
    167  1.1  christos 
    168  1.1  christos   /* Write the address.  */
    169  1.1  christos   *dst++ = '@';
    170  1.1  christos   TOHEX (dst, (address >> 24));
    171  1.1  christos   dst += 2;
    172  1.1  christos   TOHEX (dst, (address >> 16));
    173  1.1  christos   dst += 2;
    174  1.1  christos   TOHEX (dst, (address >> 8));
    175  1.1  christos   dst += 2;
    176  1.1  christos   TOHEX (dst, (address));
    177  1.1  christos   dst += 2;
    178  1.1  christos   *dst++ = '\r';
    179  1.1  christos   *dst++ = '\n';
    180  1.1  christos   wrlen = dst - buffer;
    181  1.1  christos 
    182  1.1  christos   return bfd_bwrite ((void *) buffer, wrlen, abfd) == wrlen;
    183  1.1  christos }
    184  1.1  christos 
    185  1.1  christos /* Write a record of type, of the supplied number of bytes. The
    186  1.1  christos    supplied bytes and length don't have a checksum. That's worked out
    187  1.1  christos    here.  */
    188  1.1  christos 
    189  1.1  christos static bfd_boolean
    190  1.1  christos verilog_write_record (bfd *abfd,
    191  1.1  christos 		      const bfd_byte *data,
    192  1.1  christos 		      const bfd_byte *end)
    193  1.1  christos {
    194  1.5  christos   char buffer[50];
    195  1.1  christos   const bfd_byte *src = data;
    196  1.1  christos   char *dst = buffer;
    197  1.1  christos   bfd_size_type wrlen;
    198  1.1  christos 
    199  1.1  christos   /* Write the data.  */
    200  1.1  christos   for (src = data; src < end; src++)
    201  1.1  christos     {
    202  1.1  christos       TOHEX (dst, *src);
    203  1.1  christos       dst += 2;
    204  1.1  christos       *dst++ = ' ';
    205  1.1  christos     }
    206  1.1  christos   *dst++ = '\r';
    207  1.1  christos   *dst++ = '\n';
    208  1.1  christos   wrlen = dst - buffer;
    209  1.1  christos 
    210  1.1  christos   return bfd_bwrite ((void *) buffer, wrlen, abfd) == wrlen;
    211  1.1  christos }
    212  1.1  christos 
    213  1.1  christos static bfd_boolean
    214  1.1  christos verilog_write_section (bfd *abfd,
    215  1.1  christos 		       tdata_type *tdata ATTRIBUTE_UNUSED,
    216  1.1  christos 		       verilog_data_list_type *list)
    217  1.1  christos {
    218  1.1  christos   unsigned int octets_written = 0;
    219  1.1  christos   bfd_byte *location = list->data;
    220  1.1  christos 
    221  1.1  christos   verilog_write_address (abfd, list->where);
    222  1.1  christos   while (octets_written < list->size)
    223  1.1  christos     {
    224  1.1  christos       unsigned int octets_this_chunk = list->size - octets_written;
    225  1.1  christos 
    226  1.1  christos       if (octets_this_chunk > 16)
    227  1.1  christos 	octets_this_chunk = 16;
    228  1.1  christos 
    229  1.1  christos       if (! verilog_write_record (abfd,
    230  1.1  christos 				  location,
    231  1.1  christos 				  location + octets_this_chunk))
    232  1.1  christos 	return FALSE;
    233  1.1  christos 
    234  1.1  christos       octets_written += octets_this_chunk;
    235  1.1  christos       location += octets_this_chunk;
    236  1.1  christos     }
    237  1.1  christos 
    238  1.1  christos   return TRUE;
    239  1.1  christos }
    240  1.1  christos 
    241  1.1  christos static bfd_boolean
    242  1.1  christos verilog_write_object_contents (bfd *abfd)
    243  1.1  christos {
    244  1.1  christos   tdata_type *tdata = abfd->tdata.verilog_data;
    245  1.1  christos   verilog_data_list_type *list;
    246  1.1  christos 
    247  1.1  christos   /* Now wander though all the sections provided and output them.  */
    248  1.1  christos   list = tdata->head;
    249  1.1  christos 
    250  1.1  christos   while (list != (verilog_data_list_type *) NULL)
    251  1.1  christos     {
    252  1.1  christos       if (! verilog_write_section (abfd, tdata, list))
    253  1.1  christos 	return FALSE;
    254  1.1  christos       list = list->next;
    255  1.1  christos     }
    256  1.1  christos   return TRUE;
    257  1.1  christos }
    258  1.1  christos 
    259  1.1  christos /* Initialize by filling in the hex conversion array.  */
    260  1.1  christos 
    261  1.1  christos static void
    262  1.1  christos verilog_init (void)
    263  1.1  christos {
    264  1.1  christos   static bfd_boolean inited = FALSE;
    265  1.1  christos 
    266  1.1  christos   if (! inited)
    267  1.1  christos     {
    268  1.1  christos       inited = TRUE;
    269  1.1  christos       hex_init ();
    270  1.1  christos     }
    271  1.1  christos }
    272  1.1  christos 
    273  1.1  christos /* Set up the verilog tdata information.  */
    274  1.1  christos 
    275  1.1  christos static bfd_boolean
    276  1.1  christos verilog_mkobject (bfd *abfd)
    277  1.1  christos {
    278  1.1  christos   tdata_type *tdata;
    279  1.1  christos 
    280  1.1  christos   verilog_init ();
    281  1.1  christos 
    282  1.1  christos   tdata = (tdata_type *) bfd_alloc (abfd, sizeof (tdata_type));
    283  1.1  christos   if (tdata == NULL)
    284  1.1  christos     return FALSE;
    285  1.1  christos 
    286  1.1  christos   abfd->tdata.verilog_data = tdata;
    287  1.1  christos   tdata->head = NULL;
    288  1.1  christos   tdata->tail = NULL;
    289  1.1  christos 
    290  1.1  christos   return TRUE;
    291  1.1  christos }
    292  1.1  christos 
    293  1.8  christos #define verilog_close_and_cleanup		     _bfd_generic_close_and_cleanup
    294  1.8  christos #define verilog_bfd_free_cached_info		     _bfd_generic_bfd_free_cached_info
    295  1.8  christos #define verilog_new_section_hook		     _bfd_generic_new_section_hook
    296  1.8  christos #define verilog_bfd_is_target_special_symbol	     _bfd_bool_bfd_asymbol_false
    297  1.8  christos #define verilog_bfd_is_local_label_name		     bfd_generic_is_local_label_name
    298  1.8  christos #define verilog_get_lineno			     _bfd_nosymbols_get_lineno
    299  1.8  christos #define verilog_find_nearest_line		     _bfd_nosymbols_find_nearest_line
    300  1.8  christos #define verilog_find_inliner_info		     _bfd_nosymbols_find_inliner_info
    301  1.8  christos #define verilog_make_empty_symbol		     _bfd_generic_make_empty_symbol
    302  1.8  christos #define verilog_bfd_make_debug_symbol		     _bfd_nosymbols_bfd_make_debug_symbol
    303  1.8  christos #define verilog_read_minisymbols		     _bfd_generic_read_minisymbols
    304  1.8  christos #define verilog_minisymbol_to_symbol		     _bfd_generic_minisymbol_to_symbol
    305  1.8  christos #define verilog_get_section_contents_in_window	     _bfd_generic_get_section_contents_in_window
    306  1.1  christos #define verilog_bfd_get_relocated_section_contents   bfd_generic_get_relocated_section_contents
    307  1.8  christos #define verilog_bfd_relax_section		     bfd_generic_relax_section
    308  1.8  christos #define verilog_bfd_gc_sections			     bfd_generic_gc_sections
    309  1.8  christos #define verilog_bfd_merge_sections		     bfd_generic_merge_sections
    310  1.8  christos #define verilog_bfd_is_group_section		     bfd_generic_is_group_section
    311  1.8  christos #define verilog_bfd_discard_group		     bfd_generic_discard_group
    312  1.8  christos #define verilog_section_already_linked		     _bfd_generic_section_already_linked
    313  1.8  christos #define verilog_bfd_link_hash_table_create	     _bfd_generic_link_hash_table_create
    314  1.8  christos #define verilog_bfd_link_add_symbols		     _bfd_generic_link_add_symbols
    315  1.8  christos #define verilog_bfd_link_just_syms		     _bfd_generic_link_just_syms
    316  1.8  christos #define verilog_bfd_final_link			     _bfd_generic_final_link
    317  1.8  christos #define verilog_bfd_link_split_section		     _bfd_generic_link_split_section
    318  1.1  christos 
    319  1.1  christos const bfd_target verilog_vec =
    320  1.1  christos {
    321  1.1  christos   "verilog",			/* Name.  */
    322  1.1  christos   bfd_target_verilog_flavour,
    323  1.1  christos   BFD_ENDIAN_UNKNOWN,		/* Target byte order.  */
    324  1.1  christos   BFD_ENDIAN_UNKNOWN,		/* Target headers byte order.  */
    325  1.1  christos   (HAS_RELOC | EXEC_P |		/* Object flags.  */
    326  1.1  christos    HAS_LINENO | HAS_DEBUG |
    327  1.1  christos    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
    328  1.1  christos   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
    329  1.1  christos    | SEC_ALLOC | SEC_LOAD | SEC_RELOC),	/* Section flags.  */
    330  1.1  christos   0,				/* Leading underscore.  */
    331  1.1  christos   ' ',				/* AR_pad_char.  */
    332  1.1  christos   16,				/* AR_max_namelen.  */
    333  1.1  christos   0,				/* match priority.  */
    334  1.1  christos   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
    335  1.1  christos   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
    336  1.1  christos   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Data.  */
    337  1.1  christos   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
    338  1.1  christos   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
    339  1.1  christos   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Hdrs.  */
    340  1.1  christos 
    341  1.1  christos   {
    342  1.1  christos     _bfd_dummy_target,
    343  1.1  christos     _bfd_dummy_target,
    344  1.1  christos     _bfd_dummy_target,
    345  1.1  christos     _bfd_dummy_target,
    346  1.1  christos   },
    347  1.1  christos   {
    348  1.8  christos     _bfd_bool_bfd_false_error,
    349  1.1  christos     verilog_mkobject,
    350  1.8  christos     _bfd_bool_bfd_false_error,
    351  1.8  christos     _bfd_bool_bfd_false_error,
    352  1.1  christos   },
    353  1.1  christos   {				/* bfd_write_contents.  */
    354  1.8  christos     _bfd_bool_bfd_false_error,
    355  1.1  christos     verilog_write_object_contents,
    356  1.8  christos     _bfd_bool_bfd_false_error,
    357  1.8  christos     _bfd_bool_bfd_false_error,
    358  1.1  christos   },
    359  1.1  christos 
    360  1.1  christos   BFD_JUMP_TABLE_GENERIC (_bfd_generic),
    361  1.1  christos   BFD_JUMP_TABLE_COPY (_bfd_generic),
    362  1.1  christos   BFD_JUMP_TABLE_CORE (_bfd_nocore),
    363  1.1  christos   BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
    364  1.1  christos   BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
    365  1.1  christos   BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
    366  1.1  christos   BFD_JUMP_TABLE_WRITE (verilog),
    367  1.1  christos   BFD_JUMP_TABLE_LINK (_bfd_nolink),
    368  1.1  christos   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
    369  1.1  christos 
    370  1.1  christos   NULL,
    371  1.1  christos 
    372  1.1  christos   NULL
    373  1.1  christos };
    374