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