xref: /llvm-project/clang/lib/Serialization/ObjectFilePCHContainerReader.cpp (revision d64eccf4335e99360132b724d060d704892fbb02)
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