1 /* $NetBSD: md.c,v 1.16 1999/04/12 00:52:44 gwr 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
));
95 _cachectl (addr
, RELOC_TARGET_SIZE(rp
)); /* maintain cache coherency */
100 * Set up a "direct" transfer (ie. not through the run-time binder) from
101 * jmpslot at OFFSET to ADDR. Used by `ld' when the SYMBOLIC flag is on,
102 * and by `ld.so' after resolving the symbol.
103 * On the m68k, we use the BRA instruction which is PC relative, so no
104 * further RRS relocations will be necessary for such a jmpslot.
107 md_fix_jmpslot(sp
, offset
, addr
, first
)
113 u_long fudge
= addr
- (sizeof(sp
->opcode
) + offset
);
116 sp
->addr
[0] = fudge
>> 16;
120 _cachectl (sp
, 6); /* maintain cache coherency */
125 md_set_breakpoint(where
, savep
)
129 *savep
= *(long *)where
;
130 *(short *)where
= BPT
;
137 * Machine dependent part of claim_rrs_reloc().
138 * Set RRS relocation type.
141 md_make_reloc(rp
, r
, type
)
142 struct relocation_info
*rp
, *r
;
145 /* Relocation size */
146 r
->r_length
= rp
->r_length
;
148 if (RELOC_PCREL_P(rp
))
151 if (type
& RELTYPE_RELATIVE
)
154 if (type
& RELTYPE_COPY
)
161 * Set up a transfer from jmpslot at OFFSET (relative to the PLT table)
162 * to the binder slot (which is at offset 0 of the PLT).
165 md_make_jmpslot(sp
, offset
, index
)
171 * On m68k machines, a long branch offset is relative to
172 * the address of the offset.
174 u_long fudge
= - (sizeof(sp
->opcode
) + offset
);
177 sp
->addr
[0] = fudge
>> 16;
179 sp
->reloc_index
= index
;
181 _cachectl (sp
, 6); /* maintain cache coherency */
186 * Update the relocation record for a RRS jmpslot.
189 md_make_jmpreloc(rp
, r
, type
)
190 struct relocation_info
*rp
, *r
;
196 * Fix relocation address to point to the correct
197 * location within this jmpslot.
199 r
->r_address
+= sizeof(sp
->opcode
);
201 /* Relocation size */
204 /* Set relocation type */
206 if (type
& RELTYPE_RELATIVE
)
212 * Set relocation type for a RRS GOT relocation.
215 md_make_gotreloc(rp
, r
, type
)
216 struct relocation_info
*rp
, *r
;
220 if (type
& RELTYPE_RELATIVE
)
223 /* Relocation size */
228 * Set relocation type for a RRS copy operation.
231 md_make_cpyreloc(rp
, r
)
232 struct relocation_info
*rp
, *r
;
234 /* Relocation size */
241 * Initialize (output) exec header such that useful values are
242 * obtained from subsequent N_*() macro evaluations.
245 md_init_header(hp
, magic
, flags
)
250 hp
->a_midmag
= oldmagic
;
252 N_SETMAGIC((*hp
), magic
, MID_MACHINE
, flags
);
254 /* TEXT_START depends on the value of outheader.a_entry. */
255 if (!(link_mode
& SHAREABLE
))
256 hp
->a_entry
= PAGSIZ
;
260 * Check for acceptable foreign machine Ids
266 int mid
= N_GETMID(*hp
);
268 if (mid
== MID_M68K
||
276 mid
= (md_swap_long(hp
->a_midmag
) & 0x00ff0000) >> 16;
277 if (mid
== MID_SUN020
)
287 * Byte swap routines for cross-linking.
291 md_swapin_exec_hdr(h
)
299 swap_longs((long *)h
+ skip
, sizeof(*h
)/sizeof(long) - skip
);
303 md_swapout_exec_hdr(h
)
306 /* NetBSD: Always leave magic alone */
309 if (N_GETMAGIC(*h
) == OMAGIC
)
313 swap_longs((long *)h
+ skip
, sizeof(*h
)/sizeof(long) - skip
);
318 md_swapin_reloc(r
, n
)
319 struct relocation_info
*r
;
324 for (; n
; n
--, r
++) {
325 r
->r_address
= md_swap_long(r
->r_address
);
326 bits
= ((int *)r
)[1];
327 r
->r_symbolnum
= md_swap_long(bits
) >> 8;
329 r
->r_pcrel
= (bits
>> 7) & 1;
330 r
->r_length
= (bits
>> 5) & 3;
331 r
->r_extern
= (bits
>> 4) & 1;
332 r
->r_baserel
= (bits
>> 3) & 1;
333 r
->r_jmptable
= (bits
>> 2) & 1;
334 r
->r_relative
= (bits
>> 1) & 1;
336 r
->r_copy
= (bits
& 1);
342 md_swapout_reloc(r
, n
)
343 struct relocation_info
*r
;
348 for (; n
; n
--, r
++) {
349 r
->r_address
= md_swap_long(r
->r_address
);
350 bits
= (r
->r_pcrel
& 1) << 7;
351 bits
|= (r
->r_length
& 3) << 5;
352 bits
|= (r
->r_extern
& 1) << 4;
353 bits
|= (r
->r_baserel
& 1) << 3;
354 bits
|= (r
->r_jmptable
& 1) << 2;
355 bits
|= (r
->r_relative
& 1) << 1;
357 bits
|= (r
->r_copy
& 1);
359 ((int *)r
)[1] = md_swap_long(r
->r_symbolnum
) >> 8;
360 ((unsigned char *)r
)[7] = bits
;
365 md_swapout_jmpslot(j
, n
)
369 for (; n
; n
--, j
++) {
370 j
->opcode
= md_swap_short(j
->opcode
);
371 j
->addr
[0] = md_swap_short(j
->addr
[0]);
372 j
->addr
[1] = md_swap_short(j
->addr
[1]);
373 j
->reloc_index
= md_swap_short(j
->reloc_index
);
377 #endif /* NEED_SWAP */