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 "llvm/Support/ErrorOr.h" 29#include <cstdint> 30#include <system_error> 31 32namespace llvm { 33namespace object { 34 35/// @brief Base class for object file relocation visitors. 36class RelocVisitor { 37public: 38 explicit RelocVisitor(const ObjectFile &Obj) : ObjToVisit(Obj) {} 39 40 // TODO: Should handle multiple applied relocations via either passing in the 41 // previously computed value or just count paired relocations as a single 42 // visit. 43 uint64_t visit(uint32_t Rel, RelocationRef R, uint64_t Value = 0) { 44 if (isa<ELFObjectFileBase>(ObjToVisit)) 45 return visitELF(Rel, R, Value); 46 if (isa<COFFObjectFile>(ObjToVisit)) 47 return visitCOFF(Rel, R, Value); 48 if (isa<MachOObjectFile>(ObjToVisit)) 49 return visitMachO(Rel, R, Value); 50 51 HasError = true; 52 return 0; 53 } 54 55 bool error() { return HasError; } 56 57private: 58 const ObjectFile &ObjToVisit; 59 bool HasError = false; 60 61 uint64_t visitELF(uint32_t Rel, RelocationRef R, uint64_t Value) { 62 if (ObjToVisit.getBytesInAddress() == 8) { // 64-bit object file 63 switch (ObjToVisit.getArch()) { 64 case Triple::x86_64: 65 return visitX86_64(Rel, R, Value); 66 case Triple::aarch64: 67 case Triple::aarch64_be: 68 return visitAarch64(Rel, R, Value); 69 case Triple::bpfel: 70 case Triple::bpfeb: 71 return visitBpf(Rel, R, Value); 72 case Triple::mips64el: 73 case Triple::mips64: 74 return visitMips64(Rel, R, Value); 75 case Triple::ppc64le: 76 case Triple::ppc64: 77 return visitPPC64(Rel, R, Value); 78 case Triple::systemz: 79 return visitSystemz(Rel, R, Value); 80 case Triple::sparcv9: 81 return visitSparc64(Rel, R, Value); 82 case Triple::amdgcn: 83 return visitAmdgpu(Rel, R, Value); 84 default: 85 HasError = true; 86 return 0; 87 } 88 } 89 90 // 32-bit object file 91 assert(ObjToVisit.getBytesInAddress() == 4 && 92 "Invalid word size in object file"); 93 94 switch (ObjToVisit.getArch()) { 95 case Triple::x86: 96 return visitX86(Rel, R, Value); 97 case Triple::ppc: 98 return visitPPC32(Rel, R, Value); 99 case Triple::arm: 100 case Triple::armeb: 101 return visitARM(Rel, R, Value); 102 case Triple::lanai: 103 return visitLanai(Rel, R, Value); 104 case Triple::mipsel: 105 case Triple::mips: 106 return visitMips32(Rel, R, Value); 107 case Triple::sparc: 108 return visitSparc32(Rel, R, Value); 109 case Triple::hexagon: 110 return visitHexagon(Rel, R, Value); 111 default: 112 HasError = true; 113 return 0; 114 } 115 } 116 117 int64_t getELFAddend(RelocationRef R) { 118 ErrorOr<int64_t> AddendOrErr = ELFRelocationRef(R).getAddend(); 119 if (std::error_code EC = AddendOrErr.getError()) 120 report_fatal_error(EC.message()); 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 } 173 HasError = true; 174 return 0; 175 } 176 177 uint64_t visitPPC64(uint32_t Rel, RelocationRef R, uint64_t Value) { 178 switch (Rel) { 179 case ELF::R_PPC64_ADDR32: 180 return (Value + getELFAddend(R)) & 0xFFFFFFFF; 181 case ELF::R_PPC64_ADDR64: 182 return Value + getELFAddend(R); 183 } 184 HasError = true; 185 return 0; 186 } 187 188 uint64_t visitSystemz(uint32_t Rel, RelocationRef R, uint64_t Value) { 189 switch (Rel) { 190 case ELF::R_390_32: { 191 int64_t Res = Value + getELFAddend(R); 192 if (Res < INT32_MIN || Res > UINT32_MAX) 193 HasError = true; 194 return static_cast<uint32_t>(Res); 195 } 196 case ELF::R_390_64: 197 return Value + getELFAddend(R); 198 } 199 HasError = true; 200 return 0; 201 } 202 203 uint64_t visitSparc64(uint32_t Rel, RelocationRef R, uint64_t Value) { 204 switch (Rel) { 205 case ELF::R_SPARC_32: 206 case ELF::R_SPARC_64: 207 case ELF::R_SPARC_UA32: 208 case ELF::R_SPARC_UA64: 209 return Value + getELFAddend(R); 210 } 211 HasError = true; 212 return 0; 213 } 214 215 uint64_t visitAmdgpu(uint32_t Rel, RelocationRef R, uint64_t Value) { 216 switch (Rel) { 217 case ELF::R_AMDGPU_ABS32: 218 case ELF::R_AMDGPU_ABS64: 219 return Value + getELFAddend(R); 220 } 221 HasError = true; 222 return 0; 223 } 224 225 uint64_t visitX86(uint32_t Rel, RelocationRef R, uint64_t Value) { 226 switch (Rel) { 227 case ELF::R_386_NONE: 228 return 0; 229 case ELF::R_386_32: 230 return Value; 231 case ELF::R_386_PC32: 232 return Value - R.getOffset(); 233 } 234 HasError = true; 235 return 0; 236 } 237 238 uint64_t visitPPC32(uint32_t Rel, RelocationRef R, uint64_t Value) { 239 if (Rel == ELF::R_PPC_ADDR32) 240 return (Value + getELFAddend(R)) & 0xFFFFFFFF; 241 HasError = true; 242 return 0; 243 } 244 245 uint64_t visitARM(uint32_t Rel, RelocationRef R, uint64_t Value) { 246 if (Rel == ELF::R_ARM_ABS32) { 247 if ((int64_t)Value < INT32_MIN || (int64_t)Value > UINT32_MAX) 248 HasError = true; 249 return static_cast<uint32_t>(Value); 250 } 251 HasError = true; 252 return 0; 253 } 254 255 uint64_t visitLanai(uint32_t Rel, RelocationRef R, uint64_t Value) { 256 if (Rel == ELF::R_LANAI_32) 257 return (Value + getELFAddend(R)) & 0xFFFFFFFF; 258 HasError = true; 259 return 0; 260 } 261 262 uint64_t visitMips32(uint32_t Rel, RelocationRef R, uint64_t Value) { 263 if (Rel == ELF::R_MIPS_32) 264 return Value & 0xFFFFFFFF; 265 HasError = true; 266 return 0; 267 } 268 269 uint64_t visitSparc32(uint32_t Rel, RelocationRef R, uint64_t Value) { 270 if (Rel == ELF::R_SPARC_32 || Rel == ELF::R_SPARC_UA32) 271 return Value + getELFAddend(R); 272 HasError = true; 273 return 0; 274 } 275 276 uint64_t visitHexagon(uint32_t Rel, RelocationRef R, uint64_t Value) { 277 if (Rel == ELF::R_HEX_32) 278 return Value + getELFAddend(R); 279 HasError = true; 280 return 0; 281 } 282 283 uint64_t visitCOFF(uint32_t Rel, RelocationRef R, uint64_t Value) { 284 switch (ObjToVisit.getArch()) { 285 case Triple::x86: 286 switch (Rel) { 287 case COFF::IMAGE_REL_I386_SECREL: 288 case COFF::IMAGE_REL_I386_DIR32: 289 return static_cast<uint32_t>(Value); 290 } 291 break; 292 case Triple::x86_64: 293 switch (Rel) { 294 case COFF::IMAGE_REL_AMD64_SECREL: 295 return static_cast<uint32_t>(Value); 296 case COFF::IMAGE_REL_AMD64_ADDR64: 297 return Value; 298 } 299 break; 300 } 301 HasError = true; 302 return 0; 303 } 304 305 uint64_t visitMachO(uint32_t Rel, RelocationRef R, uint64_t Value) { 306 if (ObjToVisit.getArch() == Triple::x86_64 && 307 Rel == MachO::X86_64_RELOC_UNSIGNED) 308 return Value; 309 HasError = true; 310 return 0; 311 } 312}; 313 314} // end namespace object 315} // end namespace llvm 316 317#endif // LLVM_OBJECT_RELOCVISITOR_H 318