ef_amd64.c revision 134362
11541Srgrimes/*- 21541Srgrimes * Copyright (c) 2003 Jake Burkholder. 31541Srgrimes * Copyright 1996-1998 John D. Polstra. 41541Srgrimes * All rights reserved. 51541Srgrimes * 61541Srgrimes * Redistribution and use in source and binary forms, with or without 71541Srgrimes * modification, are permitted provided that the following conditions 81541Srgrimes * are met: 91541Srgrimes * 1. Redistributions of source code must retain the above copyright 101541Srgrimes * notice, this list of conditions and the following disclaimer. 111541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 121541Srgrimes * notice, this list of conditions and the following disclaimer in the 131541Srgrimes * documentation and/or other materials provided with the distribution. 141541Srgrimes * 151541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 161541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 171541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 181541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 191541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 201541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 211541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 221541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 231541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 241541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 251541Srgrimes * SUCH DAMAGE. 261541Srgrimes * 271541Srgrimes * $FreeBSD: head/usr.sbin/kldxref/ef_amd64.c 134362 2004-08-27 01:06:57Z iedowse $ 281541Srgrimes */ 291541Srgrimes 301541Srgrimes#include <sys/types.h> 311541Srgrimes#include <machine/elf.h> 321541Srgrimes 331541Srgrimes#include <err.h> 341541Srgrimes#include <errno.h> 351541Srgrimes#include <string.h> 361541Srgrimes 371541Srgrimes#include "ef.h" 381541Srgrimes 391541Srgrimes/* 401541Srgrimes * Apply relocations to the values we got from the file. 411541Srgrimes */ 421541Srgrimesint 431541Srgrimesef_reloc(struct elf_file *ef, const void *data, int type, Elf_Off offset, 441541Srgrimes size_t len, void *dest) 451541Srgrimes{ 461541Srgrimes Elf64_Addr *where, val; 471541Srgrimes Elf32_Addr *where32, val32; 481541Srgrimes Elf_Addr addend, addr; 491541Srgrimes Elf_Word rtype, symidx; 501541Srgrimes const Elf_Rel *rel; 511541Srgrimes const Elf_Rela *rela; 521541Srgrimes 531541Srgrimes switch (type) { 541541Srgrimes case EF_RELOC_REL: 551541Srgrimes rel = (const Elf_Rel *)data; 561541Srgrimes where = (Elf_Addr *)(dest + rel->r_offset - offset); 571541Srgrimes rtype = ELF_R_TYPE(rel->r_info); 581541Srgrimes symidx = ELF_R_SYM(rel->r_info); 591541Srgrimes break; 601541Srgrimes case EF_RELOC_RELA: 611541Srgrimes rela = (const Elf_Rela *)data; 621541Srgrimes where = (Elf_Addr *)(dest + rela->r_offset - offset); 631541Srgrimes addend = rela->r_addend; 641541Srgrimes rtype = ELF_R_TYPE(rela->r_info); 651541Srgrimes symidx = ELF_R_SYM(rela->r_info); 661541Srgrimes break; 671541Srgrimes default: 681541Srgrimes return (EINVAL); 691541Srgrimes } 701541Srgrimes 711541Srgrimes if ((char *)where < (char *)dest || (char *)where >= (char *)dest + len) 721541Srgrimes return (0); 731541Srgrimes 741541Srgrimes if (type == EF_RELOC_REL) { 751541Srgrimes /* Addend is 32 bit on 32 bit relocs */ 761541Srgrimes switch (rtype) { 771541Srgrimes case R_X86_64_PC32: 781541Srgrimes case R_X86_64_32S: 791541Srgrimes addend = *(Elf32_Addr *)where; 801541Srgrimes break; 811541Srgrimes default: 821541Srgrimes addend = *where; 831541Srgrimes break; 841541Srgrimes } 851541Srgrimes } 861541Srgrimes 871541Srgrimes switch (rtype) { 881541Srgrimes case R_X86_64_NONE: /* none */ 891541Srgrimes break; 901541Srgrimes case R_X86_64_64: /* S + A */ 911541Srgrimes addr = EF_SYMADDR(ef, symidx); 921541Srgrimes val = addr + addend; 931541Srgrimes *where = val; 941541Srgrimes break; 951541Srgrimes case R_X86_64_32S: /* S + A sign extend */ 961541Srgrimes addr = EF_SYMADDR(ef, symidx); 971541Srgrimes val32 = (Elf32_Addr)(addr + addend); 981541Srgrimes where32 = (Elf32_Addr *)where; 991541Srgrimes *where32 = val32; 1001541Srgrimes break; 1011541Srgrimes case R_X86_64_GLOB_DAT: /* S */ 1021541Srgrimes addr = EF_SYMADDR(ef, symidx); 1031541Srgrimes *where = addr; 1041541Srgrimes break; 1051541Srgrimes case R_X86_64_RELATIVE: /* B + A */ 1061541Srgrimes addr = (Elf_Addr)addend; 1071541Srgrimes val = addr; 1081541Srgrimes *where = val; 1091541Srgrimes break; 1101541Srgrimes default: 1111541Srgrimes warnx("unhandled relocation type %d", (int)rtype); 1121541Srgrimes } 1131541Srgrimes return (0); 1141541Srgrimes} 1151541Srgrimes