| Ulrich Drepper | b08d5a8 | 2005-07-26 05:00:05 +0000 | [diff] [blame^] | 1 | /* PPC specific symbolic name handling. | 
 | 2 |    Copyright (C) 2004, 2005 Red Hat, Inc. | 
 | 3 |    Written by Ulrich Drepper <drepper@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 __attribute__ ((unused)), | 
 | 113 | 		     size_t len __attribute__ ((unused))) | 
 | 114 | { | 
 | 115 |   if (type < 0 || type >= R_PPC_NUM) | 
 | 116 |     return NULL; | 
 | 117 |  | 
 | 118 |   return reloc_map_table[type].name; | 
 | 119 | } | 
 | 120 |  | 
 | 121 |  | 
 | 122 | /* Check for correct relocation type.  */ | 
 | 123 | bool | 
 | 124 | ppc_reloc_type_check (int type) | 
 | 125 | { | 
 | 126 |   return (type >= R_PPC_NONE && type < R_PPC_NUM | 
 | 127 | 	  && reloc_map_table[type].name != NULL) ? true : false; | 
 | 128 | } | 
 | 129 |  | 
 | 130 |  | 
 | 131 | /* Check for correct relocation type use.  */ | 
 | 132 | bool | 
 | 133 | ppc_reloc_valid_use (Elf *elf, int type) | 
 | 134 | { | 
 | 135 |   if (type < R_PPC_NONE || type >= R_PPC_NUM | 
 | 136 |       || reloc_map_table[type].name == NULL) | 
 | 137 |     return false; | 
 | 138 |  | 
 | 139 |   Elf32_Ehdr *ehdr = elf32_getehdr (elf); | 
 | 140 |   assert (ehdr != NULL); | 
 | 141 |  | 
 | 142 |   if (reloc_map_table[type].appear == rel) | 
 | 143 |     return ehdr->e_type == ET_REL; | 
 | 144 |  | 
 | 145 |   if (reloc_map_table[type].appear == exec) | 
 | 146 |     return ehdr->e_type != ET_REL; | 
 | 147 |  | 
 | 148 |   assert (reloc_map_table[type].appear == both); | 
 | 149 |   return true; | 
 | 150 | } | 
 | 151 |  | 
 | 152 |  | 
 | 153 | /* Check for the simple reloc types.  */ | 
 | 154 | Elf_Type | 
 | 155 | ppc_reloc_simple_type (Elf *elf __attribute__ ((unused)), int type) | 
 | 156 | { | 
 | 157 |   switch (type) | 
 | 158 |     { | 
 | 159 |     case R_PPC_ADDR32: | 
 | 160 |     case R_PPC_UADDR32: | 
 | 161 |       return ELF_T_WORD; | 
 | 162 |     case R_PPC_UADDR16: | 
 | 163 |       return ELF_T_HALF; | 
 | 164 |     default: | 
 | 165 |       return ELF_T_NUM; | 
 | 166 |     } | 
 | 167 | } | 
 | 168 |  | 
 | 169 | /* Check whether given relocation is a copy relocation.  */ | 
 | 170 | bool | 
 | 171 | ppc_copy_reloc_p (int reloc) | 
 | 172 | { | 
 | 173 |   return reloc == R_PPC_COPY; | 
 | 174 | } |