LLVM API Documentation

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ARMELFObjectWriter.cpp
Go to the documentation of this file.
1 //===-- ARMELFObjectWriter.cpp - ARM ELF Writer ---------------------------===//
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 
12 #include "llvm/ADT/Statistic.h"
13 #include "llvm/ADT/StringSwitch.h"
15 #include "llvm/MC/MCExpr.h"
16 #include "llvm/MC/MCSectionELF.h"
17 #include "llvm/MC/MCValue.h"
18 #include "llvm/Support/Debug.h"
21 
22 using namespace llvm;
23 
24 namespace {
25  class ARMELFObjectWriter : public MCELFObjectTargetWriter {
26  enum { DefaultEABIVersion = 0x05000000U };
27  unsigned GetRelocTypeInner(const MCValue &Target,
28  const MCFixup &Fixup,
29  bool IsPCRel) const;
30 
31 
32  public:
33  ARMELFObjectWriter(uint8_t OSABI);
34 
35  virtual ~ARMELFObjectWriter();
36 
37  virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
38  bool IsPCRel, bool IsRelocWithSymbol,
39  int64_t Addend) const;
40  virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm,
41  const MCValue &Target,
42  const MCFragment &F,
43  const MCFixup &Fixup,
44  bool IsPCRel) const;
45  };
46 }
47 
48 ARMELFObjectWriter::ARMELFObjectWriter(uint8_t OSABI)
49  : MCELFObjectTargetWriter(/*Is64Bit*/ false, OSABI,
50  ELF::EM_ARM,
51  /*HasRelocationAddend*/ false) {}
52 
53 ARMELFObjectWriter::~ARMELFObjectWriter() {}
54 
55 // In ARM, _MergedGlobals and other most symbols get emitted directly.
56 // I.e. not as an offset to a section symbol.
57 // This code is an approximation of what ARM/gcc does.
58 
59 STATISTIC(PCRelCount, "Total number of PIC Relocations");
60 STATISTIC(NonPCRelCount, "Total number of non-PIC relocations");
61 
62 const MCSymbol *ARMELFObjectWriter::ExplicitRelSym(const MCAssembler &Asm,
63  const MCValue &Target,
64  const MCFragment &F,
65  const MCFixup &Fixup,
66  bool IsPCRel) const {
67  const MCSymbol &Symbol = Target.getSymA()->getSymbol().AliasedSymbol();
68  bool EmitThisSym = false;
69 
70  const MCSectionELF &Section =
71  static_cast<const MCSectionELF&>(Symbol.getSection());
72  bool InNormalSection = true;
73  unsigned RelocType = 0;
74  RelocType = GetRelocTypeInner(Target, Fixup, IsPCRel);
75 
76  DEBUG(
79  Kind2 = Target.getSymB() ? Target.getSymB()->getKind() :
80  MCSymbolRefExpr::VK_None;
81  dbgs() << "considering symbol "
82  << Section.getSectionName() << "/"
83  << Symbol.getName() << "/"
84  << " Rel:" << (unsigned)RelocType
85  << " Kind: " << (int)Kind << "/" << (int)Kind2
86  << " Tmp:"
87  << Symbol.isAbsolute() << "/" << Symbol.isDefined() << "/"
88  << Symbol.isVariable() << "/" << Symbol.isTemporary()
89  << " Counts:" << PCRelCount << "/" << NonPCRelCount << "\n");
90 
91  if (IsPCRel) { ++PCRelCount;
92  switch (RelocType) {
93  default:
94  // Most relocation types are emitted as explicit symbols
95  InNormalSection =
97  .Case(".data.rel.ro.local", false)
98  .Case(".data.rel", false)
99  .Case(".bss", false)
100  .Default(true);
101  EmitThisSym = true;
102  break;
103  case ELF::R_ARM_ABS32:
104  // But things get strange with R_ARM_ABS32
105  // In this case, most things that go in .rodata show up
106  // as section relative relocations
107  InNormalSection =
109  .Case(".data.rel.ro.local", false)
110  .Case(".data.rel", false)
111  .Case(".rodata", false)
112  .Case(".bss", false)
113  .Default(true);
114  EmitThisSym = false;
115  break;
116  }
117  } else {
118  NonPCRelCount++;
119  InNormalSection =
121  .Case(".data.rel.ro.local", false)
122  .Case(".rodata", false)
123  .Case(".data.rel", false)
124  .Case(".bss", false)
125  .Default(true);
126 
127  switch (RelocType) {
128  default: EmitThisSym = true; break;
129  case ELF::R_ARM_ABS32: EmitThisSym = false; break;
130  case ELF::R_ARM_PREL31: EmitThisSym = false; break;
131  }
132  }
133 
134  if (EmitThisSym)
135  return &Symbol;
136  if (! Symbol.isTemporary() && InNormalSection) {
137  return &Symbol;
138  }
139  return NULL;
140 }
141 
142 // Need to examine the Fixup when determining whether to
143 // emit the relocation as an explicit symbol or as a section relative
144 // offset
145 unsigned ARMELFObjectWriter::GetRelocType(const MCValue &Target,
146  const MCFixup &Fixup,
147  bool IsPCRel,
148  bool IsRelocWithSymbol,
149  int64_t Addend) const {
150  return GetRelocTypeInner(Target, Fixup, IsPCRel);
151 }
152 
153 unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target,
154  const MCFixup &Fixup,
155  bool IsPCRel) const {
156  MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ?
157  MCSymbolRefExpr::VK_None : Target.getSymA()->getKind();
158 
159  unsigned Type = 0;
160  if (IsPCRel) {
161  switch ((unsigned)Fixup.getKind()) {
162  default: llvm_unreachable("Unimplemented");
163  case FK_Data_4:
164  switch (Modifier) {
165  default: llvm_unreachable("Unsupported Modifier");
166  case MCSymbolRefExpr::VK_None:
167  Type = ELF::R_ARM_REL32;
168  break;
169  case MCSymbolRefExpr::VK_ARM_TLSGD:
170  llvm_unreachable("unimplemented");
171  case MCSymbolRefExpr::VK_ARM_GOTTPOFF:
172  Type = ELF::R_ARM_TLS_IE32;
173  break;
174  }
175  break;
176  case ARM::fixup_arm_blx:
178  switch (Modifier) {
179  case MCSymbolRefExpr::VK_ARM_PLT:
180  Type = ELF::R_ARM_PLT32;
181  break;
182  default:
183  Type = ELF::R_ARM_CALL;
184  break;
185  }
186  break;
190  Type = ELF::R_ARM_JUMP24;
191  break;
194  Type = ELF::R_ARM_THM_JUMP24;
195  break;
198  Type = ELF::R_ARM_MOVT_PREL;
199  break;
203  break;
207  break;
211  break;
214  Type = ELF::R_ARM_THM_CALL;
215  break;
216  }
217  } else {
218  switch ((unsigned)Fixup.getKind()) {
219  default: llvm_unreachable("invalid fixup kind!");
220  case FK_Data_4:
221  switch (Modifier) {
222  default: llvm_unreachable("Unsupported Modifier");
223  case MCSymbolRefExpr::VK_ARM_NONE:
224  Type = ELF::R_ARM_NONE;
225  break;
226  case MCSymbolRefExpr::VK_ARM_GOT:
227  Type = ELF::R_ARM_GOT_BREL;
228  break;
229  case MCSymbolRefExpr::VK_ARM_TLSGD:
230  Type = ELF::R_ARM_TLS_GD32;
231  break;
232  case MCSymbolRefExpr::VK_ARM_TPOFF:
233  Type = ELF::R_ARM_TLS_LE32;
234  break;
235  case MCSymbolRefExpr::VK_ARM_GOTTPOFF:
236  Type = ELF::R_ARM_TLS_IE32;
237  break;
238  case MCSymbolRefExpr::VK_None:
239  Type = ELF::R_ARM_ABS32;
240  break;
241  case MCSymbolRefExpr::VK_ARM_GOTOFF:
242  Type = ELF::R_ARM_GOTOFF32;
243  break;
244  case MCSymbolRefExpr::VK_ARM_TARGET1:
245  Type = ELF::R_ARM_TARGET1;
246  break;
247  case MCSymbolRefExpr::VK_ARM_TARGET2:
248  Type = ELF::R_ARM_TARGET2;
249  break;
250  case MCSymbolRefExpr::VK_ARM_PREL31:
251  Type = ELF::R_ARM_PREL31;
252  break;
253  }
254  break;
262  llvm_unreachable("Unimplemented");
265  Type = ELF::R_ARM_JUMP24;
266  break;
268  Type = ELF::R_ARM_MOVT_ABS;
269  break;
271  Type = ELF::R_ARM_MOVW_ABS_NC;
272  break;
275  break;
278  break;
279  }
280  }
281 
282  return Type;
283 }
284 
286  uint8_t OSABI) {
287  MCELFObjectTargetWriter *MOTW = new ARMELFObjectWriter(OSABI);
288  return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/true);
289 }
COFF::RelocationTypeX86 Type
Definition: COFFYAML.cpp:227
StringRef getSectionName() const
Definition: MCSectionELF.h:61
const MCSymbol & getSymbol() const
Definition: MCExpr.h:283
F(f)
StringSwitch & Case(const char(&S)[N], const T &Value)
Definition: StringSwitch.h:55
const MCSection & getSection() const
Definition: MCSymbol.h:111
#define llvm_unreachable(msg)
#define false
Definition: ConvertUTF.c:64
A four-byte fixup.
Definition: MCFixup.h:25
bool isAbsolute() const
isAbsolute - Is this an absolute (as opposed to relocatable) value.
Definition: MCValue.h:47
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:42
STATISTIC(PCRelCount,"Total number of PIC Relocations")
MCFixupKind getKind() const
Definition: MCFixup.h:88
const MCSymbolRefExpr * getSymB() const
Definition: MCValue.h:44
MCObjectWriter * createELFObjectWriter(MCELFObjectTargetWriter *MOTW, raw_ostream &OS, bool IsLittleEndian)
Construct a new ELF writer instance.
bool isAbsolute() const
isAbsolute - Check if this is an absolute symbol.
Definition: MCSymbol.h:105
bool isDefined() const
Definition: MCSymbol.h:89
const MCSymbolRefExpr * getSymA() const
Definition: MCValue.h:43
R Default(const T &Value) const
Definition: StringSwitch.h:111
raw_ostream & dbgs()
dbgs - Return a circular-buffered debug stream.
Definition: Debug.cpp:101
bool isTemporary() const
isTemporary - Check if this is an assembler temporary symbol.
Definition: MCSymbol.h:76
MCObjectWriter * createARMELFObjectWriter(raw_ostream &OS, uint8_t OSABI)
createARMELFObjectWriter - Construct an ELF Mach-O object writer.
StringRef getName() const
getName - Get the symbol name.
Definition: MCSymbol.h:70
const MCSymbol & AliasedSymbol() const
Definition: MCSymbol.cpp:42
bool isVariable() const
isVariable - Check if this is a variable symbol.
Definition: MCSymbol.h:132
VariantKind getKind() const
Definition: MCExpr.h:285
#define DEBUG(X)
Definition: Debug.h:97