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