Automatic date update in version.in
[external/binutils.git] / bfd / riscix.c
1 /* BFD back-end for RISC iX (Acorn, arm) binaries.
2    Copyright (C) 1994-2018 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
156 static bfd_reloc_status_type
157 riscix_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
169 static bfd_reloc_status_type riscix_fix_pcrel_26 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
170 static const bfd_target *arm_aout_riscix_callback (bfd *);
171
172 static 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
191 static bfd_reloc_status_type
192 riscix_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
248 static reloc_howto_type *
249 riscix_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
275 static reloc_howto_type *
276 riscix_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
301 static void
302 riscix_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
389 static bfd_boolean
390 riscix_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
429 static long
430 MY (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
481 static const bfd_target *
482 riscix_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   if (oldrawptr != NULL)
500     *abfd->tdata.aout_data = *oldrawptr;
501
502   abfd->tdata.aout_data->a.hdr = &rawptr->e;
503   /* Copy in the internal_exec struct.  */
504   *(abfd->tdata.aout_data->a.hdr) = *execp;
505   execp = abfd->tdata.aout_data->a.hdr;
506
507   /* Set the file flags.  */
508   abfd->flags = BFD_NO_FLAGS;
509   if (execp->a_drsize || execp->a_trsize)
510     abfd->flags |= HAS_RELOC;
511   /* Setting of EXEC_P has been deferred to the bottom of this function.  */
512   if (execp->a_syms)
513     abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
514   if (N_DYNAMIC (execp))
515     abfd->flags |= DYNAMIC;
516
517  /* Squeezed files aren't supported (yet)!  */
518   if ((execp->a_info & MF_SQUEEZED) != 0)
519     {
520       bfd_set_error (bfd_error_wrong_format);
521       return NULL;
522     }
523   else if ((execp->a_info & MF_IS_SL) != 0)
524     {
525       /* Nor are shared libraries.  */
526       bfd_set_error (bfd_error_wrong_format);
527       return NULL;
528     }
529   else if (N_MAGIC (execp) == ZMAGIC)
530     {
531       abfd->flags |= D_PAGED | WP_TEXT;
532       adata (abfd).magic = z_magic;
533     }
534   else if (N_MAGIC (execp) == NMAGIC)
535     {
536       abfd->flags |= WP_TEXT;
537       adata (abfd).magic = n_magic;
538     }
539   else if (N_MAGIC (execp) == OMAGIC)
540     adata (abfd).magic = o_magic;
541   else
542     /* Should have been checked with N_BADMAG before this routine
543        was called.  */
544     abort ();
545
546   bfd_get_start_address (abfd) = execp->a_entry;
547
548   obj_aout_symbols (abfd) = NULL;
549   bfd_get_symcount (abfd) = execp->a_syms / sizeof (struct external_nlist);
550
551   /* The default relocation entry size is that of traditional V7 Unix.  */
552   obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
553
554   /* The default symbol entry size is that of traditional Unix.  */
555   obj_symbol_entry_size (abfd) = EXTERNAL_NLIST_SIZE;
556
557   obj_aout_external_syms (abfd) = NULL;
558   obj_aout_external_strings (abfd) = NULL;
559   obj_aout_sym_hashes (abfd) = NULL;
560
561   if (! NAME (aout, make_sections) (abfd))
562     return NULL;
563
564   obj_datasec (abfd)->size = execp->a_data;
565   obj_bsssec (abfd)->size = execp->a_bss;
566
567   obj_textsec (abfd)->flags =
568     (execp->a_trsize != 0
569      ? (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS | SEC_RELOC)
570      : (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS));
571   obj_datasec (abfd)->flags =
572     (execp->a_drsize != 0
573      ? (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS | SEC_RELOC)
574      : (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS));
575   obj_bsssec (abfd)->flags = SEC_ALLOC;
576
577   result = (*callback_to_real_object_p) (abfd);
578
579 #if defined(MACH) || defined(STAT_FOR_EXEC)
580   /* The original heuristic doesn't work in some important cases. The
581      a.out file has no information about the text start address. For
582      files (like kernels) linked to non-standard addresses (ld -Ttext
583      nnn) the entry point may not be between the default text start
584      (obj_textsec(abfd)->vma) and (obj_textsec(abfd)->vma) + text size
585      This is not just a mach issue. Many kernels are loaded at non
586      standard addresses.  */
587   {
588     struct stat stat_buf;
589
590     if (abfd->iostream != NULL
591         && (abfd->flags & BFD_IN_MEMORY) == 0
592         && (fstat(fileno((FILE *) (abfd->iostream)), &stat_buf) == 0)
593         && ((stat_buf.st_mode & 0111) != 0))
594       abfd->flags |= EXEC_P;
595   }
596 #else /* ! MACH */
597   /* Now that the segment addresses have been worked out, take a better
598      guess at whether the file is executable.  If the entry point
599      is within the text segment, assume it is.  (This makes files
600      executable even if their entry point address is 0, as long as
601      their text starts at zero.)
602
603      At some point we should probably break down and stat the file and
604      declare it executable if (one of) its 'x' bits are on...  */
605   if ((execp->a_entry >= obj_textsec(abfd)->vma) &&
606       (execp->a_entry < obj_textsec(abfd)->vma + obj_textsec(abfd)->size))
607     abfd->flags |= EXEC_P;
608 #endif /* MACH */
609   if (result == NULL)
610     {
611       free (rawptr);
612       abfd->tdata.aout_data = oldrawptr;
613     }
614   return result;
615 }
616
617 static const bfd_target *
618 MY (object_p) (bfd *abfd)
619 {
620   struct external_exec exec_bytes;      /* Raw exec header from file.  */
621   struct internal_exec exec;            /* Cleaned-up exec header.  */
622   const bfd_target *target;
623
624   if (bfd_bread ((void *) &exec_bytes, (bfd_size_type) EXEC_BYTES_SIZE, abfd)
625       != EXEC_BYTES_SIZE)
626     {
627       if (bfd_get_error () != bfd_error_system_call)
628         bfd_set_error (bfd_error_wrong_format);
629       return NULL;
630     }
631
632   exec.a_info = H_GET_32 (abfd, exec_bytes.e_info);
633
634   if (N_BADMAG (&exec))
635     return NULL;
636
637 #ifdef MACHTYPE_OK
638   if (!(MACHTYPE_OK (N_MACHTYPE (&exec))))
639     return NULL;
640 #endif
641
642   NAME (aout, swap_exec_header_in) (abfd, & exec_bytes, & exec);
643
644   target = riscix_some_aout_object_p (abfd, & exec, MY (callback));
645
646   return target;
647 }
648
649 #include "aout-target.h"