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