ef_amd64.c revision 251439
1199482Srdivacky/*- 2199482Srdivacky * Copyright (c) 2003 Jake Burkholder. 3199482Srdivacky * Copyright 1996-1998 John D. Polstra. 4199482Srdivacky * All rights reserved. 5199482Srdivacky * 6199482Srdivacky * Redistribution and use in source and binary forms, with or without 7199482Srdivacky * modification, are permitted provided that the following conditions 8199482Srdivacky * are met: 9199482Srdivacky * 1. Redistributions of source code must retain the above copyright 10199482Srdivacky * notice, this list of conditions and the following disclaimer. 11199482Srdivacky * 2. Redistributions in binary form must reproduce the above copyright 12199482Srdivacky * notice, this list of conditions and the following disclaimer in the 13199482Srdivacky * documentation and/or other materials provided with the distribution. 14245431Sdim * 15199482Srdivacky * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16199482Srdivacky * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17199482Srdivacky * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18199482Srdivacky * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19245431Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20245431Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21245431Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22245431Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23199482Srdivacky * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24199482Srdivacky * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25199482Srdivacky * SUCH DAMAGE. 26199482Srdivacky * 27245431Sdim * $FreeBSD: head/usr.sbin/kldxref/ef_amd64.c 251439 2013-06-05 21:55:20Z delphij $ 28199482Srdivacky */ 29199482Srdivacky 30199482Srdivacky#include <sys/types.h> 31199482Srdivacky#include <machine/elf.h> 32199482Srdivacky 33199482Srdivacky#include <err.h> 34199482Srdivacky#include <errno.h> 35199482Srdivacky 36199482Srdivacky#include "ef.h" 37208600Srdivacky 38208600Srdivacky/* 39203955Srdivacky * Apply relocations to the values we got from the file. `relbase' is the 40199482Srdivacky * target relocation address of the section, and `dataoff' is the target 41226890Sdim * relocation address of the data in `dest'. 42199482Srdivacky */ 43199482Srdivackyint 44205408Srdivackyef_reloc(struct elf_file *ef, const void *reldata, int reltype, Elf_Off relbase, 45252723Sdim Elf_Off dataoff, size_t len, void *dest) 46199482Srdivacky{ 47199482Srdivacky Elf64_Addr *where, val; 48199482Srdivacky Elf32_Addr *where32, val32; 49212904Sdim Elf_Addr addend, addr; 50199482Srdivacky Elf_Size rtype, symidx; 51245431Sdim const Elf_Rel *rel; 52199482Srdivacky const Elf_Rela *rela; 53199482Srdivacky 54199482Srdivacky switch (reltype) { 55235633Sdim case EF_RELOC_REL: 56199482Srdivacky rel = (const Elf_Rel *)reldata; 57199482Srdivacky where = (Elf_Addr *)(dest + relbase + rel->r_offset - dataoff); 58199482Srdivacky addend = 0; 59199482Srdivacky rtype = ELF_R_TYPE(rel->r_info); 60235633Sdim symidx = ELF_R_SYM(rel->r_info); 61235633Sdim break; 62235633Sdim case EF_RELOC_RELA: 63235633Sdim rela = (const Elf_Rela *)reldata; 64235633Sdim where = (Elf_Addr *)(dest + relbase + rela->r_offset - dataoff); 65235633Sdim addend = rela->r_addend; 66235633Sdim rtype = ELF_R_TYPE(rela->r_info); 67235633Sdim symidx = ELF_R_SYM(rela->r_info); 68235633Sdim break; 69235633Sdim default: 70235633Sdim return (EINVAL); 71235633Sdim } 72235633Sdim 73235633Sdim if ((char *)where < (char *)dest || (char *)where >= (char *)dest + len) 74235633Sdim return (0); 75235633Sdim 76235633Sdim if (reltype == EF_RELOC_REL) { 77235633Sdim /* Addend is 32 bit on 32 bit relocs */ 78235633Sdim switch (rtype) { 79245431Sdim case R_X86_64_PC32: 80235633Sdim case R_X86_64_32S: 81235633Sdim addend = *(Elf32_Addr *)where; 82235633Sdim break; 83245431Sdim default: 84245431Sdim addend = *where; 85235633Sdim break; 86235633Sdim } 87235633Sdim } 88235633Sdim 89235633Sdim switch (rtype) { 90245431Sdim case R_X86_64_NONE: /* none */ 91245431Sdim break; 92245431Sdim case R_X86_64_64: /* S + A */ 93235633Sdim addr = EF_SYMADDR(ef, symidx); 94245431Sdim val = addr + addend; 95245431Sdim *where = val; 96245431Sdim break; 97245431Sdim case R_X86_64_32S: /* S + A sign extend */ 98245431Sdim addr = EF_SYMADDR(ef, symidx); 99245431Sdim val32 = (Elf32_Addr)(addr + addend); 100245431Sdim where32 = (Elf32_Addr *)where; 101245431Sdim *where32 = val32; 102245431Sdim break; 103245431Sdim case R_X86_64_GLOB_DAT: /* S */ 104245431Sdim addr = EF_SYMADDR(ef, symidx); 105245431Sdim *where = addr; 106245431Sdim break; 107245431Sdim case R_X86_64_RELATIVE: /* B + A */ 108245431Sdim addr = (Elf_Addr)addend + relbase; 109245431Sdim val = addr; 110245431Sdim *where = val; 111245431Sdim break; 112245431Sdim default: 113245431Sdim warnx("unhandled relocation type %d", (int)rtype); 114235633Sdim } 115245431Sdim return (0); 116199482Srdivacky} 117199482Srdivacky