Home | History | Annotate | Download | only in bfd
      1 /* BFD back-end for VERSAdos-E objects.
      2    Copyright (C) 1995-2014 Free Software Foundation, Inc.
      3    Written by Steve Chamberlain of Cygnus Support <sac (at) cygnus.com>.
      4 
      5    Versados is a Motorola trademark.
      6 
      7    This file is part of BFD, the Binary File Descriptor library.
      8 
      9    This program is free software; you can redistribute it and/or modify
     10    it under the terms of the GNU General Public License as published by
     11    the Free Software Foundation; either version 3 of the License, or
     12    (at your option) any later version.
     13 
     14    This program is distributed in the hope that it will be useful,
     15    but WITHOUT ANY WARRANTY; without even the implied warranty of
     16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17    GNU General Public License for more details.
     18 
     19    You should have received a copy of the GNU General Public License
     20    along with this program; if not, write to the Free Software
     21    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     22    MA 02110-1301, USA.  */
     23 
     24 /*
     25    SUBSECTION
     26    VERSAdos-E relocatable object file format
     27 
     28    DESCRIPTION
     29 
     30    This module supports reading of VERSAdos relocatable
     31    object files.
     32 
     33    A VERSAdos file looks like contains
     34 
     35    o Identification Record
     36    o External Symbol Definition Record
     37    o Object Text Record
     38    o End Record.  */
     39 
     40 #include "sysdep.h"
     41 #include "bfd.h"
     42 #include "libbfd.h"
     43 #include "libiberty.h"
     44 
     45 
     46 #define VHEADER '1'
     47 #define VESTDEF '2'
     48 #define VOTR '3'
     49 #define VEND '4'
     50 
     51 #define ES_BASE 17		/* First symbol has esdid 17.  */
     52 
     53 /* Per file target dependent information.  */
     54 
     55 /* One for each section.  */
     56 struct esdid
     57 {
     58   asection *section;		/* Ptr to bfd version.  */
     59   unsigned char *contents;	/* Used to build image.  */
     60   int pc;
     61   int relocs;			/* Reloc count, valid end of pass 1.  */
     62   int donerel;			/* Have relocs been translated.  */
     63 };
     64 
     65 typedef struct versados_data_struct
     66 {
     67   int es_done;			/* Count of symbol index, starts at ES_BASE.  */
     68   asymbol *symbols;		/* Pointer to local symbols.  */
     69   char *strings;		/* Strings of all the above.  */
     70   int stringlen;		/* Len of string table (valid end of pass1).  */
     71   int nsecsyms;			/* Number of sections.  */
     72 
     73   int ndefs;			/* Number of exported symbols (they dont get esdids).  */
     74   int nrefs;			/* Number of imported symbols  (valid end of pass1).  */
     75 
     76   int ref_idx;			/* Current processed value of the above.  */
     77   int def_idx;
     78 
     79   int pass_2_done;
     80 
     81   struct esdid e[16];		/* Per section info.  */
     82   int alert;			/* To see if we're trampling.  */
     83   asymbol *rest[256 - 16];	/* Per symbol info.  */
     84 }
     85 tdata_type;
     86 
     87 #define VDATA(abfd)       (abfd->tdata.versados_data)
     88 #define EDATA(abfd, n)    (abfd->tdata.versados_data->e[n])
     89 #define RDATA(abfd, n)    (abfd->tdata.versados_data->rest[n])
     90 
     91 struct ext_otr
     92 {
     93   unsigned char size;
     94   char type;
     95   unsigned char map[4];
     96   unsigned char esdid;
     97   unsigned char data[200];
     98 };
     99 
    100 struct ext_vheader
    101 {
    102   unsigned char size;
    103   char type;			/* Record type.  */
    104   char name[10];		/* Module name.  */
    105   char rev;			/* Module rev number.  */
    106   char lang;
    107   char vol[4];
    108   char user[2];
    109   char cat[8];
    110   char fname[8];
    111   char ext[2];
    112   char time[3];
    113   char date[3];
    114   char rest[211];
    115 };
    116 
    117 struct ext_esd
    118 {
    119   unsigned char size;
    120   char type;
    121   unsigned char esd_entries[1];
    122 };
    123 
    124 #define ESD_ABS 	  0
    125 #define ESD_COMMON 	  1
    126 #define ESD_STD_REL_SEC   2
    127 #define ESD_SHRT_REL_SEC  3
    128 #define ESD_XDEF_IN_SEC   4
    129 #define ESD_XDEF_IN_ABS   5
    130 #define ESD_XREF_SEC	  6
    131 #define ESD_XREF_SYM      7
    132 
    133 union ext_any
    134 {
    135   unsigned char size;
    136   struct ext_vheader header;
    137   struct ext_esd esd;
    138   struct ext_otr otr;
    139 };
    140 
    141 /* Initialize by filling in the hex conversion array.  */
    142 
    143 /* Set up the tdata information.  */
    144 
    145 static bfd_boolean
    146 versados_mkobject (bfd *abfd)
    147 {
    148   if (abfd->tdata.versados_data == NULL)
    149     {
    150       bfd_size_type amt = sizeof (tdata_type);
    151       tdata_type *tdata = bfd_alloc (abfd, amt);
    152 
    153       if (tdata == NULL)
    154 	return FALSE;
    155       abfd->tdata.versados_data = tdata;
    156       tdata->symbols = NULL;
    157       VDATA (abfd)->alert = 0x12345678;
    158     }
    159 
    160   bfd_default_set_arch_mach (abfd, bfd_arch_m68k, 0);
    161   return TRUE;
    162 }
    163 
    164 /* Report a problem in an S record file.  FIXME: This probably should
    165    not call fprintf, but we really do need some mechanism for printing
    166    error messages.  */
    167 
    168 static asymbol *
    169 versados_new_symbol (bfd *abfd,
    170 		     int snum,
    171 		     const char *name,
    172 		     bfd_vma val,
    173 		     asection *sec)
    174 {
    175   asymbol *n = VDATA (abfd)->symbols + snum;
    176   n->name = name;
    177   n->value = val;
    178   n->section = sec;
    179   n->the_bfd = abfd;
    180   n->flags = 0;
    181   return n;
    182 }
    183 
    184 static int
    185 get_record (bfd *abfd, union ext_any *ptr)
    186 {
    187   if (bfd_bread (&ptr->size, (bfd_size_type) 1, abfd) != 1
    188       || (bfd_bread ((char *) ptr + 1, (bfd_size_type) ptr->size, abfd)
    189 	  != ptr->size))
    190     return 0;
    191   return 1;
    192 }
    193 
    194 static int
    195 get_4 (unsigned char **pp)
    196 {
    197   unsigned char *p = *pp;
    198 
    199   *pp += 4;
    200   return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3] << 0);
    201 }
    202 
    203 static void
    204 get_10 (unsigned char **pp, char *name)
    205 {
    206   char *p = (char *) *pp;
    207   int len = 10;
    208 
    209   *pp += len;
    210   while (*p != ' ' && len)
    211     {
    212       *name++ = *p++;
    213       len--;
    214     }
    215   *name = 0;
    216 }
    217 
    218 static char *
    219 new_symbol_string (bfd *abfd, const char *name)
    220 {
    221   char *n = VDATA (abfd)->strings;
    222 
    223   strcpy (VDATA (abfd)->strings, name);
    224   VDATA (abfd)->strings += strlen (VDATA (abfd)->strings) + 1;
    225   return n;
    226 }
    227 
    228 static void
    229 process_esd (bfd *abfd, struct ext_esd *esd, int pass)
    230 {
    231   /* Read through the ext def for the est entries.  */
    232   int togo = esd->size - 2;
    233   bfd_vma size;
    234   bfd_vma start;
    235   asection *sec;
    236   char name[11];
    237   unsigned char *ptr = esd->esd_entries;
    238   unsigned char *end = ptr + togo;
    239 
    240   while (ptr < end)
    241     {
    242       int scn = *ptr & 0xf;
    243       int typ = (*ptr >> 4) & 0xf;
    244 
    245       /* Declare this section.  */
    246       sprintf (name, "%d", scn);
    247       sec = bfd_make_section_old_way (abfd, strdup (name));
    248       sec->target_index = scn;
    249       EDATA (abfd, scn).section = sec;
    250       ptr++;
    251 
    252       switch (typ)
    253 	{
    254 	default:
    255 	  abort ();
    256 	case ESD_XREF_SEC:
    257 	case ESD_XREF_SYM:
    258 	  {
    259 	    int snum = VDATA (abfd)->ref_idx++;
    260 	    get_10 (&ptr, name);
    261 	    if (pass == 1)
    262 	      VDATA (abfd)->stringlen += strlen (name) + 1;
    263 	    else
    264 	      {
    265 		int esidx;
    266 		asymbol *s;
    267 		char *n = new_symbol_string (abfd, name);
    268 
    269 		s = versados_new_symbol (abfd, snum, n, (bfd_vma) 0,
    270 					 bfd_und_section_ptr);
    271 		esidx = VDATA (abfd)->es_done++;
    272 		RDATA (abfd, esidx - ES_BASE) = s;
    273 	      }
    274 	  }
    275 	  break;
    276 
    277 	case ESD_ABS:
    278 	  size = get_4 (&ptr);
    279 	  (void) size;
    280 	  start = get_4 (&ptr);
    281 	  (void) start;
    282 	  break;
    283 	case ESD_STD_REL_SEC:
    284 	case ESD_SHRT_REL_SEC:
    285 	  sec->size = get_4 (&ptr);
    286 	  sec->flags |= SEC_ALLOC;
    287 	  break;
    288 	case ESD_XDEF_IN_ABS:
    289 	  sec = bfd_abs_section_ptr;
    290 	case ESD_XDEF_IN_SEC:
    291 	  {
    292 	    int snum = VDATA (abfd)->def_idx++;
    293 	    bfd_vma val;
    294 
    295 	    get_10 (&ptr, name);
    296 	    val = get_4 (&ptr);
    297 	    if (pass == 1)
    298 	      /* Just remember the symbol.  */
    299 	      VDATA (abfd)->stringlen += strlen (name) + 1;
    300 	    else
    301 	      {
    302 		asymbol *s;
    303 		char *n = new_symbol_string (abfd, name);
    304 
    305 		s = versados_new_symbol (abfd, snum + VDATA (abfd)->nrefs, n,
    306 					 val, sec);
    307 		s->flags |= BSF_GLOBAL;
    308 	      }
    309 	  }
    310 	  break;
    311 	}
    312     }
    313 }
    314 
    315 #define R_RELWORD     1
    316 #define R_RELLONG     2
    317 #define R_RELWORD_NEG 3
    318 #define R_RELLONG_NEG 4
    319 
    320 reloc_howto_type versados_howto_table[] =
    321 {
    322   HOWTO (R_RELWORD, 0, 1, 16, FALSE,
    323 	 0, complain_overflow_dont, 0,
    324 	 "+v16", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
    325   HOWTO (R_RELLONG, 0, 2, 32, FALSE,
    326 	 0, complain_overflow_dont, 0,
    327 	 "+v32", TRUE, 0xffffffff, 0xffffffff, FALSE),
    328 
    329   HOWTO (R_RELWORD_NEG, 0, -1, 16, FALSE,
    330 	 0, complain_overflow_dont, 0,
    331 	 "-v16", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
    332   HOWTO (R_RELLONG_NEG, 0, -2, 32, FALSE,
    333 	 0, complain_overflow_dont, 0,
    334 	 "-v32", TRUE, 0xffffffff, 0xffffffff, FALSE),
    335 };
    336 
    337 static int
    338 get_offset (int len, unsigned char *ptr)
    339 {
    340   int val = 0;
    341 
    342   if (len)
    343     {
    344       int i;
    345 
    346       val = *ptr++;
    347       if (val & 0x80)
    348 	val |= ~0xff;
    349       for (i = 1; i < len; i++)
    350 	val = (val << 8) | *ptr++;
    351     }
    352 
    353   return val;
    354 }
    355 
    356 static void
    357 process_otr (bfd *abfd, struct ext_otr *otr, int pass)
    358 {
    359   unsigned long shift;
    360   unsigned char *srcp = otr->data;
    361   unsigned char *endp = (unsigned char *) otr + otr->size;
    362   unsigned int bits = (otr->map[0] << 24)
    363   | (otr->map[1] << 16)
    364   | (otr->map[2] << 8)
    365   | (otr->map[3] << 0);
    366 
    367   struct esdid *esdid = &EDATA (abfd, otr->esdid - 1);
    368   unsigned char *contents = esdid->contents;
    369   int need_contents = 0;
    370   unsigned int dst_idx = esdid->pc;
    371 
    372   for (shift = ((unsigned long) 1 << 31); shift && srcp < endp; shift >>= 1)
    373     {
    374       if (bits & shift)
    375 	{
    376 	  int flag = *srcp++;
    377 	  int esdids = (flag >> 5) & 0x7;
    378 	  int sizeinwords = ((flag >> 3) & 1) ? 2 : 1;
    379 	  int offsetlen = flag & 0x7;
    380 	  int j;
    381 
    382 	  if (esdids == 0)
    383 	    {
    384 	      /* A zero esdid means the new pc is the offset given.  */
    385 	      dst_idx += get_offset (offsetlen, srcp);
    386 	      srcp += offsetlen;
    387 	    }
    388 	  else
    389 	    {
    390 	      int val = get_offset (offsetlen, srcp + esdids);
    391 
    392 	      if (pass == 1)
    393 		need_contents = 1;
    394 	      else
    395 		for (j = 0; j < sizeinwords * 2; j++)
    396 		  {
    397 		    contents[dst_idx + (sizeinwords * 2) - j - 1] = val;
    398 		    val >>= 8;
    399 		  }
    400 
    401 	      for (j = 0; j < esdids; j++)
    402 		{
    403 		  int id = *srcp++;
    404 
    405 		  if (id)
    406 		    {
    407 		      int rn = EDATA (abfd, otr->esdid - 1).relocs++;
    408 
    409 		      if (pass == 1)
    410 			{
    411 			  /* This is the first pass over the data,
    412 			     just remember that we need a reloc.  */
    413 			}
    414 		      else
    415 			{
    416 			  arelent *n =
    417 			  EDATA (abfd, otr->esdid - 1).section->relocation + rn;
    418 			  n->address = dst_idx;
    419 
    420 			  n->sym_ptr_ptr = (asymbol **) (size_t) id;
    421 			  n->addend = 0;
    422 			  n->howto = versados_howto_table + ((j & 1) * 2) + (sizeinwords - 1);
    423 			}
    424 		    }
    425 		}
    426 	      srcp += offsetlen;
    427 	      dst_idx += sizeinwords * 2;
    428 	    }
    429 	}
    430       else
    431 	{
    432 	  need_contents = 1;
    433 	  if (dst_idx < esdid->section->size)
    434 	    if (pass == 2)
    435 	      {
    436 		/* Absolute code, comes in 16 bit lumps.  */
    437 		contents[dst_idx] = srcp[0];
    438 		contents[dst_idx + 1] = srcp[1];
    439 	      }
    440 	  dst_idx += 2;
    441 	  srcp += 2;
    442 	}
    443     }
    444   EDATA (abfd, otr->esdid - 1).pc = dst_idx;
    445 
    446   if (!contents && need_contents)
    447     {
    448       bfd_size_type size = esdid->section->size;
    449       esdid->contents = bfd_alloc (abfd, size);
    450     }
    451 }
    452 
    453 static bfd_boolean
    454 versados_scan (bfd *abfd)
    455 {
    456   int loop = 1;
    457   int i;
    458   int j;
    459   int nsecs = 0;
    460   bfd_size_type amt;
    461 
    462   VDATA (abfd)->stringlen = 0;
    463   VDATA (abfd)->nrefs = 0;
    464   VDATA (abfd)->ndefs = 0;
    465   VDATA (abfd)->ref_idx = 0;
    466   VDATA (abfd)->def_idx = 0;
    467   VDATA (abfd)->pass_2_done = 0;
    468 
    469   while (loop)
    470     {
    471       union ext_any any;
    472 
    473       if (!get_record (abfd, &any))
    474 	return TRUE;
    475       switch (any.header.type)
    476 	{
    477 	case VHEADER:
    478 	  break;
    479 	case VEND:
    480 	  loop = 0;
    481 	  break;
    482 	case VESTDEF:
    483 	  process_esd (abfd, &any.esd, 1);
    484 	  break;
    485 	case VOTR:
    486 	  process_otr (abfd, &any.otr, 1);
    487 	  break;
    488 	}
    489     }
    490 
    491   /* Now allocate space for the relocs and sections.  */
    492   VDATA (abfd)->nrefs = VDATA (abfd)->ref_idx;
    493   VDATA (abfd)->ndefs = VDATA (abfd)->def_idx;
    494   VDATA (abfd)->ref_idx = 0;
    495   VDATA (abfd)->def_idx = 0;
    496 
    497   abfd->symcount = VDATA (abfd)->nrefs + VDATA (abfd)->ndefs;
    498 
    499   for (i = 0; i < 16; i++)
    500     {
    501       struct esdid *esdid = &EDATA (abfd, i);
    502 
    503       if (esdid->section)
    504 	{
    505 	  amt = (bfd_size_type) esdid->relocs * sizeof (arelent);
    506 	  esdid->section->relocation = bfd_alloc (abfd, amt);
    507 
    508 	  esdid->pc = 0;
    509 
    510 	  if (esdid->contents)
    511 	    esdid->section->flags |= SEC_HAS_CONTENTS | SEC_LOAD;
    512 
    513 	  esdid->section->reloc_count = esdid->relocs;
    514 	  if (esdid->relocs)
    515 	    esdid->section->flags |= SEC_RELOC;
    516 
    517 	  esdid->relocs = 0;
    518 
    519 	  /* Add an entry into the symbol table for it.  */
    520 	  nsecs++;
    521 	  VDATA (abfd)->stringlen += strlen (esdid->section->name) + 1;
    522 	}
    523     }
    524 
    525   abfd->symcount += nsecs;
    526 
    527   amt = abfd->symcount;
    528   amt *= sizeof (asymbol);
    529   VDATA (abfd)->symbols = bfd_alloc (abfd, amt);
    530 
    531   amt = VDATA (abfd)->stringlen;
    532   VDATA (abfd)->strings = bfd_alloc (abfd, amt);
    533 
    534   if ((VDATA (abfd)->symbols == NULL && abfd->symcount > 0)
    535       || (VDATA (abfd)->strings == NULL && VDATA (abfd)->stringlen > 0))
    536     return FALSE;
    537 
    538   /* Actually fill in the section symbols,
    539      we stick them at the end of the table.  */
    540   for (j = VDATA (abfd)->nrefs + VDATA (abfd)->ndefs, i = 0; i < 16; i++)
    541     {
    542       struct esdid *esdid = &EDATA (abfd, i);
    543       asection *sec = esdid->section;
    544 
    545       if (sec)
    546 	{
    547 	  asymbol *s = VDATA (abfd)->symbols + j;
    548 	  s->name = new_symbol_string (abfd, sec->name);
    549 	  s->section = sec;
    550 	  s->flags = BSF_LOCAL;
    551 	  s->value = 0;
    552 	  s->the_bfd = abfd;
    553 	  j++;
    554 	}
    555     }
    556 
    557   if (abfd->symcount)
    558     abfd->flags |= HAS_SYMS;
    559 
    560   /* Set this to nsecs - since we've already planted the section
    561      symbols.  */
    562   VDATA (abfd)->nsecsyms = nsecs;
    563 
    564   VDATA (abfd)->ref_idx = 0;
    565 
    566   return 1;
    567 }
    568 
    569 /* Check whether an existing file is a versados  file.  */
    570 
    571 static const bfd_target *
    572 versados_object_p (bfd *abfd)
    573 {
    574   struct ext_vheader ext;
    575   unsigned char len;
    576   tdata_type *tdata_save;
    577 
    578   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
    579     return NULL;
    580 
    581   if (bfd_bread (&len, (bfd_size_type) 1, abfd) != 1)
    582     {
    583       if (bfd_get_error () != bfd_error_system_call)
    584 	bfd_set_error (bfd_error_wrong_format);
    585       return NULL;
    586     }
    587 
    588   if (bfd_bread (&ext.type, (bfd_size_type) len, abfd) != len)
    589     {
    590       if (bfd_get_error () != bfd_error_system_call)
    591 	bfd_set_error (bfd_error_wrong_format);
    592       return NULL;
    593     }
    594 
    595   /* We guess that the language field will never be larger than 10.
    596      In sample files, it is always either 0 or 1.  Checking for this
    597      prevents confusion with Intel Hex files.  */
    598   if (ext.type != VHEADER
    599       || ext.lang > 10)
    600     {
    601       bfd_set_error (bfd_error_wrong_format);
    602       return NULL;
    603     }
    604 
    605   /* OK, looks like a record, build the tdata and read in.  */
    606   tdata_save = abfd->tdata.versados_data;
    607   if (!versados_mkobject (abfd) || !versados_scan (abfd))
    608     {
    609       abfd->tdata.versados_data = tdata_save;
    610       return NULL;
    611     }
    612 
    613   return abfd->xvec;
    614 }
    615 
    616 static bfd_boolean
    617 versados_pass_2 (bfd *abfd)
    618 {
    619   union ext_any any;
    620 
    621   if (VDATA (abfd)->pass_2_done)
    622     return 1;
    623 
    624   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
    625     return 0;
    626 
    627   VDATA (abfd)->es_done = ES_BASE;
    628 
    629   /* Read records till we get to where we want to be.  */
    630   while (1)
    631     {
    632       get_record (abfd, &any);
    633       switch (any.header.type)
    634 	{
    635 	case VEND:
    636 	  VDATA (abfd)->pass_2_done = 1;
    637 	  return 1;
    638 	case VESTDEF:
    639 	  process_esd (abfd, &any.esd, 2);
    640 	  break;
    641 	case VOTR:
    642 	  process_otr (abfd, &any.otr, 2);
    643 	  break;
    644 	}
    645     }
    646 }
    647 
    648 static bfd_boolean
    649 versados_get_section_contents (bfd *abfd,
    650 			       asection *section,
    651 			       void * location,
    652 			       file_ptr offset,
    653 			       bfd_size_type count)
    654 {
    655   if (!versados_pass_2 (abfd))
    656     return FALSE;
    657 
    658   memcpy (location,
    659 	  EDATA (abfd, section->target_index).contents + offset,
    660 	  (size_t) count);
    661 
    662   return TRUE;
    663 }
    664 
    665 #define versados_get_section_contents_in_window \
    666   _bfd_generic_get_section_contents_in_window
    667 
    668 static bfd_boolean
    669 versados_set_section_contents (bfd *abfd ATTRIBUTE_UNUSED,
    670 			       sec_ptr section ATTRIBUTE_UNUSED,
    671 			       const void * location ATTRIBUTE_UNUSED,
    672 			       file_ptr offset ATTRIBUTE_UNUSED,
    673 			       bfd_size_type bytes_to_do ATTRIBUTE_UNUSED)
    674 {
    675   return FALSE;
    676 }
    677 
    678 static int
    679 versados_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
    680 			 struct bfd_link_info *info ATTRIBUTE_UNUSED)
    681 {
    682   return 0;
    683 }
    684 
    685 /* Return the amount of memory needed to read the symbol table.  */
    686 
    687 static long
    688 versados_get_symtab_upper_bound (bfd *abfd)
    689 {
    690   return (bfd_get_symcount (abfd) + 1) * sizeof (asymbol *);
    691 }
    692 
    693 /* Return the symbol table.  */
    694 
    695 static long
    696 versados_canonicalize_symtab (bfd *abfd, asymbol **alocation)
    697 {
    698   unsigned int symcount = bfd_get_symcount (abfd);
    699   unsigned int i;
    700   asymbol *s;
    701 
    702   versados_pass_2 (abfd);
    703 
    704   for (i = 0, s = VDATA (abfd)->symbols;
    705        i < symcount;
    706        s++, i++)
    707     *alocation++ = s;
    708 
    709   *alocation = NULL;
    710 
    711   return symcount;
    712 }
    713 
    714 static void
    715 versados_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED,
    716 			  asymbol *symbol,
    717 			  symbol_info *ret)
    718 {
    719   bfd_symbol_info (symbol, ret);
    720 }
    721 
    722 static void
    723 versados_print_symbol (bfd *abfd,
    724 		       void * afile,
    725 		       asymbol *symbol,
    726 		       bfd_print_symbol_type how)
    727 {
    728   FILE *file = (FILE *) afile;
    729 
    730   switch (how)
    731     {
    732     case bfd_print_symbol_name:
    733       fprintf (file, "%s", symbol->name);
    734       break;
    735     default:
    736       bfd_print_symbol_vandf (abfd, (void *) file, symbol);
    737       fprintf (file, " %-5s %s",
    738 	       symbol->section->name,
    739 	       symbol->name);
    740     }
    741 }
    742 
    743 static long
    744 versados_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED,
    745 				sec_ptr asect)
    746 {
    747   return (asect->reloc_count + 1) * sizeof (arelent *);
    748 }
    749 
    750 static long
    751 versados_canonicalize_reloc (bfd *abfd,
    752 			     sec_ptr section,
    753 			     arelent **relptr,
    754 			     asymbol **symbols)
    755 {
    756   unsigned int count;
    757   arelent *src;
    758 
    759   versados_pass_2 (abfd);
    760   src = section->relocation;
    761   if (!EDATA (abfd, section->target_index).donerel)
    762     {
    763       EDATA (abfd, section->target_index).donerel = 1;
    764       /* Translate from indexes to symptr ptrs.  */
    765       for (count = 0; count < section->reloc_count; count++)
    766 	{
    767 	  int esdid = (int) (size_t) src[count].sym_ptr_ptr;
    768 
    769 	  if (esdid == 0)
    770 	    src[count].sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
    771 	  else if (esdid < ES_BASE)
    772 	    {
    773 	      /* Section relative thing.  */
    774 	      struct esdid *e = &EDATA (abfd, esdid - 1);
    775 
    776 	      src[count].sym_ptr_ptr = e->section->symbol_ptr_ptr;
    777 	    }
    778 	  else
    779 	    src[count].sym_ptr_ptr = symbols + esdid - ES_BASE;
    780 	}
    781     }
    782 
    783   for (count = 0; count < section->reloc_count; count++)
    784     *relptr++ = src++;
    785 
    786   *relptr = 0;
    787   return section->reloc_count;
    788 }
    789 
    790 #define	versados_close_and_cleanup                    _bfd_generic_close_and_cleanup
    791 #define versados_bfd_free_cached_info                 _bfd_generic_bfd_free_cached_info
    792 #define versados_new_section_hook                     _bfd_generic_new_section_hook
    793 #define versados_bfd_is_target_special_symbol   ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
    794 #define versados_bfd_is_local_label_name              bfd_generic_is_local_label_name
    795 #define versados_get_lineno                           _bfd_nosymbols_get_lineno
    796 #define versados_find_nearest_line                    _bfd_nosymbols_find_nearest_line
    797 #define versados_find_line                            _bfd_nosymbols_find_line
    798 #define versados_find_inliner_info                    _bfd_nosymbols_find_inliner_info
    799 #define versados_make_empty_symbol                    _bfd_generic_make_empty_symbol
    800 #define versados_bfd_make_debug_symbol                _bfd_nosymbols_bfd_make_debug_symbol
    801 #define versados_read_minisymbols                     _bfd_generic_read_minisymbols
    802 #define versados_minisymbol_to_symbol                 _bfd_generic_minisymbol_to_symbol
    803 #define versados_bfd_reloc_type_lookup                _bfd_norelocs_bfd_reloc_type_lookup
    804 #define versados_bfd_reloc_name_lookup          _bfd_norelocs_bfd_reloc_name_lookup
    805 #define versados_set_arch_mach                        bfd_default_set_arch_mach
    806 #define versados_bfd_get_relocated_section_contents   bfd_generic_get_relocated_section_contents
    807 #define versados_bfd_relax_section                    bfd_generic_relax_section
    808 #define versados_bfd_gc_sections                      bfd_generic_gc_sections
    809 #define versados_bfd_lookup_section_flags             bfd_generic_lookup_section_flags
    810 #define versados_bfd_merge_sections                   bfd_generic_merge_sections
    811 #define versados_bfd_is_group_section                 bfd_generic_is_group_section
    812 #define versados_bfd_discard_group                    bfd_generic_discard_group
    813 #define versados_section_already_linked               _bfd_generic_section_already_linked
    814 #define versados_bfd_define_common_symbol             bfd_generic_define_common_symbol
    815 #define versados_bfd_link_hash_table_create           _bfd_generic_link_hash_table_create
    816 #define versados_bfd_link_add_symbols                 _bfd_generic_link_add_symbols
    817 #define versados_bfd_link_just_syms                   _bfd_generic_link_just_syms
    818 #define versados_bfd_copy_link_hash_symbol_type \
    819   _bfd_generic_copy_link_hash_symbol_type
    820 #define versados_bfd_final_link                       _bfd_generic_final_link
    821 #define versados_bfd_link_split_section               _bfd_generic_link_split_section
    822 
    823 const bfd_target m68k_versados_vec =
    824 {
    825   "versados",			/* Name.  */
    826   bfd_target_versados_flavour,
    827   BFD_ENDIAN_BIG,		/* Target byte order.  */
    828   BFD_ENDIAN_BIG,		/* Target headers byte order.  */
    829   (HAS_RELOC | EXEC_P |		/* Object flags.  */
    830    HAS_LINENO | HAS_DEBUG |
    831    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
    832   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
    833    | SEC_ALLOC | SEC_LOAD | SEC_RELOC),		/* Section flags.  */
    834   0,				/* Leading underscore.  */
    835   ' ',				/* AR_pad_char.  */
    836   16,				/* AR_max_namelen.  */
    837   0,				/* match priority.  */
    838   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
    839   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
    840   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Data.  */
    841   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
    842   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
    843   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Headers.  */
    844 
    845   {
    846     _bfd_dummy_target,
    847     versados_object_p,		/* bfd_check_format.  */
    848     _bfd_dummy_target,
    849     _bfd_dummy_target,
    850   },
    851   {
    852     bfd_false,
    853     versados_mkobject,
    854     _bfd_generic_mkarchive,
    855     bfd_false,
    856   },
    857   {				/* bfd_write_contents.  */
    858     bfd_false,
    859     bfd_false,
    860     _bfd_write_archive_contents,
    861     bfd_false,
    862   },
    863 
    864   BFD_JUMP_TABLE_GENERIC (versados),
    865   BFD_JUMP_TABLE_COPY (_bfd_generic),
    866   BFD_JUMP_TABLE_CORE (_bfd_nocore),
    867   BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
    868   BFD_JUMP_TABLE_SYMBOLS (versados),
    869   BFD_JUMP_TABLE_RELOCS (versados),
    870   BFD_JUMP_TABLE_WRITE (versados),
    871   BFD_JUMP_TABLE_LINK (versados),
    872   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
    873 
    874   NULL,
    875 
    876   NULL
    877 };
    878