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