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