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