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