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