This is Paul K's latest set of ld changes. A commit was necessary at this
[unix-history] / gnu / usr.bin / ld / i386 / md.c
CommitLineData
1136f72d
PR
1/*
2 * Copyright (c) 1993 Paul Kranenburg
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Paul Kranenburg.
16 * 4. The name of the author may not be used to endorse or promote products
17 * derived from this software withough specific prior written permission
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
6a61ea88 30 * $Id: md.c,v 1.8 1994/01/19 15:00:37 davidg Exp $
1136f72d
PR
31 */
32
33#include <sys/param.h>
34#include <stdio.h>
35#include <stdlib.h>
36#include <sys/types.h>
37#include <fcntl.h>
38#include <a.out.h>
39#include <stab.h>
40#include <string.h>
41
42#include "ld.h"
43
44/*
45 * Get relocation addend corresponding to relocation record RP
46 * from address ADDR
47 */
48long
49md_get_addend(rp, addr)
50struct relocation_info *rp;
51unsigned char *addr;
52{
53 switch (RELOC_TARGET_SIZE(rp)) {
54 case 0:
55 return get_byte(addr);
56 break;
57 case 1:
58 return get_short(addr);
59 break;
60 case 2:
61 return get_long(addr);
62 break;
63 }
64}
65
66/*
67 * Put RELOCATION at ADDR according to relocation record RP.
68 */
69void
70md_relocate(rp, relocation, addr, relocatable_output)
71struct relocation_info *rp;
72long relocation;
73unsigned char *addr;
74{
75 switch (RELOC_TARGET_SIZE(rp)) {
76 case 0:
77 put_byte(addr, relocation);
78 break;
79 case 1:
80 put_short(addr, relocation);
81 break;
82 case 2:
83 put_long(addr, relocation);
84 break;
85 default:
86 fatal("Unsupported relocation size: %x", RELOC_TARGET_SIZE(rp));
87 }
88}
89
1136f72d
PR
90/*
91 * Machine dependent part of claim_rrs_reloc().
92 * Set RRS relocation type.
93 */
94int
95md_make_reloc(rp, r, type)
96struct relocation_info *rp, *r;
97int type;
98{
99 /* Relocation size */
100 r->r_length = rp->r_length;
101
102 if (RELOC_PCREL_P(rp))
103 r->r_pcrel = 1;
104
105 if (type & RELTYPE_RELATIVE)
106 r->r_relative = 1;
107
108 if (type & RELTYPE_COPY)
109 r->r_copy = 1;
110
111 return 0;
112}
113
114/*
115 * Set up a transfer from jmpslot at OFFSET (relative to the PLT table)
116 * to the binder slot (which is at offset 0 of the PLT).
117 */
118void
119md_make_jmpslot(sp, offset, index)
120jmpslot_t *sp;
121long offset;
122long index;
123{
124 /*
125 * i386 PC-relative "fixed point" is located right after the
126 * instruction it pertains to.
127 */
128 u_long fudge = - (sizeof(sp->opcode) + sizeof(sp->addr) + offset);
129
130 sp->opcode = CALL;
131#if 0
132 sp->addr = fudge;
133#else
134 sp->addr[0] = fudge & 0xffff;
135 sp->addr[1] = fudge >> 16;
136#endif
137 sp->reloc_index = index;
138}
139
140/*
141 * Set up a "direct" transfer (ie. not through the run-time binder) from
142 * jmpslot at OFFSET to ADDR. Used by `ld' when the SYMBOLIC flag is on,
143 * and by `ld.so' after resolving the symbol.
144 * On the i386, we use the JMP instruction which is PC relative, so no
145 * further RRS relocations will be necessary for such a jmpslot.
146 */
147void
148md_fix_jmpslot(sp, offset, addr)
149jmpslot_t *sp;
150long offset;
151u_long addr;
152{
153 u_long fudge = addr - (sizeof(sp->opcode) + sizeof(sp->addr) + offset);
154
155 sp->opcode = JUMP;
156#if 0
157 sp->addr = fudge;
158#else
159 sp->addr[0] = fudge & 0xffff;
160 sp->addr[1] = fudge >> 16;
161#endif
162 sp->reloc_index = 0;
163}
164
165/*
166 * Update the relocation record for a RRS jmpslot.
167 */
168void
169md_make_jmpreloc(rp, r, type)
170struct relocation_info *rp, *r;
171int type;
172{
173 jmpslot_t *sp;
174
175 /*
176 * Fix relocation address to point to the correct
177 * location within this jmpslot.
178 */
179 r->r_address += sizeof(sp->opcode);
180
181 /* Relocation size */
182 r->r_length = 2;
183
184 /* Set relocation type */
185 r->r_jmptable = 1;
186 if (type & RELTYPE_RELATIVE)
187 r->r_relative = 1;
188
189}
190
191/*
192 * Set relocation type for a RRS GOT relocation.
193 */
194void
195md_make_gotreloc(rp, r, type)
196struct relocation_info *rp, *r;
197int type;
198{
199 r->r_baserel = 1;
200 if (type & RELTYPE_RELATIVE)
201 r->r_relative = 1;
202
203 /* Relocation size */
204 r->r_length = 2;
205}
206
207/*
208 * Set relocation type for a RRS copy operation.
209 */
210void
211md_make_cpyreloc(rp, r)
212struct relocation_info *rp, *r;
213{
214 /* Relocation size */
215 r->r_length = 2;
216
217 r->r_copy = 1;
218}
219
80f25b52
JH
220void
221md_set_breakpoint(where, savep)
222long where;
223long *savep;
224{
225 *savep = *(long *)where;
27b6ced7 226 *(char *)where = TRAP;
80f25b52 227}
1136f72d 228
6a61ea88
JH
229#ifndef RTLD
230
231#ifdef FreeBSD
232int netzmagic;
233#endif
1136f72d 234
6a61ea88
JH
235/*
236 * Initialize (output) exec header such that useful values are
237 * obtained from subsequent N_*() macro evaluations.
238 */
239void
240md_init_header(hp, magic, flags)
241struct exec *hp;
242int magic, flags;
243{
244#ifdef NetBSD
245 if (oldmagic || magic == QMAGIC)
246 hp->a_midmag = magic;
247 else
248 N_SETMAGIC((*hp), magic, MID_I386, flags);
249#endif
250#ifdef FreeBSD
251 if (oldmagic)
252 hp->a_midmag = magic;
253 else if (netzmagic)
254 N_SETMAGIC_NET((*hp), magic, MID_I386, flags);
255 else
256 N_SETMAGIC((*hp), magic, MID_I386, flags);
257#endif
258
259 /* TEXT_START depends on the value of outheader.a_entry. */
260 if (!(link_mode & SHAREABLE)) /*WAS: if (entry_symbol) */
261 hp->a_entry = PAGSIZ;
262}
263#endif /* RTLD */
264
265
266#ifdef NEED_SWAP
1136f72d
PR
267/*
268 * Byte swap routines for cross-linking.
269 */
270
271void
272md_swapin_exec_hdr(h)
273struct exec *h;
274{
275 int skip = 0;
276
277 if (!N_BADMAG(*h))
278 skip = 1;
279
280 swap_longs((long *)h + skip, sizeof(*h)/sizeof(long) - skip);
281}
282
283void
284md_swapout_exec_hdr(h)
285struct exec *h;
286{
287 /* NetBSD: Always leave magic alone */
288 int skip = 1;
289#if 0
290 if (N_GETMAGIC(*h) == OMAGIC)
291 skip = 0;
292#endif
293
294 swap_longs((long *)h + skip, sizeof(*h)/sizeof(long) - skip);
295}
296
297
298void
299md_swapin_reloc(r, n)
300struct relocation_info *r;
301int n;
302{
303 int bits;
304
305 for (; n; n--, r++) {
306 r->r_address = md_swap_long(r->r_address);
307 bits = ((int *)r)[1];
308 r->r_symbolnum = md_swap_long(bits & 0xffffff00);
309 r->r_pcrel = (bits & 1);
310 r->r_length = ((bits >> 1) & 3);
311 r->r_extern = ((bits >> 3) & 1);
312 r->r_baserel = ((bits >> 4) & 1);
313 r->r_jmptable = ((bits >> 5) & 1);
314 r->r_relative = ((bits >> 6) & 1);
315#ifdef N_SIZE
316 r->r_copy = ((bits >> 7) & 1);
317#endif
318 }
319}
320
321void
322md_swapout_reloc(r, n)
323struct relocation_info *r;
324int n;
325{
326 int bits;
327
328 for (; n; n--, r++) {
329 r->r_address = md_swap_long(r->r_address);
330 bits = (md_swap_long(r->r_symbolnum) & 0xffffff00);
331 bits |= (r->r_pcrel & 1);
332 bits |= ((r->r_length << 1) & 6);
333 bits |= ((r->r_extern << 3) & 8);
334 bits |= ((r->r_baserel << 4) & 0x10);
335 bits |= ((r->r_jmptable << 5) & 0x20);
336 bits |= ((r->r_relative << 6) & 0x40);
337#ifdef N_SIZE
338 bits |= ((r->r_copy << 7) & 0x80);
339#endif
340 ((int *)r)[1] = bits;
341 }
342}
343
344void
345md_swapout_jmpslot(j, n)
346jmpslot_t *j;
347int n;
348{
349 for (; n; n--, j++) {
350 j->opcode = md_swap_short(j->opcode);
351 j->addr[0] = md_swap_short(j->addr[0]);
352 j->addr[1] = md_swap_short(j->addr[1]);
353 j->reloc_index = md_swap_short(j->reloc_index);
354 }
355}
356
357#endif /* NEED_SWAP */