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