Home | History | Annotate | Download | only in libebl
      1 /* PPC specific symbolic name handling.
      2    Copyright (C) 2004 Red Hat, Inc.
      3    Written by Ulrich Drepper <drepper (at) redhat.com>, 2004.
      4 
      5    This program is Open Source software; you can redistribute it and/or
      6    modify it under the terms of the Open Software License version 1.0 as
      7    published by the Open Source Initiative.
      8 
      9    You should have received a copy of the Open Software License along
     10    with this program; if not, you may obtain a copy of the Open Software
     11    License version 1.0 from http://www.opensource.org/licenses/osl.php or
     12    by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
     13    3001 King Ranch Road, Ukiah, CA 95482.   */
     14 
     15 #ifdef HAVE_CONFIG_H
     16 # include <config.h>
     17 #endif
     18 
     19 #include <assert.h>
     20 #include <elf.h>
     21 #include <stddef.h>
     22 
     23 #include <libebl_ppc.h>
     24 
     25 
     26 /* Return of the backend.  */
     27 const char *
     28 ppc_backend_name (void)
     29 {
     30   return "ppc";
     31 }
     32 
     33 
     34 /* Relocation mapping table.  */
     35 static struct
     36 {
     37   const char *name;
     38   enum { both = 0, rel = 1, exec = 2 } appear;
     39 } reloc_map_table[] =
     40   {
     41     // XXX Check all the appear values.
     42     [R_PPC_NONE] = { "R_PPC_NONE", both },
     43     [R_PPC_ADDR32] = { "R_PPC_ADDR32", both },
     44     [R_PPC_ADDR24] = { "R_PPC_ADDR24", both },
     45     [R_PPC_ADDR16] = { "R_PPC_ADDR16", both },
     46     [R_PPC_ADDR16_LO] = { "R_PPC_ADDR16_LO", both },
     47     [R_PPC_ADDR16_HI] = { "R_PPC_ADDR16_HI", both },
     48     [R_PPC_ADDR16_HA] = { "R_PPC_ADDR16_HA", both },
     49     [R_PPC_ADDR14] = { "R_PPC_ADDR14", exec },
     50     [R_PPC_ADDR14_BRTAKEN] = { "R_PPC_ADDR14_BRTAKEN", exec },
     51     [R_PPC_ADDR14_BRNTAKEN] = { "R_PPC_ADDR14_BRNTAKEN", exec },
     52     [R_PPC_REL24] = { "R_PPC_REL24", both },
     53     [R_PPC_REL14] = { "R_PPC_REL14", both },
     54     [R_PPC_REL14_BRTAKEN] = { "R_PPC_REL14_BRTAKEN", exec },
     55     [R_PPC_REL14_BRNTAKEN] = { "R_PPC_REL14_BRNTAKEN", exec },
     56     [R_PPC_GOT16] = { "R_PPC_GOT16", rel },
     57     [R_PPC_GOT16_LO] = { "R_PPC_GOT16_LO", rel },
     58     [R_PPC_GOT16_HI] = { "R_PPC_GOT16_HI", rel },
     59     [R_PPC_GOT16_HA] = { "R_PPC_GOT16_HA", rel },
     60     [R_PPC_PLTREL24] = { "R_PPC_PLTREL24", rel },
     61     [R_PPC_COPY] = { "R_PPC_COPY", exec },
     62     [R_PPC_GLOB_DAT] = { "R_PPC_GLOB_DAT", exec },
     63     [R_PPC_JMP_SLOT] = { "R_PPC_JMP_SLOT", exec },
     64     [R_PPC_RELATIVE] = { "R_PPC_RELATIVE", exec },
     65     [R_PPC_LOCAL24PC] = { "R_PPC_LOCAL24PC", rel },
     66     [R_PPC_UADDR32] = { "R_PPC_UADDR32", exec },
     67     [R_PPC_UADDR16] = { "R_PPC_UADDR16", exec },
     68     [R_PPC_REL32] = { "R_PPC_REL32", exec },
     69     [R_PPC_PLT32] = { "R_PPC_PLT32", exec },
     70     [R_PPC_PLTREL32] = { "R_PPC_PLTREL32", both },
     71     [R_PPC_PLT16_LO] = { "R_PPC_PLT16_LO", both },
     72     [R_PPC_PLT16_HI] = { "R_PPC_PLT16_HI", both },
     73     [R_PPC_PLT16_HA] = { "R_PPC_PLT16_HA", both },
     74     [R_PPC_SDAREL16] = { "R_PPC_SDAREL16", both },
     75     [R_PPC_SECTOFF] = { "R_PPC_SECTOFF", both },
     76     [R_PPC_SECTOFF_LO] = { "R_PPC_SECTOFF_LO", both },
     77     [R_PPC_SECTOFF_HI] = { "R_PPC_SECTOFF_HI", both },
     78     [R_PPC_SECTOFF_HA] = { "R_PPC_SECTOFF_HA", both },
     79     [R_PPC_TLS] = { "R_PPC_TLS", both },
     80     [R_PPC_DTPMOD32] = { "R_PPC_DTPMOD32", exec },
     81     [R_PPC_TPREL16] = { "R_PPC_TPREL16", rel },
     82     [R_PPC_TPREL16_LO] = { "R_PPC_TPREL16_LO", rel },
     83     [R_PPC_TPREL16_HI] = { "R_PPC_TPREL16_HI", rel },
     84     [R_PPC_TPREL16_HA] = { "R_PPC_TPREL16_HA", rel },
     85     [R_PPC_TPREL32] = { "R_PPC_TPREL32", exec },
     86     [R_PPC_DTPREL16] = { "R_PPC_DTPREL16", rel },
     87     [R_PPC_DTPREL16_LO] = { "R_PPC_DTPREL16_LO", rel },
     88     [R_PPC_DTPREL16_HI] = { "R_PPC_DTPREL16_HI", rel },
     89     [R_PPC_DTPREL16_HA] = { "R_PPC_DTPREL16_HA", rel },
     90     [R_PPC_DTPREL32] = { "R_PPC_DTPREL32", exec },
     91     [R_PPC_GOT_TLSGD16] = { "R_PPC_GOT_TLSGD16", exec },
     92     [R_PPC_GOT_TLSGD16_LO] = { "R_PPC_GOT_TLSGD16_LO", exec },
     93     [R_PPC_GOT_TLSGD16_HI] = { "R_PPC_GOT_TLSGD16_HI", exec },
     94     [R_PPC_GOT_TLSGD16_HA] = { "R_PPC_GOT_TLSGD16_HA", exec },
     95     [R_PPC_GOT_TLSLD16] = { "R_PPC_GOT_TLSLD16", exec },
     96     [R_PPC_GOT_TLSLD16_LO] = { "R_PPC_GOT_TLSLD16_LO", exec },
     97     [R_PPC_GOT_TLSLD16_HI] = { "R_PPC_GOT_TLSLD16_HI", exec },
     98     [R_PPC_GOT_TLSLD16_HA] = { "R_PPC_GOT_TLSLD16_HA", exec },
     99     [R_PPC_GOT_TPREL16] = { "R_PPC_GOT_TPREL16", exec },
    100     [R_PPC_GOT_TPREL16_LO] = { "R_PPC_GOT_TPREL16_LO", exec },
    101     [R_PPC_GOT_TPREL16_HI] = { "R_PPC_GOT_TPREL16_HI", exec },
    102     [R_PPC_GOT_TPREL16_HA] = { "R_PPC_GOT_TPREL16_HA", exec },
    103     [R_PPC_GOT_DTPREL16] = { "R_PPC_GOT_DTPREL16", exec },
    104     [R_PPC_GOT_DTPREL16_LO] = { "R_PPC_GOT_DTPREL16_LO", exec },
    105     [R_PPC_GOT_DTPREL16_HI] = { "R_PPC_GOT_DTPREL16_HI", exec },
    106     [R_PPC_GOT_DTPREL16_HA] = { "R_PPC_GOT_DTPREL16_HA", exec }
    107   };
    108 
    109 
    110 /* Determine relocation type string for PPC.  */
    111 const char *
    112 ppc_reloc_type_name (int type, char *buf, size_t len)
    113 {
    114   if (type < 0 || type >= R_PPC_NUM)
    115     return NULL;
    116 
    117   return reloc_map_table[type].name;
    118 }
    119 
    120 
    121 /* Check for correct relocation type.  */
    122 bool
    123 ppc_reloc_type_check (int type)
    124 {
    125   return (type >= R_PPC_NONE && type < R_PPC_NUM
    126 	  && reloc_map_table[type].name != NULL) ? true : false;
    127 }
    128 
    129 
    130 /* Check for correct relocation type use.  */
    131 bool
    132 ppc_reloc_valid_use (Elf *elf, int type)
    133 {
    134   if (type < R_PPC_NONE || type >= R_PPC_NUM
    135       || reloc_map_table[type].name == NULL)
    136     return false;
    137 
    138   Elf32_Ehdr *ehdr = elf32_getehdr (elf);
    139   assert (ehdr != NULL);
    140 
    141   if (reloc_map_table[type].appear == rel)
    142     return ehdr->e_type == ET_REL;
    143 
    144   if (reloc_map_table[type].appear == exec)
    145     return ehdr->e_type != ET_REL;
    146 
    147   assert (reloc_map_table[type].appear == both);
    148   return true;
    149 }
    150