170856Sjhb/* BFD back-end for RISC iX (Acorn, arm) binaries.
270856Sjhb   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2004,
370856Sjhb   2005 Free Software Foundation, Inc.
470856Sjhb   Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
570856Sjhb
670856Sjhb   This file is part of BFD, the Binary File Descriptor library.
770856Sjhb
870856Sjhb   This program is free software; you can redistribute it and/or modify
970856Sjhb   it under the terms of the GNU General Public License as published by
1070856Sjhb   the Free Software Foundation; either version 2 of the License, or
1170856Sjhb   (at your option) any later version.
1270856Sjhb
1370856Sjhb   This program is distributed in the hope that it will be useful,
1470856Sjhb   but WITHOUT ANY WARRANTY; without even the implied warranty of
1570856Sjhb   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1670856Sjhb   GNU General Public License for more details.
1770856Sjhb
1870856Sjhb   You should have received a copy of the GNU General Public License
1970856Sjhb   along with this program; if not, write to the Free Software
2070856Sjhb   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
2170856Sjhb
2270856Sjhb/* RISC iX overloads the MAGIC field to indicate more than just the usual
2370856Sjhb   [ZNO]MAGIC values.  Also included are squeezing information and
2470856Sjhb   shared library usage.  */
2570856Sjhb
2670856Sjhb/* The following come from the man page.  */
2770856Sjhb#define SHLIBLEN 60
2870856Sjhb
2970856Sjhb#define MF_IMPURE       00200
30100280Sgordon#define MF_SQUEEZED     01000
31153430Siedowse#define MF_USES_SL      02000
32136224Smtm#define MF_IS_SL        04000
33100280Sgordon
34100280Sgordon/* Common combinations.  */
35100280Sgordon
36100280Sgordon/* Demand load (impure text).  */
37156331Semax#define IMAGIC          (MF_IMPURE | ZMAGIC)
38156331Semax
39102993Sfenner/* OMAGIC with large header.
40102993Sfenner   May contain a ref to a shared lib required by the object.  */
41165389Syar#define SPOMAGIC        (MF_USES_SL | OMAGIC)
42100280Sgordon
4370856Sjhb/* A reference to a shared library.
4470856Sjhb   The text portion of the object contains "overflow text" from
4570856Sjhb   the shared library to be linked in with an object.  */
4670856Sjhb#define SLOMAGIC        (MF_IS_SL | OMAGIC)
4770856Sjhb
48179981Smtm/* Sqeezed demand paged.
49179981Smtm   NOTE: This interpretation of QMAGIC seems to be at variance
50179981Smtm   with that used on other architectures.  */
51179981Smtm#define QMAGIC          (MF_SQUEEZED | ZMAGIC)
52179981Smtm
53179981Smtm/* Program which uses sl.  */
54179981Smtm#define SPZMAGIC        (MF_USES_SL | ZMAGIC)
55179981Smtm
56179981Smtm/* Sqeezed ditto.  */
57179981Smtm#define SPQMAGIC        (MF_USES_SL | QMAGIC)
58156782Semax
59156782Semax/* Shared lib part of prog.  */
60156331Semax#define SLZMAGIC        (MF_IS_SL | ZMAGIC)
61102993Sfenner
62102993Sfenner/* Sl which uses another.  */
63102993Sfenner#define SLPZMAGIC       (MF_USES_SL | SLZMAGIC)
64102993Sfenner
65102993Sfenner#define N_SHARED_LIB(x) ((x).a_info & MF_USES_SL)
66102993Sfenner
67179981Smtm/* Only a pure OMAGIC file has the minimal header.  */
68102993Sfenner#define N_TXTOFF(x)		\
69102993Sfenner ((x).a_info == OMAGIC		\
70102993Sfenner  ? 32				\
7170856Sjhb  : (N_MAGIC(x) == ZMAGIC	\
72102993Sfenner     ? TARGET_PAGE_SIZE		\
73102993Sfenner     : 999))
74102993Sfenner
75102993Sfenner#define N_TXTADDR(x)							     \
76102993Sfenner  (N_MAGIC(x) != ZMAGIC							     \
77102993Sfenner   ? (bfd_vma) 0 /* object file or NMAGIC */				     \
78179981Smtm   /* Programs with shared libs are loaded at the first page after all the   \
79102993Sfenner      text segments of the shared library programs.  Without looking this    \
80102993Sfenner      up we can't know exactly what the address will be.  A reasonable guess \
81102993Sfenner      is that a_entry will be in the first page of the executable.  */	     \
8270856Sjhb   : (N_SHARED_LIB(x)							     \
83102993Sfenner      ? ((x).a_entry & ~(bfd_vma) (TARGET_PAGE_SIZE - 1))		     \
84102993Sfenner      : (bfd_vma) TEXT_START_ADDR))
85102993Sfenner
86102993Sfenner#define N_SYMOFF(x) \
87102993Sfenner  (N_TXTOFF (x) + (x).a_text + (x).a_data + (x).a_trsize + (x).a_drsize)
88102993Sfenner
89179981Smtm#define N_STROFF(x) (N_SYMOFF (x) + (x).a_syms)
90102993Sfenner
91102993Sfenner#define TEXT_START_ADDR   32768
92102993Sfenner#define TARGET_PAGE_SIZE  32768
9370856Sjhb#define SEGMENT_SIZE      TARGET_PAGE_SIZE
94102993Sfenner#define DEFAULT_ARCH      bfd_arch_arm
95102993Sfenner
96102993Sfenner/* Do not "beautify" the CONCAT* macro args.  Traditional C will not
97102993Sfenner   remove whitespace added here, and thus will fail to concatenate
98102993Sfenner   the tokens.  */
99102993Sfenner#define MY(OP) CONCAT2 (riscix_,OP)
100179981Smtm#define TARGETNAME "a.out-riscix"
101102993Sfenner#define N_BADMAG(x) ((((x).a_info & ~007200) != ZMAGIC) \
102102993Sfenner                  && (((x).a_info & ~006000) != OMAGIC) \
103102993Sfenner                  && ((x).a_info != NMAGIC))
104102993Sfenner#define N_MAGIC(x) ((x).a_info & ~07200)
105102993Sfenner
106102993Sfenner#include "bfd.h"
107102993Sfenner#include "sysdep.h"
108102993Sfenner#include "libbfd.h"
10970856Sjhb
110156782Semax#define WRITE_HEADERS(abfd, execp)					    \
111156782Semax  {									    \
112156782Semax    bfd_size_type text_size; /* Dummy vars.  */				    \
113179981Smtm    file_ptr text_end;							    \
114156782Semax    									    \
115156782Semax    if (adata (abfd).magic == undecided_magic)				    \
116156782Semax      NAME (aout, adjust_sizes_and_vmas) (abfd, & text_size, & text_end);   \
117156782Semax    									    \
118156782Semax    execp->a_syms = bfd_get_symcount (abfd) * EXTERNAL_NLIST_SIZE;	    \
119156782Semax    execp->a_entry = bfd_get_start_address (abfd);			    \
120156782Semax    									    \
121156782Semax    execp->a_trsize = ((obj_textsec (abfd)->reloc_count) *		    \
122156782Semax		       obj_reloc_entry_size (abfd));			    \
123156782Semax    execp->a_drsize = ((obj_datasec (abfd)->reloc_count) *		    \
124156782Semax		       obj_reloc_entry_size (abfd));			    \
125156782Semax    NAME (aout, swap_exec_header_out) (abfd, execp, & exec_bytes);	    \
126156782Semax    									    \
127156782Semax    if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0			    \
128156782Semax	|| bfd_bwrite ((void *) & exec_bytes, (bfd_size_type) EXEC_BYTES_SIZE,  \
129156782Semax		      abfd) != EXEC_BYTES_SIZE)				    \
130156782Semax      return FALSE;							    \
131167889Sbrooks    /* Now write out reloc info, followed by syms and strings.  */	    \
132156782Semax									    \
133156782Semax    if (bfd_get_outsymbols (abfd) != NULL			    	    \
134156782Semax	&& bfd_get_symcount (abfd) != 0)				    \
135179981Smtm      {									    \
136156782Semax	if (bfd_seek (abfd, (file_ptr) (N_SYMOFF (* execp)), SEEK_SET) != 0)\
137179981Smtm	  return FALSE;							    \
138179981Smtm									    \
139179981Smtm	if (! NAME (aout, write_syms) (abfd))				    \
140179981Smtm          return FALSE;							    \
141179981Smtm									    \
142179981Smtm	if (bfd_seek (abfd, (file_ptr) (N_TRELOFF (* execp)), SEEK_SET) != 0)\
143179981Smtm	  return FALSE;							    \
144179981Smtm									    \
145179981Smtm	if (! riscix_squirt_out_relocs (abfd, obj_textsec (abfd)))	    \
146156782Semax	  return FALSE;							    \
147156782Semax	if (bfd_seek (abfd, (file_ptr) (N_DRELOFF (* execp)), SEEK_SET) != 0)\
148156782Semax	  return FALSE;							    \
149156782Semax									    \
150156782Semax	if (!NAME (aout, squirt_out_relocs) (abfd, obj_datasec (abfd)))	    \
151156782Semax	  return FALSE;							    \
152156782Semax      }									    \
153156782Semax  }
154156782Semax
155156782Semax#include "libaout.h"
156156782Semax#include "aout/aout64.h"
157156782Semax
158156782Semaxstatic bfd_reloc_status_type
159156782Semaxriscix_fix_pcrel_26_done (bfd *abfd ATTRIBUTE_UNUSED,
160156782Semax			  arelent *reloc_entry ATTRIBUTE_UNUSED,
161156782Semax			  asymbol *symbol ATTRIBUTE_UNUSED,
162179981Smtm			  void * data ATTRIBUTE_UNUSED,
163156782Semax			  asection *input_section ATTRIBUTE_UNUSED,
164156782Semax			  bfd *output_bfd ATTRIBUTE_UNUSED,
165156782Semax			  char **error_message ATTRIBUTE_UNUSED)
166156782Semax{
167102993Sfenner  /* This is dead simple at present.  */
168102993Sfenner  return bfd_reloc_ok;
169102993Sfenner}
170102993Sfenner
171102993Sfennerstatic bfd_reloc_status_type riscix_fix_pcrel_26 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
172102993Sfennerstatic const bfd_target *riscix_callback (bfd *);
173179981Smtm
174102993Sfennerstatic reloc_howto_type riscix_std_reloc_howto[] =
175102993Sfenner{
176102993Sfenner  /* Type              rs size bsz  pcrel bitpos ovrf                     sf name     part_inpl readmask  setmask    pcdone */
17770856Sjhb  HOWTO( 0,              0,  0,   8,  FALSE, 0, complain_overflow_bitfield,0,"8",         TRUE, 0x000000ff,0x000000ff, FALSE),
178102993Sfenner  HOWTO( 1,              0,  1,   16, FALSE, 0, complain_overflow_bitfield,0,"16",        TRUE, 0x0000ffff,0x0000ffff, FALSE),
179102993Sfenner  HOWTO( 2,              0,  2,   32, FALSE, 0, complain_overflow_bitfield,0,"32",        TRUE, 0xffffffff,0xffffffff, FALSE),
180102993Sfenner  HOWTO( 3,              2,  3,   26, TRUE,  0, complain_overflow_signed,  riscix_fix_pcrel_26 , "ARM26",      TRUE, 0x00ffffff,0x00ffffff, FALSE),
181102993Sfenner  HOWTO( 4,              0,  0,   8,  TRUE,  0, complain_overflow_signed,  0,"DISP8",     TRUE, 0x000000ff,0x000000ff, TRUE),
182102993Sfenner  HOWTO( 5,              0,  1,   16, TRUE,  0, complain_overflow_signed,  0,"DISP16",    TRUE, 0x0000ffff,0x0000ffff, TRUE),
183102993Sfenner  HOWTO( 6,              0,  2,   32, TRUE,  0, complain_overflow_signed,  0,"DISP32",    TRUE, 0xffffffff,0xffffffff, TRUE),
184179981Smtm  HOWTO( 7,              2,  3,   26, FALSE, 0, complain_overflow_signed,  riscix_fix_pcrel_26_done, "ARM26D",TRUE,0x00ffffff,0x00ffffff, FALSE),
185102993Sfenner  EMPTY_HOWTO (-1),
186102993Sfenner  HOWTO( 9,              0, -1,   16, FALSE, 0, complain_overflow_bitfield,0,"NEG16",     TRUE, 0x0000ffff,0x0000ffff, FALSE),
187102993Sfenner  HOWTO( 10,              0, -2,  32, FALSE, 0, complain_overflow_bitfield,0,"NEG32",     TRUE, 0xffffffff,0xffffffff, FALSE)
18870856Sjhb};
189102993Sfenner
190102993Sfenner#define RISCIX_TABLE_SIZE \
191102993Sfenner  (sizeof (riscix_std_reloc_howto) / sizeof (reloc_howto_type))
192102993Sfenner
193102993Sfennerstatic bfd_reloc_status_type
194102993Sfennerriscix_fix_pcrel_26 (bfd *abfd,
195179981Smtm		     arelent *reloc_entry,
196102993Sfenner		     asymbol *symbol,
197102993Sfenner		     void * data,
198102993Sfenner		     asection *input_section,
19970856Sjhb		     bfd *output_bfd,
200102993Sfenner		     char **error_message ATTRIBUTE_UNUSED)
201102993Sfenner{
202102993Sfenner  bfd_vma relocation;
203102993Sfenner  bfd_size_type addr = reloc_entry->address;
204102993Sfenner  long target = bfd_get_32 (abfd, (bfd_byte *) data + addr);
205102993Sfenner  bfd_reloc_status_type flag = bfd_reloc_ok;
206179981Smtm
207102993Sfenner  /* If this is an undefined symbol, return error.  */
208102993Sfenner  if (symbol->section == &bfd_und_section
209102993Sfenner      && (symbol->flags & BSF_WEAK) == 0)
21070856Sjhb    return output_bfd ? bfd_reloc_continue : bfd_reloc_undefined;
211102993Sfenner
212102993Sfenner  /* If the sections are different, and we are doing a partial relocation,
213102993Sfenner     just ignore it for now.  */
214102993Sfenner  if (symbol->section->name != input_section->name
215102993Sfenner      && output_bfd != NULL)
216102993Sfenner    return bfd_reloc_continue;
217179981Smtm
218102993Sfenner  relocation = (target & 0x00ffffff) << 2;
219102993Sfenner  relocation = (relocation ^ 0x02000000) - 0x02000000; /* Sign extend.  */
220102993Sfenner  relocation += symbol->value;
22170856Sjhb  relocation += symbol->section->output_section->vma;
222102993Sfenner  relocation += symbol->section->output_offset;
223102993Sfenner  relocation += reloc_entry->addend;
224102993Sfenner  relocation -= input_section->output_section->vma;
225102993Sfenner  relocation -= input_section->output_offset;
226102993Sfenner  relocation -= addr;
227102993Sfenner  if (relocation & 3)
228179981Smtm    return bfd_reloc_overflow;
229102993Sfenner
230102993Sfenner  /* Check for overflow.  */
231102993Sfenner  if (relocation & 0x02000000)
23270856Sjhb    {
233102993Sfenner      if ((relocation & ~ (bfd_vma) 0x03ffffff) != ~ (bfd_vma) 0x03ffffff)
234102993Sfenner	flag = bfd_reloc_overflow;
235102993Sfenner    }
236102993Sfenner  else if (relocation & ~ (bfd_vma) 0x03ffffff)
237102993Sfenner    flag = bfd_reloc_overflow;
238102993Sfenner
239179981Smtm  target &= ~0x00ffffff;
240102993Sfenner  target |= (relocation >> 2) & 0x00ffffff;
241167495Smux  bfd_put_32 (abfd, (bfd_vma) target, (bfd_byte *) data + addr);
242102993Sfenner
243102993Sfenner  /* Now the ARM magic... Change the reloc type so that it is marked as done.
244165683Syar     Strictly this is only necessary if we are doing a partial relocation.  */
245102993Sfenner  reloc_entry->howto = &riscix_std_reloc_howto[7];
246102993Sfenner
24770856Sjhb  return flag;
248102993Sfenner}
249102993Sfenner
250102993Sfennerstatic reloc_howto_type *
251179981Smtmriscix_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code)
252102993Sfenner{
253102993Sfenner#define ASTD(i,j)       case i: return &riscix_std_reloc_howto[j]
254102993Sfenner  if (code == BFD_RELOC_CTOR)
255102993Sfenner    switch (bfd_get_arch_info (abfd)->bits_per_address)
256102993Sfenner      {
257100284Sdougb      case 32:
258179981Smtm        code = BFD_RELOC_32;
259102993Sfenner        break;
260103161Sgordon      default:
261103161Sgordon	return NULL;
262156331Semax      }
263156331Semax
264  switch (code)
265    {
266      ASTD (BFD_RELOC_16, 1);
267      ASTD (BFD_RELOC_32, 2);
268      ASTD (BFD_RELOC_ARM_PCREL_BRANCH, 3);
269      ASTD (BFD_RELOC_8_PCREL, 4);
270      ASTD (BFD_RELOC_16_PCREL, 5);
271      ASTD (BFD_RELOC_32_PCREL, 6);
272    default:
273      return NULL;
274    }
275}
276
277#define MY_bfd_link_hash_table_create  _bfd_generic_link_hash_table_create
278#define MY_bfd_link_add_symbols        _bfd_generic_link_add_symbols
279#define MY_final_link_callback         should_not_be_used
280#define MY_bfd_final_link              _bfd_generic_final_link
281
282#define MY_bfd_reloc_type_lookup       riscix_reloc_type_lookup
283#define MY_canonicalize_reloc          riscix_canonicalize_reloc
284#define MY_object_p                    riscix_object_p
285
286static void
287riscix_swap_std_reloc_out (bfd *abfd,
288			   arelent *g,
289			   struct reloc_std_external *natptr)
290{
291  int r_index;
292  asymbol *sym = *(g->sym_ptr_ptr);
293  int r_extern;
294  int r_length;
295  int r_pcrel;
296  int r_neg = 0;	/* Negative relocs use the BASEREL bit.  */
297  asection *output_section = sym->section->output_section;
298
299  PUT_WORD(abfd, g->address, natptr->r_address);
300
301  r_length = g->howto->size ;   /* Size as a power of two.  */
302  if (r_length < 0)
303    {
304      r_length = -r_length;
305      r_neg = 1;
306    }
307
308  r_pcrel  = (int) g->howto->pc_relative; /* Relative to PC?  */
309
310  /* For RISC iX, in pc-relative relocs the r_pcrel bit means that the
311     relocation has been done already (Only for the 26-bit one I think)?  */
312  if (r_length == 3)
313    r_pcrel = r_pcrel ? 0 : 1;
314
315  /* Name was clobbered by aout_write_syms to be symbol index.  */
316
317  /* If this relocation is relative to a symbol then set the
318     r_index to the symbols index, and the r_extern bit.
319
320     Absolute symbols can come in in two ways, either as an offset
321     from the abs section, or as a symbol which has an abs value.
322     check for that here.  */
323
324  if (bfd_is_com_section (output_section)
325      || output_section == & bfd_abs_section
326      || output_section == & bfd_und_section)
327    {
328      if (bfd_abs_section.symbol == sym)
329	{
330	  /* Whoops, looked like an abs symbol, but is really an offset
331	     from the abs section.  */
332	  r_index = 0;
333	  r_extern = 0;
334	}
335      else
336	{
337	  /* Fill in symbol.  */
338	  r_extern = 1;
339	  r_index = (*g->sym_ptr_ptr)->udata.i;
340	}
341    }
342  else
343    {
344      /* Just an ordinary section.  */
345      r_extern = 0;
346      r_index  = output_section->target_index;
347    }
348
349  /* Now the fun stuff.  */
350  if (bfd_header_big_endian (abfd))
351    {
352      natptr->r_index[0] = r_index >> 16;
353      natptr->r_index[1] = r_index >> 8;
354      natptr->r_index[2] = r_index;
355      natptr->r_type[0] =
356	(  (r_extern ?   RELOC_STD_BITS_EXTERN_BIG: 0)
357	 | (r_pcrel  ?   RELOC_STD_BITS_PCREL_BIG: 0)
358	 | (r_neg    ?   RELOC_STD_BITS_BASEREL_BIG: 0)
359	 | (r_length <<  RELOC_STD_BITS_LENGTH_SH_BIG));
360    }
361  else
362    {
363      natptr->r_index[2] = r_index >> 16;
364      natptr->r_index[1] = r_index >> 8;
365      natptr->r_index[0] = r_index;
366      natptr->r_type[0] =
367	(  (r_extern ?   RELOC_STD_BITS_EXTERN_LITTLE: 0)
368	 | (r_pcrel  ?   RELOC_STD_BITS_PCREL_LITTLE: 0)
369	 | (r_neg    ?   RELOC_STD_BITS_BASEREL_LITTLE: 0)
370	 | (r_length <<  RELOC_STD_BITS_LENGTH_SH_LITTLE));
371    }
372}
373
374static bfd_boolean
375riscix_squirt_out_relocs (bfd *abfd, asection *section)
376{
377  arelent **generic;
378  unsigned char *native, *natptr;
379  size_t each_size;
380  unsigned int count = section->reloc_count;
381  bfd_size_type natsize;
382
383  if (count == 0)
384    return TRUE;
385
386  each_size = obj_reloc_entry_size (abfd);
387  natsize = each_size;
388  natsize *= count;
389  native = bfd_zalloc (abfd, natsize);
390  if (!native)
391    return FALSE;
392
393  generic = section->orelocation;
394
395  for (natptr = native;
396       count != 0;
397       --count, natptr += each_size, ++generic)
398    riscix_swap_std_reloc_out (abfd, *generic,
399			       (struct reloc_std_external *) natptr);
400
401  if (bfd_bwrite ((void *) native, natsize, abfd) != natsize)
402    {
403      bfd_release (abfd, native);
404      return FALSE;
405    }
406
407  bfd_release (abfd, native);
408  return TRUE;
409}
410
411/* This is just like the standard aoutx.h version but we need to do our
412   own mapping of external reloc type values to howto entries.  */
413
414static long
415MY (canonicalize_reloc) (bfd *abfd,
416			 sec_ptr section,
417			 arelent **relptr,
418			 asymbol **symbols)
419{
420  arelent *tblptr = section->relocation;
421  unsigned int count, c;
422  extern reloc_howto_type NAME (aout, std_howto_table)[];
423
424  /* If we have already read in the relocation table, return the values.  */
425  if (section->flags & SEC_CONSTRUCTOR)
426    {
427      arelent_chain *chain = section->constructor_chain;
428
429      for (count = 0; count < section->reloc_count; count++)
430	{
431	  *relptr++ = &chain->relent;
432	  chain = chain->next;
433	}
434      *relptr = 0;
435      return section->reloc_count;
436    }
437
438  if (tblptr && section->reloc_count)
439    {
440      for (count = 0; count++ < section->reloc_count;)
441	*relptr++ = tblptr++;
442      *relptr = 0;
443      return section->reloc_count;
444    }
445
446  if (!NAME (aout, slurp_reloc_table) (abfd, section, symbols))
447    return -1;
448  tblptr = section->relocation;
449
450  /* Fix up howto entries.  */
451  for (count = 0; count++ < section->reloc_count;)
452    {
453      c = tblptr->howto - NAME(aout,std_howto_table);
454      BFD_ASSERT (c < RISCIX_TABLE_SIZE);
455      tblptr->howto = &riscix_std_reloc_howto[c];
456
457      *relptr++ = tblptr++;
458    }
459  *relptr = 0;
460  return section->reloc_count;
461}
462
463/* This is the same as NAME(aout,some_aout_object_p), but has different
464   expansions of the macro definitions.  */
465
466static const bfd_target *
467riscix_some_aout_object_p (bfd *abfd,
468			   struct internal_exec *execp,
469			   const bfd_target *(*callback_to_real_object_p) (bfd *))
470{
471  struct aout_data_struct *rawptr, *oldrawptr;
472  const bfd_target *result;
473  bfd_size_type amt = sizeof (struct aout_data_struct);
474
475  rawptr = bfd_zalloc (abfd, amt);
476
477  if (rawptr == NULL)
478    return NULL;
479
480  oldrawptr = abfd->tdata.aout_data;
481  abfd->tdata.aout_data = rawptr;
482
483  /* Copy the contents of the old tdata struct.
484     In particular, we want the subformat, since for hpux it was set in
485     hp300hpux.c:swap_exec_header_in and will be used in
486     hp300hpux.c:callback.  */
487  if (oldrawptr != NULL)
488    *abfd->tdata.aout_data = *oldrawptr;
489
490  abfd->tdata.aout_data->a.hdr = &rawptr->e;
491  /* Copy in the internal_exec struct.  */
492  *(abfd->tdata.aout_data->a.hdr) = *execp;
493  execp = abfd->tdata.aout_data->a.hdr;
494
495  /* Set the file flags.  */
496  abfd->flags = BFD_NO_FLAGS;
497  if (execp->a_drsize || execp->a_trsize)
498    abfd->flags |= HAS_RELOC;
499  /* Setting of EXEC_P has been deferred to the bottom of this function.  */
500  if (execp->a_syms)
501    abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
502  if (N_DYNAMIC(*execp))
503    abfd->flags |= DYNAMIC;
504
505 /* Squeezed files aren't supported (yet)!  */
506  if ((execp->a_info & MF_SQUEEZED) != 0)
507    {
508      bfd_set_error (bfd_error_wrong_format);
509      return NULL;
510    }
511  else if ((execp->a_info & MF_IS_SL) != 0)
512    {
513      /* Nor are shared libraries.  */
514      bfd_set_error (bfd_error_wrong_format);
515      return NULL;
516    }
517  else if (N_MAGIC (*execp) == ZMAGIC)
518    {
519      abfd->flags |= D_PAGED | WP_TEXT;
520      adata (abfd).magic = z_magic;
521    }
522  else if (N_MAGIC (*execp) == NMAGIC)
523    {
524      abfd->flags |= WP_TEXT;
525      adata (abfd).magic = n_magic;
526    }
527  else if (N_MAGIC (*execp) == OMAGIC)
528    adata (abfd).magic = o_magic;
529  else
530    /* Should have been checked with N_BADMAG before this routine
531       was called.  */
532    abort ();
533
534  bfd_get_start_address (abfd) = execp->a_entry;
535
536  obj_aout_symbols (abfd) = NULL;
537  bfd_get_symcount (abfd) = execp->a_syms / sizeof (struct external_nlist);
538
539  /* The default relocation entry size is that of traditional V7 Unix.  */
540  obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
541
542  /* The default symbol entry size is that of traditional Unix.  */
543  obj_symbol_entry_size (abfd) = EXTERNAL_NLIST_SIZE;
544
545  obj_aout_external_syms (abfd) = NULL;
546  obj_aout_external_strings (abfd) = NULL;
547  obj_aout_sym_hashes (abfd) = NULL;
548
549  if (! NAME (aout, make_sections) (abfd))
550    return NULL;
551
552  obj_datasec (abfd)->size = execp->a_data;
553  obj_bsssec (abfd)->size = execp->a_bss;
554
555  obj_textsec (abfd)->flags =
556    (execp->a_trsize != 0
557     ? (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS | SEC_RELOC)
558     : (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS));
559  obj_datasec (abfd)->flags =
560    (execp->a_drsize != 0
561     ? (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS | SEC_RELOC)
562     : (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS));
563  obj_bsssec (abfd)->flags = SEC_ALLOC;
564
565  result = (*callback_to_real_object_p) (abfd);
566
567#if defined(MACH) || defined(STAT_FOR_EXEC)
568  /* The original heuristic doesn't work in some important cases. The
569     a.out file has no information about the text start address. For
570     files (like kernels) linked to non-standard addresses (ld -Ttext
571     nnn) the entry point may not be between the default text start
572     (obj_textsec(abfd)->vma) and (obj_textsec(abfd)->vma) + text size
573     This is not just a mach issue. Many kernels are loaded at non
574     standard addresses.  */
575  {
576    struct stat stat_buf;
577
578    if (abfd->iostream != NULL
579	&& (abfd->flags & BFD_IN_MEMORY) == 0
580        && (fstat(fileno((FILE *) (abfd->iostream)), &stat_buf) == 0)
581        && ((stat_buf.st_mode & 0111) != 0))
582      abfd->flags |= EXEC_P;
583  }
584#else /* ! MACH */
585  /* Now that the segment addresses have been worked out, take a better
586     guess at whether the file is executable.  If the entry point
587     is within the text segment, assume it is.  (This makes files
588     executable even if their entry point address is 0, as long as
589     their text starts at zero.)
590
591     At some point we should probably break down and stat the file and
592     declare it executable if (one of) its 'x' bits are on...  */
593  if ((execp->a_entry >= obj_textsec(abfd)->vma) &&
594      (execp->a_entry < obj_textsec(abfd)->vma + obj_textsec(abfd)->size))
595    abfd->flags |= EXEC_P;
596#endif /* MACH */
597  if (result == NULL)
598    {
599      free (rawptr);
600      abfd->tdata.aout_data = oldrawptr;
601    }
602  return result;
603}
604
605static const bfd_target *
606MY (object_p) (bfd *abfd)
607{
608  struct external_exec exec_bytes;      /* Raw exec header from file.  */
609  struct internal_exec exec;            /* Cleaned-up exec header.  */
610  const bfd_target *target;
611
612  if (bfd_bread ((void *) &exec_bytes, (bfd_size_type) EXEC_BYTES_SIZE, abfd)
613      != EXEC_BYTES_SIZE)
614    {
615      if (bfd_get_error () != bfd_error_system_call)
616	bfd_set_error (bfd_error_wrong_format);
617      return NULL;
618    }
619
620  exec.a_info = H_GET_32 (abfd, exec_bytes.e_info);
621
622  if (N_BADMAG (exec))
623    return NULL;
624
625#ifdef MACHTYPE_OK
626  if (!(MACHTYPE_OK (N_MACHTYPE (exec))))
627    return NULL;
628#endif
629
630  NAME (aout, swap_exec_header_in) (abfd, & exec_bytes, & exec);
631
632  target = riscix_some_aout_object_p (abfd, & exec, MY (callback));
633
634  return target;
635}
636
637#include "aout-target.h"
638