123d0f849SIan Dowse /*- 21de7b4b8SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 31de7b4b8SPedro F. Giffuni * 423d0f849SIan Dowse * Copyright (c) 2003 Jake Burkholder. 523d0f849SIan Dowse * Copyright 1996-1998 John D. Polstra. 623d0f849SIan Dowse * All rights reserved. 723d0f849SIan Dowse * 823d0f849SIan Dowse * Redistribution and use in source and binary forms, with or without 923d0f849SIan Dowse * modification, are permitted provided that the following conditions 1023d0f849SIan Dowse * are met: 1123d0f849SIan Dowse * 1. Redistributions of source code must retain the above copyright 1223d0f849SIan Dowse * notice, this list of conditions and the following disclaimer. 1323d0f849SIan Dowse * 2. Redistributions in binary form must reproduce the above copyright 1423d0f849SIan Dowse * notice, this list of conditions and the following disclaimer in the 1523d0f849SIan Dowse * documentation and/or other materials provided with the distribution. 1623d0f849SIan Dowse * 1723d0f849SIan Dowse * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1823d0f849SIan Dowse * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1923d0f849SIan Dowse * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2023d0f849SIan Dowse * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2123d0f849SIan Dowse * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2223d0f849SIan Dowse * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2323d0f849SIan Dowse * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2423d0f849SIan Dowse * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2523d0f849SIan Dowse * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2623d0f849SIan Dowse * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2723d0f849SIan Dowse * SUCH DAMAGE. 2823d0f849SIan Dowse * 2923d0f849SIan Dowse * $FreeBSD$ 3023d0f849SIan Dowse */ 3123d0f849SIan Dowse 3223d0f849SIan Dowse #include <sys/types.h> 3323d0f849SIan Dowse #include <machine/elf.h> 3423d0f849SIan Dowse 3523d0f849SIan Dowse #include <err.h> 3623d0f849SIan Dowse #include <errno.h> 3723d0f849SIan Dowse 3823d0f849SIan Dowse #include "ef.h" 3923d0f849SIan Dowse 4023d0f849SIan Dowse /* 419dba198bSIan Dowse * Apply relocations to the values we got from the file. `relbase' is the 429dba198bSIan Dowse * target relocation address of the section, and `dataoff' is the target 439dba198bSIan Dowse * relocation address of the data in `dest'. 4423d0f849SIan Dowse */ 4523d0f849SIan Dowse int 469dba198bSIan Dowse ef_reloc(struct elf_file *ef, const void *reldata, int reltype, Elf_Off relbase, 479dba198bSIan Dowse Elf_Off dataoff, size_t len, void *dest) 4823d0f849SIan Dowse { 4923d0f849SIan Dowse Elf64_Addr *where, val; 5023d0f849SIan Dowse Elf32_Addr *where32, val32; 5123d0f849SIan Dowse Elf_Addr addend, addr; 52757686b1SMarcel Moolenaar Elf_Size rtype, symidx; 5323d0f849SIan Dowse const Elf_Rel *rel; 5423d0f849SIan Dowse const Elf_Rela *rela; 5523d0f849SIan Dowse 569dba198bSIan Dowse switch (reltype) { 5723d0f849SIan Dowse case EF_RELOC_REL: 589dba198bSIan Dowse rel = (const Elf_Rel *)reldata; 599dba198bSIan Dowse where = (Elf_Addr *)(dest + relbase + rel->r_offset - dataoff); 609dba198bSIan Dowse addend = 0; 6123d0f849SIan Dowse rtype = ELF_R_TYPE(rel->r_info); 6223d0f849SIan Dowse symidx = ELF_R_SYM(rel->r_info); 6323d0f849SIan Dowse break; 6423d0f849SIan Dowse case EF_RELOC_RELA: 659dba198bSIan Dowse rela = (const Elf_Rela *)reldata; 669dba198bSIan Dowse where = (Elf_Addr *)(dest + relbase + rela->r_offset - dataoff); 6723d0f849SIan Dowse addend = rela->r_addend; 6823d0f849SIan Dowse rtype = ELF_R_TYPE(rela->r_info); 6923d0f849SIan Dowse symidx = ELF_R_SYM(rela->r_info); 7023d0f849SIan Dowse break; 7123d0f849SIan Dowse default: 7223d0f849SIan Dowse return (EINVAL); 7323d0f849SIan Dowse } 7423d0f849SIan Dowse 7523d0f849SIan Dowse if ((char *)where < (char *)dest || (char *)where >= (char *)dest + len) 7623d0f849SIan Dowse return (0); 7723d0f849SIan Dowse 789dba198bSIan Dowse if (reltype == EF_RELOC_REL) { 7923d0f849SIan Dowse /* Addend is 32 bit on 32 bit relocs */ 8023d0f849SIan Dowse switch (rtype) { 8123d0f849SIan Dowse case R_X86_64_PC32: 8223d0f849SIan Dowse case R_X86_64_32S: 8323d0f849SIan Dowse addend = *(Elf32_Addr *)where; 8423d0f849SIan Dowse break; 8523d0f849SIan Dowse default: 8623d0f849SIan Dowse addend = *where; 8723d0f849SIan Dowse break; 8823d0f849SIan Dowse } 8923d0f849SIan Dowse } 9023d0f849SIan Dowse 9123d0f849SIan Dowse switch (rtype) { 9223d0f849SIan Dowse case R_X86_64_NONE: /* none */ 9323d0f849SIan Dowse break; 9423d0f849SIan Dowse case R_X86_64_64: /* S + A */ 9523d0f849SIan Dowse addr = EF_SYMADDR(ef, symidx); 9623d0f849SIan Dowse val = addr + addend; 9723d0f849SIan Dowse *where = val; 9823d0f849SIan Dowse break; 9923d0f849SIan Dowse case R_X86_64_32S: /* S + A sign extend */ 10023d0f849SIan Dowse addr = EF_SYMADDR(ef, symidx); 10123d0f849SIan Dowse val32 = (Elf32_Addr)(addr + addend); 10223d0f849SIan Dowse where32 = (Elf32_Addr *)where; 10323d0f849SIan Dowse *where32 = val32; 10423d0f849SIan Dowse break; 10523d0f849SIan Dowse case R_X86_64_GLOB_DAT: /* S */ 10623d0f849SIan Dowse addr = EF_SYMADDR(ef, symidx); 10723d0f849SIan Dowse *where = addr; 10823d0f849SIan Dowse break; 10923d0f849SIan Dowse case R_X86_64_RELATIVE: /* B + A */ 1109dba198bSIan Dowse addr = (Elf_Addr)addend + relbase; 11123d0f849SIan Dowse val = addr; 11223d0f849SIan Dowse *where = val; 11323d0f849SIan Dowse break; 11423d0f849SIan Dowse default: 11523d0f849SIan Dowse warnx("unhandled relocation type %d", (int)rtype); 11623d0f849SIan Dowse } 11723d0f849SIan Dowse return (0); 11823d0f849SIan Dowse } 119