11844Swollman/* BFD back-end for RISC iX (Acorn, arm) binaries.
250476Speter   Copyright (C) 1994-2017 Free Software Foundation, Inc.
31844Swollman   Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
41638Srgrimes
594940Sru   This file is part of BFD, the Binary File Descriptor library.
61638Srgrimes
742915Sjdp   This program is free software; you can redistribute it and/or modify
842915Sjdp   it under the terms of the GNU General Public License as published by
942915Sjdp   the Free Software Foundation; either version 3 of the License, or
1042915Sjdp   (at your option) any later version.
1142915Sjdp
1242915Sjdp   This program is distributed in the hope that it will be useful,
1342915Sjdp   but WITHOUT ANY WARRANTY; without even the implied warranty of
1442915Sjdp   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1599362Sru   GNU General Public License for more details.
1642915Sjdp
1729141Speter   You should have received a copy of the GNU General Public License
18100375Sru   along with this program; if not, write to the Free Software
19100332Sru   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20100332Sru   MA 02110-1301, USA.  */
2142915Sjdp
2242915Sjdp
2329141Speter/* RISC iX overloads the MAGIC field to indicate more than just the usual
24119607Sru   [ZNO]MAGIC values.  Also included are squeezing information and
25117034Sgordon   shared library usage.  */
26119607Sru
27117034Sgordon/* The following come from the man page.  */
282827Sjkh#define SHLIBLEN 60
292827Sjkh
302827Sjkh#define MF_IMPURE       00200
312827Sjkh#define MF_SQUEEZED     01000
322827Sjkh#define MF_USES_SL      02000
331638Srgrimes#define MF_IS_SL        04000
342827Sjkh
351638Srgrimes/* Common combinations.  */
3618529Sbde
3718529Sbde/* Demand load (impure text).  */
381638Srgrimes#define IMAGIC          (MF_IMPURE | ZMAGIC)
3942450Sjdp
401638Srgrimes/* OMAGIC with large header.
41117173Sru   May contain a ref to a shared lib required by the object.  */
421638Srgrimes#define SPOMAGIC        (MF_USES_SL | OMAGIC)
4396512Sru
4496512Sru/* A reference to a shared library.
4596512Sru   The text portion of the object contains "overflow text" from
4696512Sru   the shared library to be linked in with an object.  */
4796512Sru#define SLOMAGIC        (MF_IS_SL | OMAGIC)
4896512Sru
4996512Sru/* Sqeezed demand paged.
5096512Sru   NOTE: This interpretation of QMAGIC seems to be at variance
511638Srgrimes   with that used on other architectures.  */
5224761Sjdp#define QMAGIC          (MF_SQUEEZED | ZMAGIC)
531638Srgrimes
5442450Sjdp/* Program which uses sl.  */
551844Swollman#define SPZMAGIC        (MF_USES_SL | ZMAGIC)
561844Swollman
5736673Sdt/* Sqeezed ditto.  */
5824761Sjdp#define SPQMAGIC        (MF_USES_SL | QMAGIC)
591844Swollman
6042450Sjdp/* Shared lib part of prog.  */
611844Swollman#define SLZMAGIC        (MF_IS_SL | ZMAGIC)
621844Swollman
631844Swollman/* Sl which uses another.  */
6424761Sjdp#define SLPZMAGIC       (MF_USES_SL | SLZMAGIC)
651844Swollman
6642450Sjdp#define N_SHARED_LIB(x) ((x)->a_info & MF_USES_SL)
671844Swollman
681844Swollman/* Only a pure OMAGIC file has the minimal header.  */
6936054Sbde#define N_TXTOFF(x)		\
7036054Sbde ((x)->a_info == OMAGIC		\
7136054Sbde  ? 32				\
7242450Sjdp  : (N_MAGIC(x) == ZMAGIC	\
7336054Sbde     ? TARGET_PAGE_SIZE		\
7436054Sbde     : 999))
75117173Sru
76117159Sru#define N_TXTADDR(x)							     \
771638Srgrimes  (N_MAGIC(x) != ZMAGIC							     \
78117173Sru   ? (bfd_vma) 0 /* object file or NMAGIC */				     \
79117173Sru   /* Programs with shared libs are loaded at the first page after all the   \
80117173Sru      text segments of the shared library programs.  Without looking this    \
81117173Sru      up we can't know exactly what the address will be.  A reasonable guess \
82117173Sru      is that a_entry will be in the first page of the executable.  */	     \
83117173Sru   : (N_SHARED_LIB(x)							     \
84117173Sru      ? ((x)->a_entry & ~(bfd_vma) (TARGET_PAGE_SIZE - 1))		     \
851844Swollman      : (bfd_vma) TEXT_START_ADDR))
86117122Sru
871844Swollman#define N_SYMOFF(x) \
8842450Sjdp  (N_TXTOFF (x) + (x)->a_text + (x)->a_data + (x)->a_trsize + (x)->a_drsize)
89117122Sru
901844Swollman#define N_STROFF(x) (N_SYMOFF (x) + (x)->a_syms)
9196512Sru
921638Srgrimes#define TEXT_START_ADDR   32768
9399362Sru#define TARGET_PAGE_SIZE  32768
9499362Sru#define SEGMENT_SIZE      TARGET_PAGE_SIZE
9599362Sru#define DEFAULT_ARCH      bfd_arch_arm
9699362Sru
9796512Sru/* Do not "beautify" the CONCAT* macro args.  Traditional C will not
9896512Sru   remove whitespace added here, and thus will fail to concatenate
991638Srgrimes   the tokens.  */
10096512Sru#define MY(OP) CONCAT2 (arm_aout_riscix_,OP)
10196512Sru#define TARGETNAME "a.out-riscix"
10296512Sru#define N_BADMAG(x) ((((x)->a_info & ~007200) != ZMAGIC) \
10396512Sru                  && (((x)->a_info & ~006000) != OMAGIC) \
10496512Sru                  && ((x)->a_info != NMAGIC))
10599362Sru#define N_MAGIC(x) ((x)->a_info & ~07200)
1061638Srgrimes
10796512Sru#include "sysdep.h"
10895114Sobrien#include "bfd.h"
10999362Sru#include "libbfd.h"
11096512Sru
11196512Sru#define WRITE_HEADERS(abfd, execp)					    \
11295306Sru  {									    \
11396512Sru    if (adata (abfd).magic == undecided_magic)				    \
11496512Sru      NAME (aout, adjust_sizes_and_vmas) (abfd);			    \
11596512Sru    									    \
11696512Sru    execp->a_syms = bfd_get_symcount (abfd) * EXTERNAL_NLIST_SIZE;	    \
11796512Sru    execp->a_entry = bfd_get_start_address (abfd);			    \
11874805Sru    									    \
1191844Swollman    execp->a_trsize = ((obj_textsec (abfd)->reloc_count) *		    \
12099362Sru		       obj_reloc_entry_size (abfd));			    \
12199362Sru    execp->a_drsize = ((obj_datasec (abfd)->reloc_count) *		    \
12296512Sru		       obj_reloc_entry_size (abfd));			    \
12399362Sru    NAME (aout, swap_exec_header_out) (abfd, execp, & exec_bytes);	    \
1241844Swollman    									    \
12596512Sru    if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0			    \
12696512Sru	|| bfd_bwrite ((void *) & exec_bytes, (bfd_size_type) EXEC_BYTES_SIZE,  \
1271638Srgrimes		      abfd) != EXEC_BYTES_SIZE)				    \
12842915Sjdp      return FALSE;							    \
12942915Sjdp    /* Now write out reloc info, followed by syms and strings.  */	    \
13096512Sru									    \
13142915Sjdp    if (bfd_get_outsymbols (abfd) != NULL			    	    \
13296512Sru	&& bfd_get_symcount (abfd) != 0)				    \
13342915Sjdp      {									    \
13496343Sobrien	if (bfd_seek (abfd, (file_ptr) (N_SYMOFF (execp)), SEEK_SET) != 0)  \
13596512Sru	  return FALSE;							    \
13691011Sru									    \
13728945Speter	if (! NAME (aout, write_syms) (abfd))				    \
1381844Swollman          return FALSE;							    \
13999362Sru									    \
14096512Sru	if (bfd_seek (abfd, (file_ptr) (N_TRELOFF (execp)), SEEK_SET) != 0) \
14196512Sru	  return FALSE;							    \
14296512Sru									    \
1432353Sbde	if (! riscix_squirt_out_relocs (abfd, obj_textsec (abfd)))	    \
14496512Sru	  return FALSE;							    \
14596512Sru	if (bfd_seek (abfd, (file_ptr) (N_DRELOFF (execp)), SEEK_SET) != 0) \
14696512Sru	  return FALSE;							    \
1473859Sbde									    \
1481844Swollman	if (!NAME (aout, squirt_out_relocs) (abfd, obj_datasec (abfd)))	    \
149103713Smarkm	  return FALSE;							    \
15096512Sru      }									    \
15196512Sru  }
15296512Sru
15396512Sru#include "libaout.h"
15492491Smarkm#include "aout/aout64.h"
15596512Sru
15696512Srustatic bfd_reloc_status_type
15792491Smarkmriscix_fix_pcrel_26_done (bfd *abfd ATTRIBUTE_UNUSED,
15892491Smarkm			  arelent *reloc_entry ATTRIBUTE_UNUSED,
1591638Srgrimes			  asymbol *symbol ATTRIBUTE_UNUSED,
16096512Sru			  void * data ATTRIBUTE_UNUSED,
16196512Sru			  asection *input_section ATTRIBUTE_UNUSED,
16296512Sru			  bfd *output_bfd ATTRIBUTE_UNUSED,
16396512Sru			  char **error_message ATTRIBUTE_UNUSED)
16496512Sru{
16596512Sru  /* This is dead simple at present.  */
1661638Srgrimes  return bfd_reloc_ok;
1671638Srgrimes}
16834179Sbde
16924750Sbdestatic bfd_reloc_status_type riscix_fix_pcrel_26 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
17042450Sjdpstatic const bfd_target *arm_aout_riscix_callback (bfd *);
17124750Sbde
17224750Sbdestatic reloc_howto_type riscix_std_reloc_howto[] =
17342915Sjdp{
17431809Sbde  /* Type              rs size bsz  pcrel bitpos ovrf                     sf name     part_inpl readmask  setmask    pcdone */
17542915Sjdp  HOWTO( 0,              0,  0,   8,  FALSE, 0, complain_overflow_bitfield,0,"8",         TRUE, 0x000000ff,0x000000ff, FALSE),
17627910Sasami  HOWTO( 1,              0,  1,   16, FALSE, 0, complain_overflow_bitfield,0,"16",        TRUE, 0x0000ffff,0x0000ffff, FALSE),
17728945Speter  HOWTO( 2,              0,  2,   32, FALSE, 0, complain_overflow_bitfield,0,"32",        TRUE, 0xffffffff,0xffffffff, FALSE),
1781638Srgrimes  HOWTO( 3,              2,  3,   26, TRUE,  0, complain_overflow_signed,  riscix_fix_pcrel_26 , "ARM26",      TRUE, 0x00ffffff,0x00ffffff, FALSE),
1791638Srgrimes  HOWTO( 4,              0,  0,   8,  TRUE,  0, complain_overflow_signed,  0,"DISP8",     TRUE, 0x000000ff,0x000000ff, TRUE),
1801638Srgrimes  HOWTO( 5,              0,  1,   16, TRUE,  0, complain_overflow_signed,  0,"DISP16",    TRUE, 0x0000ffff,0x0000ffff, TRUE),
18148204Sjmg  HOWTO( 6,              0,  2,   32, TRUE,  0, complain_overflow_signed,  0,"DISP32",    TRUE, 0xffffffff,0xffffffff, TRUE),
1822298Swollman  HOWTO( 7,              2,  3,   26, FALSE, 0, complain_overflow_signed,  riscix_fix_pcrel_26_done, "ARM26D",TRUE,0x00ffffff,0x00ffffff, FALSE),
1832298Swollman  EMPTY_HOWTO (-1),
1842298Swollman  HOWTO( 9,              0, -1,   16, FALSE, 0, complain_overflow_bitfield,0,"NEG16",     TRUE, 0x0000ffff,0x0000ffff, FALSE),
18549328Shoek  HOWTO( 10,              0, -2,  32, FALSE, 0, complain_overflow_bitfield,0,"NEG32",     TRUE, 0xffffffff,0xffffffff, FALSE)
18649328Shoek};
18749328Shoek
18849328Shoek#define RISCIX_TABLE_SIZE \
18956971Sru  (sizeof (riscix_std_reloc_howto) / sizeof (reloc_howto_type))
19049328Shoek
19149328Shoekstatic bfd_reloc_status_type
19249328Shoekriscix_fix_pcrel_26 (bfd *abfd,
19349328Shoek		     arelent *reloc_entry,
19499362Sru		     asymbol *symbol,
19595306Sru		     void * data,
19699343Sru		     asection *input_section,
19795306Sru		     bfd *output_bfd,
19899362Sru		     char **error_message ATTRIBUTE_UNUSED)
19992980Sdes{
20049328Shoek  bfd_vma relocation;
20196512Sru  bfd_size_type addr = reloc_entry->address;
20299362Sru  long target = bfd_get_32 (abfd, (bfd_byte *) data + addr);
20392980Sdes  bfd_reloc_status_type flag = bfd_reloc_ok;
20449328Shoek
2051638Srgrimes  /* If this is an undefined symbol, return error.  */
206116144Sobrien  if (bfd_is_und_section (symbol->section)
207100872Sru      && (symbol->flags & BSF_WEAK) == 0)
20849328Shoek    return output_bfd ? bfd_reloc_continue : bfd_reloc_undefined;
20942915Sjdp
21042915Sjdp  /* If the sections are different, and we are doing a partial relocation,
211119056Sgordon     just ignore it for now.  */
212119056Sgordon  if (symbol->section->name != input_section->name
213119009Sgordon      && output_bfd != NULL)
214119009Sgordon    return bfd_reloc_continue;
2151844Swollman
21628945Speter  relocation = (target & 0x00ffffff) << 2;
217119009Sgordon  relocation = (relocation ^ 0x02000000) - 0x02000000; /* Sign extend.  */
21899362Sru  relocation += symbol->value;
219100872Sru  relocation += symbol->section->output_section->vma;
22049328Shoek  relocation += symbol->section->output_offset;
2211844Swollman  relocation += reloc_entry->addend;
222103713Smarkm  relocation -= input_section->output_section->vma;
223100872Sru  relocation -= input_section->output_offset;
22496462Sru  relocation -= addr;
22596462Sru  if (relocation & 3)
22699362Sru    return bfd_reloc_overflow;
22796462Sru
22897769Sru  /* Check for overflow.  */
22996668Sru  if (relocation & 0x02000000)
23099256Sru    {
23196462Sru      if ((relocation & ~ (bfd_vma) 0x03ffffff) != ~ (bfd_vma) 0x03ffffff)
23296162Sru	flag = bfd_reloc_overflow;
23396164Sru    }
23499343Sru  else if (relocation & ~ (bfd_vma) 0x03ffffff)
23596162Sru    flag = bfd_reloc_overflow;
23696162Sru
2371638Srgrimes  target &= ~0x00ffffff;
2381638Srgrimes  target |= (relocation >> 2) & 0x00ffffff;
2391638Srgrimes  bfd_put_32 (abfd, (bfd_vma) target, (bfd_byte *) data + addr);
24095306Sru
241103713Smarkm  /* Now the ARM magic... Change the reloc type so that it is marked as done.
2421638Srgrimes     Strictly this is only necessary if we are doing a partial relocation.  */
2431638Srgrimes  reloc_entry->howto = &riscix_std_reloc_howto[7];
2441844Swollman
2451638Srgrimes  return flag;
24674842Sru}
2471844Swollman
2481844Swollmanstatic reloc_howto_type *
24934092Sbderiscix_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code)
25099362Sru{
25196512Sru#define ASTD(i,j)       case i: return &riscix_std_reloc_howto[j]
25299362Sru  if (code == BFD_RELOC_CTOR)
25334092Sbde    switch (bfd_arch_bits_per_address (abfd))
25499362Sru      {
25599362Sru      case 32:
25699362Sru        code = BFD_RELOC_32;
25796512Sru        break;
25899362Sru      default:
25934092Sbde	return NULL;
260100457Sru      }
261100457Sru
262100457Sru  switch (code)
263100457Sru    {
264100457Sru      ASTD (BFD_RELOC_16, 1);
265100457Sru      ASTD (BFD_RELOC_32, 2);
266100457Sru      ASTD (BFD_RELOC_ARM_PCREL_BRANCH, 3);
267100457Sru      ASTD (BFD_RELOC_8_PCREL, 4);
268100457Sru      ASTD (BFD_RELOC_16_PCREL, 5);
269100457Sru      ASTD (BFD_RELOC_32_PCREL, 6);
270100457Sru    default:
271100457Sru      return NULL;
272100457Sru    }
273100457Sru}
274100457Sru
275100457Srustatic reloc_howto_type *
276100457Sruriscix_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
277100457Sru			  const char *r_name)
278100457Sru{
279100457Sru  unsigned int i;
280100457Sru
281100457Sru  for (i = 0;
282100457Sru       i < sizeof (riscix_std_reloc_howto) / sizeof (riscix_std_reloc_howto[0]);
283100457Sru       i++)
284100457Sru    if (riscix_std_reloc_howto[i].name != NULL
285100457Sru	&& strcasecmp (riscix_std_reloc_howto[i].name, r_name) == 0)
286100457Sru      return &riscix_std_reloc_howto[i];
287100457Sru
288100457Sru  return NULL;
289100457Sru}
290100457Sru
291100457Sru#define MY_bfd_link_hash_table_create  _bfd_generic_link_hash_table_create
292100457Sru#define MY_bfd_link_add_symbols        _bfd_generic_link_add_symbols
293100457Sru#define MY_final_link_callback         should_not_be_used
294100457Sru#define MY_bfd_final_link              _bfd_generic_final_link
295100457Sru
29616663Sjkh#define MY_bfd_reloc_type_lookup       riscix_reloc_type_lookup
29776861Skris#define MY_bfd_reloc_name_lookup       riscix_reloc_name_lookup
29876861Skris#define MY_canonicalize_reloc          arm_aout_riscix_canonicalize_reloc
299#define MY_object_p                    arm_aout_riscix_object_p
300
301static void
302riscix_swap_std_reloc_out (bfd *abfd,
303			   arelent *g,
304			   struct reloc_std_external *natptr)
305{
306  int r_index;
307  asymbol *sym = *(g->sym_ptr_ptr);
308  int r_extern;
309  int r_length;
310  int r_pcrel;
311  int r_neg = 0;	/* Negative relocs use the BASEREL bit.  */
312  asection *output_section = sym->section->output_section;
313
314  PUT_WORD(abfd, g->address, natptr->r_address);
315
316  r_length = g->howto->size ;   /* Size as a power of two.  */
317  if (r_length < 0)
318    {
319      r_length = -r_length;
320      r_neg = 1;
321    }
322
323  r_pcrel  = (int) g->howto->pc_relative; /* Relative to PC?  */
324
325  /* For RISC iX, in pc-relative relocs the r_pcrel bit means that the
326     relocation has been done already (Only for the 26-bit one I think)?  */
327  if (r_length == 3)
328    r_pcrel = r_pcrel ? 0 : 1;
329
330  /* Name was clobbered by aout_write_syms to be symbol index.  */
331
332  /* If this relocation is relative to a symbol then set the
333     r_index to the symbols index, and the r_extern bit.
334
335     Absolute symbols can come in in two ways, either as an offset
336     from the abs section, or as a symbol which has an abs value.
337     check for that here.  */
338
339  if (bfd_is_com_section (output_section)
340      || bfd_is_abs_section (output_section)
341      || bfd_is_und_section (output_section))
342    {
343      if (bfd_abs_section_ptr->symbol == sym)
344	{
345	  /* Whoops, looked like an abs symbol, but is really an offset
346	     from the abs section.  */
347	  r_index = 0;
348	  r_extern = 0;
349	}
350      else
351	{
352	  /* Fill in symbol.  */
353	  r_extern = 1;
354	  r_index = (*g->sym_ptr_ptr)->udata.i;
355	}
356    }
357  else
358    {
359      /* Just an ordinary section.  */
360      r_extern = 0;
361      r_index  = output_section->target_index;
362    }
363
364  /* Now the fun stuff.  */
365  if (bfd_header_big_endian (abfd))
366    {
367      natptr->r_index[0] = r_index >> 16;
368      natptr->r_index[1] = r_index >> 8;
369      natptr->r_index[2] = r_index;
370      natptr->r_type[0] =
371	(  (r_extern ?   RELOC_STD_BITS_EXTERN_BIG: 0)
372	 | (r_pcrel  ?   RELOC_STD_BITS_PCREL_BIG: 0)
373	 | (r_neg    ?   RELOC_STD_BITS_BASEREL_BIG: 0)
374	 | (r_length <<  RELOC_STD_BITS_LENGTH_SH_BIG));
375    }
376  else
377    {
378      natptr->r_index[2] = r_index >> 16;
379      natptr->r_index[1] = r_index >> 8;
380      natptr->r_index[0] = r_index;
381      natptr->r_type[0] =
382	(  (r_extern ?   RELOC_STD_BITS_EXTERN_LITTLE: 0)
383	 | (r_pcrel  ?   RELOC_STD_BITS_PCREL_LITTLE: 0)
384	 | (r_neg    ?   RELOC_STD_BITS_BASEREL_LITTLE: 0)
385	 | (r_length <<  RELOC_STD_BITS_LENGTH_SH_LITTLE));
386    }
387}
388
389static bfd_boolean
390riscix_squirt_out_relocs (bfd *abfd, asection *section)
391{
392  arelent **generic;
393  unsigned char *native, *natptr;
394  size_t each_size;
395  unsigned int count = section->reloc_count;
396  bfd_size_type natsize;
397
398  if (count == 0)
399    return TRUE;
400
401  each_size = obj_reloc_entry_size (abfd);
402  natsize = each_size;
403  natsize *= count;
404  native = bfd_zalloc (abfd, natsize);
405  if (!native)
406    return FALSE;
407
408  generic = section->orelocation;
409
410  for (natptr = native;
411       count != 0;
412       --count, natptr += each_size, ++generic)
413    riscix_swap_std_reloc_out (abfd, *generic,
414			       (struct reloc_std_external *) natptr);
415
416  if (bfd_bwrite ((void *) native, natsize, abfd) != natsize)
417    {
418      bfd_release (abfd, native);
419      return FALSE;
420    }
421
422  bfd_release (abfd, native);
423  return TRUE;
424}
425
426/* This is just like the standard aoutx.h version but we need to do our
427   own mapping of external reloc type values to howto entries.  */
428
429static long
430MY (canonicalize_reloc) (bfd *abfd,
431			 sec_ptr section,
432			 arelent **relptr,
433			 asymbol **symbols)
434{
435  arelent *tblptr = section->relocation;
436  unsigned int count, c;
437  extern reloc_howto_type NAME (aout, std_howto_table)[];
438
439  /* If we have already read in the relocation table, return the values.  */
440  if (section->flags & SEC_CONSTRUCTOR)
441    {
442      arelent_chain *chain = section->constructor_chain;
443
444      for (count = 0; count < section->reloc_count; count++)
445	{
446	  *relptr++ = &chain->relent;
447	  chain = chain->next;
448	}
449      *relptr = 0;
450      return section->reloc_count;
451    }
452
453  if (tblptr && section->reloc_count)
454    {
455      for (count = 0; count++ < section->reloc_count;)
456	*relptr++ = tblptr++;
457      *relptr = 0;
458      return section->reloc_count;
459    }
460
461  if (!NAME (aout, slurp_reloc_table) (abfd, section, symbols))
462    return -1;
463  tblptr = section->relocation;
464
465  /* Fix up howto entries.  */
466  for (count = 0; count++ < section->reloc_count;)
467    {
468      c = tblptr->howto - NAME(aout,std_howto_table);
469      BFD_ASSERT (c < RISCIX_TABLE_SIZE);
470      tblptr->howto = &riscix_std_reloc_howto[c];
471
472      *relptr++ = tblptr++;
473    }
474  *relptr = 0;
475  return section->reloc_count;
476}
477
478/* This is the same as NAME(aout,some_aout_object_p), but has different
479   expansions of the macro definitions.  */
480
481static const bfd_target *
482riscix_some_aout_object_p (bfd *abfd,
483			   struct internal_exec *execp,
484			   const bfd_target *(*callback_to_real_object_p) (bfd *))
485{
486  struct aout_data_struct *rawptr, *oldrawptr;
487  const bfd_target *result;
488  bfd_size_type amt = sizeof (struct aout_data_struct);
489
490  rawptr = bfd_zalloc (abfd, amt);
491
492  if (rawptr == NULL)
493    return NULL;
494
495  oldrawptr = abfd->tdata.aout_data;
496  abfd->tdata.aout_data = rawptr;
497
498  /* Copy the contents of the old tdata struct.
499     In particular, we want the subformat, since for hpux it was set in
500     hp300hpux.c:swap_exec_header_in and will be used in
501     hp300hpux.c:callback.  */
502  if (oldrawptr != NULL)
503    *abfd->tdata.aout_data = *oldrawptr;
504
505  abfd->tdata.aout_data->a.hdr = &rawptr->e;
506  /* Copy in the internal_exec struct.  */
507  *(abfd->tdata.aout_data->a.hdr) = *execp;
508  execp = abfd->tdata.aout_data->a.hdr;
509
510  /* Set the file flags.  */
511  abfd->flags = BFD_NO_FLAGS;
512  if (execp->a_drsize || execp->a_trsize)
513    abfd->flags |= HAS_RELOC;
514  /* Setting of EXEC_P has been deferred to the bottom of this function.  */
515  if (execp->a_syms)
516    abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
517  if (N_DYNAMIC (execp))
518    abfd->flags |= DYNAMIC;
519
520 /* Squeezed files aren't supported (yet)!  */
521  if ((execp->a_info & MF_SQUEEZED) != 0)
522    {
523      bfd_set_error (bfd_error_wrong_format);
524      return NULL;
525    }
526  else if ((execp->a_info & MF_IS_SL) != 0)
527    {
528      /* Nor are shared libraries.  */
529      bfd_set_error (bfd_error_wrong_format);
530      return NULL;
531    }
532  else if (N_MAGIC (execp) == ZMAGIC)
533    {
534      abfd->flags |= D_PAGED | WP_TEXT;
535      adata (abfd).magic = z_magic;
536    }
537  else if (N_MAGIC (execp) == NMAGIC)
538    {
539      abfd->flags |= WP_TEXT;
540      adata (abfd).magic = n_magic;
541    }
542  else if (N_MAGIC (execp) == OMAGIC)
543    adata (abfd).magic = o_magic;
544  else
545    /* Should have been checked with N_BADMAG before this routine
546       was called.  */
547    abort ();
548
549  bfd_get_start_address (abfd) = execp->a_entry;
550
551  obj_aout_symbols (abfd) = NULL;
552  bfd_get_symcount (abfd) = execp->a_syms / sizeof (struct external_nlist);
553
554  /* The default relocation entry size is that of traditional V7 Unix.  */
555  obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
556
557  /* The default symbol entry size is that of traditional Unix.  */
558  obj_symbol_entry_size (abfd) = EXTERNAL_NLIST_SIZE;
559
560  obj_aout_external_syms (abfd) = NULL;
561  obj_aout_external_strings (abfd) = NULL;
562  obj_aout_sym_hashes (abfd) = NULL;
563
564  if (! NAME (aout, make_sections) (abfd))
565    return NULL;
566
567  obj_datasec (abfd)->size = execp->a_data;
568  obj_bsssec (abfd)->size = execp->a_bss;
569
570  obj_textsec (abfd)->flags =
571    (execp->a_trsize != 0
572     ? (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS | SEC_RELOC)
573     : (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS));
574  obj_datasec (abfd)->flags =
575    (execp->a_drsize != 0
576     ? (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS | SEC_RELOC)
577     : (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS));
578  obj_bsssec (abfd)->flags = SEC_ALLOC;
579
580  result = (*callback_to_real_object_p) (abfd);
581
582#if defined(MACH) || defined(STAT_FOR_EXEC)
583  /* The original heuristic doesn't work in some important cases. The
584     a.out file has no information about the text start address. For
585     files (like kernels) linked to non-standard addresses (ld -Ttext
586     nnn) the entry point may not be between the default text start
587     (obj_textsec(abfd)->vma) and (obj_textsec(abfd)->vma) + text size
588     This is not just a mach issue. Many kernels are loaded at non
589     standard addresses.  */
590  {
591    struct stat stat_buf;
592
593    if (abfd->iostream != NULL
594	&& (abfd->flags & BFD_IN_MEMORY) == 0
595        && (fstat(fileno((FILE *) (abfd->iostream)), &stat_buf) == 0)
596        && ((stat_buf.st_mode & 0111) != 0))
597      abfd->flags |= EXEC_P;
598  }
599#else /* ! MACH */
600  /* Now that the segment addresses have been worked out, take a better
601     guess at whether the file is executable.  If the entry point
602     is within the text segment, assume it is.  (This makes files
603     executable even if their entry point address is 0, as long as
604     their text starts at zero.)
605
606     At some point we should probably break down and stat the file and
607     declare it executable if (one of) its 'x' bits are on...  */
608  if ((execp->a_entry >= obj_textsec(abfd)->vma) &&
609      (execp->a_entry < obj_textsec(abfd)->vma + obj_textsec(abfd)->size))
610    abfd->flags |= EXEC_P;
611#endif /* MACH */
612  if (result == NULL)
613    {
614      free (rawptr);
615      abfd->tdata.aout_data = oldrawptr;
616    }
617  return result;
618}
619
620static const bfd_target *
621MY (object_p) (bfd *abfd)
622{
623  struct external_exec exec_bytes;      /* Raw exec header from file.  */
624  struct internal_exec exec;            /* Cleaned-up exec header.  */
625  const bfd_target *target;
626
627  if (bfd_bread ((void *) &exec_bytes, (bfd_size_type) EXEC_BYTES_SIZE, abfd)
628      != EXEC_BYTES_SIZE)
629    {
630      if (bfd_get_error () != bfd_error_system_call)
631	bfd_set_error (bfd_error_wrong_format);
632      return NULL;
633    }
634
635  exec.a_info = H_GET_32 (abfd, exec_bytes.e_info);
636
637  if (N_BADMAG (&exec))
638    return NULL;
639
640#ifdef MACHTYPE_OK
641  if (!(MACHTYPE_OK (N_MACHTYPE (&exec))))
642    return NULL;
643#endif
644
645  NAME (aout, swap_exec_header_in) (abfd, & exec_bytes, & exec);
646
647  target = riscix_some_aout_object_p (abfd, & exec, MY (callback));
648
649  return target;
650}
651
652#include "aout-target.h"
653