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