Index: include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h +++ include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h @@ -52,9 +52,11 @@ uint32_t Magic; uint16_t Version; uint16_t HashFunction; - uint32_t NumBuckets; - uint32_t NumHashes; + uint32_t BucketCount; + uint32_t HashCount; uint32_t HeaderDataLength; + + void dump(ScopedPrinter &W) const; }; struct HeaderData { @@ -69,6 +71,11 @@ struct HeaderData HdrData; bool IsValid = false; + /// Returns true if we should continue scanning for entries or false if we've + /// reached the last (sentinel) entry of encountered a parsing error. + bool dumpName(ScopedPrinter &W, SmallVectorImpl &AtomForms, + uint32_t *DataOffset) const; + public: /// An iterator for the entries associated with one key. Each entry can have /// multiple DWARFFormValues. Index: lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp +++ lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp @@ -60,8 +60,8 @@ Hdr.Magic = AccelSection.getU32(&Offset); Hdr.Version = AccelSection.getU16(&Offset); Hdr.HashFunction = AccelSection.getU16(&Offset); - Hdr.NumBuckets = AccelSection.getU32(&Offset); - Hdr.NumHashes = AccelSection.getU32(&Offset); + Hdr.BucketCount = AccelSection.getU32(&Offset); + Hdr.HashCount = AccelSection.getU32(&Offset); Hdr.HeaderDataLength = AccelSection.getU32(&Offset); // Check that we can read all the hashes and offsets from the @@ -69,7 +69,7 @@ // We need to substract one because we're checking for an *offset* which is // equal to the size for an empty table and hence pointer after the section. if (!AccelSection.isValidOffset(sizeof(Hdr) + Hdr.HeaderDataLength + - Hdr.NumBuckets * 4 + Hdr.NumHashes * 8 - 1)) + Hdr.BucketCount * 4 + Hdr.HashCount * 8 - 1)) return make_error( "Section too small: cannot read buckets and hashes.", inconvertibleErrorCode()); @@ -87,8 +87,8 @@ return Error::success(); } -uint32_t AppleAcceleratorTable::getNumBuckets() { return Hdr.NumBuckets; } -uint32_t AppleAcceleratorTable::getNumHashes() { return Hdr.NumHashes; } +uint32_t AppleAcceleratorTable::getNumBuckets() { return Hdr.BucketCount; } +uint32_t AppleAcceleratorTable::getNumHashes() { return Hdr.HashCount; } uint32_t AppleAcceleratorTable::getSizeHdr() { return sizeof(Hdr); } uint32_t AppleAcceleratorTable::getHeaderDataLength() { return Hdr.HeaderDataLength; @@ -142,78 +142,101 @@ return {DieOffset, DieTag}; } +void AppleAcceleratorTable::Header::dump(ScopedPrinter &W) const { + DictScope HeaderScope(W, "Header"); + W.printHex("Magic", Magic); + W.printHex("Version", Version); + W.printHex("Hash function", HashFunction); + W.printNumber("Bucket count", BucketCount); + W.printNumber("Hashes count", HashCount); + W.printNumber("HeaderData length", HeaderDataLength); +} + +bool AppleAcceleratorTable::dumpName(ScopedPrinter &W, + SmallVectorImpl &AtomForms, + uint32_t *DataOffset) const { + DWARFFormParams FormParams = {Hdr.Version, 0, dwarf::DwarfFormat::DWARF32}; + uint32_t NameOffset = *DataOffset; + if (!AccelSection.isValidOffsetForDataOfSize(*DataOffset, 4)) { + W.printString("Incorrectly terminated list."); + return false; + } + unsigned StringOffset = AccelSection.getRelocatedValue(4, DataOffset); + if (!StringOffset) + return false; // End of list + + DictScope NameScope(W, ("Name@0x" + Twine::utohexstr(NameOffset)).str()); + W.startLine() << format("String: 0x%08x", StringOffset); + W.getOStream() << " \"" << StringSection.getCStr(&StringOffset) << "\"\n"; + + unsigned NumData = AccelSection.getU32(DataOffset); + for (unsigned Data = 0; Data < NumData; ++Data) { + ListScope DataScope(W, ("Data " + Twine(Data)).str()); + unsigned i = 0; + for (auto &Atom : AtomForms) { + W.startLine() << format("Atom[%d]: ", i++); + if (Atom.extractValue(AccelSection, DataOffset, FormParams)) + Atom.dump(W.getOStream()); + else + W.getOStream() << "Error extracting the value"; + W.getOStream() << "\n"; + } + } + return true; // more entries follow +} + LLVM_DUMP_METHOD void AppleAcceleratorTable::dump(raw_ostream &OS) const { if (!IsValid) return; - // Dump the header. - OS << "Magic = " << format("0x%08x", Hdr.Magic) << '\n' - << "Version = " << format("0x%04x", Hdr.Version) << '\n' - << "Hash function = " << format("0x%08x", Hdr.HashFunction) << '\n' - << "Bucket count = " << Hdr.NumBuckets << '\n' - << "Hashes count = " << Hdr.NumHashes << '\n' - << "HeaderData length = " << Hdr.HeaderDataLength << '\n' - << "DIE offset base = " << HdrData.DIEOffsetBase << '\n' - << "Number of atoms = " << HdrData.Atoms.size() << '\n'; - - unsigned i = 0; + ScopedPrinter W(OS); + + Hdr.dump(W); + + W.printNumber("DIE offset base", HdrData.DIEOffsetBase); + W.printNumber("Number of atoms", HdrData.Atoms.size()); SmallVector AtomForms; - for (const auto &Atom: HdrData.Atoms) { - OS << format("Atom[%d] Type: ", i++) << formatAtom(Atom.first) - << " Form: " << formatForm(Atom.second) << '\n'; - AtomForms.push_back(DWARFFormValue(Atom.second)); + { + ListScope AtomsScope(W, "Atoms"); + unsigned i = 0; + for (const auto &Atom : HdrData.Atoms) { + DictScope AtomScope(W, ("Atom " + Twine(i++)).str()); + W.startLine() << "Type: " << formatAtom(Atom.first) << '\n'; + W.startLine() << "Form: " << formatForm(Atom.second) << '\n'; + AtomForms.push_back(DWARFFormValue(Atom.second)); + } } // Now go through the actual tables and dump them. uint32_t Offset = sizeof(Hdr) + Hdr.HeaderDataLength; - unsigned HashesBase = Offset + Hdr.NumBuckets * 4; - unsigned OffsetsBase = HashesBase + Hdr.NumHashes * 4; - DWARFFormParams FormParams = {Hdr.Version, 0, dwarf::DwarfFormat::DWARF32}; + unsigned HashesBase = Offset + Hdr.BucketCount * 4; + unsigned OffsetsBase = HashesBase + Hdr.HashCount * 4; - for (unsigned Bucket = 0; Bucket < Hdr.NumBuckets; ++Bucket) { + for (unsigned Bucket = 0; Bucket < Hdr.BucketCount; ++Bucket) { unsigned Index = AccelSection.getU32(&Offset); - OS << format("Bucket[%d]\n", Bucket); + ListScope BucketScope(W, ("Bucket " + Twine(Bucket)).str()); if (Index == UINT32_MAX) { - OS << " EMPTY\n"; + W.printString("EMPTY"); continue; } - for (unsigned HashIdx = Index; HashIdx < Hdr.NumHashes; ++HashIdx) { + for (unsigned HashIdx = Index; HashIdx < Hdr.HashCount; ++HashIdx) { unsigned HashOffset = HashesBase + HashIdx*4; unsigned OffsetsOffset = OffsetsBase + HashIdx*4; uint32_t Hash = AccelSection.getU32(&HashOffset); - if (Hash % Hdr.NumBuckets != Bucket) + if (Hash % Hdr.BucketCount != Bucket) break; unsigned DataOffset = AccelSection.getU32(&OffsetsOffset); - OS << format(" Hash = 0x%08x Offset = 0x%08x\n", Hash, DataOffset); + ListScope HashScope(W, ("Hash 0x" + Twine::utohexstr(Hash)).str()); if (!AccelSection.isValidOffset(DataOffset)) { - OS << " Invalid section offset\n"; + W.printString("Invalid section offset"); continue; } - while (AccelSection.isValidOffsetForDataOfSize(DataOffset, 4)) { - unsigned StringOffset = AccelSection.getRelocatedValue(4, &DataOffset); - if (!StringOffset) - break; - OS << format(" Name: %08x \"%s\"\n", StringOffset, - StringSection.getCStr(&StringOffset)); - unsigned NumData = AccelSection.getU32(&DataOffset); - for (unsigned Data = 0; Data < NumData; ++Data) { - OS << format(" Data[%d] => ", Data); - unsigned i = 0; - for (auto &Atom : AtomForms) { - OS << format("{Atom[%d]: ", i++); - if (Atom.extractValue(AccelSection, &DataOffset, FormParams)) - Atom.dump(OS); - else - OS << "Error extracting the value"; - OS << "} "; - } - OS << '\n'; - } - } + while (dumpName(W, AtomForms, &DataOffset)) + /*empty*/; } } } @@ -254,21 +277,21 @@ // Find the bucket. unsigned HashValue = dwarf::djbHash(Key); - unsigned Bucket = HashValue % Hdr.NumBuckets; + unsigned Bucket = HashValue % Hdr.BucketCount; unsigned BucketBase = sizeof(Hdr) + Hdr.HeaderDataLength; - unsigned HashesBase = BucketBase + Hdr.NumBuckets * 4; - unsigned OffsetsBase = HashesBase + Hdr.NumHashes * 4; + unsigned HashesBase = BucketBase + Hdr.BucketCount * 4; + unsigned OffsetsBase = HashesBase + Hdr.HashCount * 4; unsigned BucketOffset = BucketBase + Bucket * 4; unsigned Index = AccelSection.getU32(&BucketOffset); // Search through all hashes in the bucket. - for (unsigned HashIdx = Index; HashIdx < Hdr.NumHashes; ++HashIdx) { + for (unsigned HashIdx = Index; HashIdx < Hdr.HashCount; ++HashIdx) { unsigned HashOffset = HashesBase + HashIdx * 4; unsigned OffsetsOffset = OffsetsBase + HashIdx * 4; uint32_t Hash = AccelSection.getU32(&HashOffset); - if (Hash % Hdr.NumBuckets != Bucket) + if (Hash % Hdr.BucketCount != Bucket) // We are already in the next bucket. break; Index: test/DebugInfo/Generic/accel-table-hash-collisions.ll =================================================================== --- test/DebugInfo/Generic/accel-table-hash-collisions.ll +++ test/DebugInfo/Generic/accel-table-hash-collisions.ll @@ -23,33 +23,33 @@ ; int _ZN4llvm22MachineModuleInfoMachOD2Ev; ; Check that we have the right amount of hashes. -; CHECK: Bucket count = 6 -; CHECK: Hashes count = 6 +; CHECK: Bucket count: 6 +; CHECK: Hashes count: 6 ; Check that all the names are present in the output -; CHECK: Hash = 0x00597841 -; CHECK: Name: {{[0-9a-f]*}} "is" -; CHECK: Name: {{[0-9a-f]*}} "k1" +; CHECK: Hash 0x597841 +; CHECK: String: 0x{{[0-9a-f]*}} "is" +; CHECK: String: 0x{{[0-9a-f]*}} "k1" -; CHECK: Hash = 0xa4b42a1e -; CHECK: Name: {{[0-9a-f]*}} "_ZN5clang23DataRecursiveASTVisitorIN12_GLOBAL__N_124UnusedBackingIvarCheckerEE26TraverseCUDAKernelCallExprEPNS_18CUDAKernelCallExprE" -; CHECK: Name: {{[0-9a-f]*}} "_ZN4llvm16DenseMapIteratorIPNS_10MDLocationENS_6detail13DenseSetEmptyENS_10MDNodeInfoIS1_EENS3_12DenseSetPairIS2_EELb0EE23AdvancePastEmptyBucketsEv" +; CHECK: Hash 0xa4b42a1e +; CHECK: String: 0x{{[0-9a-f]*}} "_ZN5clang23DataRecursiveASTVisitorIN12_GLOBAL__N_124UnusedBackingIvarCheckerEE26TraverseCUDAKernelCallExprEPNS_18CUDAKernelCallExprE" +; CHECK: String: 0x{{[0-9a-f]*}} "_ZN4llvm16DenseMapIteratorIPNS_10MDLocationENS_6detail13DenseSetEmptyENS_10MDNodeInfoIS1_EENS3_12DenseSetPairIS2_EELb0EE23AdvancePastEmptyBucketsEv" -; CHECK: Hash = 0xeee7c0b2 -; CHECK: Name: {{[0-9a-f]*}} "_ZNK4llvm12LivePhysRegs5printERNS_11raw_ostreamE" -; CHECK: Name: {{[0-9a-f]*}} "_ZN4llvm15ScalarEvolution14getSignedRangeEPKNS_4SCEVE" +; CHECK: Hash 0xeee7c0b2 +; CHECK: String: 0x{{[0-9a-f]*}} "_ZNK4llvm12LivePhysRegs5printERNS_11raw_ostreamE" +; CHECK: String: 0x{{[0-9a-f]*}} "_ZN4llvm15ScalarEvolution14getSignedRangeEPKNS_4SCEVE" -; CHECK: Hash = 0xea48ac5f -; CHECK: Name: {{[0-9a-f]*}} "ForceTopDown" -; CHECK: Name: {{[0-9a-f]*}} "_ZNSt3__116allocator_traitsINS_9allocatorINS_11__tree_nodeINS_12__value_typeIPN4llvm10BasicBlockEPNS4_10RegionNodeEEEPvEEEEE11__constructIS9_JNS_4pairIS6_S8_EEEEEvNS_17integral_constantIbLb1EEERSC_PT_DpOT0_" +; CHECK: Hash 0xea48ac5f +; CHECK: String: 0x{{[0-9a-f]*}} "ForceTopDown" +; CHECK: String: 0x{{[0-9a-f]*}} "_ZNSt3__116allocator_traitsINS_9allocatorINS_11__tree_nodeINS_12__value_typeIPN4llvm10BasicBlockEPNS4_10RegionNodeEEEPvEEEEE11__constructIS9_JNS_4pairIS6_S8_EEEEEvNS_17integral_constantIbLb1EEERSC_PT_DpOT0_" -; CHECK: Hash = 0x6b22f71f -; CHECK: Name: {{[0-9a-f]*}} "_ZNK5clang12OverrideAttr5cloneERNS_10ASTContextE" -; CHECK: Name: {{[0-9a-f]*}} "_ZN4llvm22MachineModuleInfoMachOD2Ev" +; CHECK: Hash 0x6b22f71f +; CHECK: String: 0x{{[0-9a-f]*}} "_ZNK5clang12OverrideAttr5cloneERNS_10ASTContextE" +; CHECK: String: 0x{{[0-9a-f]*}} "_ZN4llvm22MachineModuleInfoMachOD2Ev" -; CHECK: Hash = 0x8c248979 -; CHECK: Name: {{[0-9a-f]*}} "setStmt" -; CHECK: Name: {{[0-9a-f]*}} "_ZN4llvm5TwineC1Ei" +; CHECK: Hash 0x8c248979 +; CHECK: String: 0x{{[0-9a-f]*}} "setStmt" +; CHECK: String: 0x{{[0-9a-f]*}} "_ZN4llvm5TwineC1Ei" source_filename = "test/DebugInfo/Generic/accel-table-hash-collisions.ll" Index: test/DebugInfo/Generic/cross-cu-inlining.ll =================================================================== --- test/DebugInfo/Generic/cross-cu-inlining.ll +++ test/DebugInfo/Generic/cross-cu-inlining.ll @@ -57,10 +57,10 @@ ; correctly referenced in the accelerator table. Before r221837, the one ; in the second compilation unit had a wrong offset ; CHECK-ACCEL: .apple_names contents: -; CHECK-ACCEL: Name{{.*}}"func" -; CHECK-ACCEL-NOT: Name +; CHECK-ACCEL: String{{.*}}"func" +; CHECK-ACCEL-NOT: String ; CHECK-ACCEL: Atom[0]{{.*}}[[INLINED]] -; CHECK-ACCEL-NOT: Name +; CHECK-ACCEL-NOT: String ; CHECK-ACCEL: Atom[0]{{.*}}[[FUNC]] @i = external global i32 Index: test/DebugInfo/dwarfdump-accel.test =================================================================== --- test/DebugInfo/dwarfdump-accel.test +++ test/DebugInfo/dwarfdump-accel.test @@ -19,39 +19,42 @@ Check that the section header is printed correclty. CHECK: .apple_names contents: -CHECK: Magic = 0x48415348 -CHECK: Version = 0x0001 -CHECK: Hash function = 0x00000000 -CHECK: Bucket count = 21 -CHECK: Hashes count = 42 -CHECK: HeaderData length = 12 -CHECK: DIE offset base = 0 -CHECK: Number of atoms = 1 -CHECK: Atom[0] Type: DW_ATOM_die_offset Form: DW_FORM_data4 +CHECK: Magic: 0x48415348 +CHECK: Version: 0x1 +CHECK: Hash function: 0x0 +CHECK: Bucket count: 21 +CHECK: Hashes count: 42 +CHECK: HeaderData length: 12 +CHECK: DIE offset base: 0 +CHECK: Number of atoms: 1 + +CHECK: Atom 0 { +CHECK-NEXT: Type: DW_ATOM_die_offset +CHECK-NEXT: Form: DW_FORM_data4 Check that the accelerators point to the right DIEs. -CHECK: Name:{{.*}}"-[TestInterface ReadOnly]" -CHECK-NOT: Name -CHECK: {Atom[0]: [[READONLY]]} +CHECK: String:{{.*}}"-[TestInterface ReadOnly]" +CHECK-NOT: String +CHECK: Atom[0]: [[READONLY]] Check that empty buckets are handled correctly. -CHECK: Bucket[3] +CHECK: Bucket 3 CHECK: EMPTY -CHECK: Bucket[4] +CHECK: Bucket 4 Check that the accelerators point to the right DIEs. -CHECK: Name:{{.*}}"-[TestInterface Assign]" -CHECK-NOT: Name -CHECK: {Atom[0]: [[ASSIGN]]} -CHECK: Name:{{.*}}"-[TestInterface setAssign:]" -CHECK-NOT: Name -CHECK: {Atom[0]: [[SETASSIGN]]} +CHECK: String:{{.*}}"-[TestInterface Assign]" +CHECK-NOT: String +CHECK: Atom[0]: [[ASSIGN]] +CHECK: String:{{.*}}"-[TestInterface setAssign:]" +CHECK-NOT: String +CHECK: Atom[0]: [[SETASSIGN]] Check that types are referenced correctly. CHECK: .apple_types contents: -CHECK: Name{{.*}}"TestInterface" -CHECK-NOT: Name -CHECK: {Atom[0]: [[TESTINTERFACE]]} +CHECK: String:{{.*}}"TestInterface" +CHECK-NOT: String +CHECK: Atom[0]: [[TESTINTERFACE]] Check that an empty accelerator section is handled correctly. CHECK: .apple_namespaces contents: @@ -59,11 +62,11 @@ Check ObjC specific accelerators. CHECK: .apple_objc contents: -CHECK: Name{{.*}}"TestInterface" -CHECK-NOT: Name -CHECK: {Atom[0]: [[READONLY]]} -CHECK: {Atom[0]: [[ASSIGN]]} -CHECK: {Atom[0]: [[SETASSIGN]]} +CHECK: String{{.*}}"TestInterface" +CHECK-NOT: String +CHECK: Atom[0]: [[READONLY]] +CHECK: Atom[0]: [[ASSIGN]] +CHECK: Atom[0]: [[SETASSIGN]] Verify the debug info in the apple_names accelerator table. VERIFY: Verifying .apple_names...