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 FlushPendingOffset(); 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 unsigned PersonalityIndex; 225 unsigned FPReg; // Frame pointer register 226 int64_t FPOffset; // Offset: (final frame pointer) - (initial $sp) 227 int64_t SPOffset; // Offset: (final $sp) - (initial $sp) 228 int64_t PendingOffset; // Offset: (final $sp) - (emitted $sp) 229 bool UsedFP; 230 bool CantUnwind; 231 SmallVector<uint8_t, 64> Opcodes; 232 UnwindOpcodeAssembler UnwindOpAsm; 233 }; 234 } // end anonymous namespace 235 236 inline void ARMELFStreamer::SwitchToEHSection(const char *Prefix, 237 unsigned Type, 238 unsigned Flags, 239 SectionKind Kind, 240 const MCSymbol &Fn) { 241 const MCSectionELF &FnSection = 242 static_cast<const MCSectionELF &>(Fn.getSection()); 243 244 // Create the name for new section 245 StringRef FnSecName(FnSection.getSectionName()); 246 SmallString<128> EHSecName(Prefix); 247 if (FnSecName != ".text") { 248 EHSecName += FnSecName; 249 } 250 251 // Get .ARM.extab or .ARM.exidx section 252 const MCSectionELF *EHSection = NULL; 253 if (const MCSymbol *Group = FnSection.getGroup()) { 254 EHSection = getContext().getELFSection( 255 EHSecName, Type, Flags | ELF::SHF_GROUP, Kind, 256 FnSection.getEntrySize(), Group->getName()); 257 } else { 258 EHSection = getContext().getELFSection(EHSecName, Type, Flags, Kind); 259 } 260 assert(EHSection && "Failed to get the required EH section"); 261 262 // Switch to .ARM.extab or .ARM.exidx section 263 SwitchSection(EHSection); 264 EmitCodeAlignment(4, 0); 265 } 266 267 inline void ARMELFStreamer::SwitchToExTabSection(const MCSymbol &FnStart) { 268 SwitchToEHSection(".ARM.extab", 269 ELF::SHT_PROGBITS, 270 ELF::SHF_ALLOC, 271 SectionKind::getDataRel(), 272 FnStart); 273 } 274 275 inline void ARMELFStreamer::SwitchToExIdxSection(const MCSymbol &FnStart) { 276 SwitchToEHSection(".ARM.exidx", 277 ELF::SHT_ARM_EXIDX, 278 ELF::SHF_ALLOC | ELF::SHF_LINK_ORDER, 279 SectionKind::getDataRel(), 280 FnStart); 281 } 282 283 void ARMELFStreamer::Reset() { 284 ExTab = NULL; 285 FnStart = NULL; 286 Personality = NULL; 287 PersonalityIndex = NUM_PERSONALITY_INDEX; 288 FPReg = ARM::SP; 289 FPOffset = 0; 290 SPOffset = 0; 291 PendingOffset = 0; 292 UsedFP = false; 293 CantUnwind = false; 294 295 Opcodes.clear(); 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::EmitFnStart() { 316 assert(FnStart == 0); 317 FnStart = getContext().CreateTempSymbol(); 318 EmitLabel(FnStart); 319 } 320 321 void ARMELFStreamer::EmitFnEnd() { 322 assert(FnStart && ".fnstart must preceeds .fnend"); 323 324 // Emit unwind opcodes if there is no .handlerdata directive 325 if (!ExTab && !CantUnwind) 326 FlushUnwindOpcodes(true); 327 328 // Emit the exception index table entry 329 SwitchToExIdxSection(*FnStart); 330 331 if (PersonalityIndex < NUM_PERSONALITY_INDEX) 332 EmitPersonalityFixup(GetAEABIUnwindPersonalityName(PersonalityIndex)); 333 334 const MCSymbolRefExpr *FnStartRef = 335 MCSymbolRefExpr::Create(FnStart, 336 MCSymbolRefExpr::VK_ARM_PREL31, 337 getContext()); 338 339 EmitValue(FnStartRef, 4, 0); 340 341 if (CantUnwind) { 342 EmitIntValue(EXIDX_CANTUNWIND, 4, 0); 343 } else if (ExTab) { 344 // Emit a reference to the unwind opcodes in the ".ARM.extab" section. 345 const MCSymbolRefExpr *ExTabEntryRef = 346 MCSymbolRefExpr::Create(ExTab, 347 MCSymbolRefExpr::VK_ARM_PREL31, 348 getContext()); 349 EmitValue(ExTabEntryRef, 4, 0); 350 } else { 351 // For the __aeabi_unwind_cpp_pr0, we have to emit the unwind opcodes in 352 // the second word of exception index table entry. The size of the unwind 353 // opcodes should always be 4 bytes. 354 assert(PersonalityIndex == AEABI_UNWIND_CPP_PR0 && 355 "Compact model must use __aeabi_cpp_unwind_pr0 as personality"); 356 assert(Opcodes.size() == 4u && 357 "Unwind opcode size for __aeabi_cpp_unwind_pr0 must be equal to 4"); 358 EmitBytes(StringRef(reinterpret_cast<const char*>(Opcodes.data()), 359 Opcodes.size()), 0); 360 } 361 362 // Switch to the section containing FnStart 363 SwitchSection(&FnStart->getSection()); 364 365 // Clean exception handling frame information 366 Reset(); 367 } 368 369 void ARMELFStreamer::EmitCantUnwind() { 370 CantUnwind = true; 371 } 372 373 void ARMELFStreamer::FlushPendingOffset() { 374 if (PendingOffset != 0) { 375 UnwindOpAsm.EmitSPOffset(-PendingOffset); 376 PendingOffset = 0; 377 } 378 } 379 380 void ARMELFStreamer::FlushUnwindOpcodes(bool AllowCompactModel0) { 381 // Emit the unwind opcode to restore $sp. 382 if (UsedFP) { 383 const MCRegisterInfo &MRI = getContext().getRegisterInfo(); 384 int64_t LastRegSaveSPOffset = SPOffset - PendingOffset; 385 UnwindOpAsm.EmitSPOffset(LastRegSaveSPOffset - FPOffset); 386 UnwindOpAsm.EmitSetSP(MRI.getEncodingValue(FPReg)); 387 } else { 388 FlushPendingOffset(); 389 } 390 391 // Finalize the unwind opcode sequence 392 UnwindOpAsm.Finalize(PersonalityIndex, Opcodes); 393 394 // For compact model 0, we have to emit the unwind opcodes in the .ARM.exidx 395 // section. Thus, we don't have to create an entry in the .ARM.extab 396 // section. 397 if (AllowCompactModel0 && PersonalityIndex == AEABI_UNWIND_CPP_PR0) 398 return; 399 400 // Switch to .ARM.extab section. 401 SwitchToExTabSection(*FnStart); 402 403 // Create .ARM.extab label for offset in .ARM.exidx 404 assert(!ExTab); 405 ExTab = getContext().CreateTempSymbol(); 406 EmitLabel(ExTab); 407 408 // Emit personality 409 if (Personality) { 410 const MCSymbolRefExpr *PersonalityRef = 411 MCSymbolRefExpr::Create(Personality, 412 MCSymbolRefExpr::VK_ARM_PREL31, 413 getContext()); 414 415 EmitValue(PersonalityRef, 4, 0); 416 } 417 418 // Emit unwind opcodes 419 EmitBytes(StringRef(reinterpret_cast<const char *>(Opcodes.data()), 420 Opcodes.size()), 0); 421 } 422 423 void ARMELFStreamer::EmitHandlerData() { 424 FlushUnwindOpcodes(false); 425 } 426 427 void ARMELFStreamer::EmitPersonality(const MCSymbol *Per) { 428 Personality = Per; 429 UnwindOpAsm.setPersonality(Per); 430 } 431 432 void ARMELFStreamer::EmitSetFP(unsigned NewFPReg, 433 unsigned NewSPReg, 434 int64_t Offset) { 435 assert((NewSPReg == ARM::SP || NewSPReg == FPReg) && 436 "the operand of .setfp directive should be either $sp or $fp"); 437 438 UsedFP = true; 439 FPReg = NewFPReg; 440 441 if (NewSPReg == ARM::SP) 442 FPOffset = SPOffset + Offset; 443 else 444 FPOffset += Offset; 445 } 446 447 void ARMELFStreamer::EmitPad(int64_t Offset) { 448 // Track the change of the $sp offset 449 SPOffset -= Offset; 450 451 // To squash multiple .pad directives, we should delay the unwind opcode 452 // until the .save, .vsave, .handlerdata, or .fnend directives. 453 PendingOffset -= Offset; 454 } 455 456 void ARMELFStreamer::EmitRegSave(const SmallVectorImpl<unsigned> &RegList, 457 bool IsVector) { 458 // Collect the registers in the register list 459 unsigned Count = 0; 460 uint32_t Mask = 0; 461 const MCRegisterInfo &MRI = getContext().getRegisterInfo(); 462 for (size_t i = 0; i < RegList.size(); ++i) { 463 unsigned Reg = MRI.getEncodingValue(RegList[i]); 464 assert(Reg < (IsVector ? 32U : 16U) && "Register out of range"); 465 unsigned Bit = (1u << Reg); 466 if ((Mask & Bit) == 0) { 467 Mask |= Bit; 468 ++Count; 469 } 470 } 471 472 // Track the change the $sp offset: For the .save directive, the 473 // corresponding push instruction will decrease the $sp by (4 * Count). 474 // For the .vsave directive, the corresponding vpush instruction will 475 // decrease $sp by (8 * Count). 476 SPOffset -= Count * (IsVector ? 8 : 4); 477 478 // Emit the opcode 479 FlushPendingOffset(); 480 if (IsVector) 481 UnwindOpAsm.EmitVFPRegSave(Mask); 482 else 483 UnwindOpAsm.EmitRegSave(Mask); 484 } 485 486 namespace llvm { 487 MCELFStreamer* createARMELFStreamer(MCContext &Context, MCAsmBackend &TAB, 488 raw_ostream &OS, MCCodeEmitter *Emitter, 489 bool RelaxAll, bool NoExecStack, 490 bool IsThumb) { 491 ARMELFStreamer *S = new ARMELFStreamer(Context, TAB, OS, Emitter, IsThumb); 492 if (RelaxAll) 493 S->getAssembler().setRelaxAll(true); 494 if (NoExecStack) 495 S->getAssembler().setNoExecStack(true); 496 return S; 497 } 498 499 } 500 501 502