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