13fe1377iedowse/*-
27551d83pfg * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
37551d83pfg *
43fe1377iedowse * Copyright (c) 2003 Jake Burkholder.
53fe1377iedowse * Copyright 1996-1998 John D. Polstra.
63fe1377iedowse * All rights reserved.
73fe1377iedowse *
83fe1377iedowse * Redistribution and use in source and binary forms, with or without
93fe1377iedowse * modification, are permitted provided that the following conditions
103fe1377iedowse * are met:
113fe1377iedowse * 1. Redistributions of source code must retain the above copyright
123fe1377iedowse *    notice, this list of conditions and the following disclaimer.
133fe1377iedowse * 2. Redistributions in binary form must reproduce the above copyright
143fe1377iedowse *    notice, this list of conditions and the following disclaimer in the
153fe1377iedowse *    documentation and/or other materials provided with the distribution.
163fe1377iedowse *
173fe1377iedowse * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
183fe1377iedowse * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
193fe1377iedowse * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
203fe1377iedowse * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
213fe1377iedowse * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
223fe1377iedowse * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
233fe1377iedowse * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
243fe1377iedowse * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
253fe1377iedowse * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
263fe1377iedowse * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
273fe1377iedowse * SUCH DAMAGE.
283fe1377iedowse *
293fe1377iedowse * $FreeBSD$
303fe1377iedowse */
313fe1377iedowse
323fe1377iedowse#include <sys/types.h>
333fe1377iedowse#include <machine/elf.h>
343fe1377iedowse
353fe1377iedowse#include <err.h>
363fe1377iedowse#include <errno.h>
373fe1377iedowse
383fe1377iedowse#include "ef.h"
393fe1377iedowse
403fe1377iedowse/*
41d0d1e68iedowse * Apply relocations to the values we got from the file. `relbase' is the
42d0d1e68iedowse * target relocation address of the section, and `dataoff' is the target
43d0d1e68iedowse * relocation address of the data in `dest'.
443fe1377iedowse */
453fe1377iedowseint
46d0d1e68iedowseef_reloc(struct elf_file *ef, const void *reldata, int reltype, Elf_Off relbase,
47e7aa89bluigi    Elf_Off dataoff, size_t len, void *_dest)
483fe1377iedowse{
493fe1377iedowse	Elf_Addr *where, addr, addend;
500a081d0marcel	Elf_Size rtype, symidx;
513fe1377iedowse	const Elf_Rel *rel;
523fe1377iedowse	const Elf_Rela *rela;
53e7aa89bluigi	char *dest = _dest;
543fe1377iedowse
55d0d1e68iedowse	switch (reltype) {
563fe1377iedowse	case EF_RELOC_REL:
57d0d1e68iedowse		rel = (const Elf_Rel *)reldata;
58d0d1e68iedowse		where = (Elf_Addr *)(dest + relbase + rel->r_offset - dataoff);
59d0d1e68iedowse		addend = 0;
603fe1377iedowse		rtype = ELF_R_TYPE(rel->r_info);
613fe1377iedowse		symidx = ELF_R_SYM(rel->r_info);
623fe1377iedowse		break;
633fe1377iedowse	case EF_RELOC_RELA:
64d0d1e68iedowse		rela = (const Elf_Rela *)reldata;
65d0d1e68iedowse		where = (Elf_Addr *)(dest + relbase + rela->r_offset - dataoff);
663fe1377iedowse		addend = rela->r_addend;
673fe1377iedowse		rtype = ELF_R_TYPE(rela->r_info);
683fe1377iedowse		symidx = ELF_R_SYM(rela->r_info);
693fe1377iedowse		break;
703fe1377iedowse	default:
713fe1377iedowse		return (EINVAL);
723fe1377iedowse	}
733fe1377iedowse
743fe1377iedowse	if ((char *)where < (char *)dest || (char *)where >= (char *)dest + len)
753fe1377iedowse		return (0);
763fe1377iedowse
77d0d1e68iedowse	if (reltype == EF_RELOC_REL)
783fe1377iedowse		addend = *where;
793fe1377iedowse
803fe1377iedowse	switch (rtype) {
813fe1377iedowse	case R_386_RELATIVE:	/* A + B */
82d0d1e68iedowse		addr = (Elf_Addr)addend + relbase;
833fe1377iedowse		*where = addr;
843fe1377iedowse		break;
853fe1377iedowse	case R_386_32:	/* S + A - P */
863fe1377iedowse		addr = EF_SYMADDR(ef, symidx);
873fe1377iedowse		addr += addend;
883fe1377iedowse		*where = addr;
893fe1377iedowse		break;
903fe1377iedowse	case R_386_GLOB_DAT:	/* S */
913fe1377iedowse		addr = EF_SYMADDR(ef, symidx);
923fe1377iedowse		*where = addr;
933fe1377iedowse		break;
943fe1377iedowse	default:
953fe1377iedowse		warnx("unhandled relocation type %d", (int)rtype);
963fe1377iedowse	}
973fe1377iedowse	return (0);
983fe1377iedowse}
99