1/* BFD back-end for RISC iX (Acorn, arm) binaries.
2   Copyright (C) 1994-2017 Free Software Foundation, Inc.
3   Contributed by Richard Earnshaw (rwe@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    if (adata (abfd).magic == undecided_magic)				    \
114      NAME (aout, adjust_sizes_and_vmas) (abfd);			    \
115    									    \
116    execp->a_syms = bfd_get_symcount (abfd) * EXTERNAL_NLIST_SIZE;	    \
117    execp->a_entry = bfd_get_start_address (abfd);			    \
118    									    \
119    execp->a_trsize = ((obj_textsec (abfd)->reloc_count) *		    \
120		       obj_reloc_entry_size (abfd));			    \
121    execp->a_drsize = ((obj_datasec (abfd)->reloc_count) *		    \
122		       obj_reloc_entry_size (abfd));			    \
123    NAME (aout, swap_exec_header_out) (abfd, execp, & exec_bytes);	    \
124    									    \
125    if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0			    \
126	|| bfd_bwrite ((void *) & exec_bytes, (bfd_size_type) EXEC_BYTES_SIZE,  \
127		      abfd) != EXEC_BYTES_SIZE)				    \
128      return FALSE;							    \
129    /* Now write out reloc info, followed by syms and strings.  */	    \
130									    \
131    if (bfd_get_outsymbols (abfd) != NULL			    	    \
132	&& bfd_get_symcount (abfd) != 0)				    \
133      {									    \
134	if (bfd_seek (abfd, (file_ptr) (N_SYMOFF (execp)), SEEK_SET) != 0)  \
135	  return FALSE;							    \
136									    \
137	if (! NAME (aout, write_syms) (abfd))				    \
138          return FALSE;							    \
139									    \
140	if (bfd_seek (abfd, (file_ptr) (N_TRELOFF (execp)), SEEK_SET) != 0) \
141	  return FALSE;							    \
142									    \
143	if (! riscix_squirt_out_relocs (abfd, obj_textsec (abfd)))	    \
144	  return FALSE;							    \
145	if (bfd_seek (abfd, (file_ptr) (N_DRELOFF (execp)), SEEK_SET) != 0) \
146	  return FALSE;							    \
147									    \
148	if (!NAME (aout, squirt_out_relocs) (abfd, obj_datasec (abfd)))	    \
149	  return FALSE;							    \
150      }									    \
151  }
152
153#include "libaout.h"
154#include "aout/aout64.h"
155
156static bfd_reloc_status_type
157riscix_fix_pcrel_26_done (bfd *abfd ATTRIBUTE_UNUSED,
158			  arelent *reloc_entry ATTRIBUTE_UNUSED,
159			  asymbol *symbol ATTRIBUTE_UNUSED,
160			  void * data ATTRIBUTE_UNUSED,
161			  asection *input_section ATTRIBUTE_UNUSED,
162			  bfd *output_bfd ATTRIBUTE_UNUSED,
163			  char **error_message ATTRIBUTE_UNUSED)
164{
165  /* This is dead simple at present.  */
166  return bfd_reloc_ok;
167}
168
169static bfd_reloc_status_type riscix_fix_pcrel_26 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
170static const bfd_target *arm_aout_riscix_callback (bfd *);
171
172static reloc_howto_type riscix_std_reloc_howto[] =
173{
174  /* Type              rs size bsz  pcrel bitpos ovrf                     sf name     part_inpl readmask  setmask    pcdone */
175  HOWTO( 0,              0,  0,   8,  FALSE, 0, complain_overflow_bitfield,0,"8",         TRUE, 0x000000ff,0x000000ff, FALSE),
176  HOWTO( 1,              0,  1,   16, FALSE, 0, complain_overflow_bitfield,0,"16",        TRUE, 0x0000ffff,0x0000ffff, FALSE),
177  HOWTO( 2,              0,  2,   32, FALSE, 0, complain_overflow_bitfield,0,"32",        TRUE, 0xffffffff,0xffffffff, FALSE),
178  HOWTO( 3,              2,  3,   26, TRUE,  0, complain_overflow_signed,  riscix_fix_pcrel_26 , "ARM26",      TRUE, 0x00ffffff,0x00ffffff, FALSE),
179  HOWTO( 4,              0,  0,   8,  TRUE,  0, complain_overflow_signed,  0,"DISP8",     TRUE, 0x000000ff,0x000000ff, TRUE),
180  HOWTO( 5,              0,  1,   16, TRUE,  0, complain_overflow_signed,  0,"DISP16",    TRUE, 0x0000ffff,0x0000ffff, TRUE),
181  HOWTO( 6,              0,  2,   32, TRUE,  0, complain_overflow_signed,  0,"DISP32",    TRUE, 0xffffffff,0xffffffff, TRUE),
182  HOWTO( 7,              2,  3,   26, FALSE, 0, complain_overflow_signed,  riscix_fix_pcrel_26_done, "ARM26D",TRUE,0x00ffffff,0x00ffffff, FALSE),
183  EMPTY_HOWTO (-1),
184  HOWTO( 9,              0, -1,   16, FALSE, 0, complain_overflow_bitfield,0,"NEG16",     TRUE, 0x0000ffff,0x0000ffff, FALSE),
185  HOWTO( 10,              0, -2,  32, FALSE, 0, complain_overflow_bitfield,0,"NEG32",     TRUE, 0xffffffff,0xffffffff, FALSE)
186};
187
188#define RISCIX_TABLE_SIZE \
189  (sizeof (riscix_std_reloc_howto) / sizeof (reloc_howto_type))
190
191static bfd_reloc_status_type
192riscix_fix_pcrel_26 (bfd *abfd,
193		     arelent *reloc_entry,
194		     asymbol *symbol,
195		     void * data,
196		     asection *input_section,
197		     bfd *output_bfd,
198		     char **error_message ATTRIBUTE_UNUSED)
199{
200  bfd_vma relocation;
201  bfd_size_type addr = reloc_entry->address;
202  long target = bfd_get_32 (abfd, (bfd_byte *) data + addr);
203  bfd_reloc_status_type flag = bfd_reloc_ok;
204
205  /* If this is an undefined symbol, return error.  */
206  if (bfd_is_und_section (symbol->section)
207      && (symbol->flags & BSF_WEAK) == 0)
208    return output_bfd ? bfd_reloc_continue : bfd_reloc_undefined;
209
210  /* If the sections are different, and we are doing a partial relocation,
211     just ignore it for now.  */
212  if (symbol->section->name != input_section->name
213      && output_bfd != NULL)
214    return bfd_reloc_continue;
215
216  relocation = (target & 0x00ffffff) << 2;
217  relocation = (relocation ^ 0x02000000) - 0x02000000; /* Sign extend.  */
218  relocation += symbol->value;
219  relocation += symbol->section->output_section->vma;
220  relocation += symbol->section->output_offset;
221  relocation += reloc_entry->addend;
222  relocation -= input_section->output_section->vma;
223  relocation -= input_section->output_offset;
224  relocation -= addr;
225  if (relocation & 3)
226    return bfd_reloc_overflow;
227
228  /* Check for overflow.  */
229  if (relocation & 0x02000000)
230    {
231      if ((relocation & ~ (bfd_vma) 0x03ffffff) != ~ (bfd_vma) 0x03ffffff)
232	flag = bfd_reloc_overflow;
233    }
234  else if (relocation & ~ (bfd_vma) 0x03ffffff)
235    flag = bfd_reloc_overflow;
236
237  target &= ~0x00ffffff;
238  target |= (relocation >> 2) & 0x00ffffff;
239  bfd_put_32 (abfd, (bfd_vma) target, (bfd_byte *) data + addr);
240
241  /* Now the ARM magic... Change the reloc type so that it is marked as done.
242     Strictly this is only necessary if we are doing a partial relocation.  */
243  reloc_entry->howto = &riscix_std_reloc_howto[7];
244
245  return flag;
246}
247
248static reloc_howto_type *
249riscix_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code)
250{
251#define ASTD(i,j)       case i: return &riscix_std_reloc_howto[j]
252  if (code == BFD_RELOC_CTOR)
253    switch (bfd_arch_bits_per_address (abfd))
254      {
255      case 32:
256        code = BFD_RELOC_32;
257        break;
258      default:
259	return NULL;
260      }
261
262  switch (code)
263    {
264      ASTD (BFD_RELOC_16, 1);
265      ASTD (BFD_RELOC_32, 2);
266      ASTD (BFD_RELOC_ARM_PCREL_BRANCH, 3);
267      ASTD (BFD_RELOC_8_PCREL, 4);
268      ASTD (BFD_RELOC_16_PCREL, 5);
269      ASTD (BFD_RELOC_32_PCREL, 6);
270    default:
271      return NULL;
272    }
273}
274
275static reloc_howto_type *
276riscix_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
277			  const char *r_name)
278{
279  unsigned int i;
280
281  for (i = 0;
282       i < sizeof (riscix_std_reloc_howto) / sizeof (riscix_std_reloc_howto[0]);
283       i++)
284    if (riscix_std_reloc_howto[i].name != NULL
285	&& strcasecmp (riscix_std_reloc_howto[i].name, r_name) == 0)
286      return &riscix_std_reloc_howto[i];
287
288  return NULL;
289}
290
291#define MY_bfd_link_hash_table_create  _bfd_generic_link_hash_table_create
292#define MY_bfd_link_add_symbols        _bfd_generic_link_add_symbols
293#define MY_final_link_callback         should_not_be_used
294#define MY_bfd_final_link              _bfd_generic_final_link
295
296#define MY_bfd_reloc_type_lookup       riscix_reloc_type_lookup
297#define MY_bfd_reloc_name_lookup       riscix_reloc_name_lookup
298#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