1 /* $NetBSD: md.c,v 1.15 1999/06/28 17:28:56 ragge 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>
36 #include <sys/types.h>
45 /* Pull in the ld(1) bits as well */
50 * Get relocation addend corresponding to relocation record RP
54 md_get_addend(rp
, addr
)
55 struct relocation_info
*rp
;
58 switch (RELOC_TARGET_SIZE(rp
)) {
60 return get_byte(addr
);
62 return get_short(addr
);
65 long addend
= get_long(addr
);
67 addend
+= rp
->r_address
+ 4;
69 put_long(addr
, -(rp
->r_address
+4));
73 return get_long(addr
);
75 errx(1, "Unsupported relocation size: %x",
76 RELOC_TARGET_SIZE(rp
));
81 * Put RELOCATION at ADDR according to relocation record RP.
84 md_relocate(rp
, relocation
, addr
, relocatable_output
)
85 struct relocation_info
*rp
;
88 int relocatable_output
;
90 switch (RELOC_TARGET_SIZE(rp
)) {
92 put_byte(addr
, relocation
);
95 put_short(addr
, relocation
);
100 relocation
+= got_symbol
->value
+ get_long(addr
);
102 put_byte(addr
-1, 0x10 | get_byte(addr
-1));
105 put_long(addr
, relocation
);
108 errx(1, "Unsupported relocation size: %x",
109 RELOC_TARGET_SIZE(rp
));
114 * Set up a "direct" transfer (ie. not through the run-time binder) from
115 * jmpslot at OFFSET to ADDR. Used by `ld' when the SYMBOLIC flag is on,
116 * and by `ld.so' after resolving the symbol.
117 * On the VAX, we use a PC relative JMP instruction, so no
118 * further RRS relocations will be necessary for such a jmpslot.
121 md_fix_jmpslot(sp
, offset
, addr
, first
)
127 u_long fudge
= addr
- (offset
+ 9);
130 sp
->mask
= 0x0101; /* NOP NOP */
131 sp
->insn
[0] = 0x01; /* nop */
132 sp
->insn
[1] = 0x17; /* jmp */
135 sp
->mask
= *(u_int16_t
*) addr
;
136 sp
->insn
[0] = 0x01; /* nop */
137 sp
->insn
[1] = 0x17; /* jmp */
138 fudge
+= 2; /* skip entry mask */
141 sp
->insn
[0] = 0xfa; /* callg */
142 sp
->insn
[1] = 0x6c; /* (ap) */
145 sp
->insn
[2] = 0xef; /* L^(pc) */
146 sp
->insn
[3] = (fudge
>> 0) & 0xff;
147 sp
->insn
[4] = (fudge
>> 8) & 0xff;
148 sp
->insn
[5] = (fudge
>> 16) & 0xff;
149 sp
->insn
[6] = (fudge
>> 24) & 0xff;
150 sp
->insn
[7] = 0x04; /* ret */
154 md_set_breakpoint(where
, savep
)
158 *savep
= *(long *)where
;
159 *(char *)where
= BPT
;
166 * Machine dependent part of claim_rrs_reloc().
167 * Set RRS relocation type.
170 md_make_reloc(rp
, r
, type
)
171 struct relocation_info
*rp
, *r
;
174 /* Relocation size */
175 r
->r_length
= rp
->r_length
;
177 if (RELOC_PCREL_P(rp
))
180 if (type
& RELTYPE_RELATIVE
)
183 if (type
& RELTYPE_COPY
)
190 * Set up a transfer from jmpslot at OFFSET (relative to the PLT table)
191 * to the binder slot (which is at offset 0 of the PLT).
194 md_make_jmpslot(sp
, offset
, index
)
200 * On VAX a branch offset given in immediate mode is relative to
201 * the end of the address itself.
203 u_long fudge
= - (offset
+ 9);
205 sp
->mask
= (1 << 6); /* Just R6 (for setjmp) */
206 sp
->insn
[0] = 0x01; /* nop */
207 sp
->insn
[1] = 0x16; /* jsb */
208 sp
->insn
[2] = 0xef; /* L^(pc) */
209 sp
->insn
[3] = (fudge
>> 0) & 0xff;
210 sp
->insn
[4] = (fudge
>> 8) & 0xff;
211 sp
->insn
[5] = (fudge
>> 16) & 0xff;
212 sp
->insn
[6] = (fudge
>> 24) & 0xff;
213 sp
->insn
[7] = 0x00; /* halt */
214 sp
->reloc_index
= index
;
218 * Update the relocation record for a RRS jmpslot.
221 md_make_jmpreloc(rp
, r
, type
)
222 struct relocation_info
*rp
, *r
;
228 * Fix relocation address to point to the correct
229 * location within this jmpslot.
231 r
->r_address
+= sizeof(sp
->mask
);
233 /* Relocation size */
234 r
->r_length
= 2; /* 4 bytes */
236 /* Set relocation type */
238 if (type
& RELTYPE_RELATIVE
)
243 * Set relocation type for a RRS GOT relocation.
246 md_make_gotreloc(rp
, r
, type
)
247 struct relocation_info
*rp
, *r
;
252 if (type
& RELTYPE_RELATIVE
)
255 /* Relocation size */
256 r
->r_length
= 2; /* 4 bytes */
260 * Set relocation type for a RRS copy operation.
263 md_make_cpyreloc(rp
, r
)
264 struct relocation_info
*rp
, *r
;
266 /* Relocation size */
267 r
->r_length
= 2; /* 4 bytes */
273 md_convert_textreloc(r
)
274 struct relocation_info
*r
;
276 if (r
->r_length
!= 2 || !r
->r_pcrel
|| !r
->r_copy
)
288 * Initialize (output) exec header such that useful values are
289 * obtained from subsequent N_*() macro evaluations.
292 md_init_header(hp
, magic
, flags
)
297 if (oldmagic
|| magic
== QMAGIC
)
298 hp
->a_midmag
= magic
;
300 N_SETMAGIC((*hp
), magic
, MID_VAX
, flags
);
304 hp
->a_midmag
= magic
;
306 N_SETMAGIC_NET((*hp
), magic
, MID_VAX
, flags
);
308 N_SETMAGIC((*hp
), magic
, MID_VAX
, flags
);
311 /* TEXT_START depends on the value of outheader.a_entry. */
312 if (!(link_mode
& SHAREABLE
))
313 hp
->a_entry
= PAGSIZ
;
320 * Byte swap routines for cross-linking.
324 md_swapin_exec_hdr(h
)
332 swap_longs((long *)h
+ skip
, sizeof(*h
)/sizeof(long) - skip
);
336 md_swapout_exec_hdr(h
)
339 /* NetBSD: Always leave magic alone */
342 if (N_GETMAGIC(*h
) == OMAGIC
)
346 swap_longs((long *)h
+ skip
, sizeof(*h
)/sizeof(long) - skip
);
351 md_swapin_reloc(r
, n
)
352 struct relocation_info
*r
;
357 for (; n
; n
--, r
++) {
358 r
->r_address
= md_swap_long(r
->r_address
);
359 bits
= ((int *)r
)[1];
360 r
->r_symbolnum
= md_swap_long(bits
) & 0x00ffffff;
361 r
->r_pcrel
= (bits
& 1);
362 r
->r_length
= (bits
>> 1) & 3;
363 r
->r_extern
= (bits
>> 3) & 1;
364 r
->r_baserel
= (bits
>> 4) & 1;
365 r
->r_jmptable
= (bits
>> 5) & 1;
366 r
->r_relative
= (bits
>> 6) & 1;
368 r
->r_copy
= (bits
>> 7) & 1;
374 md_swapout_reloc(r
, n
)
375 struct relocation_info
*r
;
380 for (; n
; n
--, r
++) {
381 r
->r_address
= md_swap_long(r
->r_address
);
382 bits
= md_swap_long(r
->r_symbolnum
) & 0xffffff00;
383 bits
|= (r
->r_pcrel
& 1);
384 bits
|= (r
->r_length
& 3) << 1;
385 bits
|= (r
->r_extern
& 1) << 3;
386 bits
|= (r
->r_baserel
& 1) << 4;
387 bits
|= (r
->r_jmptable
& 1) << 5;
388 bits
|= (r
->r_relative
& 1) << 6;
390 bits
|= (r
->r_copy
& 1) << 7;
392 ((int *)r
)[1] = bits
;
397 md_swapout_jmpslot(j
, n
)
401 for (; n
; n
--, j
++) {
402 j
->mask
= md_swap_short(j
->mask
);
403 j
->reloc_index
= md_swap_short(j
->reloc_index
);
406 #endif /* NEED_SWAP */