Home | History | Annotate | Download | only in libebl
      1 /* PPC64 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_ppc64.h>
     24 
     25 
     26 /* Return of the backend.  */
     27 const char *
     28 ppc64_backend_name (void)
     29 {
     30   return "ppc64";
     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_PPC64_NONE] = { "R_PPC64_NONE", both },
     43     [R_PPC64_ADDR32] = { "R_PPC64_ADDR32", both },
     44     [R_PPC64_ADDR24] = { "R_PPC64_ADDR24", both },
     45     [R_PPC64_ADDR16] = { "R_PPC64_ADDR16", both },
     46     [R_PPC64_ADDR16_LO] = { "R_PPC64_ADDR16_LO", both },
     47     [R_PPC64_ADDR16_HI] = { "R_PPC64_ADDR16_HI", both },
     48     [R_PPC64_ADDR16_HA] = { "R_PPC64_ADDR16_HA", both },
     49     [R_PPC64_ADDR14] = { "R_PPC64_ADDR14", both },
     50     [R_PPC64_ADDR14_BRTAKEN] = { "R_PPC64_ADDR14_BRTAKEN", exec },
     51     [R_PPC64_ADDR14_BRNTAKEN] = { "R_PPC64_ADDR14_BRNTAKEN", exec },
     52     [R_PPC64_REL24] = { "R_PPC64_REL24", both },
     53     [R_PPC64_REL14] = { "R_PPC64_REL14", both },
     54     [R_PPC64_REL14_BRTAKEN] = { "R_PPC64_REL14_BRTAKEN", exec },
     55     [R_PPC64_REL14_BRNTAKEN] = { "R_PPC64_REL14_BRNTAKEN", exec },
     56     [R_PPC64_GOT16] = { "R_PPC64_GOT16", rel },
     57     [R_PPC64_GOT16_LO] = { "R_PPC64_GOT16_LO", rel },
     58     [R_PPC64_GOT16_HI] = { "R_PPC64_GOT16_HI", rel },
     59     [R_PPC64_GOT16_HA] = { "R_PPC64_GOT16_HA", rel },
     60     [R_PPC64_COPY] = { "R_PPC64_COPY", exec },
     61     [R_PPC64_GLOB_DAT] = { "R_PPC64_GLOB_DAT", exec },
     62     [R_PPC64_JMP_SLOT] = { "R_PPC64_JMP_SLOT", exec },
     63     [R_PPC64_RELATIVE] = { "R_PPC64_RELATIVE", exec },
     64     [R_PPC64_UADDR32] = { "R_PPC64_UADDR32", exec },
     65     [R_PPC64_UADDR16] = { "R_PPC64_UADDR16", exec },
     66     [R_PPC64_REL32] = { "R_PPC64_REL32", exec },
     67     [R_PPC64_PLT32] = { "R_PPC64_PLT32", exec },
     68     [R_PPC64_PLTREL32] = { "R_PPC64_PLTREL32", both },
     69     [R_PPC64_PLT16_LO] = { "R_PPC64_PLT16_LO", both },
     70     [R_PPC64_PLT16_HI] = { "R_PPC64_PLT16_HI", both },
     71     [R_PPC64_PLT16_HA] = { "R_PPC64_PLT16_HA", both },
     72     [R_PPC64_SECTOFF] = { "R_PPC64_SECTOFF", both },
     73     [R_PPC64_SECTOFF_LO] = { "R_PPC64_SECTOFF_LO", both },
     74     [R_PPC64_SECTOFF_HI] = { "R_PPC64_SECTOFF_HI", both },
     75     [R_PPC64_SECTOFF_HA] = { "R_PPC64_SECTOFF_HA", both },
     76     [R_PPC64_ADDR30] = { "R_PPC64_ADDR30", both },
     77     [R_PPC64_ADDR64] = { "R_PPC64_ADDR64", both },
     78     [R_PPC64_ADDR16_HIGHER] = { "R_PPC64_ADDR16_HIGHER", both },
     79     [R_PPC64_ADDR16_HIGHERA] = { "R_PPC64_ADDR16_HIGHERA", both },
     80     [R_PPC64_ADDR16_HIGHEST] = { "R_PPC64_ADDR16_HIGHEST", both },
     81     [R_PPC64_ADDR16_HIGHESTA] = { "R_PPC64_ADDR16_HIGHESTA", both },
     82     [R_PPC64_UADDR64] = { "R_PPC64_UADDR64", both },
     83     [R_PPC64_REL64] = { "R_PPC64_REL64", both },
     84     [R_PPC64_PLT64] = { "R_PPC64_PLT64", both },
     85     [R_PPC64_PLTREL64] = { "R_PPC64_PLTREL64", both },
     86     [R_PPC64_TOC16] = { "R_PPC64_TOC16", both },
     87     [R_PPC64_TOC16_LO] = { "R_PPC64_TOC16_LO", both },
     88     [R_PPC64_TOC16_HI] = { "R_PPC64_TOC16_HI", both },
     89     [R_PPC64_TOC16_HA] = { "R_PPC64_TOC16_HA", both },
     90     [R_PPC64_TOC] = { "R_PPC64_TOC", both },
     91     [R_PPC64_PLTGOT16] = { "R_PPC64_PLTGOT16", both },
     92     [R_PPC64_PLTGOT16_LO] = { "R_PPC64_PLTGOT16_LO", both },
     93     [R_PPC64_PLTGOT16_HI] = { "R_PPC64_PLTGOT16_HI", both },
     94     [R_PPC64_PLTGOT16_HA] = { "R_PPC64_PLTGOT16_HA", both },
     95     [R_PPC64_ADDR16_DS] = { "R_PPC64_ADDR16_DS", both },
     96     [R_PPC64_ADDR16_LO_DS] = { "R_PPC64_ADDR16_LO_DS", both },
     97     [R_PPC64_GOT16_DS] = { "R_PPC64_GOT16_DS", both },
     98     [R_PPC64_GOT16_LO_DS] = { "R_PPC64_GOT16_LO_DS", both },
     99     [R_PPC64_PLT16_LO_DS] = { "R_PPC64_PLT16_LO_DS", both },
    100     [R_PPC64_SECTOFF_DS] = { "R_PPC64_SECTOFF_DS", both },
    101     [R_PPC64_SECTOFF_LO_DS] = { "R_PPC64_SECTOFF_LO_DS", both },
    102     [R_PPC64_TOC16_DS] = { "R_PPC64_TOC16_DS", both },
    103     [R_PPC64_TOC16_LO_DS] = { "R_PPC64_TOC16_LO_DS", both },
    104     [R_PPC64_PLTGOT16_DS] = { "R_PPC64_PLTGOT16_DS", both },
    105     [R_PPC64_PLTGOT16_LO_DS] = { "R_PPC64_PLTGOT16_LO_DS", both },
    106     [R_PPC64_TLS] = { "R_PPC64_TLS", both },
    107     [R_PPC64_DTPMOD64] = { "R_PPC64_DTPMOD64", both },
    108     [R_PPC64_TPREL16] = { "R_PPC64_TPREL16", both },
    109     [R_PPC64_TPREL16_LO] = { "R_PPC64_TPREL16_LO", both },
    110     [R_PPC64_TPREL16_HI] = { "R_PPC64_TPREL16_HI", both },
    111     [R_PPC64_TPREL16_HA] = { "R_PPC64_TPREL16_HA", both },
    112     [R_PPC64_TPREL64] = { "R_PPC64_TPREL64", both },
    113     [R_PPC64_DTPREL16] = { "R_PPC64_DTPREL16", both },
    114     [R_PPC64_DTPREL16_LO] = { "R_PPC64_DTPREL16_LO", both },
    115     [R_PPC64_DTPREL16_HI] = { "R_PPC64_DTPREL16_HI", both },
    116     [R_PPC64_DTPREL16_HA] = { "R_PPC64_DTPREL16_HA", both },
    117     [R_PPC64_DTPREL64] = { "R_PPC64_DTPREL64", both },
    118     [R_PPC64_GOT_TLSGD16] = { "R_PPC64_GOT_TLSGD16", both },
    119     [R_PPC64_GOT_TLSGD16_LO] = { "R_PPC64_GOT_TLSGD16_LO", both },
    120     [R_PPC64_GOT_TLSGD16_HI] = { "R_PPC64_GOT_TLSGD16_HI", both },
    121     [R_PPC64_GOT_TLSGD16_HA] = { "R_PPC64_GOT_TLSGD16_HA", both },
    122     [R_PPC64_GOT_TLSLD16] = { "R_PPC64_GOT_TLSLD16", both },
    123     [R_PPC64_GOT_TLSLD16_LO] = { "R_PPC64_GOT_TLSLD16_LO", both },
    124     [R_PPC64_GOT_TLSLD16_HI] = { "R_PPC64_GOT_TLSLD16_HI", both },
    125     [R_PPC64_GOT_TLSLD16_HA] = { "R_PPC64_GOT_TLSLD16_HA", both },
    126     [R_PPC64_GOT_TPREL16_DS] = { "R_PPC64_GOT_TPREL16_DS", both },
    127     [R_PPC64_GOT_TPREL16_LO_DS] = { "R_PPC64_GOT_TPREL16_LO_DS", both },
    128     [R_PPC64_GOT_TPREL16_HI] = { "R_PPC64_GOT_TPREL16_HI", both },
    129     [R_PPC64_GOT_TPREL16_HA] = { "R_PPC64_GOT_TPREL16_HA", both },
    130     [R_PPC64_GOT_DTPREL16_DS] = { "R_PPC64_GOT_DTPREL16_DS", both },
    131     [R_PPC64_GOT_DTPREL16_LO_DS] = { "R_PPC64_GOT_DTPREL16_LO_DS", both },
    132     [R_PPC64_GOT_DTPREL16_HI] = { "R_PPC64_GOT_DTPREL16_HI", both },
    133     [R_PPC64_GOT_DTPREL16_HA] = { "R_PPC64_GOT_DTPREL16_HA", both },
    134     [R_PPC64_TPREL16_DS] = { "R_PPC64_TPREL16_DS", both },
    135     [R_PPC64_TPREL16_LO_DS] = { "R_PPC64_TPREL16_LO_DS", both },
    136     [R_PPC64_TPREL16_HIGHER] = { "R_PPC64_TPREL16_HIGHER", both },
    137     [R_PPC64_TPREL16_HIGHERA] = { "R_PPC64_TPREL16_HIGHERA", both },
    138     [R_PPC64_TPREL16_HIGHEST] = { "R_PPC64_TPREL16_HIGHEST", both },
    139     [R_PPC64_TPREL16_HIGHESTA] = { "R_PPC64_TPREL16_HIGHESTA", both },
    140     [R_PPC64_DTPREL16_DS] = { "R_PPC64_DTPREL16_DS", both },
    141     [R_PPC64_DTPREL16_LO_DS] = { "R_PPC64_DTPREL16_LO_DS", both },
    142     [R_PPC64_DTPREL16_HIGHER] = { "R_PPC64_DTPREL16_HIGHER", both },
    143     [R_PPC64_DTPREL16_HIGHERA] = { "R_PPC64_DTPREL16_HIGHERA", both },
    144     [R_PPC64_DTPREL16_HIGHEST] = { "R_PPC64_DTPREL16_HIGHEST", both },
    145     [R_PPC64_DTPREL16_HIGHESTA] = { "R_PPC64_DTPREL16_HIGHESTA", both }
    146  };
    147 
    148 
    149 /* Determine relocation type string for PPC.  */
    150 const char *
    151 ppc64_reloc_type_name (int type, char *buf, size_t len)
    152 {
    153   if (type < R_PPC64_NONE || type >= R_PPC64_NUM)
    154     return NULL;
    155 
    156   return reloc_map_table[type].name;
    157 }
    158 
    159 
    160 /* Check for correct relocation type.  */
    161 bool
    162 ppc64_reloc_type_check (int type)
    163 {
    164   return (type >= R_PPC64_NONE && type < R_PPC64_NUM
    165 	  && reloc_map_table[type].name != NULL) ? true : false;
    166 }
    167 
    168 
    169 /* Check for correct relocation type use.  */
    170 bool
    171 ppc64_reloc_valid_use (Elf *elf, int type)
    172 {
    173   if (type < R_PPC64_NONE || type >= R_PPC64_NUM
    174       || reloc_map_table[type].name == NULL)
    175     return false;
    176 
    177   Elf64_Ehdr *ehdr = elf64_getehdr (elf);
    178   assert (ehdr != NULL);
    179 
    180   if (reloc_map_table[type].appear == rel)
    181     return ehdr->e_type == ET_REL;
    182 
    183   if (reloc_map_table[type].appear == exec)
    184     return ehdr->e_type != ET_REL;
    185 
    186   assert (reloc_map_table[type].appear == both);
    187   return true;
    188 }
    189 
    190 
    191 const char *
    192 ppc64_dynamic_tag_name (int64_t tag, char *buf, size_t len)
    193 {
    194   switch (tag)
    195     {
    196     case DT_PPC64_GLINK:
    197       return "PPC64_GLINK";
    198     case DT_PPC64_OPD:
    199       return "PPC64_OPD";
    200     case DT_PPC64_OPDSZ:
    201       return "PPC64_OPDSZ";
    202     default:
    203       break;
    204     }
    205   return NULL;
    206 }
    207