Swift: add trap linkage awareness infrastructure

This commit is contained in:
Paolo Tranquilli
2023-01-18 09:53:23 +01:00
parent 5fdb09380c
commit f7a046ccd2
9 changed files with 211 additions and 15 deletions

View File

@@ -1,6 +1,8 @@
#include "swift/extractor/infra/TargetDomains.h"
#include <iomanip>
namespace codeql {
static const char* typeToStr(TrapType type) {
switch (type) {
case TrapType::source:
@@ -9,6 +11,8 @@ static const char* typeToStr(TrapType type) {
return "modules";
case TrapType::invocation:
return "invocations";
case TrapType::linkage:
return "linkage";
default:
return "";
}
@@ -42,4 +46,33 @@ std::optional<TrapDomain> createTargetTrapDomain(SwiftExtractorState& state,
}
return std::nullopt;
}
std::optional<LinkDomain> createTargetLinkDomain(const SwiftExtractorState& state,
const std::filesystem::path& target) {
if (target.empty()) {
return std::nullopt;
}
auto file = getRelativeTrapPath(target, TrapType::linkage, ".link");
auto ret =
TargetFile::create(file, state.configuration.trapDir, state.configuration.getTempTrapDir());
if (ret) {
return LinkDomain{*std::move(ret)};
}
return std::nullopt;
}
std::optional<ObjectDomain> createTargetObjectDomain(const SwiftExtractorState& state,
const std::filesystem::path& target) {
if (target.empty()) {
return std::nullopt;
}
auto file = getRelativeTrapPath(target, TrapType::linkage, ".odep");
auto ret =
TargetFile::create(file, state.configuration.trapDir, state.configuration.getTempTrapDir());
if (ret) {
return ObjectDomain{*std::move(ret)};
}
return std::nullopt;
}
} // namespace codeql

View File

@@ -1,6 +1,8 @@
#pragma once
#include "swift/extractor/trap/TrapDomain.h"
#include "swift/extractor/trap/LinkDomain.h"
#include "swift/extractor/trap/ObjectDomain.h"
#include "swift/extractor/config/SwiftExtractorState.h"
namespace codeql {
@@ -9,10 +11,17 @@ enum class TrapType {
source,
module,
invocation,
linkage,
};
std::optional<TrapDomain> createTargetTrapDomain(SwiftExtractorState& state,
const std::filesystem::path& target,
TrapType type);
std::optional<LinkDomain> createTargetLinkDomain(const SwiftExtractorState& state,
const std::filesystem::path& target);
std::optional<ObjectDomain> createTargetObjectDomain(const SwiftExtractorState& state,
const std::filesystem::path& target);
} // namespace codeql

View File

@@ -30,7 +30,7 @@ filegroup(
swift_cc_library(
name = "trap",
srcs = [
srcs = glob(["*.cpp"]) + [
"generated/%s%s.cpp" % (dir, name)
for dir in _dirs
for name in ("TrapEntries", "TrapClasses")
@@ -43,4 +43,7 @@ swift_cc_library(
for name in ("TrapEntries", "TrapClasses")
],
visibility = ["//visibility:public"],
deps = [
"//swift/extractor/infra/file",
],
)

View File

@@ -0,0 +1,37 @@
#include "swift/extractor/trap/LinkDomain.h"
namespace codeql {
LinkDomain::LinkDomain(TargetFile out) : out{std::move(out)} {
this->out << "Linker invocation 1.0\n";
}
void LinkDomain::emitTarget(const std::string& target) {
ensurePhase(Phase::target);
out << target << '\n';
}
void LinkDomain::emitObjectDependency(const std::string& object) {
ensurePhase(Phase::objects);
out << object << '\n';
}
void LinkDomain::ensurePhase(Phase phase) {
assert(phase >= current && "wrong order in .link file attributes");
if (phase > current) {
switch (phase) {
case Phase::target:
out << "TARGET\n";
break;
case Phase::objects:
out << "OBJECTS\n";
break;
default:
assert(false && "unexpected phase");
break;
}
}
current = phase;
}
} // namespace codeql

View File

@@ -0,0 +1,30 @@
#pragma once
#include <cassert>
#include "swift/extractor/infra/file/TargetFile.h"
namespace codeql {
class LinkDomain {
TargetFile out;
enum class Phase {
header,
target,
objects,
end,
};
Phase current{Phase::header};
public:
explicit LinkDomain(TargetFile out);
void emitTarget(const std::string& target);
void emitObjectDependency(const std::string& object);
private:
void ensurePhase(Phase phase);
};
} // namespace codeql

View File

@@ -0,0 +1,45 @@
#include "swift/extractor/trap/ObjectDomain.h"
namespace codeql {
ObjectDomain::ObjectDomain(TargetFile out) : out{std::move(out)} {
this->out << "TRAP dependencies 1.2\n";
}
void ObjectDomain::emitObject(const std::string& object) {
ensurePhase(Phase::objects);
out << object << '\n';
}
void ObjectDomain::emitObjectDependency(const std::string& object) {
ensurePhase(Phase::input_objects);
out << object << '\n';
}
void ObjectDomain::emitTrapDependency(const std::filesystem::path& trap) {
ensurePhase(Phase::traps);
out << trap.c_str() << '\n';
}
void ObjectDomain::ensurePhase(Phase phase) {
assert(phase >= current && "wrong order in .odep file attributes");
if (phase > current) {
switch (phase) {
case Phase::objects:
out << "OBJECTS\n";
break;
case Phase::input_objects:
out << "INPUT_OBJECTS\n";
break;
case Phase::traps:
out << "TRAPS\n";
break;
default:
assert(false && "unexpected phase");
break;
}
}
current = phase;
}
} // namespace codeql

View File

@@ -0,0 +1,33 @@
#pragma once
#include <cassert>
#include <filesystem>
#include "swift/extractor/infra/file/TargetFile.h"
namespace codeql {
class ObjectDomain {
TargetFile out;
enum class Phase {
header,
objects,
input_objects,
traps,
end,
};
Phase current{Phase::header};
public:
explicit ObjectDomain(TargetFile out);
void emitObject(const std::string& object);
void emitObjectDependency(const std::string& object);
void emitTrapDependency(const std::filesystem::path& trap);
private:
void ensurePhase(Phase phase);
};
} // namespace codeql

View File

@@ -10,27 +10,28 @@ namespace codeql {
// Abstracts a given trap output file, with its own universe of trap labels
class TrapDomain {
TargetFile out_;
TargetFile out;
public:
explicit TrapDomain(TargetFile&& out) : out_{std::move(out)} {}
explicit TrapDomain(TargetFile&& out) : out{std::move(out)} {}
template <typename Entry>
void emit(const Entry& e) {
print(e);
out << e << '\n';
}
template <typename... Args>
void debug(const Args&... args) {
print("/* DEBUG:");
print(args...);
print("*/");
out << "/* DEBUG:\n";
(out << ... << args);
out << "\n*/\n";
}
template <typename Tag>
TrapLabel<Tag> createLabel() {
auto ret = allocateLabel<Tag>();
assignStar(ret);
out << '\n';
return ret;
}
@@ -38,6 +39,16 @@ class TrapDomain {
TrapLabel<Tag> createLabel(Args&&... args) {
auto ret = allocateLabel<Tag>();
assignKey(ret, std::forward<Args>(args)...);
out << '\n';
return ret;
}
template <typename Tag, typename... Args>
TrapLabel<Tag> createLabelWithImplementationId(const std::string_view& implementationId,
Args&&... args) {
auto ret = allocateLabel<Tag>();
assignKey(ret, std::forward<Args>(args)...);
out << " .implementation " << trapQuoted(implementationId) << '\n';
return ret;
}
@@ -49,21 +60,16 @@ class TrapDomain {
return TrapLabel<Tag>::unsafeCreateFromExplicitId(id_++);
}
template <typename... Args>
void print(const Args&... args) {
(out_ << ... << args) << '\n';
}
template <typename Tag>
void assignStar(TrapLabel<Tag> label) {
print(label, "=*");
out << label << "=*";
}
template <typename Tag>
void assignKey(TrapLabel<Tag> label, const std::string& key) {
// prefix the key with the id to guarantee the same key is not used wrongly with different tags
auto prefixed = std::string(Tag::prefix) + '_' + key;
print(label, "=@", trapQuoted(prefixed));
out << label << "=@" << trapQuoted(prefixed);
}
template <typename Tag, typename... Args>

View File

@@ -86,7 +86,7 @@ struct TrapLabelVectorWrapper {
}
};
inline auto trapQuoted(const std::string& s) {
inline auto trapQuoted(const std::string_view& s) {
return std::quoted(s, '"', '"');
}