doreloc.c revision 6136c589445a3ea081bd34ab72db1060875b6bcc
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
#if defined(_KERNEL)
#include "reloc.h"
#else
#define ELF_TARGET_AMD64
#if defined(DO_RELOC_LIBLD)
#define DO_RELOC_LIBLD_X86
#endif
#include <stdio.h>
#include "sgs.h"
#include "machdep.h"
#include "libld.h"
#include "reloc.h"
#include "conv.h"
#include "msg.h"
#endif
/*
* We need to build this code differently when it is used for
* cross linking:
* - Data alignment requirements can differ from those
* of the running system, so we can't access data
* in units larger than a byte
* - We have to include code to do byte swapping when the
* target and linker host use different byte ordering,
* but such code is a waste when running natively.
*/
#define DORELOC_NATIVE
#endif
/*
* This table represents the current relocations that do_reloc() is able to
* process. The relocations below that are marked SPECIAL are relocations that
* take special processing and shouldn't actually ever be passed to do_reloc().
*/
/* R_AMD64_NONE */ {0, FLG_RE_NOTREL, 0, 0, 0},
/* R_AMD64_GOT32 */ {0, FLG_RE_NOTSUP, 0, 0, 0},
4, 0, 0},
4, 0, 0},
4, 0, 0},
4, 0, 0},
/* R_AMD64_GOT64 */ {0, FLG_RE_NOTSUP, 0, 0, 0},
/* R_AMD64_GOTPCREL64 */ {FLG_RE_NOTSUP, 0, 0, 0},
/* R_AMD64_GOTPC6 */ {0, FLG_RE_NOTSUP, 0, 0, 0},
/* R_AMD64_GOTPLT64 */ {0, FLG_RE_NOTSUP, 0, 0, 0},
/* R_AMD64_PLTOFF64 */ {0, FLG_RE_NOTSUP, 0, 0, 0},
};
#error "R_AMD64_NUM has grown"
#endif
/*
* Write a single relocated value to its reference location.
* We assume we wish to add the relocation amount, value, to the
* value of the address already present at the offset.
*
* NAME VALUE FIELD CALCULATION
*
* R_AMD64_NONE 0 none none
* R_AMD64_64 1 word64 S + A
* R_AMD64_PC32 2 word64 S + A
* R_AMD64_GOT32 3 word32 G + A
* R_AMD64_PLT32 4 word32 L + A - P
* R_AMD64_COPY 5 none none
* R_AMD64_GLOB_DAT 6 word64 S
* R_AMD64_JUMP_SLOT 7 word64 S
* R_AMD64_RELATIVE 8 word64 B + A
* R_AMD64_GOTPCREL 9 word32 G + GOT + A - P
* R_AMD64_32 10 word32 S + A
* R_AMD64_32S 11 word32 S + A
* R_AMD64_16 12 word16 S + A
* R_AMD64_PC16 13 word16 S + A - P
* R_AMD64_8 14 word8 S + A
* R_AMD64_PC8 15 word8 S + A - P
* R_AMD64_DTPMOD64 16 word64
* R_AMD64_DTPOFF64 17 word64
* R_AMD64_TPOFF64 18 word64
* R_AMD64_TLSGD 19 word32
* R_AMD64_TLSLD 20 word32
* R_AMD64_DTPOFF32 21 word32
* R_AMD64_GOTTPOFF 22 word32
* R_AMD64_TPOFF32 23 word32
* R_AMD64_PC64 24 word32 S + A - P
* R_AMD64_GOTOFF64 25 word32 S + A - GOT
* R_AMD64_GOTPC32 26 word32 GOT + A - P
* R_AMD64_GOT64 27 reserved for future expansion
* R_AMD64_GOTPCREL64 28 reserved for future expansion
* R_AMD64_GOTPC64 29 reserved for future expansion
* R_AMD64_GOTPLT64 30 reserved for future expansion
* R_AMD64_PLTOFF64 31 reserved for future expansion
* R_AMD64_SIZE32 32 word32 Z + A
* R_AMD64_SIZE64 33 word64 Z + A
*
* Relocation calculations:
* A Represents the addend used to compute the value of the
* relocatable field.
*
* B Represents the base address at which a shared objects has
* been loaded into memory during executaion. Generally, a
* shared objects is built with a 0 base virtual address,
* but the execution address will be different.
*
* G Represents the offset into the global offset table
* at which the relocation entry's symbol will reside
* during execution.
*
* GOT Rrepresents the address of the global offset table.
*
* L Represents the place (section offset or address) of
* the Procedure Linkage Table entry for a symbol.
*
* P Represents the place (section offset or address) of the
* storage unit being relocated (computed using r_offset).
*
* S Represents the value of the symbol whose index resides
* in the relocation entry.
*
* Z the size of the symbol whose index resides in the relocation
* entry
*/
/*
* Bits that must be cleared or identical for a value to act as if extended in
* the given way.
*/
#define ZEROEXBITS 0xffffffff00000000ULL
#define SIGNEXBITS 0xffffffff80000000ULL
#if defined(_KERNEL)
#define lml 0 /* Needed by arglist of REL_ERR_* macros */
int
const char *file)
#elif defined(DO_RELOC_LIBLD)
/*ARGSUSED5*/
int
#else
int
#endif
{
#ifdef DO_RELOC_LIBLD
#endif
case 1:
/* LINTED */
break;
case 2:
#if defined(DORELOC_NATIVE)
/* LINTED */
#else
{
if (bswap) {
} else {
}
}
#endif
break;
case 4:
/*
* The amd64 psABI requires that we perform the following
* verifications:
*
* The R_AMD64_32 and R_AMD64_32S relocations truncate the
* computed value to 32bits. Verify that the generated value
* for the R_AMD64_32/32S relocation zero-extends (sign
* extends) to the original 64-bit value.
*
* Also, the following relocations are all 32 bit PC relative
* references. Validate that the value being written will fit
* in the field provided.
*
* R_AMD64_PC32, R_AMD64_GOTPC32, R_AMD64_GOTPCREL
*/
if (rtype == R_AMD64_32) {
/*
* Verify that this value will act as a zero-extended
* unsigned 32 bit value. That is, that the upper
* 32 bits are zero.
*/
if ((*value & ZEROEXBITS) != 0) {
/*
* To keep chkmsg() happy:
* MSG_INTL(MSG_REL_NOFIT)
*/
return (0);
}
/*
* Verify that this value will act as a sign-extended
* signed 32 bit value, that is that the upper 33 bits
* are either all zero or all one.
*/
((*value & SIGNEXBITS) != 0)) {
/*
* To keep chkmsg() happy:
* MSG_INTL(MSG_REL_NOFIT)
*/
return (0);
}
}
#if defined(DORELOC_NATIVE)
/* LINTED */
#else
{
Word v;
if (bswap) {
v += *value;
} else {
v += *value;
}
}
#endif
break;
case 8:
#if defined(DORELOC_NATIVE)
/* LINTED */
#else
{
Xword v;
if (bswap) {
v += *value;
} else {
v += *value;
}
}
#endif
break;
default:
/*
* To keep chkmsg() happy: MSG_INTL(MSG_REL_UNSUPSZ)
*/
return (0);
}
return (1);
#ifdef DO_RELOC_LIBLD
#endif
}