Many recent fixes from Paul K, add support for chaining of shared lib deps.
[unix-history] / gnu / usr.bin / ld / sparc / md.c
CommitLineData
1136f72d 1/*
27b6ced7 2 * $Id: md.c,v 1.3 1993/11/22 19:05:30 jkh Exp $
1136f72d
PR
3 */
4
5#include <sys/param.h>
6#include <stdio.h>
7#include <stdlib.h>
8#include <sys/types.h>
9#include <fcntl.h>
10#include <a.out.h>
11#include <stab.h>
12#include <string.h>
13
14#include "ld.h"
15
16/*
17 * Relocation masks and sizes for the Sparc architecture.
18 *
19 * Note that these are very dependent on the order of the enums in
20 * enum reloc_type (in a.out.h); if they change the following must be
21 * changed.
22 * Also, note that RELOC_RELATIVE is handled as if it were a RELOC_HI22.
23 * This should work provided that relocations values have zeroes in their
24 * least significant 10 bits. As RELOC_RELATIVE is used only to relocate
25 * with load address values - which are page aligned - this condition is
26 * fulfilled as long as the system's page size is > 1024 (and a power of 2).
27 */
28static int reloc_target_rightshift[] = {
29 0, 0, 0, /* RELOC_8, _16, _32 */
30 0, 0, 0, 2, 2, /* DISP8, DISP16, DISP32, WDISP30, WDISP22 */
31 10, 0, /* HI22, _22 */
32 0, 0, /* RELOC_13, _LO10 */
33 0, 0, /* _SFA_BASE, _SFA_OFF13 */
34 0, 0, 10, /* _BASE10, _BASE13, _BASE22 */
35 0, 10, /* _PC10, _PC22 */
36 2, 0, /* _JMP_TBL, _SEGOFF16 */
37 0, 0, 0 /* _GLOB_DAT, JMP_SLOT, _RELATIVE */
38};
39static int reloc_target_size[] = {
40 0, 1, 2, /* RELOC_8, _16, _32 */
41 0, 1, 2, 2, 2, /* DISP8, DISP16, DISP32, WDISP30, WDISP22 */
42 2, 2, /* HI22, _22 */
43 2, 2, /* RELOC_13, _LO10 */
44 2, 2, /* _SFA_BASE, _SFA_OFF13 */
45 2, 2, 2, /* _BASE10, _BASE13, _BASE22 */
46 2, 2, /* _PC10, _PC22 */
47 2, 0, /* _JMP_TBL, _SEGOFF16 */
48 2, 0, 2 /* _GLOB_DAT, JMP_SLOT, _RELATIVE */
49};
50static int reloc_target_bitsize[] = {
51 8, 16, 32, /* RELOC_8, _16, _32 */
52 8, 16, 32, 30, 22, /* DISP8, DISP16, DISP32, WDISP30, WDISP22 */
53 22, 22, /* HI22, _22 */
54 13, 10, /* RELOC_13, _LO10 */
55 32, 32, /* _SFA_BASE, _SFA_OFF13 */
56 10, 13, 22, /* _BASE10, _BASE13, _BASE22 */
57 10, 22, /* _PC10, _PC22 */
58 30, 0, /* _JMP_TBL, _SEGOFF16 */
59 32, 0, 22 /* _GLOB_DAT, JMP_SLOT, _RELATIVE */
60};
61
62
63/*
64 * Get relocation addend corresponding to relocation record RP
65 * ADDR unused by SPARC impl.
66 */
67long
68md_get_addend(r, addr)
69struct relocation_info *r;
70unsigned char *addr;
71{
72 return r->r_addend;
73}
74
75void
76md_relocate(r, relocation, addr, relocatable_output)
77struct relocation_info *r;
78long relocation;
79unsigned char *addr;
80int relocatable_output;
81{
82 register unsigned long mask;
83
84 if (relocatable_output) {
85 /*
86 * Non-PC relative relocations which are absolute or
87 * which have become non-external now have fixed
88 * relocations. Set the ADD_EXTRA of this relocation
89 * to be the relocation we have now determined.
90 */
91 if (!RELOC_PCREL_P(r)) {
92 if ((int) r->r_type <= RELOC_32
93 || RELOC_EXTERN_P(r) == 0)
94 RELOC_ADD_EXTRA(r) = relocation;
95 } else if (RELOC_EXTERN_P(r))
96 /*
97 * External PC-relative relocations continue
98 * to move around; update their relocations
99 * by the amount they have moved so far.
100 */
101 RELOC_ADD_EXTRA(r) -= pc_relocation;
102 return;
103 }
104
105 relocation >>= RELOC_VALUE_RIGHTSHIFT(r);
106
107 /* Unshifted mask for relocation */
108 mask = 1 << RELOC_TARGET_BITSIZE(r) - 1;
109 mask |= mask - 1;
110 relocation &= mask;
111
112 /* Shift everything up to where it's going to be used */
113 relocation <<= RELOC_TARGET_BITPOS(r);
114 mask <<= RELOC_TARGET_BITPOS(r);
115
116 switch (RELOC_TARGET_SIZE(r)) {
117 case 0:
118 if (RELOC_MEMORY_ADD_P(r))
119 relocation += (mask & *(u_char *) (addr));
120 *(u_char *) (addr) &= ~mask;
121 *(u_char *) (addr) |= relocation;
122 break;
123
124 case 1:
125 if (RELOC_MEMORY_ADD_P(r))
126 relocation += (mask & *(u_short *) (addr));
127 *(u_short *) (addr) &= ~mask;
128 *(u_short *) (addr) |= relocation;
129 break;
130
131 case 2:
132 if (RELOC_MEMORY_ADD_P(r))
133 relocation += (mask & *(u_long *) (addr));
134 *(u_long *) (addr) &= ~mask;
135 *(u_long *) (addr) |= relocation;
136 break;
137 default:
138 fatal( "Unimplemented relocation field length in");
139 }
140}
141
142/*
143 * Initialize (output) exec header such that useful values are
144 * obtained from subsequent N_*() macro evaluations.
145 */
146void
147md_init_header(hp, magic, flags)
148struct exec *hp;
149int magic, flags;
150{
7fc7155d
PR
151#ifdef NetBSD
152 N_SETMAGIC((*hp), magic, MID_MACHINE, flags);
153
154 /* TEXT_START depends on the value of outheader.a_entry. */
155 if (!(link_mode & SHAREABLE)) /*WAS: if (entry_symbol) */
156 hp->a_entry = PAGSIZ;
157#else
1136f72d
PR
158 hp->a_magic = magic;
159 hp->a_machtype = M_SPARC;
160 hp->a_toolversion = 1;
161 hp->a_dynamic = ((flags) & EX_DYNAMIC);
162
163 /* SunOS 4.1 N_TXTADDR depends on the value of outheader.a_entry. */
164 if (!(link_mode & SHAREABLE)) /*WAS: if (entry_symbol) */
165 hp->a_entry = N_PAGSIZ(*hp);
7fc7155d 166#endif
1136f72d
PR
167}
168
169/*
170 * Machine dependent part of claim_rrs_reloc().
171 * On the Sparc the relocation offsets are stored in the r_addend member.
172 */
173int
174md_make_reloc(rp, r, type)
175struct relocation_info *rp, *r;
176int type;
177{
178 r->r_type = rp->r_type;
179 r->r_addend = rp->r_addend;
180
181#if 1
182 /*
183 * This wouldn't be strictly necessary - we could record the
184 * location value "in situ" in stead of in the r_addend field -
185 * but we are being Sun compatible here. Besides, Sun's ld.so
186 * has a bug that prevents it from handling this alternate method
187 */
188 if (RELOC_PCREL_P(rp))
189 r->r_addend -= pc_relocation;
190#endif
191
192 return 1;
193}
194
195/*
196 * Set up a transfer from jmpslot at OFFSET (relative to the PLT table)
197 * to the binder slot (which is at offset 0 of the PLT).
198 */
199void
200md_make_jmpslot(sp, offset, index)
201jmpslot_t *sp;
202long offset;
203long index;
204{
205 u_long fudge = (u_long) -(sizeof(sp->opcode1) + offset);
206 sp->opcode1 = SAVE;
207 /* The following is a RELOC_WDISP30 relocation */
208 sp->opcode2 = CALL | ((fudge >> 2) & 0x3fffffff);
209 sp->reloc_index = NOP | index;
210}
211
212/*
213 * Set up a "direct" transfer (ie. not through the run-time binder) from
214 * jmpslot at OFFSET to ADDR. Used by `ld' when the SYMBOLIC flag is on,
215 * and by `ld.so' after resolving the symbol.
216 * On the i386, we use the JMP instruction which is PC relative, so no
217 * further RRS relocations will be necessary for such a jmpslot.
218 *
219 * OFFSET unused on Sparc.
220 */
221void
222md_fix_jmpslot(sp, offset, addr)
223jmpslot_t *sp;
224long offset;
225u_long addr;
226{
227 /*
228 * Here comes a RELOC_{LO10,HI22} relocation pair
229 * The resulting code is:
230 * sethi %hi(addr), %g1
231 * jmp %g1+%lo(addr)
232 * nop ! delay slot
233 */
234 sp->opcode1 = SETHI | ((addr >> 10) & 0x003fffff);
235 sp->opcode2 = JMP | (addr & 0x000003ff);
236 sp->reloc_index = NOP;
237}
238
239/*
240 * Update the relocation record for a jmpslot.
241 */
242void
243md_make_jmpreloc(rp, r, type)
244struct relocation_info *rp, *r;
245int type;
246{
247 if (type & RELTYPE_RELATIVE)
248 r->r_type = RELOC_RELATIVE;
249 else
250 r->r_type = RELOC_JMP_SLOT;
251
252 r->r_addend = rp->r_addend;
253}
254
255/*
256 * Set relocation type for a GOT RRS relocation.
257 */
258void
259md_make_gotreloc(rp, r, type)
260struct relocation_info *rp, *r;
261int type;
262{
263 /*
264 * GOT value resolved (symbolic or entry point): R_32
265 * GOT not resolved: GLOB_DAT
266 *
267 * NOTE: I don't think it makes a difference.
268 */
269 if (type & RELTYPE_RELATIVE)
270 r->r_type = RELOC_32;
271 else
272 r->r_type = RELOC_GLOB_DAT;
273
274 r->r_addend = 0;
275}
276
277/*
278 * Set relocation type for a RRS copy operation.
279 */
280void
281md_make_cpyreloc(rp, r)
282struct relocation_info *rp, *r;
283{
284 r->r_type = RELOC_COPY_DAT;
285 r->r_addend = 0;
286}
287
80f25b52
JH
288void
289md_set_breakpoint(where, savep)
290long where;
291long *savep;
292{
293 *savep = *(long *)where;
27b6ced7 294 *(long *)where = TRAP;
80f25b52
JH
295}
296