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