ARMELFStreamer.cpp revision 249259
1249259Sdim//===- lib/MC/ARMELFStreamer.cpp - ELF Object Output for ARM --------------===// 2249259Sdim// 3249259Sdim// The LLVM Compiler Infrastructure 4249259Sdim// 5249259Sdim// This file is distributed under the University of Illinois Open Source 6249259Sdim// License. See LICENSE.TXT for details. 7249259Sdim// 8249259Sdim//===----------------------------------------------------------------------===// 9249259Sdim// 10249259Sdim// This file assembles .s files and emits ARM ELF .o object files. Different 11249259Sdim// from generic ELF streamer in emitting mapping symbols ($a, $t and $d) to 12249259Sdim// delimit regions of data and code. 13249259Sdim// 14249259Sdim//===----------------------------------------------------------------------===// 15249259Sdim 16249259Sdim#include "ARMUnwindOp.h" 17249259Sdim#include "llvm/ADT/SmallPtrSet.h" 18249259Sdim#include "llvm/ADT/Twine.h" 19249259Sdim#include "llvm/MC/MCAsmBackend.h" 20249259Sdim#include "llvm/MC/MCAssembler.h" 21249259Sdim#include "llvm/MC/MCCodeEmitter.h" 22249259Sdim#include "llvm/MC/MCContext.h" 23249259Sdim#include "llvm/MC/MCELF.h" 24249259Sdim#include "llvm/MC/MCELFStreamer.h" 25249259Sdim#include "llvm/MC/MCELFSymbolFlags.h" 26249259Sdim#include "llvm/MC/MCExpr.h" 27249259Sdim#include "llvm/MC/MCInst.h" 28249259Sdim#include "llvm/MC/MCObjectStreamer.h" 29249259Sdim#include "llvm/MC/MCSection.h" 30249259Sdim#include "llvm/MC/MCSectionELF.h" 31249259Sdim#include "llvm/MC/MCStreamer.h" 32249259Sdim#include "llvm/MC/MCSymbol.h" 33249259Sdim#include "llvm/MC/MCValue.h" 34249259Sdim#include "llvm/Support/Debug.h" 35249259Sdim#include "llvm/Support/ELF.h" 36249259Sdim#include "llvm/Support/ErrorHandling.h" 37249259Sdim#include "llvm/Support/raw_ostream.h" 38249259Sdim 39249259Sdimusing namespace llvm; 40249259Sdim 41249259Sdimnamespace { 42249259Sdim 43249259Sdim/// Extend the generic ELFStreamer class so that it can emit mapping symbols at 44249259Sdim/// the appropriate points in the object files. These symbols are defined in the 45249259Sdim/// ARM ELF ABI: infocenter.arm.com/help/topic/com.arm.../IHI0044D_aaelf.pdf. 46249259Sdim/// 47249259Sdim/// In brief: $a, $t or $d should be emitted at the start of each contiguous 48249259Sdim/// region of ARM code, Thumb code or data in a section. In practice, this 49249259Sdim/// emission does not rely on explicit assembler directives but on inherent 50249259Sdim/// properties of the directives doing the emission (e.g. ".byte" is data, "add 51249259Sdim/// r0, r0, r0" an instruction). 52249259Sdim/// 53249259Sdim/// As a result this system is orthogonal to the DataRegion infrastructure used 54249259Sdim/// by MachO. Beware! 55249259Sdimclass ARMELFStreamer : public MCELFStreamer { 56249259Sdimpublic: 57249259Sdim ARMELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, 58249259Sdim MCCodeEmitter *Emitter, bool IsThumb) 59249259Sdim : MCELFStreamer(SK_ARMELFStreamer, Context, TAB, OS, Emitter), 60249259Sdim IsThumb(IsThumb), MappingSymbolCounter(0), LastEMS(EMS_None), ExTab(0), 61249259Sdim FnStart(0), Personality(0), CantUnwind(false) {} 62249259Sdim 63249259Sdim ~ARMELFStreamer() {} 64249259Sdim 65249259Sdim // ARM exception handling directives 66249259Sdim virtual void EmitFnStart(); 67249259Sdim virtual void EmitFnEnd(); 68249259Sdim virtual void EmitCantUnwind(); 69249259Sdim virtual void EmitPersonality(const MCSymbol *Per); 70249259Sdim virtual void EmitHandlerData(); 71249259Sdim virtual void EmitSetFP(unsigned NewFpReg, 72249259Sdim unsigned NewSpReg, 73249259Sdim int64_t Offset = 0); 74249259Sdim virtual void EmitPad(int64_t Offset); 75249259Sdim virtual void EmitRegSave(const SmallVectorImpl<unsigned> &RegList, 76249259Sdim bool isVector); 77249259Sdim 78249259Sdim virtual void ChangeSection(const MCSection *Section) { 79249259Sdim // We have to keep track of the mapping symbol state of any sections we 80249259Sdim // use. Each one should start off as EMS_None, which is provided as the 81249259Sdim // default constructor by DenseMap::lookup. 82249259Sdim LastMappingSymbols[getPreviousSection()] = LastEMS; 83249259Sdim LastEMS = LastMappingSymbols.lookup(Section); 84249259Sdim 85249259Sdim MCELFStreamer::ChangeSection(Section); 86249259Sdim } 87249259Sdim 88249259Sdim /// This function is the one used to emit instruction data into the ELF 89249259Sdim /// streamer. We override it to add the appropriate mapping symbol if 90249259Sdim /// necessary. 91249259Sdim virtual void EmitInstruction(const MCInst& Inst) { 92249259Sdim if (IsThumb) 93249259Sdim EmitThumbMappingSymbol(); 94249259Sdim else 95249259Sdim EmitARMMappingSymbol(); 96249259Sdim 97249259Sdim MCELFStreamer::EmitInstruction(Inst); 98249259Sdim } 99249259Sdim 100249259Sdim /// This is one of the functions used to emit data into an ELF section, so the 101249259Sdim /// ARM streamer overrides it to add the appropriate mapping symbol ($d) if 102249259Sdim /// necessary. 103249259Sdim virtual void EmitBytes(StringRef Data, unsigned AddrSpace) { 104249259Sdim EmitDataMappingSymbol(); 105249259Sdim MCELFStreamer::EmitBytes(Data, AddrSpace); 106249259Sdim } 107249259Sdim 108249259Sdim /// This is one of the functions used to emit data into an ELF section, so the 109249259Sdim /// ARM streamer overrides it to add the appropriate mapping symbol ($d) if 110249259Sdim /// necessary. 111249259Sdim virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, 112249259Sdim unsigned AddrSpace) { 113249259Sdim EmitDataMappingSymbol(); 114249259Sdim MCELFStreamer::EmitValueImpl(Value, Size, AddrSpace); 115249259Sdim } 116249259Sdim 117249259Sdim virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) { 118249259Sdim MCELFStreamer::EmitAssemblerFlag(Flag); 119249259Sdim 120249259Sdim switch (Flag) { 121249259Sdim case MCAF_SyntaxUnified: 122249259Sdim return; // no-op here. 123249259Sdim case MCAF_Code16: 124249259Sdim IsThumb = true; 125249259Sdim return; // Change to Thumb mode 126249259Sdim case MCAF_Code32: 127249259Sdim IsThumb = false; 128249259Sdim return; // Change to ARM mode 129249259Sdim case MCAF_Code64: 130249259Sdim return; 131249259Sdim case MCAF_SubsectionsViaSymbols: 132249259Sdim return; 133249259Sdim } 134249259Sdim } 135249259Sdim 136249259Sdim static bool classof(const MCStreamer *S) { 137249259Sdim return S->getKind() == SK_ARMELFStreamer; 138249259Sdim } 139249259Sdim 140249259Sdimprivate: 141249259Sdim enum ElfMappingSymbol { 142249259Sdim EMS_None, 143249259Sdim EMS_ARM, 144249259Sdim EMS_Thumb, 145249259Sdim EMS_Data 146249259Sdim }; 147249259Sdim 148249259Sdim void EmitDataMappingSymbol() { 149249259Sdim if (LastEMS == EMS_Data) return; 150249259Sdim EmitMappingSymbol("$d"); 151249259Sdim LastEMS = EMS_Data; 152249259Sdim } 153249259Sdim 154249259Sdim void EmitThumbMappingSymbol() { 155249259Sdim if (LastEMS == EMS_Thumb) return; 156249259Sdim EmitMappingSymbol("$t"); 157249259Sdim LastEMS = EMS_Thumb; 158249259Sdim } 159249259Sdim 160249259Sdim void EmitARMMappingSymbol() { 161249259Sdim if (LastEMS == EMS_ARM) return; 162249259Sdim EmitMappingSymbol("$a"); 163249259Sdim LastEMS = EMS_ARM; 164249259Sdim } 165249259Sdim 166249259Sdim void EmitMappingSymbol(StringRef Name) { 167249259Sdim MCSymbol *Start = getContext().CreateTempSymbol(); 168249259Sdim EmitLabel(Start); 169249259Sdim 170249259Sdim MCSymbol *Symbol = 171249259Sdim getContext().GetOrCreateSymbol(Name + "." + 172249259Sdim Twine(MappingSymbolCounter++)); 173249259Sdim 174249259Sdim MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); 175249259Sdim MCELF::SetType(SD, ELF::STT_NOTYPE); 176249259Sdim MCELF::SetBinding(SD, ELF::STB_LOCAL); 177249259Sdim SD.setExternal(false); 178249259Sdim Symbol->setSection(*getCurrentSection()); 179249259Sdim 180249259Sdim const MCExpr *Value = MCSymbolRefExpr::Create(Start, getContext()); 181249259Sdim Symbol->setVariableValue(Value); 182249259Sdim } 183249259Sdim 184249259Sdim void EmitThumbFunc(MCSymbol *Func) { 185249259Sdim // FIXME: Anything needed here to flag the function as thumb? 186249259Sdim 187249259Sdim getAssembler().setIsThumbFunc(Func); 188249259Sdim 189249259Sdim MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Func); 190249259Sdim SD.setFlags(SD.getFlags() | ELF_Other_ThumbFunc); 191249259Sdim } 192249259Sdim 193249259Sdim // Helper functions for ARM exception handling directives 194249259Sdim void Reset(); 195249259Sdim 196249259Sdim void EmitPersonalityFixup(StringRef Name); 197249259Sdim 198249259Sdim void SwitchToEHSection(const char *Prefix, unsigned Type, unsigned Flags, 199249259Sdim SectionKind Kind, const MCSymbol &Fn); 200249259Sdim void SwitchToExTabSection(const MCSymbol &FnStart); 201249259Sdim void SwitchToExIdxSection(const MCSymbol &FnStart); 202249259Sdim 203249259Sdim bool IsThumb; 204249259Sdim int64_t MappingSymbolCounter; 205249259Sdim 206249259Sdim DenseMap<const MCSection *, ElfMappingSymbol> LastMappingSymbols; 207249259Sdim ElfMappingSymbol LastEMS; 208249259Sdim 209249259Sdim // ARM Exception Handling Frame Information 210249259Sdim MCSymbol *ExTab; 211249259Sdim MCSymbol *FnStart; 212249259Sdim const MCSymbol *Personality; 213249259Sdim bool CantUnwind; 214249259Sdim}; 215249259Sdim} 216249259Sdim 217249259Sdiminline void ARMELFStreamer::SwitchToEHSection(const char *Prefix, 218249259Sdim unsigned Type, 219249259Sdim unsigned Flags, 220249259Sdim SectionKind Kind, 221249259Sdim const MCSymbol &Fn) { 222249259Sdim const MCSectionELF &FnSection = 223249259Sdim static_cast<const MCSectionELF &>(Fn.getSection()); 224249259Sdim 225249259Sdim // Create the name for new section 226249259Sdim StringRef FnSecName(FnSection.getSectionName()); 227249259Sdim SmallString<128> EHSecName(Prefix); 228249259Sdim if (FnSecName != ".text") { 229249259Sdim EHSecName += FnSecName; 230249259Sdim } 231249259Sdim 232249259Sdim // Get .ARM.extab or .ARM.exidx section 233249259Sdim const MCSectionELF *EHSection = NULL; 234249259Sdim if (const MCSymbol *Group = FnSection.getGroup()) { 235249259Sdim EHSection = getContext().getELFSection( 236249259Sdim EHSecName, Type, Flags | ELF::SHF_GROUP, Kind, 237249259Sdim FnSection.getEntrySize(), Group->getName()); 238249259Sdim } else { 239249259Sdim EHSection = getContext().getELFSection(EHSecName, Type, Flags, Kind); 240249259Sdim } 241249259Sdim assert(EHSection); 242249259Sdim 243249259Sdim // Switch to .ARM.extab or .ARM.exidx section 244249259Sdim SwitchSection(EHSection); 245249259Sdim EmitCodeAlignment(4, 0); 246249259Sdim} 247249259Sdim 248249259Sdiminline void ARMELFStreamer::SwitchToExTabSection(const MCSymbol &FnStart) { 249249259Sdim SwitchToEHSection(".ARM.extab", 250249259Sdim ELF::SHT_PROGBITS, 251249259Sdim ELF::SHF_ALLOC, 252249259Sdim SectionKind::getDataRel(), 253249259Sdim FnStart); 254249259Sdim} 255249259Sdim 256249259Sdiminline void ARMELFStreamer::SwitchToExIdxSection(const MCSymbol &FnStart) { 257249259Sdim SwitchToEHSection(".ARM.exidx", 258249259Sdim ELF::SHT_ARM_EXIDX, 259249259Sdim ELF::SHF_ALLOC | ELF::SHF_LINK_ORDER, 260249259Sdim SectionKind::getDataRel(), 261249259Sdim FnStart); 262249259Sdim} 263249259Sdim 264249259Sdimvoid ARMELFStreamer::Reset() { 265249259Sdim ExTab = NULL; 266249259Sdim FnStart = NULL; 267249259Sdim Personality = NULL; 268249259Sdim CantUnwind = false; 269249259Sdim} 270249259Sdim 271249259Sdim// Add the R_ARM_NONE fixup at the same position 272249259Sdimvoid ARMELFStreamer::EmitPersonalityFixup(StringRef Name) { 273249259Sdim const MCSymbol *PersonalitySym = getContext().GetOrCreateSymbol(Name); 274249259Sdim 275249259Sdim const MCSymbolRefExpr *PersonalityRef = 276249259Sdim MCSymbolRefExpr::Create(PersonalitySym, 277249259Sdim MCSymbolRefExpr::VK_ARM_NONE, 278249259Sdim getContext()); 279249259Sdim 280249259Sdim AddValueSymbols(PersonalityRef); 281249259Sdim MCDataFragment *DF = getOrCreateDataFragment(); 282249259Sdim DF->getFixups().push_back( 283249259Sdim MCFixup::Create(DF->getContents().size(), PersonalityRef, 284249259Sdim MCFixup::getKindForSize(4, false))); 285249259Sdim} 286249259Sdim 287249259Sdimvoid ARMELFStreamer::EmitFnStart() { 288249259Sdim assert(FnStart == 0); 289249259Sdim FnStart = getContext().CreateTempSymbol(); 290249259Sdim EmitLabel(FnStart); 291249259Sdim} 292249259Sdim 293249259Sdimvoid ARMELFStreamer::EmitFnEnd() { 294249259Sdim assert(FnStart && ".fnstart must preceeds .fnend"); 295249259Sdim 296249259Sdim // Emit unwind opcodes if there is no .handlerdata directive 297249259Sdim int PersonalityIndex = -1; 298249259Sdim if (!ExTab && !CantUnwind) { 299249259Sdim // For __aeabi_unwind_cpp_pr1, we have to emit opcodes in .ARM.extab. 300249259Sdim SwitchToExTabSection(*FnStart); 301249259Sdim 302249259Sdim // Create .ARM.extab label for offset in .ARM.exidx 303249259Sdim ExTab = getContext().CreateTempSymbol(); 304249259Sdim EmitLabel(ExTab); 305249259Sdim 306249259Sdim PersonalityIndex = 1; 307249259Sdim 308249259Sdim uint32_t Entry = 0; 309249259Sdim uint32_t NumExtraEntryWords = 0; 310249259Sdim Entry |= NumExtraEntryWords << 24; 311249259Sdim Entry |= (EHT_COMPACT | PersonalityIndex) << 16; 312249259Sdim 313249259Sdim // TODO: This should be generated according to .save, .vsave, .setfp 314249259Sdim // directives. Currently, we are simply generating FINISH opcode. 315249259Sdim Entry |= UNWIND_OPCODE_FINISH << 8; 316249259Sdim Entry |= UNWIND_OPCODE_FINISH; 317249259Sdim 318249259Sdim EmitIntValue(Entry, 4, 0); 319249259Sdim } 320249259Sdim 321249259Sdim // Emit the exception index table entry 322249259Sdim SwitchToExIdxSection(*FnStart); 323249259Sdim 324249259Sdim if (PersonalityIndex == 1) 325249259Sdim EmitPersonalityFixup("__aeabi_unwind_cpp_pr1"); 326249259Sdim 327249259Sdim const MCSymbolRefExpr *FnStartRef = 328249259Sdim MCSymbolRefExpr::Create(FnStart, 329249259Sdim MCSymbolRefExpr::VK_ARM_PREL31, 330249259Sdim getContext()); 331249259Sdim 332249259Sdim EmitValue(FnStartRef, 4, 0); 333249259Sdim 334249259Sdim if (CantUnwind) { 335249259Sdim EmitIntValue(EXIDX_CANTUNWIND, 4, 0); 336249259Sdim } else { 337249259Sdim const MCSymbolRefExpr *ExTabEntryRef = 338249259Sdim MCSymbolRefExpr::Create(ExTab, 339249259Sdim MCSymbolRefExpr::VK_ARM_PREL31, 340249259Sdim getContext()); 341249259Sdim EmitValue(ExTabEntryRef, 4, 0); 342249259Sdim } 343249259Sdim 344249259Sdim // Clean exception handling frame information 345249259Sdim Reset(); 346249259Sdim} 347249259Sdim 348249259Sdimvoid ARMELFStreamer::EmitCantUnwind() { 349249259Sdim CantUnwind = true; 350249259Sdim} 351249259Sdim 352249259Sdimvoid ARMELFStreamer::EmitHandlerData() { 353249259Sdim SwitchToExTabSection(*FnStart); 354249259Sdim 355249259Sdim // Create .ARM.extab label for offset in .ARM.exidx 356249259Sdim assert(!ExTab); 357249259Sdim ExTab = getContext().CreateTempSymbol(); 358249259Sdim EmitLabel(ExTab); 359249259Sdim 360249259Sdim // Emit Personality 361249259Sdim assert(Personality && ".personality directive must preceed .handlerdata"); 362249259Sdim 363249259Sdim const MCSymbolRefExpr *PersonalityRef = 364249259Sdim MCSymbolRefExpr::Create(Personality, 365249259Sdim MCSymbolRefExpr::VK_ARM_PREL31, 366249259Sdim getContext()); 367249259Sdim 368249259Sdim EmitValue(PersonalityRef, 4, 0); 369249259Sdim 370249259Sdim // Emit unwind opcodes 371249259Sdim uint32_t Entry = 0; 372249259Sdim uint32_t NumExtraEntryWords = 0; 373249259Sdim 374249259Sdim // TODO: This should be generated according to .save, .vsave, .setfp 375249259Sdim // directives. Currently, we are simply generating FINISH opcode. 376249259Sdim Entry |= NumExtraEntryWords << 24; 377249259Sdim Entry |= UNWIND_OPCODE_FINISH << 16; 378249259Sdim Entry |= UNWIND_OPCODE_FINISH << 8; 379249259Sdim Entry |= UNWIND_OPCODE_FINISH; 380249259Sdim 381249259Sdim EmitIntValue(Entry, 4, 0); 382249259Sdim} 383249259Sdim 384249259Sdimvoid ARMELFStreamer::EmitPersonality(const MCSymbol *Per) { 385249259Sdim Personality = Per; 386249259Sdim} 387249259Sdim 388249259Sdimvoid ARMELFStreamer::EmitSetFP(unsigned NewFpReg, 389249259Sdim unsigned NewSpReg, 390249259Sdim int64_t Offset) { 391249259Sdim // TODO: Not implemented 392249259Sdim} 393249259Sdim 394249259Sdimvoid ARMELFStreamer::EmitPad(int64_t Offset) { 395249259Sdim // TODO: Not implemented 396249259Sdim} 397249259Sdim 398249259Sdimvoid ARMELFStreamer::EmitRegSave(const SmallVectorImpl<unsigned> &RegList, 399249259Sdim bool IsVector) { 400249259Sdim // TODO: Not implemented 401249259Sdim} 402249259Sdim 403249259Sdimnamespace llvm { 404249259Sdim MCELFStreamer* createARMELFStreamer(MCContext &Context, MCAsmBackend &TAB, 405249259Sdim raw_ostream &OS, MCCodeEmitter *Emitter, 406249259Sdim bool RelaxAll, bool NoExecStack, 407249259Sdim bool IsThumb) { 408249259Sdim ARMELFStreamer *S = new ARMELFStreamer(Context, TAB, OS, Emitter, IsThumb); 409249259Sdim if (RelaxAll) 410249259Sdim S->getAssembler().setRelaxAll(true); 411249259Sdim if (NoExecStack) 412249259Sdim S->getAssembler().setNoExecStack(true); 413249259Sdim return S; 414249259Sdim } 415249259Sdim 416249259Sdim} 417249259Sdim 418249259Sdim 419