diff --git a/lldb/include/lldb/Utility/UUID.h b/lldb/include/lldb/Utility/UUID.h --- a/lldb/include/lldb/Utility/UUID.h +++ b/lldb/include/lldb/Utility/UUID.h @@ -11,6 +11,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Endian.h" #include #include #include @@ -23,6 +24,23 @@ public: UUID() = default; + // Reference: + // https://crashpad.chromium.org/doxygen/structcrashpad_1_1CodeViewRecordPDB70.html + struct CvRecordPdb70 { + struct { + llvm::support::ulittle32_t Data1; + llvm::support::ulittle16_t Data2; + llvm::support::ulittle16_t Data3; + uint8_t Data4[8]; + } Uuid; + llvm::support::ulittle32_t Age; + // char PDBFileName[]; + }; + + /// Create a UUID from CvRecordPdb70. + static UUID fromData(const CvRecordPdb70 *debug_info, + bool swapByteOrder = true); + /// Creates a UUID from the data pointed to by the bytes argument. No special /// significance is attached to any of the values. static UUID fromData(const void *bytes, uint32_t num_bytes) { diff --git a/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp b/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp --- a/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp +++ b/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp @@ -27,43 +27,11 @@ LLDB_PLUGIN_DEFINE(ObjectFilePDB) -struct CVInfoPdb70 { - // 16-byte GUID - struct _Guid { - llvm::support::ulittle32_t Data1; - llvm::support::ulittle16_t Data2; - llvm::support::ulittle16_t Data3; - uint8_t Data4[8]; - } Guid; - - llvm::support::ulittle32_t Age; -}; - static UUID GetPDBUUID(InfoStream &IS) { - // This part is similar with what has done in ObjectFilePECOFF. - using llvm::support::endian::read16be; - using llvm::support::endian::read32; - using llvm::support::endian::read32be; - - GUID guid = IS.getGuid(); - const uint8_t *guid_p = guid.Guid; - struct CVInfoPdb70 info; - info.Guid.Data1 = read32be(guid_p); - guid_p += 4; - info.Guid.Data2 = read16be(guid_p); - guid_p += 2; - info.Guid.Data3 = read16be(guid_p); - guid_p += 2; - memcpy(info.Guid.Data4, guid_p, 8); - - // Return 20-byte UUID if the Age is not zero - uint32_t age = IS.getAge(); - if (age) { - info.Age = read32(&age, llvm::support::big); - return UUID::fromOptionalData(&info, sizeof(info)); - } - // Otherwise return 16-byte GUID - return UUID::fromOptionalData(&info.Guid, sizeof(info.Guid)); + UUID::CvRecordPdb70 debug_info; + memcpy(&debug_info.Uuid, IS.getGuid().Guid, sizeof(debug_info.Uuid)); + debug_info.Age = IS.getAge(); + return UUID::fromData(&debug_info); } char ObjectFilePDB::ID; diff --git a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp --- a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp +++ b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp @@ -43,45 +43,16 @@ LLDB_PLUGIN_DEFINE(ObjectFilePECOFF) -struct CVInfoPdb70 { - // 16-byte GUID - struct _Guid { - llvm::support::ulittle32_t Data1; - llvm::support::ulittle16_t Data2; - llvm::support::ulittle16_t Data3; - uint8_t Data4[8]; - } Guid; - - llvm::support::ulittle32_t Age; -}; - static UUID GetCoffUUID(llvm::object::COFFObjectFile &coff_obj) { const llvm::codeview::DebugInfo *pdb_info = nullptr; llvm::StringRef pdb_file; - // This part is similar with what has done in minidump parser. if (!coff_obj.getDebugPDBInfo(pdb_info, pdb_file) && pdb_info) { if (pdb_info->PDB70.CVSignature == llvm::OMF::Signature::PDB70) { - using llvm::support::endian::read16be; - using llvm::support::endian::read32be; - - const uint8_t *sig = pdb_info->PDB70.Signature; - struct CVInfoPdb70 info; - info.Guid.Data1 = read32be(sig); - sig += 4; - info.Guid.Data2 = read16be(sig); - sig += 2; - info.Guid.Data3 = read16be(sig); - sig += 2; - memcpy(info.Guid.Data4, sig, 8); - - // Return 20-byte UUID if the Age is not zero - if (pdb_info->PDB70.Age) { - info.Age = read32be(&pdb_info->PDB70.Age); - return UUID::fromOptionalData(&info, sizeof(info)); - } - // Otherwise return 16-byte GUID - return UUID::fromOptionalData(&info.Guid, sizeof(info.Guid)); + UUID::CvRecordPdb70 info; + memcpy(&info.Uuid, pdb_info->PDB70.Signature, sizeof(info.Uuid)); + info.Age = pdb_info->PDB70.Age; + return UUID::fromData(&info); } } diff --git a/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp b/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp --- a/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp +++ b/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp @@ -62,27 +62,12 @@ static_cast(static_cast(*signature)); if (cv_signature == CvSignature::Pdb70) { - const CvRecordPdb70 *pdb70_uuid = nullptr; + const UUID::CvRecordPdb70 *pdb70_uuid = nullptr; Status error = consumeObject(cv_record, pdb70_uuid); if (error.Fail()) return UUID(); - - CvRecordPdb70 swapped; - if (!GetArchitecture().GetTriple().isOSBinFormatELF()) { - // LLDB's UUID class treats the data as a sequence of bytes, but breakpad - // interprets it as a sequence of little-endian fields, which it converts - // to big-endian when converting to text. Swap the bytes to big endian so - // that the string representation comes out right. - swapped = *pdb70_uuid; - llvm::sys::swapByteOrder(swapped.Uuid.Data1); - llvm::sys::swapByteOrder(swapped.Uuid.Data2); - llvm::sys::swapByteOrder(swapped.Uuid.Data3); - llvm::sys::swapByteOrder(swapped.Age); - pdb70_uuid = &swapped; - } - if (pdb70_uuid->Age != 0) - return UUID::fromOptionalData(pdb70_uuid, sizeof(*pdb70_uuid)); - return UUID::fromOptionalData(&pdb70_uuid->Uuid, sizeof(pdb70_uuid->Uuid)); + return UUID::fromData(pdb70_uuid, + !GetArchitecture().GetTriple().isOSBinFormatELF()); } else if (cv_signature == CvSignature::ElfBuildId) return UUID::fromOptionalData(cv_record); diff --git a/lldb/source/Plugins/Process/minidump/MinidumpTypes.h b/lldb/source/Plugins/Process/minidump/MinidumpTypes.h --- a/lldb/source/Plugins/Process/minidump/MinidumpTypes.h +++ b/lldb/source/Plugins/Process/minidump/MinidumpTypes.h @@ -40,21 +40,6 @@ ElfBuildId = 0x4270454c, // BpEL (Breakpad/Crashpad minidumps) }; -// Reference: -// https://crashpad.chromium.org/doxygen/structcrashpad_1_1CodeViewRecordPDB70.html -struct CvRecordPdb70 { - struct { - llvm::support::ulittle32_t Data1; - llvm::support::ulittle16_t Data2; - llvm::support::ulittle16_t Data3; - uint8_t Data4[8]; - } Uuid; - llvm::support::ulittle32_t Age; - // char PDBFileName[]; -}; -static_assert(sizeof(CvRecordPdb70) == 20, - "sizeof CvRecordPdb70 is not correct!"); - enum class MinidumpMiscInfoFlags : uint32_t { ProcessID = (1 << 0), ProcessTimes = (1 << 1), diff --git a/lldb/source/Utility/UUID.cpp b/lldb/source/Utility/UUID.cpp --- a/lldb/source/Utility/UUID.cpp +++ b/lldb/source/Utility/UUID.cpp @@ -35,6 +35,21 @@ } } +UUID UUID::fromData(const UUID::CvRecordPdb70 *debug_info, bool swapByteOrder) { + UUID::CvRecordPdb70 swapped; + if (swapByteOrder) { + swapped = *debug_info; + llvm::sys::swapByteOrder(swapped.Uuid.Data1); + llvm::sys::swapByteOrder(swapped.Uuid.Data2); + llvm::sys::swapByteOrder(swapped.Uuid.Data3); + llvm::sys::swapByteOrder(swapped.Age); + debug_info = &swapped; + } + if (debug_info->Age) + return UUID::fromOptionalData(debug_info, sizeof(*debug_info)); + return UUID::fromOptionalData(&debug_info->Uuid, sizeof(debug_info->Uuid)); +} + std::string UUID::GetAsString(llvm::StringRef separator) const { std::string result; llvm::raw_string_ostream os(result);