2 * Copyright (c) 1993 Paul Kranenburg
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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 without specific prior written permission
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.
30 * $FreeBSD: src/libexec/rtld-aout/i386/md.c,v 1.17 1999/08/28 00:10:07 peter Exp $
31 * $DragonFly: src/libexec/rtld-aout/i386/Attic/md.c,v 1.3 2004/02/13 03:49:50 dillon Exp $
34 #include <sys/param.h>
38 #include <sys/types.h>
47 #if defined(RTLD) && defined(SUN_COMPAT)
48 #define REL_SIZE(r) (2) /* !!!!! Sun BUG compatible */
50 #define REL_SIZE(r) ((r)->r_length)
54 * Get relocation addend corresponding to relocation record RP
58 md_get_addend(rp, addr)
59 struct relocation_info *rp;
62 switch (REL_SIZE(rp)) {
64 return get_byte(addr);
66 return get_short(addr);
68 return get_long(addr);
70 errx(1, "Unsupported relocation size: %x",
76 * Put RELOCATION at ADDR according to relocation record RP.
79 md_relocate(rp, relocation, addr, relocatable_output)
80 struct relocation_info *rp;
83 int relocatable_output;
85 switch (REL_SIZE(rp)) {
87 put_byte(addr, relocation);
90 put_short(addr, relocation);
93 put_long(addr, relocation);
96 errx(1, "Unsupported relocation size: %x",
102 * Machine dependent part of claim_rrs_reloc().
103 * Set RRS relocation type.
106 md_make_reloc(rp, r, type)
107 struct relocation_info *rp, *r;
110 /* Relocation size */
111 r->r_length = rp->r_length;
116 if (type & RELTYPE_RELATIVE)
119 if (type & RELTYPE_COPY)
126 * Set up a transfer from jmpslot at OFFSET (relative to the PLT table)
127 * to the binder slot (which is at offset 0 of the PLT).
130 md_make_jmpslot(sp, offset, index)
136 * i386 PC-relative "fixed point" is located right after the
137 * instruction it pertains to.
139 u_long fudge = - (sizeof(sp->opcode) + sizeof(sp->addr) + offset);
145 sp->addr[0] = fudge & 0xffff;
146 sp->addr[1] = fudge >> 16;
148 sp->reloc_index = index;
152 * Set up a "direct" transfer (ie. not through the run-time binder) from
153 * jmpslot at OFFSET to ADDR. Used by `ld' when the SYMBOLIC flag is on,
154 * and by `ld.so' after resolving the symbol.
155 * On the i386, we use the JMP instruction which is PC relative, so no
156 * further RRS relocations will be necessary for such a jmpslot.
159 md_fix_jmpslot(sp, offset, addr)
164 u_long fudge = addr - (sizeof(sp->opcode) + sizeof(sp->addr) + offset);
170 sp->addr[0] = fudge & 0xffff;
171 sp->addr[1] = fudge >> 16;
177 * Bind a jmpslot to its target address. TARGET is where the jmpslot
178 * should jump to, and WHERE is a pointer to the jmpslot's address field.
179 * This is called by the dynamic linker when LD_BIND_NOW is set in the
183 md_bind_jmpslot(target, where)
188 (jmpslot_t *) (where - offsetof(jmpslot_t, addr[0]));
190 md_fix_jmpslot(sp, (long) sp, target);
194 * Update the relocation record for a RRS jmpslot.
197 md_make_jmpreloc(rp, r, type)
198 struct relocation_info *rp, *r;
204 * Fix relocation address to point to the correct
205 * location within this jmpslot.
207 r->r_address += sizeof(sp->opcode);
209 /* Relocation size */
212 /* Set relocation type */
214 if (type & RELTYPE_RELATIVE)
220 * Set relocation type for a RRS GOT relocation.
223 md_make_gotreloc(rp, r, type)
224 struct relocation_info *rp, *r;
228 if (type & RELTYPE_RELATIVE)
231 /* Relocation size */
236 * Set relocation type for a RRS copy operation.
239 md_make_cpyreloc(rp, r)
240 struct relocation_info *rp, *r;
242 /* Relocation size */
249 md_set_breakpoint(where, savep)
253 *savep = *(long *)where;
254 *(char *)where = TRAP;
259 #if defined(__DragonFly__) || defined(__FreeBSD__)
264 * Initialize (output) exec header such that useful values are
265 * obtained from subsequent N_*() macro evaluations.
268 md_init_header(hp, magic, flags)
273 if (oldmagic || magic == QMAGIC)
274 hp->a_midmag = magic;
276 N_SETMAGIC((*hp), magic, MID_I386, flags);
278 #if defined(__DragonFly__) || defined(__FreeBSD__)
280 hp->a_midmag = magic;
282 N_SETMAGIC_NET((*hp), magic, MID_I386, flags);
284 N_SETMAGIC((*hp), magic, MID_I386, flags);
287 /* TEXT_START depends on the value of outheader.a_entry. */
288 if (!(link_mode & SHAREABLE))
289 hp->a_entry = PAGSIZ;
296 * Byte swap routines for cross-linking.
300 md_swapin_exec_hdr(h)
308 swap_longs((long *)h + skip, sizeof(*h)/sizeof(long) - skip);
312 md_swapout_exec_hdr(h)
315 /* NetBSD: Always leave magic alone */
318 if (N_GETMAGIC(*h) == OMAGIC)
322 swap_longs((long *)h + skip, sizeof(*h)/sizeof(long) - skip);
327 md_swapin_reloc(r, n)
328 struct relocation_info *r;
333 for (; n; n--, r++) {
334 r->r_address = md_swap_long(r->r_address);
335 bits = ((int *)r)[1];
336 r->r_symbolnum = md_swap_long(bits) & 0x00ffffff;
337 r->r_pcrel = (bits & 1);
338 r->r_length = (bits >> 1) & 3;
339 r->r_extern = (bits >> 3) & 1;
340 r->r_baserel = (bits >> 4) & 1;
341 r->r_jmptable = (bits >> 5) & 1;
342 r->r_relative = (bits >> 6) & 1;
344 r->r_copy = (bits >> 7) & 1;
350 md_swapout_reloc(r, n)
351 struct relocation_info *r;
356 for (; n; n--, r++) {
357 r->r_address = md_swap_long(r->r_address);
358 bits = md_swap_long(r->r_symbolnum) & 0xffffff00;
359 bits |= (r->r_pcrel & 1);
360 bits |= (r->r_length & 3) << 1;
361 bits |= (r->r_extern & 1) << 3;
362 bits |= (r->r_baserel & 1) << 4;
363 bits |= (r->r_jmptable & 1) << 5;
364 bits |= (r->r_relative & 1) << 6;
366 bits |= (r->r_copy & 1) << 7;
368 ((int *)r)[1] = bits;
373 md_swapout_jmpslot(j, n)
377 for (; n; n--, j++) {
378 j->opcode = md_swap_short(j->opcode);
379 j->addr[0] = md_swap_short(j->addr[0]);
380 j->addr[1] = md_swap_short(j->addr[1]);
381 j->reloc_index = md_swap_short(j->reloc_index);
385 #endif /* NEED_SWAP */