123d0f849SIan Dowse /*- 24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 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 300299afdfSJohn Baldwin #include <sys/endian.h> 3123d0f849SIan Dowse 3223d0f849SIan Dowse #include <err.h> 3323d0f849SIan Dowse #include <errno.h> 340299afdfSJohn Baldwin #include <gelf.h> 3523d0f849SIan Dowse 3623d0f849SIan Dowse #include "ef.h" 3723d0f849SIan Dowse 3823d0f849SIan Dowse /* 399dba198bSIan Dowse * Apply relocations to the values we got from the file. `relbase' is the 409dba198bSIan Dowse * target relocation address of the section, and `dataoff' is the target 419dba198bSIan Dowse * relocation address of the data in `dest'. 4223d0f849SIan Dowse */ 430299afdfSJohn Baldwin static int 440299afdfSJohn Baldwin ef_i386_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype, 450299afdfSJohn Baldwin GElf_Addr relbase, GElf_Addr dataoff, size_t len, void *dest) 4623d0f849SIan Dowse { 470299afdfSJohn Baldwin char *where; 480299afdfSJohn Baldwin GElf_Addr addr, addend; 490299afdfSJohn Baldwin GElf_Size rtype, symidx; 500299afdfSJohn Baldwin const GElf_Rel *rel; 510299afdfSJohn Baldwin const GElf_Rela *rela; 5223d0f849SIan Dowse 539dba198bSIan Dowse switch (reltype) { 540299afdfSJohn Baldwin case ELF_T_REL: 550299afdfSJohn Baldwin rel = (const GElf_Rel *)reldata; 560299afdfSJohn Baldwin where = (char *)dest + relbase + rel->r_offset - dataoff; 579dba198bSIan Dowse addend = 0; 580299afdfSJohn Baldwin rtype = GELF_R_TYPE(rel->r_info); 590299afdfSJohn Baldwin symidx = GELF_R_SYM(rel->r_info); 6023d0f849SIan Dowse break; 610299afdfSJohn Baldwin case ELF_T_RELA: 620299afdfSJohn Baldwin rela = (const GElf_Rela *)reldata; 630299afdfSJohn Baldwin where = (char *)dest + relbase + rela->r_offset - dataoff; 6423d0f849SIan Dowse addend = rela->r_addend; 650299afdfSJohn Baldwin rtype = GELF_R_TYPE(rela->r_info); 660299afdfSJohn Baldwin symidx = GELF_R_SYM(rela->r_info); 6723d0f849SIan Dowse break; 6823d0f849SIan Dowse default: 6923d0f849SIan Dowse return (EINVAL); 7023d0f849SIan Dowse } 7123d0f849SIan Dowse 720299afdfSJohn Baldwin if (where < (char *)dest || where >= (char *)dest + len) 7323d0f849SIan Dowse return (0); 7423d0f849SIan Dowse 750299afdfSJohn Baldwin if (reltype == ELF_T_REL) 760299afdfSJohn Baldwin addend = le32dec(where); 7723d0f849SIan Dowse 7823d0f849SIan Dowse switch (rtype) { 7923d0f849SIan Dowse case R_386_RELATIVE: /* A + B */ 800299afdfSJohn Baldwin addr = addend + relbase; 810299afdfSJohn Baldwin le32enc(where, addr); 8223d0f849SIan Dowse break; 8323d0f849SIan Dowse case R_386_32: /* S + A - P */ 8423d0f849SIan Dowse addr = EF_SYMADDR(ef, symidx); 8523d0f849SIan Dowse addr += addend; 860299afdfSJohn Baldwin le32enc(where, addr); 8723d0f849SIan Dowse break; 8823d0f849SIan Dowse case R_386_GLOB_DAT: /* S */ 8923d0f849SIan Dowse addr = EF_SYMADDR(ef, symidx); 900299afdfSJohn Baldwin le32enc(where, addr); 9123d0f849SIan Dowse break; 9223d0f849SIan Dowse default: 9323d0f849SIan Dowse warnx("unhandled relocation type %d", (int)rtype); 9423d0f849SIan Dowse } 9523d0f849SIan Dowse return (0); 9623d0f849SIan Dowse } 970299afdfSJohn Baldwin 980299afdfSJohn Baldwin ELF_RELOC(ELFCLASS32, ELFDATA2LSB, EM_386, ef_i386_reloc); 99