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