diff options
| author | Stephen Hines <srhines@google.com> | 2013-01-21 13:15:17 -0800 |
|---|---|---|
| committer | Stephen Hines <srhines@google.com> | 2013-01-21 13:15:17 -0800 |
| commit | 059800f9e3fee2852672f846d91a2da14da7783a (patch) | |
| tree | a6ef16b7263252ae1b8069295ea9cbbae0d9467d /include/llvm/Object/RelocVisitor.h | |
| parent | cbefa15de4821975bb99fc6d74b3bdb42b2df45c (diff) | |
| parent | b6714227eda5d499f7667fc865f931126a8dc488 (diff) | |
| download | external_llvm-059800f9e3fee2852672f846d91a2da14da7783a.zip external_llvm-059800f9e3fee2852672f846d91a2da14da7783a.tar.gz external_llvm-059800f9e3fee2852672f846d91a2da14da7783a.tar.bz2 | |
Merge remote-tracking branch 'upstream/master' into merge-llvm
Conflicts:
lib/CodeGen/AsmPrinter/AsmPrinter.cpp
lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
lib/MC/MCAssembler.cpp
lib/Support/Atomic.cpp
lib/Support/Memory.cpp
lib/Target/ARM/ARMJITInfo.cpp
Change-Id: Ib339baf88df5b04870c8df1bedcfe1f877ccab8d
Diffstat (limited to 'include/llvm/Object/RelocVisitor.h')
| -rw-r--r-- | include/llvm/Object/RelocVisitor.h | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/include/llvm/Object/RelocVisitor.h b/include/llvm/Object/RelocVisitor.h new file mode 100644 index 0000000..2c2dd03 --- /dev/null +++ b/include/llvm/Object/RelocVisitor.h @@ -0,0 +1,146 @@ +//===-- RelocVisitor.h - Visitor for object file relocations -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides a wrapper around all the different types of relocations +// in different file formats, such that a client can handle them in a unified +// manner by only implementing a minimal number of functions. +// +//===----------------------------------------------------------------------===// + +#ifndef _LLVM_OBJECT_RELOCVISITOR +#define _LLVM_OBJECT_RELOCVISITOR + +#include "llvm/ADT/StringRef.h" +#include "llvm/Object/ELF.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { +namespace object { + +struct RelocToApply { + // The computed value after applying the relevant relocations. + int64_t Value; + + // The width of the value; how many bytes to touch when applying the + // relocation. + char Width; + RelocToApply(const RelocToApply &In) : Value(In.Value), Width(In.Width) {} + RelocToApply(int64_t Value, char Width) : Value(Value), Width(Width) {} + RelocToApply() : Value(0), Width(0) {} +}; + +/// @brief Base class for object file relocation visitors. +class RelocVisitor { +public: + explicit RelocVisitor(llvm::StringRef FileFormat) + : FileFormat(FileFormat), HasError(false) {} + + // TODO: Should handle multiple applied relocations via either passing in the + // previously computed value or just count paired relocations as a single + // visit. + RelocToApply visit(uint32_t RelocType, RelocationRef R, uint64_t SecAddr = 0, + uint64_t Value = 0) { + if (FileFormat == "ELF64-x86-64") { + switch (RelocType) { + case llvm::ELF::R_X86_64_NONE: + return visitELF_X86_64_NONE(R); + case llvm::ELF::R_X86_64_64: + return visitELF_X86_64_64(R, Value); + case llvm::ELF::R_X86_64_PC32: + return visitELF_X86_64_PC32(R, Value, SecAddr); + case llvm::ELF::R_X86_64_32: + return visitELF_X86_64_32(R, Value); + case llvm::ELF::R_X86_64_32S: + return visitELF_X86_64_32S(R, Value); + default: + HasError = true; + return RelocToApply(); + } + } else if (FileFormat == "ELF32-i386") { + switch (RelocType) { + case llvm::ELF::R_386_NONE: + return visitELF_386_NONE(R); + case llvm::ELF::R_386_32: + return visitELF_386_32(R, Value); + case llvm::ELF::R_386_PC32: + return visitELF_386_PC32(R, Value, SecAddr); + default: + HasError = true; + return RelocToApply(); + } + } + return RelocToApply(); + } + + bool error() { return HasError; } + +private: + llvm::StringRef FileFormat; + bool HasError; + + /// Operations + + /// 386-ELF + RelocToApply visitELF_386_NONE(RelocationRef R) { + return RelocToApply(0, 0); + } + + // Ideally the Addend here will be the addend in the data for + // the relocation. It's not actually the case for Rel relocations. + RelocToApply visitELF_386_32(RelocationRef R, uint64_t Value) { + int64_t Addend; + R.getAdditionalInfo(Addend); + return RelocToApply(Value + Addend, 4); + } + + RelocToApply visitELF_386_PC32(RelocationRef R, uint64_t Value, + uint64_t SecAddr) { + int64_t Addend; + R.getAdditionalInfo(Addend); + uint64_t Address; + R.getAddress(Address); + return RelocToApply(Value + Addend - Address, 4); + } + + /// X86-64 ELF + RelocToApply visitELF_X86_64_NONE(RelocationRef R) { + return RelocToApply(0, 0); + } + RelocToApply visitELF_X86_64_64(RelocationRef R, uint64_t Value) { + int64_t Addend; + R.getAdditionalInfo(Addend); + return RelocToApply(Value + Addend, 8); + } + RelocToApply visitELF_X86_64_PC32(RelocationRef R, uint64_t Value, + uint64_t SecAddr) { + int64_t Addend; + R.getAdditionalInfo(Addend); + uint64_t Address; + R.getAddress(Address); + return RelocToApply(Value + Addend - Address, 4); + } + RelocToApply visitELF_X86_64_32(RelocationRef R, uint64_t Value) { + int64_t Addend; + R.getAdditionalInfo(Addend); + uint32_t Res = (Value + Addend) & 0xFFFFFFFF; + return RelocToApply(Res, 4); + } + RelocToApply visitELF_X86_64_32S(RelocationRef R, uint64_t Value) { + int64_t Addend; + R.getAdditionalInfo(Addend); + int32_t Res = (Value + Addend) & 0xFFFFFFFF; + return RelocToApply(Res, 4); + } +}; + +} +} +#endif |
