Skip to content

[lldb] Capture error messages from parseASTSection to log from caller #67833

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 37 additions & 3 deletions include/swift/ASTSectionImporter/ASTSectionImporter.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#define SWIFT_ASTSECTION_IMPORTER_H

#include "swift/Basic/LLVM.h"
#include "swift/Serialization/Validation.h"
#include "llvm/Support/Error.h"
#include <string>

namespace llvm {
Expand All @@ -26,15 +28,47 @@ class Triple;
namespace swift {
class MemoryBufferSerializedModuleLoader;

class ASTSectionParseError : public llvm::ErrorInfo<ASTSectionParseError> {
public:
static char ID;

serialization::Status Error;
std::string ErrorMessage;

ASTSectionParseError(serialization::Status Error,
StringRef ErrorMessage = {})
: Error(Error), ErrorMessage(ErrorMessage) {
assert(Error != serialization::Status::Valid);
}
ASTSectionParseError(const ASTSectionParseError &Other)
: ASTSectionParseError(Other.Error, Other.ErrorMessage) {}
ASTSectionParseError &operator=(const ASTSectionParseError &Other) {
Error = Other.Error;
ErrorMessage = Other.ErrorMessage;
return *this;
}

std::string toString() const;
void log(llvm::raw_ostream &OS) const override;
std::error_code convertToErrorCode() const override;
};

/// Provided a memory buffer with an entire Mach-O __swift_ast section, this
/// function makes memory buffer copies of all swift modules found in it and
/// registers them using registerMemoryBuffer() so they can be found by
/// loadModule(). The access path of all modules found in the section is
/// appended to the vector foundModules.
/// loadModule().
/// \param filter If fully specified, only matching modules are registered.
/// \return true if successful.
/// \return a vector of the access path of all modules found in the
/// section if successful.
llvm::Expected<SmallVector<std::string, 4>>
parseASTSection(MemoryBufferSerializedModuleLoader &Loader,
StringRef Data, const llvm::Triple &filter);

// An old version temporarily left for remaining call site.
// TODO: remove this once the other version is committed and used.
bool parseASTSection(MemoryBufferSerializedModuleLoader &Loader,
StringRef Data, const llvm::Triple &filter,
SmallVectorImpl<std::string> &foundModules);

}
#endif
4 changes: 4 additions & 0 deletions include/swift/Serialization/SerializationOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
#include "swift/Basic/PathRemapper.h"
#include "llvm/Support/VersionTuple.h"

#include <set>
#include <string>
#include <vector>

namespace swift {

class SerializationOptions {
Expand Down
5 changes: 5 additions & 0 deletions include/swift/Serialization/Validation.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
#ifndef SWIFT_SERIALIZATION_VALIDATION_H
#define SWIFT_SERIALIZATION_VALIDATION_H

#include "swift/AST/Identifier.h"
#include "swift/Basic/LLVM.h"
#include "swift/Basic/Version.h"
#include "swift/Serialization/SerializationOptions.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
Expand Down Expand Up @@ -83,6 +85,9 @@ enum class Status {
SDKMismatch
};

/// Returns the string for the Status enum.
std::string StatusToString(Status S);

/// Returns true if the data looks like it contains a serialized AST.
bool isSerializedAST(StringRef data);

Expand Down
58 changes: 47 additions & 11 deletions lib/ASTSectionImporter/ASTSectionImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,32 @@

using namespace swift;

bool swift::parseASTSection(MemoryBufferSerializedModuleLoader &Loader,
StringRef buf,
const llvm::Triple &filter,
SmallVectorImpl<std::string> &foundModules) {
std::string ASTSectionParseError::toString() const {
std::string S;
llvm::raw_string_ostream SS(S);
SS << serialization::StatusToString(Error);
if (!ErrorMessage.empty())
SS << ": " << ErrorMessage;
return SS.str();
}

void ASTSectionParseError::log(raw_ostream &OS) const { OS << toString(); }

std::error_code ASTSectionParseError::convertToErrorCode() const {
llvm_unreachable("Function not implemented.");
}

char ASTSectionParseError::ID;

llvm::Expected<SmallVector<std::string, 4>>
swift::parseASTSection(MemoryBufferSerializedModuleLoader &Loader,
StringRef buf,
const llvm::Triple &filter) {
if (!serialization::isSerializedAST(buf))
return false;
return llvm::make_error<ASTSectionParseError>(
serialization::Status::Malformed);

SmallVector<std::string, 4> foundModules;
bool haveFilter = filter.getOS() != llvm::Triple::UnknownOS &&
filter.getArch() != llvm::Triple::UnknownArch;
// An AST section consists of one or more AST modules, optionally with
Expand All @@ -44,6 +63,8 @@ bool swift::parseASTSection(MemoryBufferSerializedModuleLoader &Loader,

assert(info.name.size() < (2 << 10) && "name failed sanity check");

std::string error;
llvm::raw_string_ostream errs(error);
if (info.status == serialization::Status::Valid) {
assert(info.bytes != 0);
bool selected = true;
Expand All @@ -62,23 +83,38 @@ bool swift::parseASTSection(MemoryBufferSerializedModuleLoader &Loader,
foundModules.push_back(info.name.str());
}
} else {
llvm::dbgs() << "Unable to load module";
errs << "Unable to load module";
if (!info.name.empty())
llvm::dbgs() << " '" << info.name << '\'';
llvm::dbgs() << ".\n";
errs << " '" << info.name << '\'';
errs << ".";
}

if (info.bytes == 0)
return false;
return llvm::make_error<ASTSectionParseError>(info.status, errs.str());

if (info.bytes > buf.size()) {
llvm::dbgs() << "AST section too small.\n";
return false;
errs << "AST section too small.";
return llvm::make_error<ASTSectionParseError>(
serialization::Status::Malformed, errs.str());
}

buf = buf.substr(
llvm::alignTo(info.bytes, swift::serialization::SWIFTMODULE_ALIGNMENT));
}

return foundModules;
}

bool swift::parseASTSection(MemoryBufferSerializedModuleLoader &Loader,
StringRef buf,
const llvm::Triple &filter,
SmallVectorImpl<std::string> &foundModules) {
auto Result = parseASTSection(Loader, buf, filter);
if (auto E = Result.takeError()) {
llvm::dbgs() << toString(std::move(E));
return false;
}
for (auto m : *Result)
foundModules.push_back(m);
return true;
}
22 changes: 22 additions & 0 deletions lib/Serialization/ModuleFileSharedCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,28 @@ static bool validateInputBlock(
return false;
}

std::string serialization::StatusToString(Status S) {
switch (S) {
case Status::Valid: return "Valid";
case Status::FormatTooOld: return "FormatTooOld";
case Status::FormatTooNew: return "FormatTooNew";
case Status::RevisionIncompatible: return "RevisionIncompatible";
case Status::NotInOSSA: return "NotInOSSA";
case Status::MissingDependency: return "MissingDependency";
case Status::MissingUnderlyingModule: return "MissingUnderlyingModule";
case Status::CircularDependency: return "CircularDependency";
case Status::FailedToLoadBridgingHeader: return "FailedToLoadBridgingHeader";
case Status::Malformed: return "Malformed";
case Status::MalformedDocumentation: return "MalformedDocumentation";
case Status::NameMismatch: return "NameMismatch";
case Status::TargetIncompatible: return "TargetIncompatible";
case Status::TargetTooNew: return "TargetTooNew";
case Status::SDKMismatch: return "SDKMismatch";
default:
llvm_unreachable("The switch should cover all cases");
}
}

bool serialization::isSerializedAST(StringRef data) {
StringRef signatureStr(reinterpret_cast<const char *>(SWIFTMODULE_SIGNATURE),
std::size(SWIFTMODULE_SIGNATURE));
Expand Down
16 changes: 11 additions & 5 deletions tools/lldb-moduleimport-test/lldb-moduleimport-test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -364,14 +364,20 @@ int main(int argc, char **argv) {
ClangImporter->setDWARFImporterDelegate(dummyDWARFImporter);
}

llvm::SmallString<0> error;
llvm::raw_svector_ostream errs(error);
llvm::Triple filter(Filter);
for (auto &Module : Modules)
if (!parseASTSection(*CI.getMemoryBufferSerializedModuleLoader(),
StringRef(Module.first, Module.second), filter,
modules)) {
llvm::errs() << "error: Failed to parse AST section!\n";
for (auto &Module : Modules) {
auto Result = parseASTSection(
*CI.getMemoryBufferSerializedModuleLoader(),
StringRef(Module.first, Module.second), filter);
if (auto E = Result.takeError()) {
std::string error = toString(std::move(E));
llvm::errs() << "error: Failed to parse AST section! " << error << "\n";
return 1;
}
modules.insert(modules.end(), Result->begin(), Result->end());
}

// Attempt to import all modules we found.
for (auto path : modules) {
Expand Down