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, 4714560a36SLuigi Rizzo Elf_Off dataoff, size_t len, void *_dest) 4823d0f849SIan Dowse { 4923d0f849SIan Dowse Elf_Addr *where, addr, addend; 50757686b1SMarcel Moolenaar Elf_Size rtype, symidx; 5123d0f849SIan Dowse const Elf_Rel *rel; 5223d0f849SIan Dowse const Elf_Rela *rela; 5314560a36SLuigi Rizzo char *dest = _dest; 5423d0f849SIan Dowse 559dba198bSIan Dowse switch (reltype) { 5623d0f849SIan Dowse case EF_RELOC_REL: 579dba198bSIan Dowse rel = (const Elf_Rel *)reldata; 589dba198bSIan Dowse where = (Elf_Addr *)(dest + relbase + rel->r_offset - dataoff); 599dba198bSIan Dowse addend = 0; 6023d0f849SIan Dowse rtype = ELF_R_TYPE(rel->r_info); 6123d0f849SIan Dowse symidx = ELF_R_SYM(rel->r_info); 6223d0f849SIan Dowse break; 6323d0f849SIan Dowse case EF_RELOC_RELA: 649dba198bSIan Dowse rela = (const Elf_Rela *)reldata; 659dba198bSIan Dowse where = (Elf_Addr *)(dest + relbase + rela->r_offset - dataoff); 6623d0f849SIan Dowse addend = rela->r_addend; 6723d0f849SIan Dowse rtype = ELF_R_TYPE(rela->r_info); 6823d0f849SIan Dowse symidx = ELF_R_SYM(rela->r_info); 6923d0f849SIan Dowse break; 7023d0f849SIan Dowse default: 7123d0f849SIan Dowse return (EINVAL); 7223d0f849SIan Dowse } 7323d0f849SIan Dowse 7423d0f849SIan Dowse if ((char *)where < (char *)dest || (char *)where >= (char *)dest + len) 7523d0f849SIan Dowse return (0); 7623d0f849SIan Dowse 779dba198bSIan Dowse if (reltype == EF_RELOC_REL) 7823d0f849SIan Dowse addend = *where; 7923d0f849SIan Dowse 8023d0f849SIan Dowse switch (rtype) { 8123d0f849SIan Dowse case R_386_RELATIVE: /* A + B */ 829dba198bSIan Dowse addr = (Elf_Addr)addend + relbase; 8323d0f849SIan Dowse *where = addr; 8423d0f849SIan Dowse break; 8523d0f849SIan Dowse case R_386_32: /* S + A - P */ 8623d0f849SIan Dowse addr = EF_SYMADDR(ef, symidx); 8723d0f849SIan Dowse addr += addend; 8823d0f849SIan Dowse *where = addr; 8923d0f849SIan Dowse break; 9023d0f849SIan Dowse case R_386_GLOB_DAT: /* S */ 9123d0f849SIan Dowse addr = EF_SYMADDR(ef, symidx); 9223d0f849SIan Dowse *where = addr; 9323d0f849SIan Dowse break; 9423d0f849SIan Dowse default: 9523d0f849SIan Dowse warnx("unhandled relocation type %d", (int)rtype); 9623d0f849SIan Dowse } 9723d0f849SIan Dowse return (0); 9823d0f849SIan Dowse } 99