1 /* $NetBSD: md.c,v 1.17 1998/12/17 20:14:44 pk Exp $ */
4 * Copyright (c) 1998 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/param.h>
35 #include <sys/types.h>
44 /* Pull in the ld(1) bits as well */
49 * Get relocation addend corresponding to relocation record RP
53 md_get_addend(rp
, addr
)
54 struct relocation_info
*rp
;
57 switch (RELOC_TARGET_SIZE(rp
)) {
59 return get_byte(addr
);
61 return get_short(addr
);
63 return get_long(addr
);
65 errx(1, "Unsupported relocation size: %x",
66 RELOC_TARGET_SIZE(rp
));
71 * Put RELOCATION at ADDR according to relocation record RP.
74 md_relocate(rp
, relocation
, addr
, relocatable_output
)
75 struct relocation_info
*rp
;
78 int relocatable_output
;
80 switch (RELOC_TARGET_SIZE(rp
)) {
82 put_byte(addr
, relocation
);
85 put_short(addr
, relocation
);
88 put_long(addr
, relocation
);
91 errx(1, "Unsupported relocation size: %x",
92 RELOC_TARGET_SIZE(rp
));
97 md_set_breakpoint(where
, savep
)
101 *savep
= *(long *)where
;
102 *(char *)where
= TRAP
;
106 * Set up a "direct" transfer (ie. not through the run-time binder) from
107 * jmpslot at OFFSET to ADDR. Used by `ld' when the SYMBOLIC flag is on,
108 * and by `ld.so' after resolving the symbol.
109 * On the i386, we use the JMP instruction which is PC relative, so no
110 * further RRS relocations will be necessary for such a jmpslot.
113 md_fix_jmpslot(sp
, offset
, addr
, first
)
119 u_long fudge
= addr
- (sizeof(sp
->opcode
) + sizeof(sp
->addr
) + offset
);
125 sp
->addr
[0] = fudge
& 0xffff;
126 sp
->addr
[1] = fudge
>> 16;
135 * Machine dependent part of claim_rrs_reloc().
136 * Set RRS relocation type.
139 md_make_reloc(rp
, r
, type
)
140 struct relocation_info
*rp
, *r
;
143 /* Relocation size */
144 r
->r_length
= rp
->r_length
;
146 if (RELOC_PCREL_P(rp
))
149 if (type
& RELTYPE_RELATIVE
)
152 if (type
& RELTYPE_COPY
)
159 * Set up a transfer from jmpslot at OFFSET (relative to the PLT table)
160 * to the binder slot (which is at offset 0 of the PLT).
163 md_make_jmpslot(sp
, offset
, index
)
169 * i386 PC-relative "fixed point" is located right after the
170 * instruction it pertains to.
172 u_long fudge
= - (sizeof(sp
->opcode
) + sizeof(sp
->addr
) + offset
);
178 sp
->addr
[0] = fudge
& 0xffff;
179 sp
->addr
[1] = fudge
>> 16;
181 sp
->reloc_index
= index
;
185 * Update the relocation record for a RRS jmpslot.
188 md_make_jmpreloc(rp
, r
, type
)
189 struct relocation_info
*rp
, *r
;
195 * Fix relocation address to point to the correct
196 * location within this jmpslot.
198 r
->r_address
+= sizeof(sp
->opcode
);
200 /* Relocation size */
203 /* Set relocation type */
205 if (type
& RELTYPE_RELATIVE
)
211 * Set relocation type for a RRS GOT relocation.
214 md_make_gotreloc(rp
, r
, type
)
215 struct relocation_info
*rp
, *r
;
219 if (type
& RELTYPE_RELATIVE
)
222 /* Relocation size */
227 * Set relocation type for a RRS copy operation.
230 md_make_cpyreloc(rp
, r
)
231 struct relocation_info
*rp
, *r
;
233 /* Relocation size */
244 * Initialize (output) exec header such that useful values are
245 * obtained from subsequent N_*() macro evaluations.
248 md_init_header(hp
, magic
, flags
)
253 if (oldmagic
|| magic
== QMAGIC
)
254 hp
->a_midmag
= magic
;
256 N_SETMAGIC((*hp
), magic
, MID_I386
, flags
);
260 hp
->a_midmag
= magic
;
262 N_SETMAGIC_NET((*hp
), magic
, MID_I386
, flags
);
264 N_SETMAGIC((*hp
), magic
, MID_I386
, flags
);
267 /* TEXT_START depends on the value of outheader.a_entry. */
268 if (!(link_mode
& SHAREABLE
))
269 hp
->a_entry
= PAGSIZ
;
276 * Byte swap routines for cross-linking.
280 md_swapin_exec_hdr(h
)
288 swap_longs((long *)h
+ skip
, sizeof(*h
)/sizeof(long) - skip
);
292 md_swapout_exec_hdr(h
)
295 /* NetBSD: Always leave magic alone */
298 if (N_GETMAGIC(*h
) == OMAGIC
)
302 swap_longs((long *)h
+ skip
, sizeof(*h
)/sizeof(long) - skip
);
307 md_swapin_reloc(r
, n
)
308 struct relocation_info
*r
;
313 for (; n
; n
--, r
++) {
314 r
->r_address
= md_swap_long(r
->r_address
);
315 bits
= ((int *)r
)[1];
316 r
->r_symbolnum
= md_swap_long(bits
) & 0x00ffffff;
317 r
->r_pcrel
= (bits
& 1);
318 r
->r_length
= (bits
>> 1) & 3;
319 r
->r_extern
= (bits
>> 3) & 1;
320 r
->r_baserel
= (bits
>> 4) & 1;
321 r
->r_jmptable
= (bits
>> 5) & 1;
322 r
->r_relative
= (bits
>> 6) & 1;
324 r
->r_copy
= (bits
>> 7) & 1;
330 md_swapout_reloc(r
, n
)
331 struct relocation_info
*r
;
336 for (; n
; n
--, r
++) {
337 r
->r_address
= md_swap_long(r
->r_address
);
338 bits
= md_swap_long(r
->r_symbolnum
) & 0xffffff00;
339 bits
|= (r
->r_pcrel
& 1);
340 bits
|= (r
->r_length
& 3) << 1;
341 bits
|= (r
->r_extern
& 1) << 3;
342 bits
|= (r
->r_baserel
& 1) << 4;
343 bits
|= (r
->r_jmptable
& 1) << 5;
344 bits
|= (r
->r_relative
& 1) << 6;
346 bits
|= (r
->r_copy
& 1) << 7;
348 ((int *)r
)[1] = bits
;
353 md_swapout_jmpslot(j
, n
)
357 for (; n
; n
--, j
++) {
358 j
->opcode
= md_swap_short(j
->opcode
);
359 j
->addr
[0] = md_swap_short(j
->addr
[0]);
360 j
->addr
[1] = md_swap_short(j
->addr
[1]);
361 j
->reloc_index
= md_swap_short(j
->reloc_index
);
364 #endif /* NEED_SWAP */