LLVM API Documentation

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MCWin64EH.cpp
Go to the documentation of this file.
1 //===- lib/MC/MCWin64EH.cpp - MCWin64EH implementation --------------------===//
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 #include "llvm/MC/MCWin64EH.h"
11 #include "llvm/ADT/Twine.h"
12 #include "llvm/MC/MCContext.h"
13 #include "llvm/MC/MCExpr.h"
15 #include "llvm/MC/MCSectionCOFF.h"
16 #include "llvm/MC/MCStreamer.h"
17 #include "llvm/MC/MCSymbol.h"
18 
19 namespace llvm {
20 
21 // NOTE: All relocations generated here are 4-byte image-relative.
22 
23 static uint8_t CountOfUnwindCodes(std::vector<MCWin64EHInstruction> &instArray){
24  uint8_t count = 0;
25  for (std::vector<MCWin64EHInstruction>::const_iterator I = instArray.begin(),
26  E = instArray.end(); I != E; ++I) {
27  switch (I->getOperation()) {
32  count += 1;
33  break;
36  count += 2;
37  break;
40  count += 3;
41  break;
43  if (I->getSize() > 512*1024-8)
44  count += 3;
45  else
46  count += 2;
47  break;
48  }
49  }
50  return count;
51 }
52 
53 static void EmitAbsDifference(MCStreamer &streamer, MCSymbol *lhs,
54  MCSymbol *rhs) {
55  MCContext &context = streamer.getContext();
57  lhs, context),
59  rhs, context),
60  context);
61  streamer.EmitAbsValue(diff, 1);
62 
63 }
64 
65 static void EmitUnwindCode(MCStreamer &streamer, MCSymbol *begin,
66  MCWin64EHInstruction &inst) {
67  uint8_t b2;
68  uint16_t w;
69  b2 = (inst.getOperation() & 0x0F);
70  switch (inst.getOperation()) {
72  EmitAbsDifference(streamer, inst.getLabel(), begin);
73  b2 |= (inst.getRegister() & 0x0F) << 4;
74  streamer.EmitIntValue(b2, 1);
75  break;
77  EmitAbsDifference(streamer, inst.getLabel(), begin);
78  if (inst.getSize() > 512*1024-8) {
79  b2 |= 0x10;
80  streamer.EmitIntValue(b2, 1);
81  w = inst.getSize() & 0xFFF8;
82  streamer.EmitIntValue(w, 2);
83  w = inst.getSize() >> 16;
84  } else {
85  streamer.EmitIntValue(b2, 1);
86  w = inst.getSize() >> 3;
87  }
88  streamer.EmitIntValue(w, 2);
89  break;
91  b2 |= (((inst.getSize()-8) >> 3) & 0x0F) << 4;
92  EmitAbsDifference(streamer, inst.getLabel(), begin);
93  streamer.EmitIntValue(b2, 1);
94  break;
96  EmitAbsDifference(streamer, inst.getLabel(), begin);
97  streamer.EmitIntValue(b2, 1);
98  break;
101  b2 |= (inst.getRegister() & 0x0F) << 4;
102  EmitAbsDifference(streamer, inst.getLabel(), begin);
103  streamer.EmitIntValue(b2, 1);
104  w = inst.getOffset() >> 3;
106  w >>= 1;
107  streamer.EmitIntValue(w, 2);
108  break;
111  b2 |= (inst.getRegister() & 0x0F) << 4;
112  EmitAbsDifference(streamer, inst.getLabel(), begin);
113  streamer.EmitIntValue(b2, 1);
115  w = inst.getOffset() & 0xFFF0;
116  else
117  w = inst.getOffset() & 0xFFF8;
118  streamer.EmitIntValue(w, 2);
119  w = inst.getOffset() >> 16;
120  streamer.EmitIntValue(w, 2);
121  break;
123  if (inst.isPushCodeFrame())
124  b2 |= 0x10;
125  EmitAbsDifference(streamer, inst.getLabel(), begin);
126  streamer.EmitIntValue(b2, 1);
127  break;
128  }
129 }
130 
131 static void EmitSymbolRefWithOfs(MCStreamer &streamer,
132  const MCSymbol *Base,
133  const MCSymbol *Other) {
134  MCContext &Context = streamer.getContext();
135  const MCSymbolRefExpr *BaseRef = MCSymbolRefExpr::Create(Base, Context);
136  const MCSymbolRefExpr *OtherRef = MCSymbolRefExpr::Create(Other, Context);
137  const MCExpr *Ofs = MCBinaryExpr::CreateSub(OtherRef, BaseRef, Context);
138  const MCSymbolRefExpr *BaseRefRel = MCSymbolRefExpr::Create(Base,
140  Context);
141  streamer.EmitValue(MCBinaryExpr::CreateAdd(BaseRefRel, Ofs, Context), 4);
142 }
143 
144 static void EmitRuntimeFunction(MCStreamer &streamer,
145  const MCWin64EHUnwindInfo *info) {
146  MCContext &context = streamer.getContext();
147 
148  streamer.EmitValueToAlignment(4);
149  EmitSymbolRefWithOfs(streamer, info->Function, info->Begin);
150  EmitSymbolRefWithOfs(streamer, info->Function, info->End);
153  context), 4);
154 }
155 
157  // If this UNWIND_INFO already has a symbol, it's already been emitted.
158  if (info->Symbol) return;
159 
160  MCContext &context = streamer.getContext();
161  streamer.EmitValueToAlignment(4);
162  info->Symbol = context.CreateTempSymbol();
163  streamer.EmitLabel(info->Symbol);
164 
165  // Upper 3 bits are the version number (currently 1).
166  uint8_t flags = 0x01;
167  if (info->ChainedParent)
168  flags |= Win64EH::UNW_ChainInfo << 3;
169  else {
170  if (info->HandlesUnwind)
171  flags |= Win64EH::UNW_TerminateHandler << 3;
172  if (info->HandlesExceptions)
173  flags |= Win64EH::UNW_ExceptionHandler << 3;
174  }
175  streamer.EmitIntValue(flags, 1);
176 
177  if (info->PrologEnd)
178  EmitAbsDifference(streamer, info->PrologEnd, info->Begin);
179  else
180  streamer.EmitIntValue(0, 1);
181 
182  uint8_t numCodes = CountOfUnwindCodes(info->Instructions);
183  streamer.EmitIntValue(numCodes, 1);
184 
185  uint8_t frame = 0;
186  if (info->LastFrameInst >= 0) {
187  MCWin64EHInstruction &frameInst = info->Instructions[info->LastFrameInst];
188  assert(frameInst.getOperation() == Win64EH::UOP_SetFPReg);
189  frame = (frameInst.getRegister() & 0x0F) |
190  (frameInst.getOffset() & 0xF0);
191  }
192  streamer.EmitIntValue(frame, 1);
193 
194  // Emit unwind instructions (in reverse order).
195  uint8_t numInst = info->Instructions.size();
196  for (uint8_t c = 0; c < numInst; ++c) {
197  MCWin64EHInstruction inst = info->Instructions.back();
198  info->Instructions.pop_back();
199  EmitUnwindCode(streamer, info->Begin, inst);
200  }
201 
202  // For alignment purposes, the instruction array will always have an even
203  // number of entries, with the final entry potentially unused (in which case
204  // the array will be one longer than indicated by the count of unwind codes
205  // field).
206  if (numCodes & 1) {
207  streamer.EmitIntValue(0, 2);
208  }
209 
210  if (flags & (Win64EH::UNW_ChainInfo << 3))
211  EmitRuntimeFunction(streamer, info->ChainedParent);
212  else if (flags &
216  context), 4);
217  else if (numCodes == 0) {
218  // The minimum size of an UNWIND_INFO struct is 8 bytes. If we're not
219  // a chained unwind info, if there is no handler, and if there are fewer
220  // than 2 slots used in the unwind code array, we have to pad to 8 bytes.
221  streamer.EmitIntValue(0, 4);
222  }
223 }
224 
226  if (!func || !func->isInSection()) return "";
227  const MCSection *section = &func->getSection();
228  const MCSectionCOFF *COFFSection;
229  if ((COFFSection = dyn_cast<MCSectionCOFF>(section))) {
230  StringRef name = COFFSection->getSectionName();
231  size_t dollar = name.find('$');
232  size_t dot = name.find('.', 1);
233  if (dollar == StringRef::npos && dot == StringRef::npos)
234  return "";
235  if (dot == StringRef::npos)
236  return name.substr(dollar);
237  if (dollar == StringRef::npos || dot < dollar)
238  return name.substr(dot);
239  return name.substr(dollar);
240  }
241  return "";
242 }
243 
245  MCContext &context) {
246  if (suffix == "")
247  return context.getObjectFileInfo()->getXDataSection();
248 
249  return context.getCOFFSection((".xdata"+suffix).str(),
250  COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
251  COFF::IMAGE_SCN_MEM_READ,
253 }
254 
256  MCContext &context) {
257  if (suffix == "")
258  return context.getObjectFileInfo()->getPDataSection();
259  return context.getCOFFSection((".pdata"+suffix).str(),
260  COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
261  COFF::IMAGE_SCN_MEM_READ,
263 }
264 
267  // Switch sections (the static function above is meant to be called from
268  // here and from Emit().
269  MCContext &context = streamer.getContext();
270  const MCSection *xdataSect =
272  streamer.SwitchSection(xdataSect);
273 
274  llvm::EmitUnwindInfo(streamer, info);
275 }
276 
278  MCContext &context = streamer.getContext();
279  // Emit the unwind info structs first.
280  for (unsigned i = 0; i < streamer.getNumW64UnwindInfos(); ++i) {
282  const MCSection *xdataSect =
284  streamer.SwitchSection(xdataSect);
285  llvm::EmitUnwindInfo(streamer, &info);
286  }
287  // Now emit RUNTIME_FUNCTION entries.
288  for (unsigned i = 0; i < streamer.getNumW64UnwindInfos(); ++i) {
290  const MCSection *pdataSect =
292  streamer.SwitchSection(pdataSect);
293  EmitRuntimeFunction(streamer, &info);
294  }
295 }
296 
297 } // End of namespace llvm
298 
const MCSymbol * ExceptionHandler
Definition: MCWin64EH.h:71
const MCSymbol * Function
Definition: MCWin64EH.h:72
const MCSection * getPDataSection() const
size_t find(char C, size_t From=0) const
Definition: StringRef.h:233
static SectionKind getDataRel()
Definition: SectionKind.h:229
StringRef substr(size_t Start, size_t N=npos) const
Definition: StringRef.h:392
const_iterator begin(StringRef path)
Get begin iterator over path.
Definition: Path.cpp:173
static void EmitUnwindInfo(MCStreamer &streamer, MCWin64EHUnwindInfo *info)
Definition: MCWin64EH.cpp:156
MCSectionCOFF - This represents a section on Windows.
Definition: MCSectionCOFF.h:24
lazy value info
static void EmitRuntimeFunction(MCStreamer &streamer, const MCWin64EHUnwindInfo *info)
Definition: MCWin64EH.cpp:144
const MCSection * getXDataSection() const
MCSymbol * CreateTempSymbol()
Definition: MCContext.cpp:165
const MCSection & getSection() const
Definition: MCSymbol.h:111
static void EmitSymbolRefWithOfs(MCStreamer &streamer, const MCSymbol *Base, const MCSymbol *Other)
Definition: MCWin64EH.cpp:131
unsigned getSize() const
Definition: MCWin64EH.h:58
static const MCSection * getWin64EHTableSection(StringRef suffix, MCContext &context)
Definition: MCWin64EH.cpp:244
MCContext & getContext() const
Definition: MCStreamer.h:168
static const MCBinaryExpr * CreateSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:460
bool isInSection() const
Definition: MCSymbol.h:95
void SwitchSection(const MCSection *Section, const MCExpr *Subsection=0)
Definition: MCStreamer.h:284
unsigned getRegister() const
Definition: MCWin64EH.h:59
std::vector< MCWin64EHInstruction > Instructions
Definition: MCWin64EH.h:79
bool isPushCodeFrame() const
Definition: MCWin64EH.h:60
static void Emit(MCStreamer &streamer)
Definition: MCWin64EH.cpp:277
MCWin64EHUnwindInfo & getW64UnwindInfo(unsigned i)
Definition: MCStreamer.h:183
virtual void EmitIntValue(uint64_t Value, unsigned Size)
Definition: MCStreamer.cpp:104
void EmitValue(const MCExpr *Value, unsigned Size)
Definition: MCStreamer.cpp:141
static const MCSymbolRefExpr * Create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:270
static const MCSection * getWin64EHFuncTableSection(StringRef suffix, MCContext &context)
Definition: MCWin64EH.cpp:255
unsigned getNumW64UnwindInfos()
Definition: MCStreamer.h:181
static uint8_t CountOfUnwindCodes(std::vector< MCWin64EHInstruction > &instArray)
Definition: MCWin64EH.cpp:23
OpType getOperation() const
Definition: MCWin64EH.h:55
static StringRef GetSectionSuffix(const MCSymbol *func)
Definition: MCWin64EH.cpp:225
virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value=0, unsigned ValueSize=1, unsigned MaxBytesToEmit=0)=0
const MCSectionCOFF * getCOFFSection(StringRef Section, unsigned Characteristics, SectionKind Kind, int Selection=0, const MCSectionCOFF *Assoc=0)
Definition: MCContext.cpp:283
static void EmitUnwindCode(MCStreamer &streamer, MCSymbol *begin, MCWin64EHInstruction &inst)
Definition: MCWin64EH.cpp:65
virtual void EmitLabel(MCSymbol *Symbol)
Definition: MCStreamer.cpp:212
StringRef getSectionName() const
Definition: MCSectionCOFF.h:63
static void EmitAbsDifference(MCStreamer &streamer, MCSymbol *lhs, MCSymbol *rhs)
Definition: MCWin64EH.cpp:53
MCWin64EHUnwindInfo * ChainedParent
Definition: MCWin64EH.h:78
static const MCBinaryExpr * CreateAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:396
static const size_t npos
Definition: StringRef.h:45
#define I(x, y, z)
Definition: MD5.cpp:54
void EmitAbsValue(const MCExpr *Value, unsigned Size)
Definition: MCStreamer.cpp:135
unsigned getOffset() const
Definition: MCWin64EH.h:57
const MCObjectFileInfo * getObjectFileInfo() const
Definition: MCContext.h:179
static void EmitUnwindInfo(MCStreamer &streamer, MCWin64EHUnwindInfo *info)
Definition: MCWin64EH.cpp:265
MCSymbol * getLabel() const
Definition: MCWin64EH.h:56