b294df2bbc96613a481aed4d02cc4fc7383df79a
[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      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
620 static const bfd_target *
621 MY (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"