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