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