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