1 //===--- ObjectFilePCHContainerReader.cpp ---------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "clang/Serialization/ObjectFilePCHContainerReader.h" 10 #include "llvm/Object/COFF.h" 11 #include "llvm/Object/ObjectFile.h" 12 13 using namespace clang; 14 15 ArrayRef<StringRef> ObjectFilePCHContainerReader::getFormats() const { 16 static StringRef Formats[] = {"obj", "raw"}; 17 return Formats; 18 } 19 20 StringRef 21 ObjectFilePCHContainerReader::ExtractPCH(llvm::MemoryBufferRef Buffer) const { 22 StringRef PCH; 23 auto OFOrErr = llvm::object::ObjectFile::createObjectFile(Buffer); 24 if (OFOrErr) { 25 auto &OF = OFOrErr.get(); 26 bool IsCOFF = isa<llvm::object::COFFObjectFile>(*OF); 27 // Find the clang AST section in the container. 28 for (auto &Section : OF->sections()) { 29 StringRef Name; 30 if (Expected<StringRef> NameOrErr = Section.getName()) 31 Name = *NameOrErr; 32 else 33 consumeError(NameOrErr.takeError()); 34 35 if ((!IsCOFF && Name == "__clangast") || (IsCOFF && Name == "clangast")) { 36 if (Expected<StringRef> E = Section.getContents()) 37 return *E; 38 else { 39 handleAllErrors(E.takeError(), [&](const llvm::ErrorInfoBase &EIB) { 40 EIB.log(llvm::errs()); 41 }); 42 return ""; 43 } 44 } 45 } 46 } 47 handleAllErrors(OFOrErr.takeError(), [&](const llvm::ErrorInfoBase &EIB) { 48 if (EIB.convertToErrorCode() == 49 llvm::object::object_error::invalid_file_type) 50 // As a fallback, treat the buffer as a raw AST. 51 PCH = Buffer.getBuffer(); 52 else 53 EIB.log(llvm::errs()); 54 }); 55 return PCH; 56 } 57