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