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/Triple.h" 20 #include "llvm/BinaryFormat/ELF.h" 21 #include "llvm/BinaryFormat/MachO.h" 22 #include "llvm/Object/COFF.h" 23 #include "llvm/Object/ELFObjectFile.h" 24 #include "llvm/Object/MachO.h" 25 #include "llvm/Object/ObjectFile.h" 26 #include "llvm/Support/Casting.h" 27 #include "llvm/Support/ErrorHandling.h" 28 #include <cstdint> 29 #include <system_error> 30 31 namespace llvm { 32 namespace object { 33 34 /// @brief Base class for object file relocation visitors. 35 class RelocVisitor { 36 public: 37 explicit RelocVisitor(const ObjectFile &Obj) : ObjToVisit(Obj) {} 38 39 // TODO: Should handle multiple applied relocations via either passing in the 40 // previously computed value or just count paired relocations as a single 41 // visit. 42 uint64_t visit(uint32_t Rel, RelocationRef R, uint64_t Value = 0) { 43 if (isa<ELFObjectFileBase>(ObjToVisit)) 44 return visitELF(Rel, R, Value); 45 if (isa<COFFObjectFile>(ObjToVisit)) 46 return visitCOFF(Rel, R, Value); 47 if (isa<MachOObjectFile>(ObjToVisit)) 48 return visitMachO(Rel, R, Value); 49 50 HasError = true; 51 return 0; 52 } 53 54 bool error() { return HasError; } 55 56 private: 57 const ObjectFile &ObjToVisit; 58 bool HasError = false; 59 60 uint64_t visitELF(uint32_t Rel, RelocationRef R, uint64_t Value) { 61 if (ObjToVisit.getBytesInAddress() == 8) { // 64-bit object file 62 switch (ObjToVisit.getArch()) { 63 case Triple::x86_64: 64 return visitX86_64(Rel, R, Value); 65 case Triple::aarch64: 66 case Triple::aarch64_be: 67 return visitAarch64(Rel, R, Value); 68 case Triple::bpfel: 69 case Triple::bpfeb: 70 return visitBpf(Rel, R, Value); 71 case Triple::mips64el: 72 case Triple::mips64: 73 return visitMips64(Rel, R, Value); 74 case Triple::ppc64le: 75 case Triple::ppc64: 76 return visitPPC64(Rel, R, Value); 77 case Triple::systemz: 78 return visitSystemz(Rel, R, Value); 79 case Triple::sparcv9: 80 return visitSparc64(Rel, R, Value); 81 case Triple::amdgcn: 82 return visitAmdgpu(Rel, R, Value); 83 default: 84 HasError = true; 85 return 0; 86 } 87 } 88 89 // 32-bit object file 90 assert(ObjToVisit.getBytesInAddress() == 4 && 91 "Invalid word size in object file"); 92 93 switch (ObjToVisit.getArch()) { 94 case Triple::x86: 95 return visitX86(Rel, R, Value); 96 case Triple::ppc: 97 return visitPPC32(Rel, R, Value); 98 case Triple::arm: 99 case Triple::armeb: 100 return visitARM(Rel, R, Value); 101 case Triple::lanai: 102 return visitLanai(Rel, R, Value); 103 case Triple::mipsel: 104 case Triple::mips: 105 return visitMips32(Rel, R, Value); 106 case Triple::sparc: 107 return visitSparc32(Rel, R, Value); 108 case Triple::hexagon: 109 return visitHexagon(Rel, R, Value); 110 default: 111 HasError = true; 112 return 0; 113 } 114 } 115 116 int64_t getELFAddend(RelocationRef R) { 117 Expected<int64_t> AddendOrErr = ELFRelocationRef(R).getAddend(); 118 handleAllErrors(AddendOrErr.takeError(), [](const ErrorInfoBase &EI) { 119 report_fatal_error(EI.message()); 120 }); 121 return *AddendOrErr; 122 } 123 124 uint64_t visitX86_64(uint32_t Rel, RelocationRef R, uint64_t Value) { 125 switch (Rel) { 126 case ELF::R_X86_64_NONE: 127 return 0; 128 case ELF::R_X86_64_64: 129 return Value + getELFAddend(R); 130 case ELF::R_X86_64_PC32: 131 return Value + getELFAddend(R) - R.getOffset(); 132 case ELF::R_X86_64_32: 133 case ELF::R_X86_64_32S: 134 return (Value + getELFAddend(R)) & 0xFFFFFFFF; 135 } 136 HasError = true; 137 return 0; 138 } 139 140 uint64_t visitAarch64(uint32_t Rel, RelocationRef R, uint64_t Value) { 141 switch (Rel) { 142 case ELF::R_AARCH64_ABS32: { 143 int64_t Res = Value + getELFAddend(R); 144 if (Res < INT32_MIN || Res > UINT32_MAX) 145 HasError = true; 146 return static_cast<uint32_t>(Res); 147 } 148 case ELF::R_AARCH64_ABS64: 149 return Value + getELFAddend(R); 150 } 151 HasError = true; 152 return 0; 153 } 154 155 uint64_t visitBpf(uint32_t Rel, RelocationRef R, uint64_t Value) { 156 switch (Rel) { 157 case ELF::R_BPF_64_32: 158 return Value & 0xFFFFFFFF; 159 case ELF::R_BPF_64_64: 160 return Value; 161 } 162 HasError = true; 163 return 0; 164 } 165 166 uint64_t visitMips64(uint32_t Rel, RelocationRef R, uint64_t Value) { 167 switch (Rel) { 168 case ELF::R_MIPS_32: 169 return (Value + getELFAddend(R)) & 0xFFFFFFFF; 170 case ELF::R_MIPS_64: 171 return Value + getELFAddend(R); 172 case ELF::R_MIPS_TLS_DTPREL64: 173 return Value + getELFAddend(R) - 0x8000; 174 } 175 HasError = true; 176 return 0; 177 } 178 179 uint64_t visitPPC64(uint32_t Rel, RelocationRef R, uint64_t Value) { 180 switch (Rel) { 181 case ELF::R_PPC64_ADDR32: 182 return (Value + getELFAddend(R)) & 0xFFFFFFFF; 183 case ELF::R_PPC64_ADDR64: 184 return Value + getELFAddend(R); 185 } 186 HasError = true; 187 return 0; 188 } 189 190 uint64_t visitSystemz(uint32_t Rel, RelocationRef R, uint64_t Value) { 191 switch (Rel) { 192 case ELF::R_390_32: { 193 int64_t Res = Value + getELFAddend(R); 194 if (Res < INT32_MIN || Res > UINT32_MAX) 195 HasError = true; 196 return static_cast<uint32_t>(Res); 197 } 198 case ELF::R_390_64: 199 return Value + getELFAddend(R); 200 } 201 HasError = true; 202 return 0; 203 } 204 205 uint64_t visitSparc64(uint32_t Rel, RelocationRef R, uint64_t Value) { 206 switch (Rel) { 207 case ELF::R_SPARC_32: 208 case ELF::R_SPARC_64: 209 case ELF::R_SPARC_UA32: 210 case ELF::R_SPARC_UA64: 211 return Value + getELFAddend(R); 212 } 213 HasError = true; 214 return 0; 215 } 216 217 uint64_t visitAmdgpu(uint32_t Rel, RelocationRef R, uint64_t Value) { 218 switch (Rel) { 219 case ELF::R_AMDGPU_ABS32: 220 case ELF::R_AMDGPU_ABS64: 221 return Value + getELFAddend(R); 222 } 223 HasError = true; 224 return 0; 225 } 226 227 uint64_t visitX86(uint32_t Rel, RelocationRef R, uint64_t Value) { 228 switch (Rel) { 229 case ELF::R_386_NONE: 230 return 0; 231 case ELF::R_386_32: 232 return Value; 233 case ELF::R_386_PC32: 234 return Value - R.getOffset(); 235 } 236 HasError = true; 237 return 0; 238 } 239 240 uint64_t visitPPC32(uint32_t Rel, RelocationRef R, uint64_t Value) { 241 if (Rel == ELF::R_PPC_ADDR32) 242 return (Value + getELFAddend(R)) & 0xFFFFFFFF; 243 HasError = true; 244 return 0; 245 } 246 247 uint64_t visitARM(uint32_t Rel, RelocationRef R, uint64_t Value) { 248 if (Rel == ELF::R_ARM_ABS32) { 249 if ((int64_t)Value < INT32_MIN || (int64_t)Value > UINT32_MAX) 250 HasError = true; 251 return static_cast<uint32_t>(Value); 252 } 253 HasError = true; 254 return 0; 255 } 256 257 uint64_t visitLanai(uint32_t Rel, RelocationRef R, uint64_t Value) { 258 if (Rel == ELF::R_LANAI_32) 259 return (Value + getELFAddend(R)) & 0xFFFFFFFF; 260 HasError = true; 261 return 0; 262 } 263 264 uint64_t visitMips32(uint32_t Rel, RelocationRef R, uint64_t Value) { 265 // FIXME: Take in account implicit addends to get correct results. 266 if (Rel == ELF::R_MIPS_32) 267 return Value & 0xFFFFFFFF; 268 if (Rel == ELF::R_MIPS_TLS_DTPREL32) 269 return Value & 0xFFFFFFFF; 270 HasError = true; 271 return 0; 272 } 273 274 uint64_t visitSparc32(uint32_t Rel, RelocationRef R, uint64_t Value) { 275 if (Rel == ELF::R_SPARC_32 || Rel == ELF::R_SPARC_UA32) 276 return Value + getELFAddend(R); 277 HasError = true; 278 return 0; 279 } 280 281 uint64_t visitHexagon(uint32_t Rel, RelocationRef R, uint64_t Value) { 282 if (Rel == ELF::R_HEX_32) 283 return Value + getELFAddend(R); 284 HasError = true; 285 return 0; 286 } 287 288 uint64_t visitCOFF(uint32_t Rel, RelocationRef R, uint64_t Value) { 289 switch (ObjToVisit.getArch()) { 290 case Triple::x86: 291 switch (Rel) { 292 case COFF::IMAGE_REL_I386_SECREL: 293 case COFF::IMAGE_REL_I386_DIR32: 294 return static_cast<uint32_t>(Value); 295 } 296 break; 297 case Triple::x86_64: 298 switch (Rel) { 299 case COFF::IMAGE_REL_AMD64_SECREL: 300 return static_cast<uint32_t>(Value); 301 case COFF::IMAGE_REL_AMD64_ADDR64: 302 return Value; 303 } 304 break; 305 } 306 HasError = true; 307 return 0; 308 } 309 310 uint64_t visitMachO(uint32_t Rel, RelocationRef R, uint64_t Value) { 311 if (ObjToVisit.getArch() == Triple::x86_64 && 312 Rel == MachO::X86_64_RELOC_UNSIGNED) 313 return Value; 314 HasError = true; 315 return 0; 316 } 317 }; 318 319 } // end namespace object 320 } // end namespace llvm 321 322 #endif // LLVM_OBJECT_RELOCVISITOR_H 323