DwarfException.cpp revision fffb7266fe9c5c95d859ff5b3aeb5386cbd0cd1e
1//===-- CodeGen/AsmPrinter/DwarfException.cpp - Dwarf Exception Impl ------===// 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 contains support for writing DWARF exception info into asm files. 11// 12//===----------------------------------------------------------------------===// 13 14#include "DwarfException.h" 15#include "llvm/Module.h" 16#include "llvm/CodeGen/MachineModuleInfo.h" 17#include "llvm/CodeGen/MachineFrameInfo.h" 18#include "llvm/CodeGen/MachineFunction.h" 19#include "llvm/CodeGen/MachineLocation.h" 20#include "llvm/MC/MCStreamer.h" 21#include "llvm/MC/MCAsmInfo.h" 22#include "llvm/Target/TargetData.h" 23#include "llvm/Target/TargetFrameInfo.h" 24#include "llvm/Target/TargetLoweringObjectFile.h" 25#include "llvm/Target/TargetOptions.h" 26#include "llvm/Target/TargetRegisterInfo.h" 27#include "llvm/Support/Dwarf.h" 28#include "llvm/Support/Timer.h" 29#include "llvm/Support/raw_ostream.h" 30#include "llvm/ADT/StringExtras.h" 31using namespace llvm; 32 33static TimerGroup &getDwarfTimerGroup() { 34 static TimerGroup DwarfTimerGroup("Dwarf Exception"); 35 return DwarfTimerGroup; 36} 37 38DwarfException::DwarfException(raw_ostream &OS, AsmPrinter *A, 39 const MCAsmInfo *T) 40 : Dwarf(OS, A, T, "eh"), shouldEmitTable(false), shouldEmitMoves(false), 41 shouldEmitTableModule(false), shouldEmitMovesModule(false), 42 ExceptionTimer(0) { 43 if (TimePassesIsEnabled) 44 ExceptionTimer = new Timer("Dwarf Exception Writer", 45 getDwarfTimerGroup()); 46} 47 48DwarfException::~DwarfException() { 49 delete ExceptionTimer; 50} 51 52/// EmitCIE - Emit a Common Information Entry (CIE). This holds information that 53/// is shared among many Frame Description Entries. There is at least one CIE 54/// in every non-empty .debug_frame section. 55void DwarfException::EmitCIE(const Function *Personality, unsigned Index) { 56 // Size and sign of stack growth. 57 int stackGrowth = 58 Asm->TM.getFrameInfo()->getStackGrowthDirection() == 59 TargetFrameInfo::StackGrowsUp ? 60 TD->getPointerSize() : -TD->getPointerSize(); 61 62 // Begin eh frame section. 63 Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getEHFrameSection()); 64 65 if (MAI->is_EHSymbolPrivate()) 66 O << MAI->getPrivateGlobalPrefix(); 67 68 O << "EH_frame" << Index << ":\n"; 69 EmitLabel("section_eh_frame", Index); 70 71 // Define base labels. 72 EmitLabel("eh_frame_common", Index); 73 74 // Define the eh frame length. 75 EmitDifference("eh_frame_common_end", Index, 76 "eh_frame_common_begin", Index, true); 77 Asm->EOL("Length of Common Information Entry"); 78 79 // EH frame header. 80 EmitLabel("eh_frame_common_begin", Index); 81 Asm->EmitInt32((int)0); 82 Asm->EOL("CIE Identifier Tag"); 83 Asm->EmitInt8(dwarf::DW_CIE_VERSION); 84 Asm->EOL("CIE Version"); 85 86 // The personality presence indicates that language specific information will 87 // show up in the eh frame. 88 Asm->EmitString(Personality ? "zPLR" : "zR"); 89 Asm->EOL("CIE Augmentation"); 90 91 // Round out reader. 92 Asm->EmitULEB128Bytes(1); 93 Asm->EOL("CIE Code Alignment Factor"); 94 Asm->EmitSLEB128Bytes(stackGrowth); 95 Asm->EOL("CIE Data Alignment Factor"); 96 Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), true)); 97 Asm->EOL("CIE Return Address Column"); 98 99 // If there is a personality, we need to indicate the function's location. 100 if (Personality) { 101 unsigned Encoding = 0; 102 Asm->EmitULEB128Bytes(7); 103 Asm->EOL("Augmentation Size"); 104 105 if (MAI->getNeedsIndirectEncoding()) { 106 Encoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4 | 107 dwarf::DW_EH_PE_indirect; 108 Asm->EmitInt8(Encoding); 109 Asm->EOL("Personality", Encoding); 110 } else { 111 Encoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; 112 Asm->EmitInt8(Encoding); 113 Asm->EOL("Personality", Encoding); 114 } 115 116 PrintRelDirective(true); 117 O << MAI->getPersonalityPrefix(); 118 Asm->EmitExternalGlobal((const GlobalVariable *)(Personality)); 119 O << MAI->getPersonalitySuffix(); 120 if (strcmp(MAI->getPersonalitySuffix(), "+4@GOTPCREL")) 121 O << "-" << MAI->getPCSymbol(); 122 Asm->EOL("Personality"); 123 124 Encoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; 125 Asm->EmitInt8(Encoding); 126 Asm->EOL("LSDA Encoding", Encoding); 127 128 Encoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; 129 Asm->EmitInt8(Encoding); 130 Asm->EOL("FDE Encoding", Encoding); 131 } else { 132 Asm->EmitULEB128Bytes(1); 133 Asm->EOL("Augmentation Size"); 134 135 unsigned Encoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; 136 Asm->EmitInt8(Encoding); 137 Asm->EOL("FDE Encoding", Encoding); 138 } 139 140 // Indicate locations of general callee saved registers in frame. 141 std::vector<MachineMove> Moves; 142 RI->getInitialFrameState(Moves); 143 EmitFrameMoves(NULL, 0, Moves, true); 144 145 // On Darwin the linker honors the alignment of eh_frame, which means it must 146 // be 8-byte on 64-bit targets to match what gcc does. Otherwise you get 147 // holes which confuse readers of eh_frame. 148 Asm->EmitAlignment(TD->getPointerSize() == sizeof(int32_t) ? 2 : 3, 149 0, 0, false); 150 EmitLabel("eh_frame_common_end", Index); 151 152 Asm->EOL(); 153} 154 155/// EmitFDE - Emit the Frame Description Entry (FDE) for the function. 156void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) { 157 assert(!EHFrameInfo.function->hasAvailableExternallyLinkage() && 158 "Should not emit 'available externally' functions at all"); 159 160 const Function *TheFunc = EHFrameInfo.function; 161 162 Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getEHFrameSection()); 163 164 // Externally visible entry into the functions eh frame info. If the 165 // corresponding function is static, this should not be externally visible. 166 if (!TheFunc->hasLocalLinkage()) 167 if (const char *GlobalEHDirective = MAI->getGlobalEHDirective()) 168 O << GlobalEHDirective << EHFrameInfo.FnName << "\n"; 169 170 // If corresponding function is weak definition, this should be too. 171 if (TheFunc->isWeakForLinker() && MAI->getWeakDefDirective()) 172 O << MAI->getWeakDefDirective() << EHFrameInfo.FnName << "\n"; 173 174 // If there are no calls then you can't unwind. This may mean we can omit the 175 // EH Frame, but some environments do not handle weak absolute symbols. If 176 // UnwindTablesMandatory is set we cannot do this optimization; the unwind 177 // info is to be available for non-EH uses. 178 if (!EHFrameInfo.hasCalls && !UnwindTablesMandatory && 179 (!TheFunc->isWeakForLinker() || 180 !MAI->getWeakDefDirective() || 181 MAI->getSupportsWeakOmittedEHFrame())) { 182 O << EHFrameInfo.FnName << " = 0\n"; 183 // This name has no connection to the function, so it might get 184 // dead-stripped when the function is not, erroneously. Prohibit 185 // dead-stripping unconditionally. 186 if (const char *UsedDirective = MAI->getUsedDirective()) 187 O << UsedDirective << EHFrameInfo.FnName << "\n\n"; 188 } else { 189 O << EHFrameInfo.FnName << ":\n"; 190 191 // EH frame header. 192 EmitDifference("eh_frame_end", EHFrameInfo.Number, 193 "eh_frame_begin", EHFrameInfo.Number, true); 194 Asm->EOL("Length of Frame Information Entry"); 195 196 EmitLabel("eh_frame_begin", EHFrameInfo.Number); 197 198 EmitSectionOffset("eh_frame_begin", "eh_frame_common", 199 EHFrameInfo.Number, EHFrameInfo.PersonalityIndex, 200 true, true, false); 201 202 Asm->EOL("FDE CIE offset"); 203 204 EmitReference("eh_func_begin", EHFrameInfo.Number, true, true); 205 Asm->EOL("FDE initial location"); 206 EmitDifference("eh_func_end", EHFrameInfo.Number, 207 "eh_func_begin", EHFrameInfo.Number, true); 208 Asm->EOL("FDE address range"); 209 210 // If there is a personality and landing pads then point to the language 211 // specific data area in the exception table. 212 if (MMI->getPersonalities()[0] != NULL) { 213 Asm->EmitULEB128Bytes(4); 214 Asm->EOL("Augmentation size"); 215 216 if (EHFrameInfo.hasLandingPads) 217 EmitReference("exception", EHFrameInfo.Number, true, true); 218 else 219 Asm->EmitInt32((int)0); 220 Asm->EOL("Language Specific Data Area"); 221 } else { 222 Asm->EmitULEB128Bytes(0); 223 Asm->EOL("Augmentation size"); 224 } 225 226 // Indicate locations of function specific callee saved registers in frame. 227 EmitFrameMoves("eh_func_begin", EHFrameInfo.Number, EHFrameInfo.Moves, 228 true); 229 230 // On Darwin the linker honors the alignment of eh_frame, which means it 231 // must be 8-byte on 64-bit targets to match what gcc does. Otherwise you 232 // get holes which confuse readers of eh_frame. 233 Asm->EmitAlignment(TD->getPointerSize() == sizeof(int32_t) ? 2 : 3, 234 0, 0, false); 235 EmitLabel("eh_frame_end", EHFrameInfo.Number); 236 237 // If the function is marked used, this table should be also. We cannot 238 // make the mark unconditional in this case, since retaining the table also 239 // retains the function in this case, and there is code around that depends 240 // on unused functions (calling undefined externals) being dead-stripped to 241 // link correctly. Yes, there really is. 242 if (MMI->isUsedFunction(EHFrameInfo.function)) 243 if (const char *UsedDirective = MAI->getUsedDirective()) 244 O << UsedDirective << EHFrameInfo.FnName << "\n\n"; 245 } 246 247 Asm->EOL(); 248} 249 250/// SharedTypeIds - How many leading type ids two landing pads have in common. 251unsigned DwarfException::SharedTypeIds(const LandingPadInfo *L, 252 const LandingPadInfo *R) { 253 const std::vector<int> &LIds = L->TypeIds, &RIds = R->TypeIds; 254 unsigned LSize = LIds.size(), RSize = RIds.size(); 255 unsigned MinSize = LSize < RSize ? LSize : RSize; 256 unsigned Count = 0; 257 258 for (; Count != MinSize; ++Count) 259 if (LIds[Count] != RIds[Count]) 260 return Count; 261 262 return Count; 263} 264 265/// PadLT - Order landing pads lexicographically by type id. 266bool DwarfException::PadLT(const LandingPadInfo *L, const LandingPadInfo *R) { 267 const std::vector<int> &LIds = L->TypeIds, &RIds = R->TypeIds; 268 unsigned LSize = LIds.size(), RSize = RIds.size(); 269 unsigned MinSize = LSize < RSize ? LSize : RSize; 270 271 for (unsigned i = 0; i != MinSize; ++i) 272 if (LIds[i] != RIds[i]) 273 return LIds[i] < RIds[i]; 274 275 return LSize < RSize; 276} 277 278/// ComputeActionsTable - Compute the actions table and gather the first action 279/// index for each landing pad site. 280unsigned DwarfException:: 281ComputeActionsTable(const SmallVectorImpl<const LandingPadInfo*> &LandingPads, 282 SmallVectorImpl<ActionEntry> &Actions, 283 SmallVectorImpl<unsigned> &FirstActions) { 284 285 // The action table follows the call-site table in the LSDA. The individual 286 // records are of two types: 287 // 288 // * Catch clause 289 // * Exception specification 290 // 291 // The two record kinds have the same format, with only small differences. 292 // They are distinguished by the "switch value" field: Catch clauses 293 // (TypeInfos) have strictly positive switch values, and exception 294 // specifications (FilterIds) have strictly negative switch values. Value 0 295 // indicates a catch-all clause. 296 // 297 // Negative type IDs index into FilterIds. Positive type IDs index into 298 // TypeInfos. The value written for a positive type ID is just the type ID 299 // itself. For a negative type ID, however, the value written is the 300 // (negative) byte offset of the corresponding FilterIds entry. The byte 301 // offset is usually equal to the type ID (because the FilterIds entries are 302 // written using a variable width encoding, which outputs one byte per entry 303 // as long as the value written is not too large) but can differ. This kind 304 // of complication does not occur for positive type IDs because type infos are 305 // output using a fixed width encoding. FilterOffsets[i] holds the byte 306 // offset corresponding to FilterIds[i]. 307 308 const std::vector<unsigned> &FilterIds = MMI->getFilterIds(); 309 SmallVector<int, 16> FilterOffsets; 310 FilterOffsets.reserve(FilterIds.size()); 311 int Offset = -1; 312 313 for (std::vector<unsigned>::const_iterator 314 I = FilterIds.begin(), E = FilterIds.end(); I != E; ++I) { 315 FilterOffsets.push_back(Offset); 316 Offset -= MCAsmInfo::getULEB128Size(*I); 317 } 318 319 FirstActions.reserve(LandingPads.size()); 320 321 int FirstAction = 0; 322 unsigned SizeActions = 0; 323 const LandingPadInfo *PrevLPI = 0; 324 325 for (SmallVectorImpl<const LandingPadInfo *>::const_iterator 326 I = LandingPads.begin(), E = LandingPads.end(); I != E; ++I) { 327 const LandingPadInfo *LPI = *I; 328 const std::vector<int> &TypeIds = LPI->TypeIds; 329 const unsigned NumShared = PrevLPI ? SharedTypeIds(LPI, PrevLPI) : 0; 330 unsigned SizeSiteActions = 0; 331 332 if (NumShared < TypeIds.size()) { 333 unsigned SizeAction = 0; 334 ActionEntry *PrevAction = 0; 335 336 if (NumShared) { 337 const unsigned SizePrevIds = PrevLPI->TypeIds.size(); 338 assert(Actions.size()); 339 PrevAction = &Actions.back(); 340 SizeAction = MCAsmInfo::getSLEB128Size(PrevAction->NextAction) + 341 MCAsmInfo::getSLEB128Size(PrevAction->ValueForTypeID); 342 343 for (unsigned j = NumShared; j != SizePrevIds; ++j) { 344 SizeAction -= 345 MCAsmInfo::getSLEB128Size(PrevAction->ValueForTypeID); 346 SizeAction += -PrevAction->NextAction; 347 PrevAction = PrevAction->Previous; 348 } 349 } 350 351 // Compute the actions. 352 for (unsigned J = NumShared, M = TypeIds.size(); J != M; ++J) { 353 int TypeID = TypeIds[J]; 354 assert(-1 - TypeID < (int)FilterOffsets.size() && "Unknown filter id!"); 355 int ValueForTypeID = TypeID < 0 ? FilterOffsets[-1 - TypeID] : TypeID; 356 unsigned SizeTypeID = MCAsmInfo::getSLEB128Size(ValueForTypeID); 357 358 int NextAction = SizeAction ? -(SizeAction + SizeTypeID) : 0; 359 SizeAction = SizeTypeID + MCAsmInfo::getSLEB128Size(NextAction); 360 SizeSiteActions += SizeAction; 361 362 ActionEntry Action = { ValueForTypeID, NextAction, PrevAction }; 363 Actions.push_back(Action); 364 PrevAction = &Actions.back(); 365 } 366 367 // Record the first action of the landing pad site. 368 FirstAction = SizeActions + SizeSiteActions - SizeAction + 1; 369 } // else identical - re-use previous FirstAction 370 371 // Information used when created the call-site table. The action record 372 // field of the call site record is the offset of the first associated 373 // action record, relative to the start of the actions table. This value is 374 // biased by 1 (1 in dicating the start of the actions table), and 0 375 // indicates that there are no actions. 376 FirstActions.push_back(FirstAction); 377 378 // Compute this sites contribution to size. 379 SizeActions += SizeSiteActions; 380 381 PrevLPI = LPI; 382 } 383 384 return SizeActions; 385} 386 387/// ComputeCallSiteTable - Compute the call-site table. The entry for an invoke 388/// has a try-range containing the call, a non-zero landing pad, and an 389/// appropriate action. The entry for an ordinary call has a try-range 390/// containing the call and zero for the landing pad and the action. Calls 391/// marked 'nounwind' have no entry and must not be contained in the try-range 392/// of any entry - they form gaps in the table. Entries must be ordered by 393/// try-range address. 394void DwarfException:: 395ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites, 396 const RangeMapType &PadMap, 397 const SmallVectorImpl<const LandingPadInfo *> &LandingPads, 398 const SmallVectorImpl<unsigned> &FirstActions) { 399 // The end label of the previous invoke or nounwind try-range. 400 unsigned LastLabel = 0; 401 402 // Whether there is a potentially throwing instruction (currently this means 403 // an ordinary call) between the end of the previous try-range and now. 404 bool SawPotentiallyThrowing = false; 405 406 // Whether the last CallSite entry was for an invoke. 407 bool PreviousIsInvoke = false; 408 409 // Visit all instructions in order of address. 410 for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); 411 I != E; ++I) { 412 for (MachineBasicBlock::const_iterator MI = I->begin(), E = I->end(); 413 MI != E; ++MI) { 414 if (!MI->isLabel()) { 415 SawPotentiallyThrowing |= MI->getDesc().isCall(); 416 continue; 417 } 418 419 unsigned BeginLabel = MI->getOperand(0).getImm(); 420 assert(BeginLabel && "Invalid label!"); 421 422 // End of the previous try-range? 423 if (BeginLabel == LastLabel) 424 SawPotentiallyThrowing = false; 425 426 // Beginning of a new try-range? 427 RangeMapType::iterator L = PadMap.find(BeginLabel); 428 if (L == PadMap.end()) 429 // Nope, it was just some random label. 430 continue; 431 432 const PadRange &P = L->second; 433 const LandingPadInfo *LandingPad = LandingPads[P.PadIndex]; 434 assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] && 435 "Inconsistent landing pad map!"); 436 437 // For Dwarf exception handling (SjLj handling doesn't use this). If some 438 // instruction between the previous try-range and this one may throw, 439 // create a call-site entry with no landing pad for the region between the 440 // try-ranges. 441 if (SawPotentiallyThrowing && 442 MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) { 443 CallSiteEntry Site = { LastLabel, BeginLabel, 0, 0 }; 444 CallSites.push_back(Site); 445 PreviousIsInvoke = false; 446 } 447 448 LastLabel = LandingPad->EndLabels[P.RangeIndex]; 449 assert(BeginLabel && LastLabel && "Invalid landing pad!"); 450 451 if (LandingPad->LandingPadLabel) { 452 // This try-range is for an invoke. 453 CallSiteEntry Site = { 454 BeginLabel, 455 LastLabel, 456 LandingPad->LandingPadLabel, 457 FirstActions[P.PadIndex] 458 }; 459 460 // Try to merge with the previous call-site. 461 if (PreviousIsInvoke) { 462 CallSiteEntry &Prev = CallSites.back(); 463 if (Site.PadLabel == Prev.PadLabel && Site.Action == Prev.Action) { 464 // Extend the range of the previous entry. 465 Prev.EndLabel = Site.EndLabel; 466 continue; 467 } 468 } 469 470 // Otherwise, create a new call-site. 471 CallSites.push_back(Site); 472 PreviousIsInvoke = true; 473 } else { 474 // Create a gap. 475 PreviousIsInvoke = false; 476 } 477 } 478 } 479 480 // If some instruction between the previous try-range and the end of the 481 // function may throw, create a call-site entry with no landing pad for the 482 // region following the try-range. 483 if (SawPotentiallyThrowing && 484 MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) { 485 CallSiteEntry Site = { LastLabel, 0, 0, 0 }; 486 CallSites.push_back(Site); 487 } 488} 489 490/// EmitExceptionTable - Emit landing pads and actions. 491/// 492/// The general organization of the table is complex, but the basic concepts are 493/// easy. First there is a header which describes the location and organization 494/// of the three components that follow. 495/// 496/// 1. The landing pad site information describes the range of code covered by 497/// the try. In our case it's an accumulation of the ranges covered by the 498/// invokes in the try. There is also a reference to the landing pad that 499/// handles the exception once processed. Finally an index into the actions 500/// table. 501/// 2. The action table, in our case, is composed of pairs of type IDs and next 502/// action offset. Starting with the action index from the landing pad 503/// site, each type ID is checked for a match to the current exception. If 504/// it matches then the exception and type id are passed on to the landing 505/// pad. Otherwise the next action is looked up. This chain is terminated 506/// with a next action of zero. If no type id is found the the frame is 507/// unwound and handling continues. 508/// 3. Type ID table contains references to all the C++ typeinfo for all 509/// catches in the function. This tables is reversed indexed base 1. 510void DwarfException::EmitExceptionTable() { 511 const std::vector<GlobalVariable *> &TypeInfos = MMI->getTypeInfos(); 512 const std::vector<unsigned> &FilterIds = MMI->getFilterIds(); 513 const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads(); 514 if (PadInfos.empty()) return; 515 516 // Sort the landing pads in order of their type ids. This is used to fold 517 // duplicate actions. 518 SmallVector<const LandingPadInfo *, 64> LandingPads; 519 LandingPads.reserve(PadInfos.size()); 520 521 for (unsigned i = 0, N = PadInfos.size(); i != N; ++i) 522 LandingPads.push_back(&PadInfos[i]); 523 524 std::sort(LandingPads.begin(), LandingPads.end(), PadLT); 525 526 // Compute the actions table and gather the first action index for each 527 // landing pad site. 528 SmallVector<ActionEntry, 32> Actions; 529 SmallVector<unsigned, 64> FirstActions; 530 unsigned SizeActions = ComputeActionsTable(LandingPads, Actions, FirstActions); 531 532 // Invokes and nounwind calls have entries in PadMap (due to being bracketed 533 // by try-range labels when lowered). Ordinary calls do not, so appropriate 534 // try-ranges for them need be deduced when using Dwarf exception handling. 535 RangeMapType PadMap; 536 for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) { 537 const LandingPadInfo *LandingPad = LandingPads[i]; 538 for (unsigned j = 0, E = LandingPad->BeginLabels.size(); j != E; ++j) { 539 unsigned BeginLabel = LandingPad->BeginLabels[j]; 540 assert(!PadMap.count(BeginLabel) && "Duplicate landing pad labels!"); 541 PadRange P = { i, j }; 542 PadMap[BeginLabel] = P; 543 } 544 } 545 546 // Compute the call-site table. 547 SmallVector<CallSiteEntry, 64> CallSites; 548 ComputeCallSiteTable(CallSites, PadMap, LandingPads, FirstActions); 549 550 // Final tallies. 551 552 // Call sites. 553 const unsigned SiteStartSize = sizeof(int32_t); // DW_EH_PE_udata4 554 const unsigned SiteLengthSize = sizeof(int32_t); // DW_EH_PE_udata4 555 const unsigned LandingPadSize = sizeof(int32_t); // DW_EH_PE_udata4 556 unsigned SizeSites; 557 558 bool HaveTTData = (MAI->getExceptionHandlingType() == ExceptionHandling::SjLj) 559 ? (!TypeInfos.empty() || !FilterIds.empty()) : true; 560 561 562 if (MAI->getExceptionHandlingType() == ExceptionHandling::SjLj) { 563 SizeSites = 0; 564 } else 565 SizeSites = CallSites.size() * 566 (SiteStartSize + SiteLengthSize + LandingPadSize); 567 for (unsigned i = 0, e = CallSites.size(); i < e; ++i) { 568 SizeSites += MCAsmInfo::getULEB128Size(CallSites[i].Action); 569 if (MAI->getExceptionHandlingType() == ExceptionHandling::SjLj) 570 SizeSites += MCAsmInfo::getULEB128Size(i); 571 } 572 // Type infos. 573 const unsigned TypeInfoSize = TD->getPointerSize(); // DW_EH_PE_absptr 574 unsigned SizeTypes = TypeInfos.size() * TypeInfoSize; 575 576 unsigned TypeOffset = sizeof(int8_t) + // Call site format 577 MCAsmInfo::getULEB128Size(SizeSites) + // Call-site table length 578 SizeSites + SizeActions + SizeTypes; 579 580 unsigned TotalSize = sizeof(int8_t) + // LPStart format 581 sizeof(int8_t) + // TType format 582 (HaveTTData ? 583 MCAsmInfo::getULEB128Size(TypeOffset) : 0) + // TType base offset 584 TypeOffset; 585 586 unsigned SizeAlign = (4 - TotalSize) & 3; 587 588 // Begin the exception table. 589 const MCSection *LSDASection = Asm->getObjFileLowering().getLSDASection(); 590 Asm->OutStreamer.SwitchSection(LSDASection); 591 Asm->EmitAlignment(2, 0, 0, false); 592 O << "GCC_except_table" << SubprogramCount << ":\n"; 593 594 for (unsigned i = 0; i != SizeAlign; ++i) { 595 Asm->EmitInt8(0); 596 Asm->EOL("Padding"); 597 } 598 599 EmitLabel("exception", SubprogramCount); 600 if (MAI->getExceptionHandlingType() == ExceptionHandling::SjLj) { 601 std::string SjLjName = "_lsda_"; 602 SjLjName += MF->getFunction()->getName().str(); 603 EmitLabel(SjLjName.c_str(), 0); 604 } 605 606 // Emit the header. 607 unsigned Encoding = dwarf::DW_EH_PE_omit; 608 Asm->EmitInt8(Encoding); 609 Asm->EOL("@LPStart format", Encoding); 610 611#if 0 612 if (TypeInfos.empty() && FilterIds.empty()) { 613 // If there are no typeinfos or filters, there is nothing to emit, optimize 614 // by specifying the "omit" encoding. 615 Encoding = dwarf::DW_EH_PE_omit; 616 Asm->EmitInt8(Encoding); 617 Asm->EOL("@TType format", Encoding); 618 } else { 619 // Okay, we have actual filters or typeinfos to emit. As such, we need to 620 // pick a type encoding for them. We're about to emit a list of pointers to 621 // typeinfo objects at the end of the LSDA. However, unless we're in static 622 // mode, this reference will require a relocation by the dynamic linker. 623 // 624 // Because of this, we have a couple of options: 625 // 1) If we are in -static mode, we can always use an absolute reference 626 // from the LSDA, because the static linker will resolve it. 627 // 2) Otherwise, if the LSDA section is writable, we can output the direct 628 // reference to the typeinfo and allow the dynamic linker to relocate 629 // it. Since it is in a writable section, the dynamic linker won't 630 // have a problem. 631 // 3) Finally, if we're in PIC mode and the LDSA section isn't writable, 632 // we need to use some form of indirection. For example, on Darwin, 633 // we can output a statically-relocatable reference to a dyld stub. The 634 // offset to the stub is constant, but the contents are in a section 635 // that is updated by the dynamic linker. This is easy enough, but we 636 // need to tell the personality function of the unwinder to indirect 637 // through the dyld stub. 638 // 639 // FIXME: When this is actually implemented, we'll have to emit the stubs 640 // somewhere. This predicate should be moved to a shared location that is 641 // in target-independent code. 642 // 643 if (LSDASection->isWritable() || 644 Asm->TM.getRelocationModel() == Reloc::Static) { 645 Encoding = DW_EH_PE_absptr; 646 Asm->EmitInt8(Encoding); 647 Asm->EOL("TType format", Encoding); 648 } else { 649 Encoding = DW_EH_PE_pcrel | DW_EH_PE_indirect | DW_EH_PE_sdata4; 650 Asm->EmitInt8(DW_EH_PE_pcrel | DW_EH_PE_indirect | DW_EH_PE_sdata4); 651 Asm->EOL("TType format", Encoding); 652 } 653 Asm->EmitULEB128Bytes(TypeOffset); 654 Asm->EOL("TType base offset"); 655 } 656#else 657 // For SjLj exceptions, if there is no TypeInfo, then we just explicitly 658 // say that we're omitting that bit. 659 // FIXME: does this apply to Dwarf also? The above #if 0 implies yes? 660 if (!HaveTTData) { 661 Encoding = dwarf::DW_EH_PE_omit; 662 Asm->EmitInt8(Encoding); 663 Asm->EOL("@TType format", Encoding); 664 } else { 665 Encoding = dwarf::DW_EH_PE_absptr; 666 Asm->EmitInt8(Encoding); 667 Asm->EOL("@TType format", Encoding); 668 Asm->EmitULEB128Bytes(TypeOffset); 669 Asm->EOL("@TType base offset"); 670 } 671#endif 672 673 // SjLj Exception handilng 674 if (MAI->getExceptionHandlingType() == ExceptionHandling::SjLj) { 675 Encoding = dwarf::DW_EH_PE_udata4; 676 Asm->EmitInt8(Encoding); 677 Asm->EOL("Call site format", Encoding); 678 Asm->EmitULEB128Bytes(SizeSites); 679 Asm->EOL("Call site table length"); 680 681 // Emit the landing pad site information. 682 unsigned idx = 0; 683 for (SmallVectorImpl<CallSiteEntry>::const_iterator 684 I = CallSites.begin(), E = CallSites.end(); I != E; ++I, ++idx) { 685 const CallSiteEntry &S = *I; 686 687 // Offset of the landing pad, counted in 16-byte bundles relative to the 688 // @LPStart address. 689 Asm->EmitULEB128Bytes(idx); 690 Asm->EOL("Landing pad"); 691 692 // Offset of the first associated action record, relative to the start of 693 // the action table. This value is biased by 1 (1 indicates the start of 694 // the action table), and 0 indicates that there are no actions. 695 Asm->EmitULEB128Bytes(S.Action); 696 Asm->EOL("Action"); 697 } 698 } else { 699 // DWARF Exception handling 700 assert(MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf); 701 702 // The call-site table is a list of all call sites that may throw an 703 // exception (including C++ 'throw' statements) in the procedure 704 // fragment. It immediately follows the LSDA header. Each entry indicates, 705 // for a given call, the first corresponding action record and corresponding 706 // landing pad. 707 // 708 // The table begins with the number of bytes, stored as an LEB128 709 // compressed, unsigned integer. The records immediately follow the record 710 // count. They are sorted in increasing call-site address. Each record 711 // indicates: 712 // 713 // * The position of the call-site. 714 // * The position of the landing pad. 715 // * The first action record for that call site. 716 // 717 // A missing entry in the call-site table indicates that a call is not 718 // supposed to throw. Such calls include: 719 // 720 // * Calls to destructors within cleanup code. C++ semantics forbids these 721 // calls to throw. 722 // * Calls to intrinsic routines in the standard library which are known 723 // not to throw (sin, memcpy, et al). 724 // 725 // If the runtime does not find the call-site entry for a given call, it 726 // will call `terminate()'. 727 728 // Emit the landing pad call site table. 729 Encoding = dwarf::DW_EH_PE_udata4; 730 Asm->EmitInt8(Encoding); 731 Asm->EOL("Call site format", Encoding); 732 Asm->EmitULEB128Bytes(SizeSites); 733 Asm->EOL("Call site table size"); 734 735 for (SmallVectorImpl<CallSiteEntry>::const_iterator 736 I = CallSites.begin(), E = CallSites.end(); I != E; ++I) { 737 const CallSiteEntry &S = *I; 738 const char *BeginTag; 739 unsigned BeginNumber; 740 741 if (!S.BeginLabel) { 742 BeginTag = "eh_func_begin"; 743 BeginNumber = SubprogramCount; 744 } else { 745 BeginTag = "label"; 746 BeginNumber = S.BeginLabel; 747 } 748 749 // Offset of the call site relative to the previous call site, counted in 750 // number of 16-byte bundles. The first call site is counted relative to 751 // the start of the procedure fragment. 752 EmitSectionOffset(BeginTag, "eh_func_begin", BeginNumber, SubprogramCount, 753 true, true); 754 Asm->EOL("Region start"); 755 756 if (!S.EndLabel) 757 EmitDifference("eh_func_end", SubprogramCount, BeginTag, BeginNumber, 758 true); 759 else 760 EmitDifference("label", S.EndLabel, BeginTag, BeginNumber, true); 761 762 Asm->EOL("Region length"); 763 764 // Offset of the landing pad, counted in 16-byte bundles relative to the 765 // @LPStart address. 766 if (!S.PadLabel) 767 Asm->EmitInt32(0); 768 else 769 EmitSectionOffset("label", "eh_func_begin", S.PadLabel, SubprogramCount, 770 true, true); 771 772 Asm->EOL("Landing pad"); 773 774 // Offset of the first associated action record, relative to the start of 775 // the action table. This value is biased by 1 (1 indicates the start of 776 // the action table), and 0 indicates that there are no actions. 777 Asm->EmitULEB128Bytes(S.Action); 778 Asm->EOL("Action"); 779 } 780 } 781 782 // Emit the Action Table. 783 for (SmallVectorImpl<ActionEntry>::const_iterator 784 I = Actions.begin(), E = Actions.end(); I != E; ++I) { 785 const ActionEntry &Action = *I; 786 787 // Type Filter 788 // 789 // Used by the runtime to match the type of the thrown exception to the 790 // type of the catch clauses or the types in the exception specification. 791 792 Asm->EmitSLEB128Bytes(Action.ValueForTypeID); 793 Asm->EOL("TypeInfo index"); 794 795 // Action Record 796 // 797 // Self-relative signed displacement in bytes of the next action record, 798 // or 0 if there is no next action record. 799 800 Asm->EmitSLEB128Bytes(Action.NextAction); 801 Asm->EOL("Next action"); 802 } 803 804 // Emit the Catch Clauses. The code for the catch clauses following the same 805 // try is similar to a switch statement. The catch clause action record 806 // informs the runtime about the type of a catch clause and about the 807 // associated switch value. 808 // 809 // Action Record Fields: 810 // 811 // * Filter Value 812 // Positive value, starting at 1. Index in the types table of the 813 // __typeinfo for the catch-clause type. 1 is the first word preceding 814 // TTBase, 2 is the second word, and so on. Used by the runtime to check 815 // if the thrown exception type matches the catch-clause type. Back-end 816 // generated switch statements check against this value. 817 // 818 // * Next 819 // Signed offset, in bytes from the start of this field, to the next 820 // chained action record, or zero if none. 821 // 822 // The order of the action records determined by the next field is the order 823 // of the catch clauses as they appear in the source code, and must be kept in 824 // the same order. As a result, changing the order of the catch clause would 825 // change the semantics of the program. 826 for (std::vector<GlobalVariable *>::const_reverse_iterator 827 I = TypeInfos.rbegin(), E = TypeInfos.rend(); I != E; ++I) { 828 const GlobalVariable *GV = *I; 829 PrintRelDirective(); 830 831 if (GV) { 832 std::string GLN; 833 O << Asm->getGlobalLinkName(GV, GLN); 834 } else { 835 O << "0"; 836 } 837 838 Asm->EOL("TypeInfo"); 839 } 840 841 // Emit the Type Table. 842 for (std::vector<unsigned>::const_iterator 843 I = FilterIds.begin(), E = FilterIds.end(); I < E; ++I) { 844 unsigned TypeID = *I; 845 Asm->EmitULEB128Bytes(TypeID); 846 Asm->EOL("Filter TypeInfo index"); 847 } 848 849 Asm->EmitAlignment(2, 0, 0, false); 850} 851 852/// EndModule - Emit all exception information that should come after the 853/// content. 854void DwarfException::EndModule() { 855 if (MAI->getExceptionHandlingType() != ExceptionHandling::Dwarf) 856 return; 857 if (TimePassesIsEnabled) 858 ExceptionTimer->startTimer(); 859 860 if (shouldEmitMovesModule || shouldEmitTableModule) { 861 const std::vector<Function *> Personalities = MMI->getPersonalities(); 862 for (unsigned i = 0; i < Personalities.size(); ++i) 863 EmitCIE(Personalities[i], i); 864 865 for (std::vector<FunctionEHFrameInfo>::iterator I = EHFrames.begin(), 866 E = EHFrames.end(); I != E; ++I) 867 EmitFDE(*I); 868 } 869 870 if (TimePassesIsEnabled) 871 ExceptionTimer->stopTimer(); 872} 873 874/// BeginFunction - Gather pre-function exception information. Assumes being 875/// emitted immediately after the function entry point. 876void DwarfException::BeginFunction(MachineFunction *MF) { 877 if (TimePassesIsEnabled) 878 ExceptionTimer->startTimer(); 879 880 this->MF = MF; 881 shouldEmitTable = shouldEmitMoves = false; 882 883 if (MMI && MAI->doesSupportExceptionHandling()) { 884 // Map all labels and get rid of any dead landing pads. 885 MMI->TidyLandingPads(); 886 887 // If any landing pads survive, we need an EH table. 888 if (MMI->getLandingPads().size()) 889 shouldEmitTable = true; 890 891 // See if we need frame move info. 892 if (!MF->getFunction()->doesNotThrow() || UnwindTablesMandatory) 893 shouldEmitMoves = true; 894 895 if (shouldEmitMoves || shouldEmitTable) 896 // Assumes in correct section after the entry point. 897 EmitLabel("eh_func_begin", ++SubprogramCount); 898 } 899 900 shouldEmitTableModule |= shouldEmitTable; 901 shouldEmitMovesModule |= shouldEmitMoves; 902 903 if (TimePassesIsEnabled) 904 ExceptionTimer->stopTimer(); 905} 906 907/// EndFunction - Gather and emit post-function exception information. 908/// 909void DwarfException::EndFunction() { 910 if (TimePassesIsEnabled) 911 ExceptionTimer->startTimer(); 912 913 if (shouldEmitMoves || shouldEmitTable) { 914 EmitLabel("eh_func_end", SubprogramCount); 915 EmitExceptionTable(); 916 917 // Save EH frame information 918 EHFrames.push_back( 919 FunctionEHFrameInfo(getAsm()->getCurrentFunctionEHName(MF), 920 SubprogramCount, 921 MMI->getPersonalityIndex(), 922 MF->getFrameInfo()->hasCalls(), 923 !MMI->getLandingPads().empty(), 924 MMI->getFrameMoves(), 925 MF->getFunction())); 926 } 927 928 if (TimePassesIsEnabled) 929 ExceptionTimer->stopTimer(); 930} 931