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