Home | History | Annotate | Download | only in bfd
      1 /* BFD back-end for RISC iX (Acorn, arm) binaries.
      2    Copyright (C) 1994-2014 Free Software Foundation, Inc.
      3    Contributed by Richard Earnshaw (rwe (at) pegasus.esprit.ec.org)
      4 
      5    This file is part of BFD, the Binary File Descriptor library.
      6 
      7    This program is free software; you can redistribute it and/or modify
      8    it under the terms of the GNU General Public License as published by
      9    the Free Software Foundation; either version 3 of the License, or
     10    (at your option) any later version.
     11 
     12    This program is distributed in the hope that it will be useful,
     13    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15    GNU General Public License for more details.
     16 
     17    You should have received a copy of the GNU General Public License
     18    along with this program; if not, write to the Free Software
     19    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     20    MA 02110-1301, USA.  */
     21 
     22 
     23 /* RISC iX overloads the MAGIC field to indicate more than just the usual
     24    [ZNO]MAGIC values.  Also included are squeezing information and
     25    shared library usage.  */
     26 
     27 /* The following come from the man page.  */
     28 #define SHLIBLEN 60
     29 
     30 #define MF_IMPURE       00200
     31 #define MF_SQUEEZED     01000
     32 #define MF_USES_SL      02000
     33 #define MF_IS_SL        04000
     34 
     35 /* Common combinations.  */
     36 
     37 /* Demand load (impure text).  */
     38 #define IMAGIC          (MF_IMPURE | ZMAGIC)
     39 
     40 /* OMAGIC with large header.
     41    May contain a ref to a shared lib required by the object.  */
     42 #define SPOMAGIC        (MF_USES_SL | OMAGIC)
     43 
     44 /* A reference to a shared library.
     45    The text portion of the object contains "overflow text" from
     46    the shared library to be linked in with an object.  */
     47 #define SLOMAGIC        (MF_IS_SL | OMAGIC)
     48 
     49 /* Sqeezed demand paged.
     50    NOTE: This interpretation of QMAGIC seems to be at variance
     51    with that used on other architectures.  */
     52 #define QMAGIC          (MF_SQUEEZED | ZMAGIC)
     53 
     54 /* Program which uses sl.  */
     55 #define SPZMAGIC        (MF_USES_SL | ZMAGIC)
     56 
     57 /* Sqeezed ditto.  */
     58 #define SPQMAGIC        (MF_USES_SL | QMAGIC)
     59 
     60 /* Shared lib part of prog.  */
     61 #define SLZMAGIC        (MF_IS_SL | ZMAGIC)
     62 
     63 /* Sl which uses another.  */
     64 #define SLPZMAGIC       (MF_USES_SL | SLZMAGIC)
     65 
     66 #define N_SHARED_LIB(x) ((x).a_info & MF_USES_SL)
     67 
     68 /* Only a pure OMAGIC file has the minimal header.  */
     69 #define N_TXTOFF(x)		\
     70  ((x).a_info == OMAGIC		\
     71   ? 32				\
     72   : (N_MAGIC(x) == ZMAGIC	\
     73      ? TARGET_PAGE_SIZE		\
     74      : 999))
     75 
     76 #define N_TXTADDR(x)							     \
     77   (N_MAGIC(x) != ZMAGIC							     \
     78    ? (bfd_vma) 0 /* object file or NMAGIC */				     \
     79    /* Programs with shared libs are loaded at the first page after all the   \
     80       text segments of the shared library programs.  Without looking this    \
     81       up we can't know exactly what the address will be.  A reasonable guess \
     82       is that a_entry will be in the first page of the executable.  */	     \
     83    : (N_SHARED_LIB(x)							     \
     84       ? ((x).a_entry & ~(bfd_vma) (TARGET_PAGE_SIZE - 1))		     \
     85       : (bfd_vma) TEXT_START_ADDR))
     86 
     87 #define N_SYMOFF(x) \
     88   (N_TXTOFF (x) + (x).a_text + (x).a_data + (x).a_trsize + (x).a_drsize)
     89 
     90 #define N_STROFF(x) (N_SYMOFF (x) + (x).a_syms)
     91 
     92 #define TEXT_START_ADDR   32768
     93 #define TARGET_PAGE_SIZE  32768
     94 #define SEGMENT_SIZE      TARGET_PAGE_SIZE
     95 #define DEFAULT_ARCH      bfd_arch_arm
     96 
     97 /* Do not "beautify" the CONCAT* macro args.  Traditional C will not
     98    remove whitespace added here, and thus will fail to concatenate
     99    the tokens.  */
    100 #define MY(OP) CONCAT2 (arm_aout_riscix_,OP)
    101 #define TARGETNAME "a.out-riscix"
    102 #define N_BADMAG(x) ((((x).a_info & ~007200) != ZMAGIC) \
    103                   && (((x).a_info & ~006000) != OMAGIC) \
    104                   && ((x).a_info != NMAGIC))
    105 #define N_MAGIC(x) ((x).a_info & ~07200)
    106 
    107 #include "sysdep.h"
    108 #include "bfd.h"
    109 #include "libbfd.h"
    110 
    111 #define WRITE_HEADERS(abfd, execp)					    \
    112   {									    \
    113     bfd_size_type text_size; /* Dummy vars.  */				    \
    114     file_ptr text_end;							    \
    115     									    \
    116     if (adata (abfd).magic == undecided_magic)				    \
    117       NAME (aout, adjust_sizes_and_vmas) (abfd, & text_size, & text_end);   \
    118     									    \
    119     execp->a_syms = bfd_get_symcount (abfd) * EXTERNAL_NLIST_SIZE;	    \
    120     execp->a_entry = bfd_get_start_address (abfd);			    \
    121     									    \
    122     execp->a_trsize = ((obj_textsec (abfd)->reloc_count) *		    \
    123 		       obj_reloc_entry_size (abfd));			    \
    124     execp->a_drsize = ((obj_datasec (abfd)->reloc_count) *		    \
    125 		       obj_reloc_entry_size (abfd));			    \
    126     NAME (aout, swap_exec_header_out) (abfd, execp, & exec_bytes);	    \
    127     									    \
    128     if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0			    \
    129 	|| bfd_bwrite ((void *) & exec_bytes, (bfd_size_type) EXEC_BYTES_SIZE,  \
    130 		      abfd) != EXEC_BYTES_SIZE)				    \
    131       return FALSE;							    \
    132     /* Now write out reloc info, followed by syms and strings.  */	    \
    133 									    \
    134     if (bfd_get_outsymbols (abfd) != NULL			    	    \
    135 	&& bfd_get_symcount (abfd) != 0)				    \
    136       {									    \
    137 	if (bfd_seek (abfd, (file_ptr) (N_SYMOFF (* execp)), SEEK_SET) != 0)\
    138 	  return FALSE;							    \
    139 									    \
    140 	if (! NAME (aout, write_syms) (abfd))				    \
    141           return FALSE;							    \
    142 									    \
    143 	if (bfd_seek (abfd, (file_ptr) (N_TRELOFF (* execp)), SEEK_SET) != 0)\
    144 	  return FALSE;							    \
    145 									    \
    146 	if (! riscix_squirt_out_relocs (abfd, obj_textsec (abfd)))	    \
    147 	  return FALSE;							    \
    148 	if (bfd_seek (abfd, (file_ptr) (N_DRELOFF (* execp)), SEEK_SET) != 0)\
    149 	  return FALSE;							    \
    150 									    \
    151 	if (!NAME (aout, squirt_out_relocs) (abfd, obj_datasec (abfd)))	    \
    152 	  return FALSE;							    \
    153       }									    \
    154   }
    155 
    156 #include "libaout.h"
    157 #include "aout/aout64.h"
    158 
    159 static bfd_reloc_status_type
    160 riscix_fix_pcrel_26_done (bfd *abfd ATTRIBUTE_UNUSED,
    161 			  arelent *reloc_entry ATTRIBUTE_UNUSED,
    162 			  asymbol *symbol ATTRIBUTE_UNUSED,
    163 			  void * data ATTRIBUTE_UNUSED,
    164 			  asection *input_section ATTRIBUTE_UNUSED,
    165 			  bfd *output_bfd ATTRIBUTE_UNUSED,
    166 			  char **error_message ATTRIBUTE_UNUSED)
    167 {
    168   /* This is dead simple at present.  */
    169   return bfd_reloc_ok;
    170 }
    171 
    172 static bfd_reloc_status_type riscix_fix_pcrel_26 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
    173 static const bfd_target *arm_aout_riscix_callback (bfd *);
    174 
    175 static reloc_howto_type riscix_std_reloc_howto[] =
    176 {
    177   /* Type              rs size bsz  pcrel bitpos ovrf                     sf name     part_inpl readmask  setmask    pcdone */
    178   HOWTO( 0,              0,  0,   8,  FALSE, 0, complain_overflow_bitfield,0,"8",         TRUE, 0x000000ff,0x000000ff, FALSE),
    179   HOWTO( 1,              0,  1,   16, FALSE, 0, complain_overflow_bitfield,0,"16",        TRUE, 0x0000ffff,0x0000ffff, FALSE),
    180   HOWTO( 2,              0,  2,   32, FALSE, 0, complain_overflow_bitfield,0,"32",        TRUE, 0xffffffff,0xffffffff, FALSE),
    181   HOWTO( 3,              2,  3,   26, TRUE,  0, complain_overflow_signed,  riscix_fix_pcrel_26 , "ARM26",      TRUE, 0x00ffffff,0x00ffffff, FALSE),
    182   HOWTO( 4,              0,  0,   8,  TRUE,  0, complain_overflow_signed,  0,"DISP8",     TRUE, 0x000000ff,0x000000ff, TRUE),
    183   HOWTO( 5,              0,  1,   16, TRUE,  0, complain_overflow_signed,  0,"DISP16",    TRUE, 0x0000ffff,0x0000ffff, TRUE),
    184   HOWTO( 6,              0,  2,   32, TRUE,  0, complain_overflow_signed,  0,"DISP32",    TRUE, 0xffffffff,0xffffffff, TRUE),
    185   HOWTO( 7,              2,  3,   26, FALSE, 0, complain_overflow_signed,  riscix_fix_pcrel_26_done, "ARM26D",TRUE,0x00ffffff,0x00ffffff, FALSE),
    186   EMPTY_HOWTO (-1),
    187   HOWTO( 9,              0, -1,   16, FALSE, 0, complain_overflow_bitfield,0,"NEG16",     TRUE, 0x0000ffff,0x0000ffff, FALSE),
    188   HOWTO( 10,              0, -2,  32, FALSE, 0, complain_overflow_bitfield,0,"NEG32",     TRUE, 0xffffffff,0xffffffff, FALSE)
    189 };
    190 
    191 #define RISCIX_TABLE_SIZE \
    192   (sizeof (riscix_std_reloc_howto) / sizeof (reloc_howto_type))
    193 
    194 static bfd_reloc_status_type
    195 riscix_fix_pcrel_26 (bfd *abfd,
    196 		     arelent *reloc_entry,
    197 		     asymbol *symbol,
    198 		     void * data,
    199 		     asection *input_section,
    200 		     bfd *output_bfd,
    201 		     char **error_message ATTRIBUTE_UNUSED)
    202 {
    203   bfd_vma relocation;
    204   bfd_size_type addr = reloc_entry->address;
    205   long target = bfd_get_32 (abfd, (bfd_byte *) data + addr);
    206   bfd_reloc_status_type flag = bfd_reloc_ok;
    207 
    208   /* If this is an undefined symbol, return error.  */
    209   if (bfd_is_und_section (symbol->section)
    210       && (symbol->flags & BSF_WEAK) == 0)
    211     return output_bfd ? bfd_reloc_continue : bfd_reloc_undefined;
    212 
    213   /* If the sections are different, and we are doing a partial relocation,
    214      just ignore it for now.  */
    215   if (symbol->section->name != input_section->name
    216       && output_bfd != NULL)
    217     return bfd_reloc_continue;
    218 
    219   relocation = (target & 0x00ffffff) << 2;
    220   relocation = (relocation ^ 0x02000000) - 0x02000000; /* Sign extend.  */
    221   relocation += symbol->value;
    222   relocation += symbol->section->output_section->vma;
    223   relocation += symbol->section->output_offset;
    224   relocation += reloc_entry->addend;
    225   relocation -= input_section->output_section->vma;
    226   relocation -= input_section->output_offset;
    227   relocation -= addr;
    228   if (relocation & 3)
    229     return bfd_reloc_overflow;
    230 
    231   /* Check for overflow.  */
    232   if (relocation & 0x02000000)
    233     {
    234       if ((relocation & ~ (bfd_vma) 0x03ffffff) != ~ (bfd_vma) 0x03ffffff)
    235 	flag = bfd_reloc_overflow;
    236     }
    237   else if (relocation & ~ (bfd_vma) 0x03ffffff)
    238     flag = bfd_reloc_overflow;
    239 
    240   target &= ~0x00ffffff;
    241   target |= (relocation >> 2) & 0x00ffffff;
    242   bfd_put_32 (abfd, (bfd_vma) target, (bfd_byte *) data + addr);
    243 
    244   /* Now the ARM magic... Change the reloc type so that it is marked as done.
    245      Strictly this is only necessary if we are doing a partial relocation.  */
    246   reloc_entry->howto = &riscix_std_reloc_howto[7];
    247 
    248   return flag;
    249 }
    250 
    251 static reloc_howto_type *
    252 riscix_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code)
    253 {
    254 #define ASTD(i,j)       case i: return &riscix_std_reloc_howto[j]
    255   if (code == BFD_RELOC_CTOR)
    256     switch (bfd_arch_bits_per_address (abfd))
    257       {
    258       case 32:
    259         code = BFD_RELOC_32;
    260         break;
    261       default:
    262 	return NULL;
    263       }
    264 
    265   switch (code)
    266     {
    267       ASTD (BFD_RELOC_16, 1);
    268       ASTD (BFD_RELOC_32, 2);
    269       ASTD (BFD_RELOC_ARM_PCREL_BRANCH, 3);
    270       ASTD (BFD_RELOC_8_PCREL, 4);
    271       ASTD (BFD_RELOC_16_PCREL, 5);
    272       ASTD (BFD_RELOC_32_PCREL, 6);
    273     default:
    274       return NULL;
    275     }
    276 }
    277 
    278 static reloc_howto_type *
    279 riscix_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
    280 			  const char *r_name)
    281 {
    282   unsigned int i;
    283 
    284   for (i = 0;
    285        i < sizeof (riscix_std_reloc_howto) / sizeof (riscix_std_reloc_howto[0]);
    286        i++)
    287     if (riscix_std_reloc_howto[i].name != NULL
    288 	&& strcasecmp (riscix_std_reloc_howto[i].name, r_name) == 0)
    289       return &riscix_std_reloc_howto[i];
    290 
    291   return NULL;
    292 }
    293 
    294 #define MY_bfd_link_hash_table_create  _bfd_generic_link_hash_table_create
    295 #define MY_bfd_link_add_symbols        _bfd_generic_link_add_symbols
    296 #define MY_final_link_callback         should_not_be_used
    297 #define MY_bfd_final_link              _bfd_generic_final_link
    298 
    299 #define MY_bfd_reloc_type_lookup       riscix_reloc_type_lookup
    300 #define MY_bfd_reloc_name_lookup       riscix_reloc_name_lookup
    301 #define MY_canonicalize_reloc          arm_aout_riscix_canonicalize_reloc
    302 #define MY_object_p                    arm_aout_riscix_object_p
    303 
    304 static void
    305 riscix_swap_std_reloc_out (bfd *abfd,
    306 			   arelent *g,
    307 			   struct reloc_std_external *natptr)
    308 {
    309   int r_index;
    310   asymbol *sym = *(g->sym_ptr_ptr);
    311   int r_extern;
    312   int r_length;
    313   int r_pcrel;
    314   int r_neg = 0;	/* Negative relocs use the BASEREL bit.  */
    315   asection *output_section = sym->section->output_section;
    316 
    317   PUT_WORD(abfd, g->address, natptr->r_address);
    318 
    319   r_length = g->howto->size ;   /* Size as a power of two.  */
    320   if (r_length < 0)
    321     {
    322       r_length = -r_length;
    323       r_neg = 1;
    324     }
    325 
    326   r_pcrel  = (int) g->howto->pc_relative; /* Relative to PC?  */
    327 
    328   /* For RISC iX, in pc-relative relocs the r_pcrel bit means that the
    329      relocation has been done already (Only for the 26-bit one I think)?  */
    330   if (r_length == 3)
    331     r_pcrel = r_pcrel ? 0 : 1;
    332 
    333   /* Name was clobbered by aout_write_syms to be symbol index.  */
    334 
    335   /* If this relocation is relative to a symbol then set the
    336      r_index to the symbols index, and the r_extern bit.
    337 
    338      Absolute symbols can come in in two ways, either as an offset
    339      from the abs section, or as a symbol which has an abs value.
    340      check for that here.  */
    341 
    342   if (bfd_is_com_section (output_section)
    343       || bfd_is_abs_section (output_section)
    344       || bfd_is_und_section (output_section))
    345     {
    346       if (bfd_abs_section_ptr->symbol == sym)
    347 	{
    348 	  /* Whoops, looked like an abs symbol, but is really an offset
    349 	     from the abs section.  */
    350 	  r_index = 0;
    351 	  r_extern = 0;
    352 	}
    353       else
    354 	{
    355 	  /* Fill in symbol.  */
    356 	  r_extern = 1;
    357 	  r_index = (*g->sym_ptr_ptr)->udata.i;
    358 	}
    359     }
    360   else
    361     {
    362       /* Just an ordinary section.  */
    363       r_extern = 0;
    364       r_index  = output_section->target_index;
    365     }
    366 
    367   /* Now the fun stuff.  */
    368   if (bfd_header_big_endian (abfd))
    369     {
    370       natptr->r_index[0] = r_index >> 16;
    371       natptr->r_index[1] = r_index >> 8;
    372       natptr->r_index[2] = r_index;
    373       natptr->r_type[0] =
    374 	(  (r_extern ?   RELOC_STD_BITS_EXTERN_BIG: 0)
    375 	 | (r_pcrel  ?   RELOC_STD_BITS_PCREL_BIG: 0)
    376 	 | (r_neg    ?   RELOC_STD_BITS_BASEREL_BIG: 0)
    377 	 | (r_length <<  RELOC_STD_BITS_LENGTH_SH_BIG));
    378     }
    379   else
    380     {
    381       natptr->r_index[2] = r_index >> 16;
    382       natptr->r_index[1] = r_index >> 8;
    383       natptr->r_index[0] = r_index;
    384       natptr->r_type[0] =
    385 	(  (r_extern ?   RELOC_STD_BITS_EXTERN_LITTLE: 0)
    386 	 | (r_pcrel  ?   RELOC_STD_BITS_PCREL_LITTLE: 0)
    387 	 | (r_neg    ?   RELOC_STD_BITS_BASEREL_LITTLE: 0)
    388 	 | (r_length <<  RELOC_STD_BITS_LENGTH_SH_LITTLE));
    389     }
    390 }
    391 
    392 static bfd_boolean
    393 riscix_squirt_out_relocs (bfd *abfd, asection *section)
    394 {
    395   arelent **generic;
    396   unsigned char *native, *natptr;
    397   size_t each_size;
    398   unsigned int count = section->reloc_count;
    399   bfd_size_type natsize;
    400 
    401   if (count == 0)
    402     return TRUE;
    403 
    404   each_size = obj_reloc_entry_size (abfd);
    405   natsize = each_size;
    406   natsize *= count;
    407   native = bfd_zalloc (abfd, natsize);
    408   if (!native)
    409     return FALSE;
    410 
    411   generic = section->orelocation;
    412 
    413   for (natptr = native;
    414        count != 0;
    415        --count, natptr += each_size, ++generic)
    416     riscix_swap_std_reloc_out (abfd, *generic,
    417 			       (struct reloc_std_external *) natptr);
    418 
    419   if (bfd_bwrite ((void *) native, natsize, abfd) != natsize)
    420     {
    421       bfd_release (abfd, native);
    422       return FALSE;
    423     }
    424 
    425   bfd_release (abfd, native);
    426   return TRUE;
    427 }
    428 
    429 /* This is just like the standard aoutx.h version but we need to do our
    430    own mapping of external reloc type values to howto entries.  */
    431 
    432 static long
    433 MY (canonicalize_reloc) (bfd *abfd,
    434 			 sec_ptr section,
    435 			 arelent **relptr,
    436 			 asymbol **symbols)
    437 {
    438   arelent *tblptr = section->relocation;
    439   unsigned int count, c;
    440   extern reloc_howto_type NAME (aout, std_howto_table)[];
    441 
    442   /* If we have already read in the relocation table, return the values.  */
    443   if (section->flags & SEC_CONSTRUCTOR)
    444     {
    445       arelent_chain *chain = section->constructor_chain;
    446 
    447       for (count = 0; count < section->reloc_count; count++)
    448 	{
    449 	  *relptr++ = &chain->relent;
    450 	  chain = chain->next;
    451 	}
    452       *relptr = 0;
    453       return section->reloc_count;
    454     }
    455 
    456   if (tblptr && section->reloc_count)
    457     {
    458       for (count = 0; count++ < section->reloc_count;)
    459 	*relptr++ = tblptr++;
    460       *relptr = 0;
    461       return section->reloc_count;
    462     }
    463 
    464   if (!NAME (aout, slurp_reloc_table) (abfd, section, symbols))
    465     return -1;
    466   tblptr = section->relocation;
    467 
    468   /* Fix up howto entries.  */
    469   for (count = 0; count++ < section->reloc_count;)
    470     {
    471       c = tblptr->howto - NAME(aout,std_howto_table);
    472       BFD_ASSERT (c < RISCIX_TABLE_SIZE);
    473       tblptr->howto = &riscix_std_reloc_howto[c];
    474 
    475       *relptr++ = tblptr++;
    476     }
    477   *relptr = 0;
    478   return section->reloc_count;
    479 }
    480 
    481 /* This is the same as NAME(aout,some_aout_object_p), but has different
    482    expansions of the macro definitions.  */
    483 
    484 static const bfd_target *
    485 riscix_some_aout_object_p (bfd *abfd,
    486 			   struct internal_exec *execp,
    487 			   const bfd_target *(*callback_to_real_object_p) (bfd *))
    488 {
    489   struct aout_data_struct *rawptr, *oldrawptr;
    490   const bfd_target *result;
    491   bfd_size_type amt = sizeof (struct aout_data_struct);
    492 
    493   rawptr = bfd_zalloc (abfd, amt);
    494 
    495   if (rawptr == NULL)
    496     return NULL;
    497 
    498   oldrawptr = abfd->tdata.aout_data;
    499   abfd->tdata.aout_data = rawptr;
    500 
    501   /* Copy the contents of the old tdata struct.
    502      In particular, we want the subformat, since for hpux it was set in
    503      hp300hpux.c:swap_exec_header_in and will be used in
    504      hp300hpux.c:callback.  */
    505   if (oldrawptr != NULL)
    506     *abfd->tdata.aout_data = *oldrawptr;
    507 
    508   abfd->tdata.aout_data->a.hdr = &rawptr->e;
    509   /* Copy in the internal_exec struct.  */
    510   *(abfd->tdata.aout_data->a.hdr) = *execp;
    511   execp = abfd->tdata.aout_data->a.hdr;
    512 
    513   /* Set the file flags.  */
    514   abfd->flags = BFD_NO_FLAGS;
    515   if (execp->a_drsize || execp->a_trsize)
    516     abfd->flags |= HAS_RELOC;
    517   /* Setting of EXEC_P has been deferred to the bottom of this function.  */
    518   if (execp->a_syms)
    519     abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
    520   if (N_DYNAMIC(*execp))
    521     abfd->flags |= DYNAMIC;
    522 
    523  /* Squeezed files aren't supported (yet)!  */
    524   if ((execp->a_info & MF_SQUEEZED) != 0)
    525     {
    526       bfd_set_error (bfd_error_wrong_format);
    527       return NULL;
    528     }
    529   else if ((execp->a_info & MF_IS_SL) != 0)
    530     {
    531       /* Nor are shared libraries.  */
    532       bfd_set_error (bfd_error_wrong_format);
    533       return NULL;
    534     }
    535   else if (N_MAGIC (*execp) == ZMAGIC)
    536     {
    537       abfd->flags |= D_PAGED | WP_TEXT;
    538       adata (abfd).magic = z_magic;
    539     }
    540   else if (N_MAGIC (*execp) == NMAGIC)
    541     {
    542       abfd->flags |= WP_TEXT;
    543       adata (abfd).magic = n_magic;
    544     }
    545   else if (N_MAGIC (*execp) == OMAGIC)
    546     adata (abfd).magic = o_magic;
    547   else
    548     /* Should have been checked with N_BADMAG before this routine
    549        was called.  */
    550     abort ();
    551 
    552   bfd_get_start_address (abfd) = execp->a_entry;
    553 
    554   obj_aout_symbols (abfd) = NULL;
    555   bfd_get_symcount (abfd) = execp->a_syms / sizeof (struct external_nlist);
    556 
    557   /* The default relocation entry size is that of traditional V7 Unix.  */
    558   obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
    559 
    560   /* The default symbol entry size is that of traditional Unix.  */
    561   obj_symbol_entry_size (abfd) = EXTERNAL_NLIST_SIZE;
    562 
    563   obj_aout_external_syms (abfd) = NULL;
    564   obj_aout_external_strings (abfd) = NULL;
    565   obj_aout_sym_hashes (abfd) = NULL;
    566 
    567   if (! NAME (aout, make_sections) (abfd))
    568     return NULL;
    569 
    570   obj_datasec (abfd)->size = execp->a_data;
    571   obj_bsssec (abfd)->size = execp->a_bss;
    572 
    573   obj_textsec (abfd)->flags =
    574     (execp->a_trsize != 0
    575      ? (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS | SEC_RELOC)
    576      : (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS));
    577   obj_datasec (abfd)->flags =
    578     (execp->a_drsize != 0
    579      ? (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS | SEC_RELOC)
    580      : (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS));
    581   obj_bsssec (abfd)->flags = SEC_ALLOC;
    582 
    583   result = (*callback_to_real_object_p) (abfd);
    584 
    585 #if defined(MACH) || defined(STAT_FOR_EXEC)
    586   /* The original heuristic doesn't work in some important cases. The
    587      a.out file has no information about the text start address. For
    588      files (like kernels) linked to non-standard addresses (ld -Ttext
    589      nnn) the entry point may not be between the default text start
    590      (obj_textsec(abfd)->vma) and (obj_textsec(abfd)->vma) + text size
    591      This is not just a mach issue. Many kernels are loaded at non
    592      standard addresses.  */
    593   {
    594     struct stat stat_buf;
    595 
    596     if (abfd->iostream != NULL
    597 	&& (abfd->flags & BFD_IN_MEMORY) == 0
    598         && (fstat(fileno((FILE *) (abfd->iostream)), &stat_buf) == 0)
    599         && ((stat_buf.st_mode & 0111) != 0))
    600       abfd->flags |= EXEC_P;
    601   }
    602 #else /* ! MACH */
    603   /* Now that the segment addresses have been worked out, take a better
    604      guess at whether the file is executable.  If the entry point
    605      is within the text segment, assume it is.  (This makes files
    606      executable even if their entry point address is 0, as long as
    607      their text starts at zero.)
    608 
    609      At some point we should probably break down and stat the file and
    610      declare it executable if (one of) its 'x' bits are on...  */
    611   if ((execp->a_entry >= obj_textsec(abfd)->vma) &&
    612       (execp->a_entry < obj_textsec(abfd)->vma + obj_textsec(abfd)->size))
    613     abfd->flags |= EXEC_P;
    614 #endif /* MACH */
    615   if (result == NULL)
    616     {
    617       free (rawptr);
    618       abfd->tdata.aout_data = oldrawptr;
    619     }
    620   return result;
    621 }
    622 
    623 static const bfd_target *
    624 MY (object_p) (bfd *abfd)
    625 {
    626   struct external_exec exec_bytes;      /* Raw exec header from file.  */
    627   struct internal_exec exec;            /* Cleaned-up exec header.  */
    628   const bfd_target *target;
    629 
    630   if (bfd_bread ((void *) &exec_bytes, (bfd_size_type) EXEC_BYTES_SIZE, abfd)
    631       != EXEC_BYTES_SIZE)
    632     {
    633       if (bfd_get_error () != bfd_error_system_call)
    634 	bfd_set_error (bfd_error_wrong_format);
    635       return NULL;
    636     }
    637 
    638   exec.a_info = H_GET_32 (abfd, exec_bytes.e_info);
    639 
    640   if (N_BADMAG (exec))
    641     return NULL;
    642 
    643 #ifdef MACHTYPE_OK
    644   if (!(MACHTYPE_OK (N_MACHTYPE (exec))))
    645     return NULL;
    646 #endif
    647 
    648   NAME (aout, swap_exec_header_in) (abfd, & exec_bytes, & exec);
    649 
    650   target = riscix_some_aout_object_p (abfd, & exec, MY (callback));
    651 
    652   return target;
    653 }
    654 
    655 #include "aout-target.h"
    656