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