The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/boot/common/reloc_elf.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2003 Jake Burkholder.
    3  * Copyright 1996-1998 John D. Polstra.
    4  * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
    5  * Copyright (c) 1998 Peter Wemm <peter@freebsd.org>
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  */
   29 
   30 #include <sys/cdefs.h>
   31 __FBSDID("$FreeBSD: releng/8.2/sys/boot/common/reloc_elf.c 153504 2005-12-18 04:52:37Z marcel $");
   32 
   33 #include <sys/types.h>
   34 #include <machine/elf.h>
   35 
   36 #include <errno.h>
   37 #include <stand.h>
   38 
   39 #define FREEBSD_ELF
   40 #include <link.h>
   41 
   42 #include "bootstrap.h"
   43 
   44 #define COPYOUT(s,d,l)  archsw.arch_copyout((vm_offset_t)(s), d, l)
   45 
   46 /*
   47  * Apply a single intra-module relocation to the data. `relbase' is the
   48  * target relocation base for the section (i.e. it corresponds to where
   49  * r_offset == 0). `dataaddr' is the relocated address corresponding to
   50  * the start of the data, and `len' is the number of bytes.
   51  */
   52 int
   53 __elfN(reloc)(struct elf_file *ef, symaddr_fn *symaddr, const void *reldata,
   54     int reltype, Elf_Addr relbase, Elf_Addr dataaddr, void *data, size_t len)
   55 {
   56 #ifdef __sparc__
   57         Elf_Size w;
   58         const Elf_Rela *a;
   59 
   60         switch (reltype) {
   61         case ELF_RELOC_RELA:
   62                 a = reldata;
   63                  if (relbase + a->r_offset >= dataaddr &&
   64                      relbase + a->r_offset < dataaddr + len) {
   65                         switch (ELF_R_TYPE(a->r_info)) {
   66                         case R_SPARC_RELATIVE:
   67                                 w = relbase + a->r_addend;
   68                                 bcopy(&w, (u_char *)data + (relbase +
   69                                     a->r_offset - dataaddr), sizeof(w));
   70                                 break;
   71                         default:
   72                                 printf("\nunhandled relocation type %u\n",
   73                                     (u_int)ELF_R_TYPE(a->r_info));
   74                                 return (EFTYPE);
   75                         }
   76                 }
   77                 break;
   78         }
   79 
   80         return (0);
   81 #elif defined(__i386__) && __ELF_WORD_SIZE == 64
   82         Elf64_Addr *where, val;
   83         Elf_Addr addend, addr;
   84         Elf_Size rtype, symidx;
   85         const Elf_Rel *rel;
   86         const Elf_Rela *rela;
   87 
   88         switch (reltype) {
   89         case ELF_RELOC_REL:
   90                 rel = (const Elf_Rel *)reldata;
   91                 where = (Elf_Addr *)((char *)data + relbase + rel->r_offset -
   92                     dataaddr);
   93                 addend = 0;
   94                 rtype = ELF_R_TYPE(rel->r_info);
   95                 symidx = ELF_R_SYM(rel->r_info);
   96                 addend = 0;
   97                 break;
   98         case ELF_RELOC_RELA:
   99                 rela = (const Elf_Rela *)reldata;
  100                 where = (Elf_Addr *)((char *)data + relbase + rela->r_offset -
  101                     dataaddr);
  102                 addend = rela->r_addend;
  103                 rtype = ELF_R_TYPE(rela->r_info);
  104                 symidx = ELF_R_SYM(rela->r_info);
  105                 break;
  106         default:
  107                 return (EINVAL);
  108         }
  109 
  110         if ((char *)where < (char *)data || (char *)where >= (char *)data + len)
  111                 return (0);
  112 
  113         if (reltype == ELF_RELOC_REL)
  114                 addend = *where;
  115 
  116 /* XXX, definitions not available on i386. */
  117 #define R_X86_64_64             1
  118 #define R_X86_64_RELATIVE       8
  119 
  120         switch (rtype) {
  121         case R_X86_64_64:               /* S + A */
  122                 addr = symaddr(ef, symidx);
  123                 if (addr == 0)
  124                         return (ESRCH);
  125                 val = addr + addend;
  126                 *where = val;
  127                 break;
  128         case R_X86_64_RELATIVE:
  129                 addr = (Elf_Addr)addend + relbase;
  130                 val = addr;
  131                 *where = val;
  132                 break;
  133         default:
  134                 printf("\nunhandled relocation type %u\n", (u_int)rtype);
  135                 return (EFTYPE);
  136         }
  137 
  138         return (0);
  139 #elif defined(__i386__) && __ELF_WORD_SIZE == 32
  140         Elf_Addr addend, addr, *where, val;
  141         Elf_Size rtype, symidx;
  142         const Elf_Rel *rel;
  143         const Elf_Rela *rela;
  144 
  145         switch (reltype) {
  146         case ELF_RELOC_REL:
  147                 rel = (const Elf_Rel *)reldata;
  148                 where = (Elf_Addr *)((char *)data + relbase + rel->r_offset -
  149                     dataaddr);
  150                 addend = 0;
  151                 rtype = ELF_R_TYPE(rel->r_info);
  152                 symidx = ELF_R_SYM(rel->r_info);
  153                 addend = 0;
  154                 break;
  155         case ELF_RELOC_RELA:
  156                 rela = (const Elf_Rela *)reldata;
  157                 where = (Elf_Addr *)((char *)data + relbase + rela->r_offset -
  158                     dataaddr);
  159                 addend = rela->r_addend;
  160                 rtype = ELF_R_TYPE(rela->r_info);
  161                 symidx = ELF_R_SYM(rela->r_info);
  162                 break;
  163         default:
  164                 return (EINVAL);
  165         }
  166 
  167         if ((char *)where < (char *)data || (char *)where >= (char *)data + len)
  168                 return (0);
  169 
  170         if (reltype == ELF_RELOC_REL)
  171                 addend = *where;
  172 
  173 /* XXX, definitions not available on amd64. */
  174 #define R_386_32        1       /* Add symbol value. */
  175 #define R_386_GLOB_DAT  6       /* Set GOT entry to data address. */
  176 #define R_386_RELATIVE  8       /* Add load address of shared object. */
  177 
  178         switch (rtype) {
  179         case R_386_RELATIVE:
  180                 addr = addend + relbase;
  181                 *where = addr;
  182                 break;
  183         case R_386_32:          /* S + A */
  184                 addr = symaddr(ef, symidx);
  185                 if (addr == 0)
  186                         return (ESRCH);
  187                 val = addr + addend;
  188                 *where = val;
  189                 break;
  190         default:
  191                 printf("\nunhandled relocation type %u\n", (u_int)rtype);
  192                 return (EFTYPE);
  193         }
  194 
  195         return (0);
  196 #else
  197         return (EOPNOTSUPP);
  198 #endif
  199 }

Cache object: 4d4e8251a0ef3c110543d6f1bf75f9be


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.