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