ARMELFStreamer.cpp revision a363b117f41700da0200753e6df62b5e2cb38378
1//===- lib/MC/ARMELFStreamer.cpp - ELF Object Output for ARM --------------===//
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 assembles .s files and emits ARM ELF .o object files. Different
11// from generic ELF streamer in emitting mapping symbols ($a, $t and $d) to
12// delimit regions of data and code.
13//
14//===----------------------------------------------------------------------===//
15
16#include "ARMRegisterInfo.h"
17#include "ARMUnwindOp.h"
18#include "ARMUnwindOpAsm.h"
19#include "llvm/ADT/SmallPtrSet.h"
20#include "llvm/ADT/Twine.h"
21#include "llvm/MC/MCAsmBackend.h"
22#include "llvm/MC/MCAssembler.h"
23#include "llvm/MC/MCCodeEmitter.h"
24#include "llvm/MC/MCContext.h"
25#include "llvm/MC/MCELF.h"
26#include "llvm/MC/MCELFStreamer.h"
27#include "llvm/MC/MCELFSymbolFlags.h"
28#include "llvm/MC/MCExpr.h"
29#include "llvm/MC/MCInst.h"
30#include "llvm/MC/MCObjectStreamer.h"
31#include "llvm/MC/MCRegisterInfo.h"
32#include "llvm/MC/MCSection.h"
33#include "llvm/MC/MCSectionELF.h"
34#include "llvm/MC/MCStreamer.h"
35#include "llvm/MC/MCSymbol.h"
36#include "llvm/MC/MCValue.h"
37#include "llvm/Support/Debug.h"
38#include "llvm/Support/ELF.h"
39#include "llvm/Support/raw_ostream.h"
40
41using namespace llvm;
42
43static std::string GetAEABIUnwindPersonalityName(unsigned Index) {
44  assert(Index < NUM_PERSONALITY_INDEX && "Invalid personality index");
45  return (Twine("__aeabi_unwind_cpp_pr") + Twine(Index)).str();
46}
47
48namespace {
49
50/// Extend the generic ELFStreamer class so that it can emit mapping symbols at
51/// the appropriate points in the object files. These symbols are defined in the
52/// ARM ELF ABI: infocenter.arm.com/help/topic/com.arm.../IHI0044D_aaelf.pdf.
53///
54/// In brief: $a, $t or $d should be emitted at the start of each contiguous
55/// region of ARM code, Thumb code or data in a section. In practice, this
56/// emission does not rely on explicit assembler directives but on inherent
57/// properties of the directives doing the emission (e.g. ".byte" is data, "add
58/// r0, r0, r0" an instruction).
59///
60/// As a result this system is orthogonal to the DataRegion infrastructure used
61/// by MachO. Beware!
62class ARMELFStreamer : public MCELFStreamer {
63public:
64  ARMELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS,
65                 MCCodeEmitter *Emitter, bool IsThumb)
66      : MCELFStreamer(SK_ARMELFStreamer, Context, TAB, OS, Emitter),
67        IsThumb(IsThumb), MappingSymbolCounter(0), LastEMS(EMS_None) {
68    Reset();
69  }
70
71  ~ARMELFStreamer() {}
72
73  // ARM exception handling directives
74  virtual void EmitFnStart();
75  virtual void EmitFnEnd();
76  virtual void EmitCantUnwind();
77  virtual void EmitPersonality(const MCSymbol *Per);
78  virtual void EmitHandlerData();
79  virtual void EmitSetFP(unsigned NewFpReg,
80                         unsigned NewSpReg,
81                         int64_t Offset = 0);
82  virtual void EmitPad(int64_t Offset);
83  virtual void EmitRegSave(const SmallVectorImpl<unsigned> &RegList,
84                           bool isVector);
85
86  virtual void ChangeSection(const MCSection *Section) {
87    // We have to keep track of the mapping symbol state of any sections we
88    // use. Each one should start off as EMS_None, which is provided as the
89    // default constructor by DenseMap::lookup.
90    LastMappingSymbols[getPreviousSection()] = LastEMS;
91    LastEMS = LastMappingSymbols.lookup(Section);
92
93    MCELFStreamer::ChangeSection(Section);
94  }
95
96  /// This function is the one used to emit instruction data into the ELF
97  /// streamer. We override it to add the appropriate mapping symbol if
98  /// necessary.
99  virtual void EmitInstruction(const MCInst& Inst) {
100    if (IsThumb)
101      EmitThumbMappingSymbol();
102    else
103      EmitARMMappingSymbol();
104
105    MCELFStreamer::EmitInstruction(Inst);
106  }
107
108  /// This is one of the functions used to emit data into an ELF section, so the
109  /// ARM streamer overrides it to add the appropriate mapping symbol ($d) if
110  /// necessary.
111  virtual void EmitBytes(StringRef Data, unsigned AddrSpace) {
112    EmitDataMappingSymbol();
113    MCELFStreamer::EmitBytes(Data, AddrSpace);
114  }
115
116  /// This is one of the functions used to emit data into an ELF section, so the
117  /// ARM streamer overrides it to add the appropriate mapping symbol ($d) if
118  /// necessary.
119  virtual void EmitValueImpl(const MCExpr *Value, unsigned Size,
120                             unsigned AddrSpace) {
121    EmitDataMappingSymbol();
122    MCELFStreamer::EmitValueImpl(Value, Size, AddrSpace);
123  }
124
125  virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) {
126    MCELFStreamer::EmitAssemblerFlag(Flag);
127
128    switch (Flag) {
129    case MCAF_SyntaxUnified:
130      return; // no-op here.
131    case MCAF_Code16:
132      IsThumb = true;
133      return; // Change to Thumb mode
134    case MCAF_Code32:
135      IsThumb = false;
136      return; // Change to ARM mode
137    case MCAF_Code64:
138      return;
139    case MCAF_SubsectionsViaSymbols:
140      return;
141    }
142  }
143
144  static bool classof(const MCStreamer *S) {
145    return S->getKind() == SK_ARMELFStreamer;
146  }
147
148private:
149  enum ElfMappingSymbol {
150    EMS_None,
151    EMS_ARM,
152    EMS_Thumb,
153    EMS_Data
154  };
155
156  void EmitDataMappingSymbol() {
157    if (LastEMS == EMS_Data) return;
158    EmitMappingSymbol("$d");
159    LastEMS = EMS_Data;
160  }
161
162  void EmitThumbMappingSymbol() {
163    if (LastEMS == EMS_Thumb) return;
164    EmitMappingSymbol("$t");
165    LastEMS = EMS_Thumb;
166  }
167
168  void EmitARMMappingSymbol() {
169    if (LastEMS == EMS_ARM) return;
170    EmitMappingSymbol("$a");
171    LastEMS = EMS_ARM;
172  }
173
174  void EmitMappingSymbol(StringRef Name) {
175    MCSymbol *Start = getContext().CreateTempSymbol();
176    EmitLabel(Start);
177
178    MCSymbol *Symbol =
179      getContext().GetOrCreateSymbol(Name + "." +
180                                     Twine(MappingSymbolCounter++));
181
182    MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
183    MCELF::SetType(SD, ELF::STT_NOTYPE);
184    MCELF::SetBinding(SD, ELF::STB_LOCAL);
185    SD.setExternal(false);
186    Symbol->setSection(*getCurrentSection());
187
188    const MCExpr *Value = MCSymbolRefExpr::Create(Start, getContext());
189    Symbol->setVariableValue(Value);
190  }
191
192  void EmitThumbFunc(MCSymbol *Func) {
193    // FIXME: Anything needed here to flag the function as thumb?
194
195    getAssembler().setIsThumbFunc(Func);
196
197    MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Func);
198    SD.setFlags(SD.getFlags() | ELF_Other_ThumbFunc);
199  }
200
201  // Helper functions for ARM exception handling directives
202  void Reset();
203
204  void EmitPersonalityFixup(StringRef Name);
205  void CollectUnwindOpcodes();
206
207  void SwitchToEHSection(const char *Prefix, unsigned Type, unsigned Flags,
208                         SectionKind Kind, const MCSymbol &Fn);
209  void SwitchToExTabSection(const MCSymbol &FnStart);
210  void SwitchToExIdxSection(const MCSymbol &FnStart);
211
212  bool IsThumb;
213  int64_t MappingSymbolCounter;
214
215  DenseMap<const MCSection *, ElfMappingSymbol> LastMappingSymbols;
216  ElfMappingSymbol LastEMS;
217
218  // ARM Exception Handling Frame Information
219  MCSymbol *ExTab;
220  MCSymbol *FnStart;
221  const MCSymbol *Personality;
222  uint32_t VFPRegSave; // Register mask for {d31-d0}
223  uint32_t RegSave; // Register mask for {r15-r0}
224  int64_t SPOffset;
225  uint16_t FPReg;
226  int64_t FPOffset;
227  bool UsedFP;
228  bool CantUnwind;
229  UnwindOpcodeAssembler UnwindOpAsm;
230};
231} // end anonymous namespace
232
233inline void ARMELFStreamer::SwitchToEHSection(const char *Prefix,
234                                              unsigned Type,
235                                              unsigned Flags,
236                                              SectionKind Kind,
237                                              const MCSymbol &Fn) {
238  const MCSectionELF &FnSection =
239    static_cast<const MCSectionELF &>(Fn.getSection());
240
241  // Create the name for new section
242  StringRef FnSecName(FnSection.getSectionName());
243  SmallString<128> EHSecName(Prefix);
244  if (FnSecName != ".text") {
245    EHSecName += FnSecName;
246  }
247
248  // Get .ARM.extab or .ARM.exidx section
249  const MCSectionELF *EHSection = NULL;
250  if (const MCSymbol *Group = FnSection.getGroup()) {
251    EHSection = getContext().getELFSection(
252      EHSecName, Type, Flags | ELF::SHF_GROUP, Kind,
253      FnSection.getEntrySize(), Group->getName());
254  } else {
255    EHSection = getContext().getELFSection(EHSecName, Type, Flags, Kind);
256  }
257  assert(EHSection && "Failed to get the required EH section");
258
259  // Switch to .ARM.extab or .ARM.exidx section
260  SwitchSection(EHSection);
261  EmitCodeAlignment(4, 0);
262}
263
264inline void ARMELFStreamer::SwitchToExTabSection(const MCSymbol &FnStart) {
265  SwitchToEHSection(".ARM.extab",
266                    ELF::SHT_PROGBITS,
267                    ELF::SHF_ALLOC,
268                    SectionKind::getDataRel(),
269                    FnStart);
270}
271
272inline void ARMELFStreamer::SwitchToExIdxSection(const MCSymbol &FnStart) {
273  SwitchToEHSection(".ARM.exidx",
274                    ELF::SHT_ARM_EXIDX,
275                    ELF::SHF_ALLOC | ELF::SHF_LINK_ORDER,
276                    SectionKind::getDataRel(),
277                    FnStart);
278}
279
280void ARMELFStreamer::Reset() {
281  const MCRegisterInfo &MRI = getContext().getRegisterInfo();
282
283  ExTab = NULL;
284  FnStart = NULL;
285  Personality = NULL;
286  VFPRegSave = 0;
287  RegSave = 0;
288  FPReg = MRI.getEncodingValue(ARM::SP);
289  FPOffset = 0;
290  SPOffset = 0;
291  UsedFP = false;
292  CantUnwind = false;
293
294  UnwindOpAsm.Reset();
295}
296
297// Add the R_ARM_NONE fixup at the same position
298void ARMELFStreamer::EmitPersonalityFixup(StringRef Name) {
299  const MCSymbol *PersonalitySym = getContext().GetOrCreateSymbol(Name);
300
301  const MCSymbolRefExpr *PersonalityRef =
302    MCSymbolRefExpr::Create(PersonalitySym,
303                            MCSymbolRefExpr::VK_ARM_NONE,
304                            getContext());
305
306  AddValueSymbols(PersonalityRef);
307  MCDataFragment *DF = getOrCreateDataFragment();
308  DF->getFixups().push_back(
309    MCFixup::Create(DF->getContents().size(), PersonalityRef,
310                    MCFixup::getKindForSize(4, false)));
311}
312
313void ARMELFStreamer::CollectUnwindOpcodes() {
314  if (UsedFP) {
315    UnwindOpAsm.EmitSetFP(FPReg);
316    UnwindOpAsm.EmitSPOffset(-FPOffset);
317  } else {
318    UnwindOpAsm.EmitSPOffset(SPOffset);
319  }
320  UnwindOpAsm.EmitVFPRegSave(VFPRegSave);
321  UnwindOpAsm.EmitRegSave(RegSave);
322  UnwindOpAsm.Finalize();
323}
324
325void ARMELFStreamer::EmitFnStart() {
326  assert(FnStart == 0);
327  FnStart = getContext().CreateTempSymbol();
328  EmitLabel(FnStart);
329}
330
331void ARMELFStreamer::EmitFnEnd() {
332  assert(FnStart && ".fnstart must preceeds .fnend");
333
334  // Emit unwind opcodes if there is no .handlerdata directive
335  if (!ExTab && !CantUnwind) {
336    CollectUnwindOpcodes();
337
338    unsigned PersonalityIndex = UnwindOpAsm.getPersonalityIndex();
339    if (PersonalityIndex == AEABI_UNWIND_CPP_PR1 ||
340        PersonalityIndex == AEABI_UNWIND_CPP_PR2) {
341      // For the __aeabi_unwind_cpp_pr1 and __aeabi_unwind_cpp_pr2, we have to
342      // emit the unwind opcodes in the corresponding ".ARM.extab" section, and
343      // then emit a reference to these unwind opcodes in the second word of
344      // the exception index table entry.
345      SwitchToExTabSection(*FnStart);
346      ExTab = getContext().CreateTempSymbol();
347      EmitLabel(ExTab);
348      EmitBytes(UnwindOpAsm.data(), 0);
349    }
350  }
351
352  // Emit the exception index table entry
353  SwitchToExIdxSection(*FnStart);
354
355  unsigned PersonalityIndex = UnwindOpAsm.getPersonalityIndex();
356  if (PersonalityIndex < NUM_PERSONALITY_INDEX)
357    EmitPersonalityFixup(GetAEABIUnwindPersonalityName(PersonalityIndex));
358
359  const MCSymbolRefExpr *FnStartRef =
360    MCSymbolRefExpr::Create(FnStart,
361                            MCSymbolRefExpr::VK_ARM_PREL31,
362                            getContext());
363
364  EmitValue(FnStartRef, 4, 0);
365
366  if (CantUnwind) {
367    EmitIntValue(EXIDX_CANTUNWIND, 4, 0);
368  } else if (ExTab) {
369    // Emit a reference to the unwind opcodes in the ".ARM.extab" section.
370    const MCSymbolRefExpr *ExTabEntryRef =
371      MCSymbolRefExpr::Create(ExTab,
372                              MCSymbolRefExpr::VK_ARM_PREL31,
373                              getContext());
374    EmitValue(ExTabEntryRef, 4, 0);
375  } else {
376    // For the __aeabi_unwind_cpp_pr0, we have to emit the unwind opcodes in
377    // the second word of exception index table entry.  The size of the unwind
378    // opcodes should always be 4 bytes.
379    assert(PersonalityIndex == AEABI_UNWIND_CPP_PR0 &&
380           "Compact model must use __aeabi_cpp_unwind_pr0 as personality");
381    assert(UnwindOpAsm.size() == 4u &&
382           "Unwind opcode size for __aeabi_cpp_unwind_pr0 must be equal to 4");
383    EmitBytes(UnwindOpAsm.data(), 0);
384  }
385
386  // Clean exception handling frame information
387  Reset();
388}
389
390void ARMELFStreamer::EmitCantUnwind() {
391  CantUnwind = true;
392}
393
394void ARMELFStreamer::EmitHandlerData() {
395  SwitchToExTabSection(*FnStart);
396
397  // Create .ARM.extab label for offset in .ARM.exidx
398  assert(!ExTab);
399  ExTab = getContext().CreateTempSymbol();
400  EmitLabel(ExTab);
401
402  // Emit Personality
403  assert(Personality && ".personality directive must preceed .handlerdata");
404
405  const MCSymbolRefExpr *PersonalityRef =
406    MCSymbolRefExpr::Create(Personality,
407                            MCSymbolRefExpr::VK_ARM_PREL31,
408                            getContext());
409
410  EmitValue(PersonalityRef, 4, 0);
411
412  // Emit unwind opcodes
413  CollectUnwindOpcodes();
414  EmitBytes(UnwindOpAsm.data(), 0);
415}
416
417void ARMELFStreamer::EmitPersonality(const MCSymbol *Per) {
418  Personality = Per;
419  UnwindOpAsm.setPersonality(Per);
420}
421
422void ARMELFStreamer::EmitSetFP(unsigned NewFPReg,
423                               unsigned NewSPReg,
424                               int64_t Offset) {
425  assert(SPOffset == 0 &&
426         "Current implementation assumes .setfp precedes .pad");
427
428  const MCRegisterInfo &MRI = getContext().getRegisterInfo();
429
430  uint16_t NewFPRegEncVal = MRI.getEncodingValue(NewFPReg);
431#ifndef NDEBUG
432  uint16_t NewSPRegEncVal = MRI.getEncodingValue(NewSPReg);
433#endif
434
435  assert((NewSPReg == ARM::SP || NewSPRegEncVal == FPReg) &&
436         "the operand of .setfp directive should be either $sp or $fp");
437
438  UsedFP = true;
439  FPReg = NewFPRegEncVal;
440  FPOffset = Offset;
441}
442
443void ARMELFStreamer::EmitPad(int64_t Offset) {
444  SPOffset += Offset;
445}
446
447void ARMELFStreamer::EmitRegSave(const SmallVectorImpl<unsigned> &RegList,
448                                 bool IsVector) {
449  const MCRegisterInfo &MRI = getContext().getRegisterInfo();
450
451#ifndef NDEBUG
452  unsigned Max = IsVector ? 32 : 16;
453#endif
454  uint32_t &RegMask = IsVector ? VFPRegSave : RegSave;
455
456  for (size_t i = 0; i < RegList.size(); ++i) {
457    unsigned Reg = MRI.getEncodingValue(RegList[i]);
458    assert(Reg < Max && "Register encoded value out of range");
459    RegMask |= 1u << Reg;
460  }
461}
462
463namespace llvm {
464  MCELFStreamer* createARMELFStreamer(MCContext &Context, MCAsmBackend &TAB,
465                                      raw_ostream &OS, MCCodeEmitter *Emitter,
466                                      bool RelaxAll, bool NoExecStack,
467                                      bool IsThumb) {
468    ARMELFStreamer *S = new ARMELFStreamer(Context, TAB, OS, Emitter, IsThumb);
469    if (RelaxAll)
470      S->getAssembler().setRelaxAll(true);
471    if (NoExecStack)
472      S->getAssembler().setNoExecStack(true);
473    return S;
474  }
475
476}
477
478
479