14fcfc199SEugene Zelenko //===- Formatters.cpp -----------------------------------------------------===// 25ce0f4a9SZachary Turner // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65ce0f4a9SZachary Turner // 75ce0f4a9SZachary Turner //===----------------------------------------------------------------------===// 85ce0f4a9SZachary Turner 95ce0f4a9SZachary Turner #include "llvm/DebugInfo/CodeView/Formatters.h" 104fcfc199SEugene Zelenko #include "llvm/ADT/ArrayRef.h" 1167653ee0SReid Kleckner #include "llvm/DebugInfo/CodeView/GUID.h" 124fcfc199SEugene Zelenko #include "llvm/Support/raw_ostream.h" 134fcfc199SEugene Zelenko #include <algorithm> 144fcfc199SEugene Zelenko #include <cassert> 155ce0f4a9SZachary Turner 165ce0f4a9SZachary Turner using namespace llvm; 175ce0f4a9SZachary Turner using namespace llvm::codeview; 185ce0f4a9SZachary Turner using namespace llvm::codeview::detail; 195ce0f4a9SZachary Turner 205ce0f4a9SZachary Turner GuidAdapter::GuidAdapter(StringRef Guid) 215ce0f4a9SZachary Turner : FormatAdapter(makeArrayRef(Guid.bytes_begin(), Guid.bytes_end())) {} 225ce0f4a9SZachary Turner 235ce0f4a9SZachary Turner GuidAdapter::GuidAdapter(ArrayRef<uint8_t> Guid) 245ce0f4a9SZachary Turner : FormatAdapter(std::move(Guid)) {} 255ce0f4a9SZachary Turner 26*d0a5d861SCarlosAlbertoEnciso // From https://docs.microsoft.com/en-us/windows/win32/msi/guid documentation: 27*d0a5d861SCarlosAlbertoEnciso // The GUID data type is a text string representing a Class identifier (ID). 28*d0a5d861SCarlosAlbertoEnciso // All GUIDs must be authored in uppercase. 29*d0a5d861SCarlosAlbertoEnciso // The valid format for a GUID is {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} where 30*d0a5d861SCarlosAlbertoEnciso // X is a hex digit (0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F). 31*d0a5d861SCarlosAlbertoEnciso // 32*d0a5d861SCarlosAlbertoEnciso // The individual string components must be padded to comply with the specific 33*d0a5d861SCarlosAlbertoEnciso // lengths of {8-4-4-4-12} characters. 34*d0a5d861SCarlosAlbertoEnciso // The llvm-yaml2obj tool checks that a GUID follow that format: 35*d0a5d861SCarlosAlbertoEnciso // - the total length to be 38 (including the curly braces. 36*d0a5d861SCarlosAlbertoEnciso // - there is a dash at the positions: 8, 13, 18 and 23. 374fcfc199SEugene Zelenko void GuidAdapter::format(raw_ostream &Stream, StringRef Style) { 385ce0f4a9SZachary Turner assert(Item.size() == 16 && "Expected 16-byte GUID"); 39f47a4c07SAlex Orlov struct MSGuid { 40f47a4c07SAlex Orlov support::ulittle32_t Data1; 41f47a4c07SAlex Orlov support::ulittle16_t Data2; 42f47a4c07SAlex Orlov support::ulittle16_t Data3; 43f47a4c07SAlex Orlov support::ubig64_t Data4; 44f47a4c07SAlex Orlov }; 45f47a4c07SAlex Orlov const MSGuid *G = reinterpret_cast<const MSGuid *>(Item.data()); 46f47a4c07SAlex Orlov Stream 47*d0a5d861SCarlosAlbertoEnciso << '{' << format_hex_no_prefix(G->Data1, 8, /*Upper=*/true) 48*d0a5d861SCarlosAlbertoEnciso << '-' << format_hex_no_prefix(G->Data2, 4, /*Upper=*/true) 49*d0a5d861SCarlosAlbertoEnciso << '-' << format_hex_no_prefix(G->Data3, 4, /*Upper=*/true) 50*d0a5d861SCarlosAlbertoEnciso << '-' << format_hex_no_prefix(G->Data4 >> 48, 4, /*Upper=*/true) << '-' 51*d0a5d861SCarlosAlbertoEnciso << format_hex_no_prefix(G->Data4 & ((1ULL << 48) - 1), 12, /*Upper=*/true) 52f47a4c07SAlex Orlov << '}'; 535ce0f4a9SZachary Turner } 5467653ee0SReid Kleckner 5567653ee0SReid Kleckner raw_ostream &llvm::codeview::operator<<(raw_ostream &OS, const GUID &Guid) { 5667653ee0SReid Kleckner codeview::detail::GuidAdapter A(Guid.Guid); 5767653ee0SReid Kleckner A.format(OS, ""); 5867653ee0SReid Kleckner return OS; 5967653ee0SReid Kleckner } 60