xref: /openbsd-src/gnu/usr.bin/binutils/bfd/riscix.c (revision c074d1c999f3e07019cd5e9a2f190b057ef3b935)
12159047fSniklas /* BFD back-end for RISC iX (Acorn, arm) binaries.
2*c074d1c9Sdrahn    Copyright 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002
3b55d4692Sfgsch    Free Software Foundation, Inc.
42159047fSniklas    Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
52159047fSniklas 
62159047fSniklas This file is part of BFD, the Binary File Descriptor library.
72159047fSniklas 
82159047fSniklas This program is free software; you can redistribute it and/or modify
92159047fSniklas it under the terms of the GNU General Public License as published by
102159047fSniklas the Free Software Foundation; either version 2 of the License, or
112159047fSniklas (at your option) any later version.
122159047fSniklas 
132159047fSniklas This program is distributed in the hope that it will be useful,
142159047fSniklas but WITHOUT ANY WARRANTY; without even the implied warranty of
152159047fSniklas MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
162159047fSniklas GNU General Public License for more details.
172159047fSniklas 
182159047fSniklas You should have received a copy of the GNU General Public License
192159047fSniklas along with this program; if not, write to the Free Software
202159047fSniklas Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
212159047fSniklas 
222159047fSniklas /* RISC iX overloads the MAGIC field to indicate more than just the usual
232159047fSniklas    [ZNO]MAGIC values.  Also included are squeezing information and
242159047fSniklas    shared library usage.  */
252159047fSniklas 
262159047fSniklas /* The following come from the man page.  */
272159047fSniklas #define SHLIBLEN 60
282159047fSniklas 
292159047fSniklas #define MF_IMPURE       00200
302159047fSniklas #define MF_SQUEEZED     01000
312159047fSniklas #define MF_USES_SL      02000
322159047fSniklas #define MF_IS_SL        04000
332159047fSniklas 
342159047fSniklas /* Common combinations.  */
352159047fSniklas #define IMAGIC          (MF_IMPURE|ZMAGIC)      /* Demand load (impure text) */
362159047fSniklas #define SPOMAGIC        (MF_USES_SL|OMAGIC)     /* OMAGIC with large header */
372159047fSniklas                                         /* -- may contain a ref to a */
382159047fSniklas                                         /* shared lib required by the */
392159047fSniklas                                         /* object.  */
402159047fSniklas #define SLOMAGIC        (MF_IS_SL|OMAGIC) /* A reference to a shared library */
412159047fSniklas                                           /* The text portion of the object */
422159047fSniklas                                           /* contains "overflow text" from */
432159047fSniklas                                           /* the shared library to be linked */
442159047fSniklas                                           /* in with an object */
452159047fSniklas #define QMAGIC          (MF_SQUEEZED|ZMAGIC)    /* Sqeezed demand paged.  */
462159047fSniklas                                           /* NOTE: This interpretation of */
472159047fSniklas                                           /* QMAGIC seems to be at variance */
482159047fSniklas                                           /* With that used on other */
492159047fSniklas                                           /* architectures.  */
502159047fSniklas #define SPZMAGIC        (MF_USES_SL|ZMAGIC)     /* program which uses sl */
512159047fSniklas #define SPQMAGIC        (MF_USES_SL|QMAGIC)     /* sqeezed ditto */
522159047fSniklas #define SLZMAGIC        (MF_IS_SL|ZMAGIC)       /* shared lib part of prog */
532159047fSniklas #define SLPZMAGIC       (MF_USES_SL|SLZMAGIC)   /* sl which uses another */
542159047fSniklas 
552159047fSniklas #define N_SHARED_LIB(x) ((x).a_info & MF_USES_SL)
562159047fSniklas 
572159047fSniklas /* Only a pure OMAGIC file has the minimal header */
582159047fSniklas #define N_TXTOFF(x)		\
59*c074d1c9Sdrahn  ((x).a_info == OMAGIC		\
60*c074d1c9Sdrahn   ? 32				\
61*c074d1c9Sdrahn   : (N_MAGIC(x) == ZMAGIC	\
62*c074d1c9Sdrahn      ? TARGET_PAGE_SIZE		\
63*c074d1c9Sdrahn      : 999))
642159047fSniklas 
652159047fSniklas #define N_TXTADDR(x)							     \
66*c074d1c9Sdrahn   (N_MAGIC(x) != ZMAGIC							     \
67*c074d1c9Sdrahn    ? (bfd_vma) 0 /* object file or NMAGIC */				     \
682159047fSniklas    /* Programs with shared libs are loaded at the first page after all the   \
692159047fSniklas       text segments of the shared library programs.  Without looking this    \
702159047fSniklas       up we can't know exactly what the address will be.  A reasonable guess \
712159047fSniklas       is that a_entry will be in the first page of the executable.  */	     \
72*c074d1c9Sdrahn    : (N_SHARED_LIB(x)							     \
73*c074d1c9Sdrahn       ? ((x).a_entry & ~(bfd_vma) (TARGET_PAGE_SIZE - 1))		     \
74*c074d1c9Sdrahn       : (bfd_vma) TEXT_START_ADDR))
752159047fSniklas 
762159047fSniklas #define N_SYMOFF(x) \
772159047fSniklas   (N_TXTOFF (x) + (x).a_text + (x).a_data + (x).a_trsize + (x).a_drsize)
782159047fSniklas 
792159047fSniklas #define N_STROFF(x) (N_SYMOFF (x) + (x).a_syms)
802159047fSniklas 
812159047fSniklas #define TEXT_START_ADDR 32768
822159047fSniklas #define TARGET_PAGE_SIZE 32768
832159047fSniklas #define SEGMENT_SIZE TARGET_PAGE_SIZE
842159047fSniklas #define DEFAULT_ARCH bfd_arch_arm
852159047fSniklas 
86*c074d1c9Sdrahn /* Do not "beautify" the CONCAT* macro args.  Traditional C will not
87*c074d1c9Sdrahn    remove whitespace added here, and thus will fail to concatenate
88*c074d1c9Sdrahn    the tokens.  */
89*c074d1c9Sdrahn #define MY(OP) CONCAT2 (riscix_,OP)
902159047fSniklas #define TARGETNAME "a.out-riscix"
912159047fSniklas #define N_BADMAG(x) ((((x).a_info & ~007200) != ZMAGIC) && \
922159047fSniklas                      (((x).a_info & ~006000) != OMAGIC) && \
932159047fSniklas                      ((x).a_info != NMAGIC))
942159047fSniklas #define N_MAGIC(x) ((x).a_info & ~07200)
952159047fSniklas 
962159047fSniklas #include "bfd.h"
972159047fSniklas #include "sysdep.h"
982159047fSniklas #include "libbfd.h"
992159047fSniklas 
1002159047fSniklas #define WRITE_HEADERS(abfd, execp)					    \
1012159047fSniklas   {									    \
1022159047fSniklas     bfd_size_type text_size; /* dummy vars */				    \
1032159047fSniklas     file_ptr text_end;							    \
1042159047fSniklas     if (adata(abfd).magic == undecided_magic)				    \
1052159047fSniklas       NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end);	    \
1062159047fSniklas     									    \
1072159047fSniklas     execp->a_syms = bfd_get_symcount (abfd) * EXTERNAL_NLIST_SIZE;	    \
1082159047fSniklas     execp->a_entry = bfd_get_start_address (abfd);			    \
1092159047fSniklas     									    \
1102159047fSniklas     execp->a_trsize = ((obj_textsec (abfd)->reloc_count) *		    \
1112159047fSniklas 		       obj_reloc_entry_size (abfd));			    \
1122159047fSniklas     execp->a_drsize = ((obj_datasec (abfd)->reloc_count) *		    \
1132159047fSniklas 		       obj_reloc_entry_size (abfd));			    \
1142159047fSniklas     NAME(aout,swap_exec_header_out) (abfd, execp, &exec_bytes);		    \
1152159047fSniklas     									    \
116*c074d1c9Sdrahn     if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0			    \
117*c074d1c9Sdrahn 	|| bfd_bwrite ((PTR) &exec_bytes, (bfd_size_type) EXEC_BYTES_SIZE,   \
118*c074d1c9Sdrahn 		      abfd) != EXEC_BYTES_SIZE)				    \
119*c074d1c9Sdrahn       return FALSE;							    \
1202159047fSniklas     /* Now write out reloc info, followed by syms and strings */	    \
1212159047fSniklas 									    \
1222159047fSniklas     if (bfd_get_outsymbols (abfd) != (asymbol **) NULL			    \
1232159047fSniklas 	&& bfd_get_symcount (abfd) != 0)				    \
1242159047fSniklas       {									    \
1252159047fSniklas 	if (bfd_seek (abfd, (file_ptr) (N_SYMOFF(*execp)), SEEK_SET) != 0)  \
126*c074d1c9Sdrahn 	  return FALSE;							    \
1272159047fSniklas 									    \
128*c074d1c9Sdrahn 	if (! NAME(aout,write_syms) (abfd)) return FALSE;		    \
1292159047fSniklas 									    \
1302159047fSniklas 	if (bfd_seek (abfd, (file_ptr) (N_TRELOFF(*execp)), SEEK_SET) != 0) \
131*c074d1c9Sdrahn 	  return FALSE;							    \
1322159047fSniklas 									    \
1332159047fSniklas 	if (! riscix_squirt_out_relocs (abfd, obj_textsec (abfd)))	    \
134*c074d1c9Sdrahn 	  return FALSE;							    \
1352159047fSniklas 	if (bfd_seek (abfd, (file_ptr) (N_DRELOFF(*execp)), SEEK_SET) != 0) \
136*c074d1c9Sdrahn 	  return FALSE;							    \
1372159047fSniklas 									    \
1382159047fSniklas 	if (!NAME(aout,squirt_out_relocs) (abfd, obj_datasec (abfd)))	    \
139*c074d1c9Sdrahn 	  return FALSE;							    \
1402159047fSniklas       }									    \
1412159047fSniklas   }
1422159047fSniklas 
1432159047fSniklas #include "libaout.h"
1442159047fSniklas #include "aout/aout64.h"
1452159047fSniklas 
1462159047fSniklas static bfd_reloc_status_type
1472159047fSniklas riscix_fix_pcrel_26_done PARAMS ((bfd *, arelent *, asymbol *, PTR,
1482159047fSniklas 				  asection *, bfd *, char **));
1492159047fSniklas 
1502159047fSniklas static bfd_reloc_status_type
1512159047fSniklas riscix_fix_pcrel_26 PARAMS ((bfd *, arelent *, asymbol *, PTR,
1522159047fSniklas 			     asection *, bfd *, char **));
153*c074d1c9Sdrahn static const bfd_target *
154*c074d1c9Sdrahn MY (object_p) PARAMS ((bfd *));
155*c074d1c9Sdrahn 
156*c074d1c9Sdrahn reloc_howto_type *
157*c074d1c9Sdrahn riscix_reloc_type_lookup PARAMS ((bfd *, bfd_reloc_code_real_type));
158*c074d1c9Sdrahn 
159*c074d1c9Sdrahn void
160*c074d1c9Sdrahn riscix_swap_std_reloc_out PARAMS ((bfd *, arelent *, struct reloc_std_external *));
161*c074d1c9Sdrahn 
162*c074d1c9Sdrahn bfd_boolean
163*c074d1c9Sdrahn riscix_squirt_out_relocs PARAMS ((bfd *, asection *));
164*c074d1c9Sdrahn 
165*c074d1c9Sdrahn long
166*c074d1c9Sdrahn MY (canonicalize_reloc) PARAMS ((bfd *, sec_ptr, arelent **, asymbol **));
167*c074d1c9Sdrahn 
168*c074d1c9Sdrahn const bfd_target *
169*c074d1c9Sdrahn riscix_some_aout_object_p PARAMS ((bfd *, struct internal_exec *, const bfd_target *(*) (bfd *)));
170*c074d1c9Sdrahn 
1712159047fSniklas 
1722159047fSniklas static reloc_howto_type riscix_std_reloc_howto[] = {
1732159047fSniklas   /* type              rs size bsz  pcrel bitpos ovrf                     sf name     part_inpl readmask  setmask    pcdone */
174*c074d1c9Sdrahn   HOWTO( 0,              0,  0,   8,  FALSE, 0, complain_overflow_bitfield,0,"8",        TRUE, 0x000000ff,0x000000ff, FALSE),
175*c074d1c9Sdrahn   HOWTO( 1,              0,  1,   16, FALSE, 0, complain_overflow_bitfield,0,"16",        TRUE, 0x0000ffff,0x0000ffff, FALSE),
176*c074d1c9Sdrahn   HOWTO( 2,              0,  2,   32, FALSE, 0, complain_overflow_bitfield,0,"32",        TRUE, 0xffffffff,0xffffffff, FALSE),
177*c074d1c9Sdrahn   HOWTO( 3,              2,  3,   26, TRUE, 0, complain_overflow_signed,  riscix_fix_pcrel_26 , "ARM26",      TRUE, 0x00ffffff,0x00ffffff, FALSE),
178*c074d1c9Sdrahn   HOWTO( 4,              0,  0,   8,  TRUE,  0, complain_overflow_signed,  0,"DISP8",     TRUE, 0x000000ff,0x000000ff, TRUE),
179*c074d1c9Sdrahn   HOWTO( 5,              0,  1,   16, TRUE,  0, complain_overflow_signed,  0,"DISP16",    TRUE, 0x0000ffff,0x0000ffff, TRUE),
180*c074d1c9Sdrahn   HOWTO( 6,              0,  2,   32, TRUE,  0, complain_overflow_signed,  0,"DISP32",    TRUE, 0xffffffff,0xffffffff, TRUE),
181*c074d1c9Sdrahn   HOWTO( 7,              2,  3,   26, FALSE, 0, complain_overflow_signed,  riscix_fix_pcrel_26_done, "ARM26D",TRUE,0x00ffffff,0x00ffffff, FALSE),
182b305b0f1Sespie   EMPTY_HOWTO (-1),
183*c074d1c9Sdrahn   HOWTO( 9,              0, -1,   16, FALSE, 0, complain_overflow_bitfield,0,"NEG16",        TRUE, 0x0000ffff,0x0000ffff, FALSE),
184*c074d1c9Sdrahn   HOWTO( 10,              0, -2,   32, FALSE, 0, complain_overflow_bitfield,0,"NEG32",        TRUE, 0xffffffff,0xffffffff, FALSE)
1852159047fSniklas };
1862159047fSniklas 
1872159047fSniklas #define RISCIX_TABLE_SIZE \
1882159047fSniklas   (sizeof (riscix_std_reloc_howto) / sizeof (reloc_howto_type))
1892159047fSniklas 
1902159047fSniklas static bfd_reloc_status_type
riscix_fix_pcrel_26_done(abfd,reloc_entry,symbol,data,input_section,output_bfd,error_message)1912159047fSniklas riscix_fix_pcrel_26_done (abfd, reloc_entry, symbol, data, input_section,
1922159047fSniklas 			  output_bfd, error_message)
193b305b0f1Sespie      bfd *abfd ATTRIBUTE_UNUSED;
194b305b0f1Sespie      arelent *reloc_entry ATTRIBUTE_UNUSED;
195b305b0f1Sespie      asymbol *symbol ATTRIBUTE_UNUSED;
196b305b0f1Sespie      PTR data ATTRIBUTE_UNUSED;
197b305b0f1Sespie      asection *input_section ATTRIBUTE_UNUSED;
198b305b0f1Sespie      bfd *output_bfd ATTRIBUTE_UNUSED;
199b305b0f1Sespie      char **error_message ATTRIBUTE_UNUSED;
2002159047fSniklas {
2012159047fSniklas   /* This is dead simple at present.  */
2022159047fSniklas   return bfd_reloc_ok;
2032159047fSniklas }
2042159047fSniklas 
2052159047fSniklas static bfd_reloc_status_type
riscix_fix_pcrel_26(abfd,reloc_entry,symbol,data,input_section,output_bfd,error_message)2062159047fSniklas riscix_fix_pcrel_26 (abfd, reloc_entry, symbol, data, input_section,
2072159047fSniklas 		     output_bfd, error_message)
2082159047fSniklas      bfd *abfd;
2092159047fSniklas      arelent *reloc_entry;
2102159047fSniklas      asymbol *symbol;
2112159047fSniklas      PTR data;
2122159047fSniklas      asection *input_section;
2132159047fSniklas      bfd *output_bfd;
214b305b0f1Sespie      char **error_message ATTRIBUTE_UNUSED;
2152159047fSniklas {
2162159047fSniklas   bfd_vma relocation;
2172159047fSniklas   bfd_size_type addr = reloc_entry->address;
2182159047fSniklas   long target = bfd_get_32 (abfd, (bfd_byte *) data + addr);
2192159047fSniklas   bfd_reloc_status_type flag = bfd_reloc_ok;
2202159047fSniklas 
2212159047fSniklas   /* If this is an undefined symbol, return error */
2222159047fSniklas   if (symbol->section == &bfd_und_section
2232159047fSniklas       && (symbol->flags & BSF_WEAK) == 0)
2242159047fSniklas     return output_bfd ? bfd_reloc_continue : bfd_reloc_undefined;
2252159047fSniklas 
2262159047fSniklas   /* If the sections are different, and we are doing a partial relocation,
2272159047fSniklas      just ignore it for now.  */
2282159047fSniklas   if (symbol->section->name != input_section->name
2292159047fSniklas       && output_bfd != (bfd *)NULL)
2302159047fSniklas     return bfd_reloc_continue;
2312159047fSniklas 
2322159047fSniklas   relocation = (target & 0x00ffffff) << 2;
2332159047fSniklas   relocation = (relocation ^ 0x02000000) - 0x02000000; /* Sign extend */
2342159047fSniklas   relocation += symbol->value;
2352159047fSniklas   relocation += symbol->section->output_section->vma;
2362159047fSniklas   relocation += symbol->section->output_offset;
2372159047fSniklas   relocation += reloc_entry->addend;
2382159047fSniklas   relocation -= input_section->output_section->vma;
2392159047fSniklas   relocation -= input_section->output_offset;
2402159047fSniklas   relocation -= addr;
2412159047fSniklas   if (relocation & 3)
2422159047fSniklas     return bfd_reloc_overflow;
2432159047fSniklas 
2442159047fSniklas   /* Check for overflow */
2452159047fSniklas   if (relocation & 0x02000000)
2462159047fSniklas     {
247b305b0f1Sespie       if ((relocation & ~ (bfd_vma) 0x03ffffff) != ~ (bfd_vma) 0x03ffffff)
2482159047fSniklas 	flag = bfd_reloc_overflow;
2492159047fSniklas     }
250*c074d1c9Sdrahn   else if (relocation & ~ (bfd_vma) 0x03ffffff)
2512159047fSniklas     flag = bfd_reloc_overflow;
2522159047fSniklas 
2532159047fSniklas   target &= ~0x00ffffff;
2542159047fSniklas   target |= (relocation >> 2) & 0x00ffffff;
255*c074d1c9Sdrahn   bfd_put_32 (abfd, (bfd_vma) target, (bfd_byte *) data + addr);
2562159047fSniklas 
2572159047fSniklas   /* Now the ARM magic... Change the reloc type so that it is marked as done.
2582159047fSniklas      Strictly this is only necessary if we are doing a partial relocation.  */
2592159047fSniklas   reloc_entry->howto = &riscix_std_reloc_howto[7];
2602159047fSniklas 
2612159047fSniklas   return flag;
2622159047fSniklas }
2632159047fSniklas 
2642159047fSniklas reloc_howto_type *
riscix_reloc_type_lookup(abfd,code)265b55d4692Sfgsch riscix_reloc_type_lookup (abfd, code)
266b55d4692Sfgsch      bfd *abfd;
267b55d4692Sfgsch      bfd_reloc_code_real_type code;
2682159047fSniklas {
2692159047fSniklas #define ASTD(i,j)       case i: return &riscix_std_reloc_howto[j]
2702159047fSniklas   if (code == BFD_RELOC_CTOR)
2712159047fSniklas     switch (bfd_get_arch_info (abfd)->bits_per_address)
2722159047fSniklas       {
2732159047fSniklas       case 32:
2742159047fSniklas         code = BFD_RELOC_32;
2752159047fSniklas         break;
2762159047fSniklas       default: return (reloc_howto_type *) NULL;
2772159047fSniklas       }
2782159047fSniklas 
2792159047fSniklas   switch (code)
2802159047fSniklas     {
2812159047fSniklas       ASTD (BFD_RELOC_16, 1);
2822159047fSniklas       ASTD (BFD_RELOC_32, 2);
2832159047fSniklas       ASTD (BFD_RELOC_ARM_PCREL_BRANCH, 3);
2842159047fSniklas       ASTD (BFD_RELOC_8_PCREL, 4);
2852159047fSniklas       ASTD (BFD_RELOC_16_PCREL, 5);
2862159047fSniklas       ASTD (BFD_RELOC_32_PCREL, 6);
2872159047fSniklas     default: return (reloc_howto_type *) NULL;
2882159047fSniklas     }
2892159047fSniklas }
2902159047fSniklas 
2912159047fSniklas #define MY_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
2922159047fSniklas #define MY_bfd_link_add_symbols _bfd_generic_link_add_symbols
293b305b0f1Sespie #define MY_final_link_callback should_not_be_used
2942159047fSniklas #define MY_bfd_final_link _bfd_generic_final_link
2952159047fSniklas 
2962159047fSniklas #define MY_bfd_reloc_type_lookup riscix_reloc_type_lookup
2972159047fSniklas #define MY_canonicalize_reloc riscix_canonicalize_reloc
2982159047fSniklas #define MY_object_p riscix_object_p
2992159047fSniklas 
3002159047fSniklas static const bfd_target *riscix_callback PARAMS ((bfd *));
3012159047fSniklas 
3022159047fSniklas void
riscix_swap_std_reloc_out(abfd,g,natptr)3032159047fSniklas riscix_swap_std_reloc_out (abfd, g, natptr)
3042159047fSniklas      bfd *abfd;
3052159047fSniklas      arelent *g;
3062159047fSniklas      struct reloc_std_external *natptr;
3072159047fSniklas {
3082159047fSniklas   int r_index;
3092159047fSniklas   asymbol *sym = *(g->sym_ptr_ptr);
3102159047fSniklas   int r_extern;
3112159047fSniklas   int r_length;
3122159047fSniklas   int r_pcrel;
3132159047fSniklas   int r_neg = 0;	/* Negative relocs use the BASEREL bit.  */
3142159047fSniklas   asection *output_section = sym->section->output_section;
3152159047fSniklas 
3162159047fSniklas   PUT_WORD(abfd, g->address, natptr->r_address);
3172159047fSniklas 
3182159047fSniklas   r_length = g->howto->size ;   /* Size as a power of two */
3192159047fSniklas   if (r_length < 0)
3202159047fSniklas     {
3212159047fSniklas       r_length = -r_length;
3222159047fSniklas       r_neg = 1;
3232159047fSniklas     }
3242159047fSniklas 
3252159047fSniklas   r_pcrel  = (int) g->howto->pc_relative; /* Relative to PC? */
3262159047fSniklas 
3272159047fSniklas   /* For RISC iX, in pc-relative relocs the r_pcrel bit means that the
3282159047fSniklas      relocation has been done already (Only for the 26-bit one I think)???!!!
3292159047fSniklas      */
3302159047fSniklas 
3312159047fSniklas   if (r_length == 3)
3322159047fSniklas     r_pcrel = r_pcrel ? 0 : 1;
3332159047fSniklas 
3342159047fSniklas #if 0
3352159047fSniklas   /* For a standard reloc, the addend is in the object file.  */
3362159047fSniklas   r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
3372159047fSniklas #endif
3382159047fSniklas 
3392159047fSniklas   /* name was clobbered by aout_write_syms to be symbol index */
3402159047fSniklas 
3412159047fSniklas   /* If this relocation is relative to a symbol then set the
3422159047fSniklas      r_index to the symbols index, and the r_extern bit.
3432159047fSniklas 
3442159047fSniklas      Absolute symbols can come in in two ways, either as an offset
3452159047fSniklas      from the abs section, or as a symbol which has an abs value.
3462159047fSniklas      check for that here
3472159047fSniklas      */
3482159047fSniklas 
3492159047fSniklas   if (bfd_is_com_section (output_section)
3502159047fSniklas       || output_section == &bfd_abs_section
3512159047fSniklas       || output_section == &bfd_und_section)
3522159047fSniklas     {
3532159047fSniklas       if (bfd_abs_section.symbol == sym)
3542159047fSniklas 	{
3552159047fSniklas 	  /* Whoops, looked like an abs symbol, but is really an offset
3562159047fSniklas 	     from the abs section */
3572159047fSniklas 	  r_index = 0;
3582159047fSniklas 	  r_extern = 0;
3592159047fSniklas 	}
3602159047fSniklas       else
3612159047fSniklas 	{
3622159047fSniklas 	  /* Fill in symbol */
3632159047fSniklas 	  r_extern = 1;
3640c6d0228Sniklas 	  r_index = (*g->sym_ptr_ptr)->udata.i;
3652159047fSniklas 	}
3662159047fSniklas     }
3672159047fSniklas   else
3682159047fSniklas     {
3692159047fSniklas       /* Just an ordinary section */
3702159047fSniklas       r_extern = 0;
3712159047fSniklas       r_index  = output_section->target_index;
3722159047fSniklas     }
3732159047fSniklas 
3742159047fSniklas   /* now the fun stuff */
375c88b1d6cSniklas   if (bfd_header_big_endian (abfd))
3762159047fSniklas     {
3772159047fSniklas       natptr->r_index[0] = r_index >> 16;
3782159047fSniklas       natptr->r_index[1] = r_index >> 8;
3792159047fSniklas       natptr->r_index[2] = r_index;
3802159047fSniklas       natptr->r_type[0] =
3812159047fSniklas 	(  (r_extern ?   RELOC_STD_BITS_EXTERN_BIG: 0)
3822159047fSniklas 	 | (r_pcrel  ?   RELOC_STD_BITS_PCREL_BIG: 0)
3832159047fSniklas 	 | (r_neg    ?   RELOC_STD_BITS_BASEREL_BIG: 0)
3842159047fSniklas 	 | (r_length <<  RELOC_STD_BITS_LENGTH_SH_BIG));
3852159047fSniklas     }
3862159047fSniklas   else
3872159047fSniklas     {
3882159047fSniklas       natptr->r_index[2] = r_index >> 16;
3892159047fSniklas       natptr->r_index[1] = r_index >> 8;
3902159047fSniklas       natptr->r_index[0] = r_index;
3912159047fSniklas       natptr->r_type[0] =
3922159047fSniklas 	(  (r_extern ?   RELOC_STD_BITS_EXTERN_LITTLE: 0)
3932159047fSniklas 	 | (r_pcrel  ?   RELOC_STD_BITS_PCREL_LITTLE: 0)
3942159047fSniklas 	 | (r_neg    ?   RELOC_STD_BITS_BASEREL_LITTLE: 0)
3952159047fSniklas 	 | (r_length <<  RELOC_STD_BITS_LENGTH_SH_LITTLE));
3962159047fSniklas     }
3972159047fSniklas }
3982159047fSniklas 
399*c074d1c9Sdrahn bfd_boolean
riscix_squirt_out_relocs(abfd,section)4002159047fSniklas riscix_squirt_out_relocs (abfd, section)
4012159047fSniklas      bfd *abfd;
4022159047fSniklas      asection *section;
4032159047fSniklas {
4042159047fSniklas   arelent **generic;
4052159047fSniklas   unsigned char *native, *natptr;
4062159047fSniklas   size_t each_size;
4072159047fSniklas 
4082159047fSniklas   unsigned int count = section->reloc_count;
409*c074d1c9Sdrahn   bfd_size_type natsize;
4102159047fSniklas 
411*c074d1c9Sdrahn   if (count == 0)
412*c074d1c9Sdrahn     return TRUE;
4132159047fSniklas 
4142159047fSniklas   each_size = obj_reloc_entry_size (abfd);
415*c074d1c9Sdrahn   natsize = each_size;
416*c074d1c9Sdrahn   natsize *= count;
4172159047fSniklas   native = (unsigned char *) bfd_zalloc (abfd, natsize);
418c88b1d6cSniklas   if (!native)
419*c074d1c9Sdrahn     return FALSE;
4202159047fSniklas 
4212159047fSniklas   generic = section->orelocation;
4222159047fSniklas 
4232159047fSniklas   for (natptr = native;
4242159047fSniklas        count != 0;
4252159047fSniklas        --count, natptr += each_size, ++generic)
4262159047fSniklas     riscix_swap_std_reloc_out (abfd, *generic,
4272159047fSniklas 			       (struct reloc_std_external *) natptr);
4282159047fSniklas 
429*c074d1c9Sdrahn   if (bfd_bwrite ((PTR) native, natsize, abfd) != natsize)
4302159047fSniklas     {
4312159047fSniklas       bfd_release (abfd, native);
432*c074d1c9Sdrahn       return FALSE;
4332159047fSniklas     }
4342159047fSniklas 
4352159047fSniklas   bfd_release (abfd, native);
436*c074d1c9Sdrahn   return TRUE;
4372159047fSniklas }
4382159047fSniklas 
4392159047fSniklas /*
4402159047fSniklas  * This is just like the standard aoutx.h version but we need to do our
4412159047fSniklas  * own mapping of external reloc type values to howto entries.
4422159047fSniklas  */
4432159047fSniklas long
4442159047fSniklas MY(canonicalize_reloc) (abfd, section, relptr, symbols)
4452159047fSniklas       bfd *abfd;
4462159047fSniklas       sec_ptr section;
4472159047fSniklas       arelent **relptr;
4482159047fSniklas       asymbol **symbols;
4492159047fSniklas {
4502159047fSniklas   arelent *tblptr = section->relocation;
4512159047fSniklas   unsigned int count, c;
4522159047fSniklas   extern reloc_howto_type NAME(aout,std_howto_table)[];
4532159047fSniklas 
4542159047fSniklas   /* If we have already read in the relocation table, return the values.  */
4552159047fSniklas   if (section->flags & SEC_CONSTRUCTOR) {
4562159047fSniklas     arelent_chain *chain = section->constructor_chain;
4572159047fSniklas 
4582159047fSniklas     for (count = 0; count < section->reloc_count; count++) {
4592159047fSniklas       *relptr++ = &chain->relent;
4602159047fSniklas       chain = chain->next;
4612159047fSniklas     }
4622159047fSniklas     *relptr = 0;
4632159047fSniklas     return section->reloc_count;
4642159047fSniklas   }
4652159047fSniklas   if (tblptr && section->reloc_count) {
4662159047fSniklas     for (count = 0; count++ < section->reloc_count;)
4672159047fSniklas       *relptr++ = tblptr++;
4682159047fSniklas     *relptr = 0;
4692159047fSniklas     return section->reloc_count;
4702159047fSniklas   }
4712159047fSniklas 
4722159047fSniklas   if (!NAME(aout,slurp_reloc_table) (abfd, section, symbols))
4732159047fSniklas     return -1;
4742159047fSniklas   tblptr = section->relocation;
4752159047fSniklas 
4762159047fSniklas   /* fix up howto entries */
4772159047fSniklas   for (count = 0; count++ < section->reloc_count;)
4782159047fSniklas     {
4792159047fSniklas       c = tblptr->howto - NAME(aout,std_howto_table);
480e93f7393Sniklas       BFD_ASSERT (c < RISCIX_TABLE_SIZE);
4812159047fSniklas       tblptr->howto = &riscix_std_reloc_howto[c];
4822159047fSniklas 
4832159047fSniklas       *relptr++ = tblptr++;
4842159047fSniklas     }
4852159047fSniklas   *relptr = 0;
4862159047fSniklas   return section->reloc_count;
4872159047fSniklas }
4882159047fSniklas 
4892159047fSniklas /* This is the same as NAME(aout,some_aout_object_p), but has different
4902159047fSniklas    expansions of the macro definitions.  */
4912159047fSniklas 
4922159047fSniklas const bfd_target *
riscix_some_aout_object_p(abfd,execp,callback_to_real_object_p)4932159047fSniklas riscix_some_aout_object_p (abfd, execp, callback_to_real_object_p)
4942159047fSniklas      bfd *abfd;
4952159047fSniklas      struct internal_exec *execp;
4962159047fSniklas      const bfd_target *(*callback_to_real_object_p) PARAMS ((bfd *));
4972159047fSniklas {
4982159047fSniklas   struct aout_data_struct *rawptr, *oldrawptr;
4992159047fSniklas   const bfd_target *result;
500*c074d1c9Sdrahn   bfd_size_type amt = sizeof (struct aout_data_struct);
5012159047fSniklas 
502*c074d1c9Sdrahn   rawptr = (struct aout_data_struct  *) bfd_zalloc (abfd, amt);
5032159047fSniklas 
504c88b1d6cSniklas   if (rawptr == NULL)
5052159047fSniklas     return 0;
5062159047fSniklas 
5072159047fSniklas   oldrawptr = abfd->tdata.aout_data;
5082159047fSniklas   abfd->tdata.aout_data = rawptr;
5092159047fSniklas 
5102159047fSniklas   /* Copy the contents of the old tdata struct.
5112159047fSniklas      In particular, we want the subformat, since for hpux it was set in
5122159047fSniklas      hp300hpux.c:swap_exec_header_in and will be used in
5132159047fSniklas      hp300hpux.c:callback.  */
5142159047fSniklas   if (oldrawptr != NULL)
5152159047fSniklas     *abfd->tdata.aout_data = *oldrawptr;
5162159047fSniklas 
5172159047fSniklas   abfd->tdata.aout_data->a.hdr = &rawptr->e;
5182159047fSniklas   *(abfd->tdata.aout_data->a.hdr) = *execp;     /* Copy in the internal_exec
5192159047fSniklas 						   struct */
5202159047fSniklas   execp = abfd->tdata.aout_data->a.hdr;
5212159047fSniklas 
5222159047fSniklas   /* Set the file flags */
5230c6d0228Sniklas   abfd->flags = BFD_NO_FLAGS;
5242159047fSniklas   if (execp->a_drsize || execp->a_trsize)
5252159047fSniklas     abfd->flags |= HAS_RELOC;
5262159047fSniklas   /* Setting of EXEC_P has been deferred to the bottom of this function */
5272159047fSniklas   if (execp->a_syms)
5282159047fSniklas     abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
5292159047fSniklas   if (N_DYNAMIC(*execp))
5302159047fSniklas     abfd->flags |= DYNAMIC;
5312159047fSniklas 
5322159047fSniklas   if ((execp->a_info & MF_SQUEEZED) != 0) /* Squeezed files aren't supported
5332159047fSniklas 					     (yet)! */
5342159047fSniklas     {
5352159047fSniklas       bfd_set_error (bfd_error_wrong_format);
5362159047fSniklas       return NULL;
5372159047fSniklas     }
5382159047fSniklas   else if ((execp->a_info & MF_IS_SL) != 0)	/* Nor are shared libraries */
5392159047fSniklas     {
5402159047fSniklas       bfd_set_error (bfd_error_wrong_format);
5412159047fSniklas       return NULL;
5422159047fSniklas     }
5432159047fSniklas   else if (N_MAGIC (*execp) == ZMAGIC)
5442159047fSniklas     {
5452159047fSniklas       abfd->flags |= D_PAGED | WP_TEXT;
5462159047fSniklas       adata (abfd).magic = z_magic;
5472159047fSniklas     }
5482159047fSniklas   else if (N_MAGIC (*execp) == NMAGIC)
5492159047fSniklas     {
5502159047fSniklas       abfd->flags |= WP_TEXT;
5512159047fSniklas       adata (abfd).magic = n_magic;
5522159047fSniklas     }
5532159047fSniklas   else if (N_MAGIC (*execp) == OMAGIC)
5542159047fSniklas     adata (abfd).magic = o_magic;
5552159047fSniklas   else
5562159047fSniklas     {
5572159047fSniklas       /* Should have been checked with N_BADMAG before this routine
5582159047fSniklas          was called.  */
5592159047fSniklas       abort ();
5602159047fSniklas     }
5612159047fSniklas 
5622159047fSniklas   bfd_get_start_address (abfd) = execp->a_entry;
5632159047fSniklas 
5642159047fSniklas   obj_aout_symbols (abfd) = (aout_symbol_type *)NULL;
5652159047fSniklas   bfd_get_symcount (abfd) = execp->a_syms / sizeof (struct external_nlist);
5662159047fSniklas 
5672159047fSniklas   /* The default relocation entry size is that of traditional V7 Unix.  */
5682159047fSniklas   obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
5692159047fSniklas 
5702159047fSniklas   /* The default symbol entry size is that of traditional Unix.  */
5712159047fSniklas   obj_symbol_entry_size (abfd) = EXTERNAL_NLIST_SIZE;
5722159047fSniklas 
5732159047fSniklas   obj_aout_external_syms (abfd) = NULL;
5742159047fSniklas   obj_aout_external_strings (abfd) = NULL;
5752159047fSniklas   obj_aout_sym_hashes (abfd) = NULL;
5762159047fSniklas 
5772159047fSniklas   if (! NAME(aout,make_sections) (abfd))
5782159047fSniklas     return NULL;
5792159047fSniklas 
5802159047fSniklas   obj_datasec (abfd)->_raw_size = execp->a_data;
5812159047fSniklas   obj_bsssec (abfd)->_raw_size = execp->a_bss;
5822159047fSniklas 
5832159047fSniklas   obj_textsec (abfd)->flags =
5842159047fSniklas     (execp->a_trsize != 0
5852159047fSniklas      ? (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS | SEC_RELOC)
5862159047fSniklas      : (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS));
5872159047fSniklas   obj_datasec (abfd)->flags =
5882159047fSniklas     (execp->a_drsize != 0
5892159047fSniklas      ? (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS | SEC_RELOC)
5902159047fSniklas      : (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS));
5912159047fSniklas   obj_bsssec (abfd)->flags = SEC_ALLOC;
5922159047fSniklas 
5932159047fSniklas   result = (*callback_to_real_object_p) (abfd);
5942159047fSniklas 
5952159047fSniklas #if defined(MACH) || defined(STAT_FOR_EXEC)
5962159047fSniklas   /* The original heuristic doesn't work in some important cases. The
5972159047fSniklas    * a.out file has no information about the text start address. For
5982159047fSniklas    * files (like kernels) linked to non-standard addresses (ld -Ttext
5992159047fSniklas    * nnn) the entry point may not be between the default text start
6002159047fSniklas    * (obj_textsec(abfd)->vma) and (obj_textsec(abfd)->vma) + text size
6012159047fSniklas    * This is not just a mach issue. Many kernels are loaded at non
6022159047fSniklas    * standard addresses.
6032159047fSniklas    */
6042159047fSniklas   {
6052159047fSniklas     struct stat stat_buf;
606c88b1d6cSniklas     if (abfd->iostream != NULL
607c88b1d6cSniklas 	&& (abfd->flags & BFD_IN_MEMORY) == 0
6082159047fSniklas         && (fstat(fileno((FILE *) (abfd->iostream)), &stat_buf) == 0)
6092159047fSniklas         && ((stat_buf.st_mode & 0111) != 0))
6102159047fSniklas       abfd->flags |= EXEC_P;
6112159047fSniklas   }
6122159047fSniklas #else /* ! MACH */
6132159047fSniklas   /* Now that the segment addresses have been worked out, take a better
6142159047fSniklas      guess at whether the file is executable.  If the entry point
6152159047fSniklas      is within the text segment, assume it is.  (This makes files
6162159047fSniklas      executable even if their entry point address is 0, as long as
6172159047fSniklas      their text starts at zero.)
6182159047fSniklas 
6192159047fSniklas      At some point we should probably break down and stat the file and
6202159047fSniklas      declare it executable if (one of) its 'x' bits are on...  */
6212159047fSniklas   if ((execp->a_entry >= obj_textsec(abfd)->vma) &&
6222159047fSniklas       (execp->a_entry < obj_textsec(abfd)->vma + obj_textsec(abfd)->_raw_size))
6232159047fSniklas     abfd->flags |= EXEC_P;
6242159047fSniklas #endif /* MACH */
6252159047fSniklas   if (result)
6262159047fSniklas     {
6272159047fSniklas     }
6282159047fSniklas   else
6292159047fSniklas     {
6302159047fSniklas       free (rawptr);
6312159047fSniklas       abfd->tdata.aout_data = oldrawptr;
6322159047fSniklas     }
6332159047fSniklas   return result;
6342159047fSniklas }
6352159047fSniklas 
6362159047fSniklas static const bfd_target *
6372159047fSniklas MY(object_p) (abfd)
6382159047fSniklas      bfd *abfd;
6392159047fSniklas {
6402159047fSniklas   struct external_exec exec_bytes;      /* Raw exec header from file */
6412159047fSniklas   struct internal_exec exec;            /* Cleaned-up exec header */
6422159047fSniklas   const bfd_target *target;
6432159047fSniklas 
644*c074d1c9Sdrahn   if (bfd_bread ((PTR) &exec_bytes, (bfd_size_type) EXEC_BYTES_SIZE, abfd)
645*c074d1c9Sdrahn       != EXEC_BYTES_SIZE)
646*c074d1c9Sdrahn     {
6472159047fSniklas       if (bfd_get_error () != bfd_error_system_call)
6482159047fSniklas 	bfd_set_error (bfd_error_wrong_format);
6492159047fSniklas       return 0;
6502159047fSniklas     }
6512159047fSniklas 
652*c074d1c9Sdrahn   exec.a_info = H_GET_32 (abfd, exec_bytes.e_info);
6532159047fSniklas 
6542159047fSniklas   if (N_BADMAG (exec)) return 0;
6552159047fSniklas #ifdef MACHTYPE_OK
6562159047fSniklas   if (!(MACHTYPE_OK (N_MACHTYPE (exec)))) return 0;
6572159047fSniklas #endif
6582159047fSniklas 
6592159047fSniklas   NAME(aout,swap_exec_header_in) (abfd, &exec_bytes, &exec);
6602159047fSniklas 
6612159047fSniklas   target = riscix_some_aout_object_p (abfd, &exec, MY(callback));
6622159047fSniklas 
6632159047fSniklas   return target;
6642159047fSniklas }
6652159047fSniklas 
6662159047fSniklas #include "aout-target.h"
667