1 //===-- RelocVisitor.h - Visitor for object file relocations -*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file provides a wrapper around all the different types of relocations 11 // in different file formats, such that a client can handle them in a unified 12 // manner by only implementing a minimal number of functions. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #ifndef LLVM_OBJECT_RELOCVISITOR_H 17 #define LLVM_OBJECT_RELOCVISITOR_H 18 19 #include "llvm/ADT/StringRef.h" 20 #include "llvm/Object/ObjectFile.h" 21 #include "llvm/Object/ELF.h" 22 #include "llvm/Support/Debug.h" 23 #include "llvm/Support/ELF.h" 24 #include "llvm/Support/raw_ostream.h" 25 26 namespace llvm { 27 namespace object { 28 29 struct RelocToApply { 30 // The computed value after applying the relevant relocations. 31 int64_t Value; 32 33 // The width of the value; how many bytes to touch when applying the 34 // relocation. 35 char Width; 36 RelocToApply(const RelocToApply &In) : Value(In.Value), Width(In.Width) {} 37 RelocToApply(int64_t Value, char Width) : Value(Value), Width(Width) {} 38 RelocToApply() : Value(0), Width(0) {} 39 }; 40 41 /// @brief Base class for object file relocation visitors. 42 class RelocVisitor { 43 public: 44 explicit RelocVisitor(StringRef FileFormat) 45 : FileFormat(FileFormat), HasError(false) {} 46 47 // TODO: Should handle multiple applied relocations via either passing in the 48 // previously computed value or just count paired relocations as a single 49 // visit. 50 RelocToApply visit(uint32_t RelocType, RelocationRef R, uint64_t SecAddr = 0, 51 uint64_t Value = 0) { 52 if (FileFormat == "ELF64-x86-64") { 53 switch (RelocType) { 54 case llvm::ELF::R_X86_64_NONE: 55 return visitELF_X86_64_NONE(R); 56 case llvm::ELF::R_X86_64_64: 57 return visitELF_X86_64_64(R, Value); 58 case llvm::ELF::R_X86_64_PC32: 59 return visitELF_X86_64_PC32(R, Value, SecAddr); 60 case llvm::ELF::R_X86_64_32: 61 return visitELF_X86_64_32(R, Value); 62 case llvm::ELF::R_X86_64_32S: 63 return visitELF_X86_64_32S(R, Value); 64 default: 65 HasError = true; 66 return RelocToApply(); 67 } 68 } else if (FileFormat == "ELF32-i386") { 69 switch (RelocType) { 70 case llvm::ELF::R_386_NONE: 71 return visitELF_386_NONE(R); 72 case llvm::ELF::R_386_32: 73 return visitELF_386_32(R, Value); 74 case llvm::ELF::R_386_PC32: 75 return visitELF_386_PC32(R, Value, SecAddr); 76 default: 77 HasError = true; 78 return RelocToApply(); 79 } 80 } else if (FileFormat == "ELF64-ppc64") { 81 switch (RelocType) { 82 case llvm::ELF::R_PPC64_ADDR32: 83 return visitELF_PPC64_ADDR32(R, Value); 84 case llvm::ELF::R_PPC64_ADDR64: 85 return visitELF_PPC64_ADDR64(R, Value); 86 default: 87 HasError = true; 88 return RelocToApply(); 89 } 90 } else if (FileFormat == "ELF32-ppc") { 91 switch (RelocType) { 92 case llvm::ELF::R_PPC_ADDR32: 93 return visitELF_PPC_ADDR32(R, Value); 94 default: 95 HasError = true; 96 return RelocToApply(); 97 } 98 } else if (FileFormat == "ELF32-mips") { 99 switch (RelocType) { 100 case llvm::ELF::R_MIPS_32: 101 return visitELF_MIPS_32(R, Value); 102 default: 103 HasError = true; 104 return RelocToApply(); 105 } 106 } else if (FileFormat == "ELF64-aarch64") { 107 switch (RelocType) { 108 case llvm::ELF::R_AARCH64_ABS32: 109 return visitELF_AARCH64_ABS32(R, Value); 110 case llvm::ELF::R_AARCH64_ABS64: 111 return visitELF_AARCH64_ABS64(R, Value); 112 default: 113 HasError = true; 114 return RelocToApply(); 115 } 116 } else if (FileFormat == "ELF64-s390") { 117 switch (RelocType) { 118 case llvm::ELF::R_390_32: 119 return visitELF_390_32(R, Value); 120 case llvm::ELF::R_390_64: 121 return visitELF_390_64(R, Value); 122 default: 123 HasError = true; 124 return RelocToApply(); 125 } 126 } 127 HasError = true; 128 return RelocToApply(); 129 } 130 131 bool error() { return HasError; } 132 133 private: 134 StringRef FileFormat; 135 bool HasError; 136 137 int64_t getAddend32LE(RelocationRef R) { 138 const ELF32LEObjectFile *Obj = cast<ELF32LEObjectFile>(R.getObjectFile()); 139 DataRefImpl DRI = R.getRawDataRefImpl(); 140 int64_t Addend; 141 Obj->getRelocationAddend(DRI, Addend); 142 return Addend; 143 } 144 145 int64_t getAddend64LE(RelocationRef R) { 146 const ELF64LEObjectFile *Obj = cast<ELF64LEObjectFile>(R.getObjectFile()); 147 DataRefImpl DRI = R.getRawDataRefImpl(); 148 int64_t Addend; 149 Obj->getRelocationAddend(DRI, Addend); 150 return Addend; 151 } 152 153 int64_t getAddend32BE(RelocationRef R) { 154 const ELF32BEObjectFile *Obj = cast<ELF32BEObjectFile>(R.getObjectFile()); 155 DataRefImpl DRI = R.getRawDataRefImpl(); 156 int64_t Addend; 157 Obj->getRelocationAddend(DRI, Addend); 158 return Addend; 159 } 160 161 int64_t getAddend64BE(RelocationRef R) { 162 const ELF64BEObjectFile *Obj = cast<ELF64BEObjectFile>(R.getObjectFile()); 163 DataRefImpl DRI = R.getRawDataRefImpl(); 164 int64_t Addend; 165 Obj->getRelocationAddend(DRI, Addend); 166 return Addend; 167 } 168 /// Operations 169 170 /// 386-ELF 171 RelocToApply visitELF_386_NONE(RelocationRef R) { 172 return RelocToApply(0, 0); 173 } 174 175 // Ideally the Addend here will be the addend in the data for 176 // the relocation. It's not actually the case for Rel relocations. 177 RelocToApply visitELF_386_32(RelocationRef R, uint64_t Value) { 178 int64_t Addend = getAddend32LE(R); 179 return RelocToApply(Value + Addend, 4); 180 } 181 182 RelocToApply visitELF_386_PC32(RelocationRef R, uint64_t Value, 183 uint64_t SecAddr) { 184 int64_t Addend = getAddend32LE(R); 185 uint64_t Address; 186 R.getOffset(Address); 187 return RelocToApply(Value + Addend - Address, 4); 188 } 189 190 /// X86-64 ELF 191 RelocToApply visitELF_X86_64_NONE(RelocationRef R) { 192 return RelocToApply(0, 0); 193 } 194 RelocToApply visitELF_X86_64_64(RelocationRef R, uint64_t Value) { 195 int64_t Addend = getAddend64LE(R); 196 return RelocToApply(Value + Addend, 8); 197 } 198 RelocToApply visitELF_X86_64_PC32(RelocationRef R, uint64_t Value, 199 uint64_t SecAddr) { 200 int64_t Addend = getAddend64LE(R); 201 uint64_t Address; 202 R.getOffset(Address); 203 return RelocToApply(Value + Addend - Address, 4); 204 } 205 RelocToApply visitELF_X86_64_32(RelocationRef R, uint64_t Value) { 206 int64_t Addend = getAddend64LE(R); 207 uint32_t Res = (Value + Addend) & 0xFFFFFFFF; 208 return RelocToApply(Res, 4); 209 } 210 RelocToApply visitELF_X86_64_32S(RelocationRef R, uint64_t Value) { 211 int64_t Addend = getAddend64LE(R); 212 int32_t Res = (Value + Addend) & 0xFFFFFFFF; 213 return RelocToApply(Res, 4); 214 } 215 216 /// PPC64 ELF 217 RelocToApply visitELF_PPC64_ADDR32(RelocationRef R, uint64_t Value) { 218 int64_t Addend = getAddend64BE(R); 219 uint32_t Res = (Value + Addend) & 0xFFFFFFFF; 220 return RelocToApply(Res, 4); 221 } 222 RelocToApply visitELF_PPC64_ADDR64(RelocationRef R, uint64_t Value) { 223 int64_t Addend = getAddend64BE(R); 224 return RelocToApply(Value + Addend, 8); 225 } 226 227 /// PPC32 ELF 228 RelocToApply visitELF_PPC_ADDR32(RelocationRef R, uint64_t Value) { 229 int64_t Addend = getAddend32BE(R); 230 uint32_t Res = (Value + Addend) & 0xFFFFFFFF; 231 return RelocToApply(Res, 4); 232 } 233 234 /// MIPS ELF 235 RelocToApply visitELF_MIPS_32(RelocationRef R, uint64_t Value) { 236 int64_t Addend; 237 getELFRelocationAddend(R, Addend); 238 uint32_t Res = (Value + Addend) & 0xFFFFFFFF; 239 return RelocToApply(Res, 4); 240 } 241 242 // AArch64 ELF 243 RelocToApply visitELF_AARCH64_ABS32(RelocationRef R, uint64_t Value) { 244 int64_t Addend = getAddend64LE(R); 245 int64_t Res = Value + Addend; 246 247 // Overflow check allows for both signed and unsigned interpretation. 248 if (Res < INT32_MIN || Res > UINT32_MAX) 249 HasError = true; 250 251 return RelocToApply(static_cast<uint32_t>(Res), 4); 252 } 253 254 RelocToApply visitELF_AARCH64_ABS64(RelocationRef R, uint64_t Value) { 255 int64_t Addend = getAddend64LE(R); 256 return RelocToApply(Value + Addend, 8); 257 } 258 259 // SystemZ ELF 260 RelocToApply visitELF_390_32(RelocationRef R, uint64_t Value) { 261 int64_t Addend = getAddend64BE(R); 262 int64_t Res = Value + Addend; 263 264 // Overflow check allows for both signed and unsigned interpretation. 265 if (Res < INT32_MIN || Res > UINT32_MAX) 266 HasError = true; 267 268 return RelocToApply(static_cast<uint32_t>(Res), 4); 269 } 270 271 RelocToApply visitELF_390_64(RelocationRef R, uint64_t Value) { 272 int64_t Addend = getAddend64BE(R); 273 return RelocToApply(Value + Addend, 8); 274 } 275 }; 276 277 } 278 } 279 #endif 280