10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 70Sstevel@tonic-gate * with the License. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 110Sstevel@tonic-gate * See the License for the specific language governing permissions 120Sstevel@tonic-gate * and limitations under the License. 130Sstevel@tonic-gate * 140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 190Sstevel@tonic-gate * 200Sstevel@tonic-gate * CDDL HEADER END 210Sstevel@tonic-gate */ 220Sstevel@tonic-gate /* 230Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 280Sstevel@tonic-gate 290Sstevel@tonic-gate #if defined(_KERNEL) 300Sstevel@tonic-gate #include <sys/types.h> 310Sstevel@tonic-gate #include "reloc.h" 320Sstevel@tonic-gate #else 330Sstevel@tonic-gate #include <stdio.h> 340Sstevel@tonic-gate #include "sgs.h" 350Sstevel@tonic-gate #include "machdep.h" 360Sstevel@tonic-gate #include "libld.h" 370Sstevel@tonic-gate #include "reloc.h" 380Sstevel@tonic-gate #include "conv.h" 390Sstevel@tonic-gate #include "msg.h" 400Sstevel@tonic-gate #endif 410Sstevel@tonic-gate 420Sstevel@tonic-gate /* 430Sstevel@tonic-gate * This table represents the current relocations that do_reloc() 440Sstevel@tonic-gate * is able to process. The relocations below that are marked 450Sstevel@tonic-gate * 'SPECIAL' in the comments are relocations that take special 460Sstevel@tonic-gate * processing and shouldn't actually ever be passed to do_reloc(). 470Sstevel@tonic-gate */ 480Sstevel@tonic-gate const Rel_entry reloc_table[R_AMD64_NUM] = { 490Sstevel@tonic-gate /* R_AMD64_NONE */ {0, 0}, 500Sstevel@tonic-gate /* R_AMD64_64 */ {FLG_RE_NOTREL, 8}, 510Sstevel@tonic-gate /* R_AMD64_PC32 */ {FLG_RE_PCREL, 4}, 520Sstevel@tonic-gate /* R_AMD64_GOT32 */ {FLG_RE_NOTSUP, 0}, 530Sstevel@tonic-gate /* R_AMD64_PLT32 */ {FLG_RE_PCREL | FLG_RE_PLTREL | 540Sstevel@tonic-gate FLG_RE_VERIFY | FLG_RE_SIGN, 4}, 550Sstevel@tonic-gate /* R_AMD64_COPY */ {FLG_RE_NOTSUP, 0}, 560Sstevel@tonic-gate /* R_AMD64_GLOB_DAT */ {FLG_RE_NOTREL, 8}, 570Sstevel@tonic-gate /* R_AMD64_JUMP_SLOT */ {FLG_RE_NOTSUP, 0}, 580Sstevel@tonic-gate /* R_AMD64_RELATIVE */ {FLG_RE_NOTREL, 8}, 590Sstevel@tonic-gate /* R_AMD64_GOTPCREL */ {FLG_RE_GOTPC | FLG_RE_GOTADD, 4}, 600Sstevel@tonic-gate /* R_AMD64_32 */ {FLG_RE_NOTREL, 4}, 610Sstevel@tonic-gate /* R_AMD64_32S */ {FLG_RE_NOTREL, 4}, 620Sstevel@tonic-gate /* R_AMD64_16 */ {FLG_RE_NOTSUP, 0}, 630Sstevel@tonic-gate /* R_AMD64_PC16 */ {FLG_RE_NOTSUP, 0}, 640Sstevel@tonic-gate /* R_AMD64_8 */ {FLG_RE_NOTSUP, 0}, 650Sstevel@tonic-gate /* R_AMD64_PC8 */ {FLG_RE_NOTSUP, 0}, 660Sstevel@tonic-gate /* R_AMD64_DTPMOD64 */ {FLG_RE_NOTREL, 8}, 670Sstevel@tonic-gate /* R_AMD64_DTPOFF64 */ {FLG_RE_NOTREL, 8}, 680Sstevel@tonic-gate /* R_AMD64_TPOFF64 */ {FLG_RE_NOTREL, 8}, 690Sstevel@tonic-gate /* R_AMD64_TLSGD */ {FLG_RE_GOTPC | FLG_RE_GOTADD | 700Sstevel@tonic-gate FLG_RE_TLSINS | FLG_RE_TLSGD, 4}, 710Sstevel@tonic-gate /* R_AMD64_TLSLD */ {FLG_RE_GOTPC | FLG_RE_GOTADD | 720Sstevel@tonic-gate FLG_RE_TLSINS | FLG_RE_TLSLD, 4}, 730Sstevel@tonic-gate /* R_AMD64_DTPOFF32 */ {FLG_RE_TLSINS | FLG_RE_NOTREL | FLG_RE_TLSLD, 4}, 740Sstevel@tonic-gate /* R_AMD64_GOTTPOFF */ {FLG_RE_GOTPC | FLG_RE_GOTADD | 750Sstevel@tonic-gate FLG_RE_TLSINS | FLG_RE_TLSIE, 4}, 760Sstevel@tonic-gate /* R_AMD64_TPOFF32 */ {FLG_RE_TLSINS | FLG_RE_NOTREL | FLG_RE_TLSLE, 4}, 770Sstevel@tonic-gate /* R_AMD64_PC64 */ {FLG_RE_PCREL, 8}, 780Sstevel@tonic-gate /* R_AMD64_GOTOFF64 */ {FLG_RE_GOTREL, 8}, 790Sstevel@tonic-gate /* R_AMD64_GOTPC32 */ {FLG_RE_PCREL | FLG_RE_GOTPC | FLG_RE_LOCLBND, 4} 800Sstevel@tonic-gate }; 810Sstevel@tonic-gate #if (R_AMD64_NUM != (R_AMD64_GOTPC32 + 1)) 820Sstevel@tonic-gate #error "R_AMD64_NUM has grown" 830Sstevel@tonic-gate #endif 840Sstevel@tonic-gate 850Sstevel@tonic-gate /* 860Sstevel@tonic-gate * Write a single relocated value to its reference location. 870Sstevel@tonic-gate * We assume we wish to add the relocatoin amount, value, to the 880Sstevel@tonic-gate * value of the address already present at the offset. 890Sstevel@tonic-gate * 900Sstevel@tonic-gate * NAME VALUE FIELD CALCULATION 910Sstevel@tonic-gate * 920Sstevel@tonic-gate * R_AMD64_NONE 0 none none 930Sstevel@tonic-gate * R_AMD64_64 1 word64 S + A 940Sstevel@tonic-gate * R_AMD64_PC32 2 word64 S + A 950Sstevel@tonic-gate * R_AMD64_GOT32 3 word32 G + A 960Sstevel@tonic-gate * R_AMD64_PLT32 4 word32 L + A - P 970Sstevel@tonic-gate * R_AMD64_COPY 5 none none 980Sstevel@tonic-gate * R_AMD64_GLOB_DAT 6 word64 S 990Sstevel@tonic-gate * R_AMD64_JUMP_SLOT 7 word64 S 1000Sstevel@tonic-gate * R_AMD64_RELATIVE 8 word64 B + A 1010Sstevel@tonic-gate * R_AMD64_GOTPCREL 9 word32 G + GOT + A - P 1020Sstevel@tonic-gate * R_AMD64_32 10 word32 S + A 1030Sstevel@tonic-gate * R_AMD64_32S 11 word32 S + A 1040Sstevel@tonic-gate * R_AMD64_16 12 word16 S + A 1050Sstevel@tonic-gate * R_AMD64_PC16 13 word16 S + A - P 1060Sstevel@tonic-gate * R_AMD64_8 14 word8 S + A 1070Sstevel@tonic-gate * R_AMD64_PC8 15 word8 S + A - P 1080Sstevel@tonic-gate * R_AMD64_DTPMOD64 16 word64 1090Sstevel@tonic-gate * R_AMD64_DTPOFF64 17 word64 1100Sstevel@tonic-gate * R_AMD64_TPOFF64 18 word64 1110Sstevel@tonic-gate * R_AMD64_TLSGD 19 word32 1120Sstevel@tonic-gate * R_AMD64_TLSLD 20 word32 1130Sstevel@tonic-gate * R_AMD64_DTPOFF32 21 word32 1140Sstevel@tonic-gate * R_AMD64_GOTTPOFF 22 word32 1150Sstevel@tonic-gate * R_AMD64_TPOFF32 23 word32 1160Sstevel@tonic-gate * R_AMD64_PC64 24 word32 S + A - P 1170Sstevel@tonic-gate * R_AMD64_GOTOFF64 25 word32 S + A - GOT 1180Sstevel@tonic-gate * R_AMD64_GOTPC32 26 word32 GOT + A - P 1190Sstevel@tonic-gate * 1200Sstevel@tonic-gate * Relocation calculations: 1210Sstevel@tonic-gate * A Represents the addend used to compute the value of the 1220Sstevel@tonic-gate * relocatable field. 1230Sstevel@tonic-gate * 1240Sstevel@tonic-gate * B Represents the base address at which a shared objects has 1250Sstevel@tonic-gate * been loaded into memory during executaion. Generally, a 1260Sstevel@tonic-gate * shared objects is built with a 0 base virtual address, 1270Sstevel@tonic-gate * but the execution address will be different. 1280Sstevel@tonic-gate * 1290Sstevel@tonic-gate * G Represents the offset into the global offset table 1300Sstevel@tonic-gate * at which the relocation entry's symbol will reside 1310Sstevel@tonic-gate * during execution. 1320Sstevel@tonic-gate * 1330Sstevel@tonic-gate * GOT Rrepresents the address of the global offset table. 1340Sstevel@tonic-gate * 1350Sstevel@tonic-gate * L Represents the place (section offset or address) of 1360Sstevel@tonic-gate * the Procedure Linkage Table entry for a symbol. 1370Sstevel@tonic-gate * 1380Sstevel@tonic-gate * P Represents the place (section offset or address) of the 1390Sstevel@tonic-gate * storage unit being relocated (computed using r_offset). 1400Sstevel@tonic-gate * 1410Sstevel@tonic-gate * S Represents the value of the symbol whose index resides 1420Sstevel@tonic-gate * in the relocation entry. 1430Sstevel@tonic-gate * 1440Sstevel@tonic-gate */ 1450Sstevel@tonic-gate 146*238Sseizo #define HIBITS 0xffffffff80000000ULL 1470Sstevel@tonic-gate 1480Sstevel@tonic-gate int 1490Sstevel@tonic-gate do_reloc(unsigned char rtype, unsigned char *off, Xword *value, 1500Sstevel@tonic-gate const char *sym, const char *file) 1510Sstevel@tonic-gate { 1520Sstevel@tonic-gate const Rel_entry *rep; 1530Sstevel@tonic-gate 1540Sstevel@tonic-gate rep = &reloc_table[rtype]; 1550Sstevel@tonic-gate 1560Sstevel@tonic-gate if (rep->re_fsize == 4) { 1570Sstevel@tonic-gate /* 1580Sstevel@tonic-gate * The amd64 psABI requires that we perform 1590Sstevel@tonic-gate * the following verifications: 1600Sstevel@tonic-gate * 1610Sstevel@tonic-gate * The R_AMD64_32 and R_AMD64_32S relocations 1620Sstevel@tonic-gate * truncate the computed value to 32bits. The linker 1630Sstevel@tonic-gate * must verify that the generated value for the 1640Sstevel@tonic-gate * R_AMD64_32(R_AMD64_32S) relocation zero-extends 1650Sstevel@tonic-gate * (sign extends) to the original 64-bit value. 1660Sstevel@tonic-gate * 1670Sstevel@tonic-gate * Also - the following relocations are all 32 bit PC relative 1680Sstevel@tonic-gate * references, so we must validate that the value being 1690Sstevel@tonic-gate * written will fit in the field provided. 1700Sstevel@tonic-gate * 1710Sstevel@tonic-gate * R_AMD64_PC32, R_AMD64_GOTPC32, R_AMD64_GOTPCREL 1720Sstevel@tonic-gate */ 1730Sstevel@tonic-gate if (rtype == R_AMD64_32) { 1740Sstevel@tonic-gate /* 1750Sstevel@tonic-gate * We must verify that this value will 'zero-extend', 1760Sstevel@tonic-gate * this requires that the upper 33bits all be 1770Sstevel@tonic-gate * 'zero'. 1780Sstevel@tonic-gate */ 1790Sstevel@tonic-gate if ((*value & HIBITS) != 0) { 1800Sstevel@tonic-gate /* 1810Sstevel@tonic-gate * to keep chkmsg() happy: 1820Sstevel@tonic-gate * MSG_INTL(MSG_REL_NOFIT) 1830Sstevel@tonic-gate */ 1840Sstevel@tonic-gate REL_ERR_NOFIT(file, sym, rtype, *value); 1850Sstevel@tonic-gate return (0); 1860Sstevel@tonic-gate } 1870Sstevel@tonic-gate } else if ((rtype == R_AMD64_32S) || 1880Sstevel@tonic-gate (rtype == R_AMD64_PC32) || 1890Sstevel@tonic-gate (rtype == R_AMD64_GOTPCREL) || 1900Sstevel@tonic-gate (rtype == R_AMD64_GOTPC32)) { 1910Sstevel@tonic-gate /* 1920Sstevel@tonic-gate * We must verify that this value will properly 1930Sstevel@tonic-gate * sign extend. This is true of the upper 1940Sstevel@tonic-gate * 33bits are all either 'zero' or 1950Sstevel@tonic-gate * all 'one'. 1960Sstevel@tonic-gate */ 1970Sstevel@tonic-gate if (((*value & HIBITS) != HIBITS) && 1980Sstevel@tonic-gate ((*value & HIBITS) != 0)) { 1990Sstevel@tonic-gate /* 2000Sstevel@tonic-gate * to keep chkmsg() happy: 2010Sstevel@tonic-gate * MSG_INTL(MSG_REL_NOFIT) 2020Sstevel@tonic-gate */ 2030Sstevel@tonic-gate REL_ERR_NOFIT(file, sym, rtype, *value); 2040Sstevel@tonic-gate return (0); 2050Sstevel@tonic-gate } 2060Sstevel@tonic-gate } 2070Sstevel@tonic-gate /* LINTED */ 2080Sstevel@tonic-gate *((Word *)off) += *value; 2090Sstevel@tonic-gate } else if (rep->re_fsize == 8) { 2100Sstevel@tonic-gate *((Xword *)off) += *value; 2110Sstevel@tonic-gate } else { 2120Sstevel@tonic-gate eprintf(ERR_FATAL, MSG_INTL(MSG_REL_UNSUPSZ), 2130Sstevel@tonic-gate conv_reloc_amd64_type_str(rtype), file, 2140Sstevel@tonic-gate (sym ? sym : MSG_INTL(MSG_STR_UNKNOWN)), 2150Sstevel@tonic-gate EC_WORD(rep->re_fsize)); 2160Sstevel@tonic-gate return (0); 2170Sstevel@tonic-gate } 2180Sstevel@tonic-gate return (1); 2190Sstevel@tonic-gate } 220