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