ef_amd64.c revision 134362
11541Srgrimes/*-
21541Srgrimes * Copyright (c) 2003 Jake Burkholder.
31541Srgrimes * Copyright 1996-1998 John D. Polstra.
41541Srgrimes * All rights reserved.
51541Srgrimes *
61541Srgrimes * Redistribution and use in source and binary forms, with or without
71541Srgrimes * modification, are permitted provided that the following conditions
81541Srgrimes * are met:
91541Srgrimes * 1. Redistributions of source code must retain the above copyright
101541Srgrimes *    notice, this list of conditions and the following disclaimer.
111541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
121541Srgrimes *    notice, this list of conditions and the following disclaimer in the
131541Srgrimes *    documentation and/or other materials provided with the distribution.
141541Srgrimes *
151541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
161541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
171541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
181541Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
191541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
201541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
211541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
221541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
231541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
241541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
251541Srgrimes * SUCH DAMAGE.
261541Srgrimes *
271541Srgrimes * $FreeBSD: head/usr.sbin/kldxref/ef_amd64.c 134362 2004-08-27 01:06:57Z iedowse $
281541Srgrimes */
291541Srgrimes
301541Srgrimes#include <sys/types.h>
311541Srgrimes#include <machine/elf.h>
321541Srgrimes
331541Srgrimes#include <err.h>
341541Srgrimes#include <errno.h>
351541Srgrimes#include <string.h>
361541Srgrimes
371541Srgrimes#include "ef.h"
381541Srgrimes
391541Srgrimes/*
401541Srgrimes * Apply relocations to the values we got from the file.
411541Srgrimes */
421541Srgrimesint
431541Srgrimesef_reloc(struct elf_file *ef, const void *data, int type, Elf_Off offset,
441541Srgrimes    size_t len, void *dest)
451541Srgrimes{
461541Srgrimes	Elf64_Addr *where, val;
471541Srgrimes	Elf32_Addr *where32, val32;
481541Srgrimes	Elf_Addr addend, addr;
491541Srgrimes	Elf_Word rtype, symidx;
501541Srgrimes	const Elf_Rel *rel;
511541Srgrimes	const Elf_Rela *rela;
521541Srgrimes
531541Srgrimes	switch (type) {
541541Srgrimes	case EF_RELOC_REL:
551541Srgrimes		rel = (const Elf_Rel *)data;
561541Srgrimes		where = (Elf_Addr *)(dest + rel->r_offset - offset);
571541Srgrimes		rtype = ELF_R_TYPE(rel->r_info);
581541Srgrimes		symidx = ELF_R_SYM(rel->r_info);
591541Srgrimes		break;
601541Srgrimes	case EF_RELOC_RELA:
611541Srgrimes		rela = (const Elf_Rela *)data;
621541Srgrimes		where = (Elf_Addr *)(dest + rela->r_offset - offset);
631541Srgrimes		addend = rela->r_addend;
641541Srgrimes		rtype = ELF_R_TYPE(rela->r_info);
651541Srgrimes		symidx = ELF_R_SYM(rela->r_info);
661541Srgrimes		break;
671541Srgrimes	default:
681541Srgrimes		return (EINVAL);
691541Srgrimes	}
701541Srgrimes
711541Srgrimes	if ((char *)where < (char *)dest || (char *)where >= (char *)dest + len)
721541Srgrimes		return (0);
731541Srgrimes
741541Srgrimes	if (type == EF_RELOC_REL) {
751541Srgrimes		/* Addend is 32 bit on 32 bit relocs */
761541Srgrimes		switch (rtype) {
771541Srgrimes		case R_X86_64_PC32:
781541Srgrimes		case R_X86_64_32S:
791541Srgrimes			addend = *(Elf32_Addr *)where;
801541Srgrimes			break;
811541Srgrimes		default:
821541Srgrimes			addend = *where;
831541Srgrimes			break;
841541Srgrimes		}
851541Srgrimes	}
861541Srgrimes
871541Srgrimes	switch (rtype) {
881541Srgrimes	case R_X86_64_NONE:	/* none */
891541Srgrimes		break;
901541Srgrimes	case R_X86_64_64:	/* S + A */
911541Srgrimes		addr = EF_SYMADDR(ef, symidx);
921541Srgrimes		val = addr + addend;
931541Srgrimes		*where = val;
941541Srgrimes		break;
951541Srgrimes	case R_X86_64_32S:	/* S + A sign extend */
961541Srgrimes		addr = EF_SYMADDR(ef, symidx);
971541Srgrimes		val32 = (Elf32_Addr)(addr + addend);
981541Srgrimes		where32 = (Elf32_Addr *)where;
991541Srgrimes		*where32 = val32;
1001541Srgrimes		break;
1011541Srgrimes	case R_X86_64_GLOB_DAT:	/* S */
1021541Srgrimes		addr = EF_SYMADDR(ef, symidx);
1031541Srgrimes		*where = addr;
1041541Srgrimes		break;
1051541Srgrimes	case R_X86_64_RELATIVE:	/* B + A */
1061541Srgrimes		addr = (Elf_Addr)addend;
1071541Srgrimes		val = addr;
1081541Srgrimes		*where = val;
1091541Srgrimes		break;
1101541Srgrimes	default:
1111541Srgrimes		warnx("unhandled relocation type %d", (int)rtype);
1121541Srgrimes	}
1131541Srgrimes	return (0);
1141541Srgrimes}
1151541Srgrimes