|
|
295890 |
From acb0ee316d5ed776253b6d7bfccfb21e0005919b Mon Sep 17 00:00:00 2001
|
|
|
295890 |
From: Jerome Marchand <jmarchan@redhat.com>
|
|
|
295890 |
Date: Thu, 16 May 2019 14:56:50 +0200
|
|
|
295890 |
Subject: [PATCH] fix clang_parser for LLVM 8+
|
|
|
295890 |
|
|
|
295890 |
LLVM changed the behavior of clang_Cursor_isAnonymous in [1]. The old
|
|
|
295890 |
behavior would returned false for direct-acccess anonymous structs
|
|
|
295890 |
within other structs, whereas LLVM 8 returns true. To circumvent this
|
|
|
295890 |
behavior change among LLVM versions, we keep track of all structs
|
|
|
295890 |
defined within a struct. We don't parse the substruct recursively (if we
|
|
|
295890 |
do it might be parsed multiple times, and since we don't know yet if
|
|
|
295890 |
this is a direct or indirect strucutre, we might parse it incorrectly),
|
|
|
295890 |
instead we keep the cursor saved in a map. If this substruct is later
|
|
|
295890 |
declared as an attribute of the supersctruct, that means we have a
|
|
|
295890 |
direct-accessible struct. We remove it from our map, and we parse
|
|
|
295890 |
recursively (parsing recursively the cursor pointing to the declaration
|
|
|
295890 |
will effectively parse the struct definition).
|
|
|
295890 |
|
|
|
295890 |
After the first parse, any struct left in our map is an indirect struct.
|
|
|
295890 |
Since we skipped the parsing stage for those, we need to run
|
|
|
295890 |
`clang_visitChildren` again for each struct cursor we have saved. We
|
|
|
295890 |
repeat this until there's no unvisited structs in the map. Keep in mind
|
|
|
295890 |
that while visiting a new struct we might find more indirect structs.
|
|
|
295890 |
|
|
|
295890 |
Also add Travis jobs to test against LLVM and clang 8 on Ubuntu.
|
|
|
295890 |
|
|
|
295890 |
[1]: llvm/llvm-project@c05e6f4
|
|
|
295890 |
---
|
|
|
295890 |
.travis.yml | 4 ++
|
|
|
295890 |
docker/Dockerfile.bionic-llvm8 | 36 ++++++++++++++
|
|
|
295890 |
src/bpforc.h | 9 ++++
|
|
|
295890 |
src/clang_parser.cpp | 87 +++++++++++++++++++++++-----------
|
|
|
295890 |
4 files changed, 108 insertions(+), 28 deletions(-)
|
|
|
295890 |
create mode 100644 docker/Dockerfile.bionic-llvm8
|
|
|
295890 |
|
|
|
295890 |
diff --git a/.travis.yml b/.travis.yml
|
|
|
295890 |
index 7fbff63..b539868 100644
|
|
|
295890 |
--- a/.travis.yml
|
|
|
295890 |
+++ b/.travis.yml
|
|
|
295890 |
@@ -20,6 +20,10 @@ sudo: required
|
|
|
295890 |
env: BASE=fedora29 TYPE=Debug
|
|
|
295890 |
- name: "LLVM 7 Release"
|
|
|
295890 |
env: BASE=fedora29 TYPE=Release
|
|
|
295890 |
+ - name: "LLVM 8 Debug"
|
|
|
295890 |
+ env: BASE=bionic-llvm8 TYPE=Debug
|
|
|
295890 |
+ - name: "LLVM 8 Release"
|
|
|
295890 |
+ env: BASE=bionic-llvm8 TYPE=Release
|
|
|
295890 |
allow_failures:
|
|
|
295890 |
- name: "Static LLVM 5 Debug"
|
|
|
295890 |
env: BASE=alpine TYPE=Debug STATIC_LINKING=ON TEST_ARGS="--gtest_filter=-codegen.string_equal_comparison:codegen.string_not_equal_comparison"
|
|
|
295890 |
diff --git a/docker/Dockerfile.bionic-llvm8 b/docker/Dockerfile.bionic-llvm8
|
|
|
295890 |
new file mode 100644
|
|
|
295890 |
index 0000000..ebf10d3
|
|
|
295890 |
--- /dev/null
|
|
|
295890 |
+++ b/docker/Dockerfile.bionic-llvm8
|
|
|
295890 |
@@ -0,0 +1,36 @@
|
|
|
295890 |
+FROM ubuntu:bionic
|
|
|
295890 |
+
|
|
|
295890 |
+ENV llvmVersion=8
|
|
|
295890 |
+
|
|
|
295890 |
+RUN apt-get update && apt-get install -y curl gnupg &&\
|
|
|
295890 |
+ llvmRepository='\n\
|
|
|
295890 |
+deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic main\n\
|
|
|
295890 |
+deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic main\n\
|
|
|
295890 |
+# 8\n\
|
|
|
295890 |
+deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-8 main\n\
|
|
|
295890 |
+deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-8 main' && \
|
|
|
295890 |
+ echo $llvmRepository >> /etc/apt/sources.list && \
|
|
|
295890 |
+ curl -L https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - && \
|
|
|
295890 |
+ apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 4052245BD4284CDD && \
|
|
|
295890 |
+ echo "deb https://repo.iovisor.org/apt/bionic bionic main" | tee /etc/apt/sources.list.d/iovisor.list
|
|
|
295890 |
+
|
|
|
295890 |
+RUN apt-get update && apt-get install -y \
|
|
|
295890 |
+ bison \
|
|
|
295890 |
+ cmake \
|
|
|
295890 |
+ flex \
|
|
|
295890 |
+ g++ \
|
|
|
295890 |
+ git \
|
|
|
295890 |
+ libelf-dev \
|
|
|
295890 |
+ zlib1g-dev \
|
|
|
295890 |
+ libbcc \
|
|
|
295890 |
+ clang-${llvmVersion} \
|
|
|
295890 |
+ libclang-${llvmVersion}-dev \
|
|
|
295890 |
+ libclang-common-${llvmVersion}-dev \
|
|
|
295890 |
+ libclang1-${llvmVersion} \
|
|
|
295890 |
+ llvm-${llvmVersion} \
|
|
|
295890 |
+ llvm-${llvmVersion}-dev \
|
|
|
295890 |
+ llvm-${llvmVersion}-runtime \
|
|
|
295890 |
+ libllvm${llvmVersion}
|
|
|
295890 |
+
|
|
|
295890 |
+COPY build.sh /build.sh
|
|
|
295890 |
+ENTRYPOINT ["bash", "/build.sh"]
|
|
|
295890 |
diff --git a/src/bpforc.h b/src/bpforc.h
|
|
|
295890 |
index 1c134d0..8eede31 100644
|
|
|
295890 |
--- a/src/bpforc.h
|
|
|
295890 |
+++ b/src/bpforc.h
|
|
|
295890 |
@@ -80,8 +80,13 @@ class BpfOrc
|
|
|
295890 |
ExecutionSession ES;
|
|
|
295890 |
std::unique_ptr<TargetMachine> TM;
|
|
|
295890 |
std::shared_ptr<SymbolResolver> Resolver;
|
|
|
295890 |
+#if LLVM_VERSION_MAJOR >= 8
|
|
|
295890 |
+ LegacyRTDyldObjectLinkingLayer ObjectLayer;
|
|
|
295890 |
+ LegacyIRCompileLayer<decltype(ObjectLayer), SimpleCompiler> CompileLayer;
|
|
|
295890 |
+#else
|
|
|
295890 |
RTDyldObjectLinkingLayer ObjectLayer;
|
|
|
295890 |
IRCompileLayer<decltype(ObjectLayer), SimpleCompiler> CompileLayer;
|
|
|
295890 |
+#endif
|
|
|
295890 |
|
|
|
295890 |
public:
|
|
|
295890 |
std::map<std::string, std::tuple<uint8_t *, uintptr_t>> sections_;
|
|
|
295890 |
@@ -91,7 +96,11 @@ class BpfOrc
|
|
|
295890 |
Resolver(createLegacyLookupResolver(ES,
|
|
|
295890 |
[](const std::string &Name __attribute__((unused))) -> JITSymbol { return nullptr; },
|
|
|
295890 |
[](Error Err) { cantFail(std::move(Err), "lookup failed"); })),
|
|
|
295890 |
+#if LLVM_VERSION_MAJOR >= 8
|
|
|
295890 |
+ ObjectLayer(ES, [this](VModuleKey) { return LegacyRTDyldObjectLinkingLayer::Resources{std::make_shared<MemoryManager>(sections_), Resolver}; }),
|
|
|
295890 |
+#else
|
|
|
295890 |
ObjectLayer(ES, [this](VModuleKey) { return RTDyldObjectLinkingLayer::Resources{std::make_shared<MemoryManager>(sections_), Resolver}; }),
|
|
|
295890 |
+#endif
|
|
|
295890 |
CompileLayer(ObjectLayer, SimpleCompiler(*TM)) {}
|
|
|
295890 |
|
|
|
295890 |
void compileModule(std::unique_ptr<Module> M) {
|
|
|
295890 |
diff --git a/src/clang_parser.cpp b/src/clang_parser.cpp
|
|
|
295890 |
index 4bb8f87..7bb8d6a 100644
|
|
|
295890 |
--- a/src/clang_parser.cpp
|
|
|
295890 |
+++ b/src/clang_parser.cpp
|
|
|
295890 |
@@ -1,5 +1,7 @@
|
|
|
295890 |
#include <clang-c/Index.h>
|
|
|
295890 |
#include <iostream>
|
|
|
295890 |
+#include <unordered_map>
|
|
|
295890 |
+#include <unordered_set>
|
|
|
295890 |
#include <string.h>
|
|
|
295890 |
#include <sys/utsname.h>
|
|
|
295890 |
#include <sys/stat.h>
|
|
|
295890 |
@@ -13,6 +15,9 @@
|
|
|
295890 |
|
|
|
295890 |
namespace bpftrace {
|
|
|
295890 |
|
|
|
295890 |
+std::unordered_map<std::string, CXCursor> indirect_structs;
|
|
|
295890 |
+std::unordered_set<std::string> unvisited_indirect_structs;
|
|
|
295890 |
+
|
|
|
295890 |
static std::string get_clang_string(CXString string)
|
|
|
295890 |
{
|
|
|
295890 |
std::string str = clang_getCString(string);
|
|
|
295890 |
@@ -30,8 +35,9 @@ static CXCursor get_indirect_field_parent_struct(CXCursor c)
|
|
|
295890 |
{
|
|
|
295890 |
CXCursor parent = clang_getCursorSemanticParent(c);
|
|
|
295890 |
|
|
|
295890 |
- while (!clang_Cursor_isNull(parent) && clang_Cursor_isAnonymous(parent))
|
|
|
295890 |
- parent = clang_getCursorSemanticParent(parent);
|
|
|
295890 |
+ while (!clang_Cursor_isNull(parent) && indirect_structs.count(get_clang_string(clang_getTypeSpelling(clang_getCanonicalType(clang_getCursorType(parent))))) > 0) {
|
|
|
295890 |
+ parent = clang_getCursorSemanticParent(parent);
|
|
|
295890 |
+ }
|
|
|
295890 |
|
|
|
295890 |
return parent;
|
|
|
295890 |
}
|
|
|
295890 |
@@ -253,44 +259,69 @@ void ClangParser::parse(ast::Program *program, BPFtrace &bpftrace)
|
|
|
295890 |
std::cerr << "Input (" << input.size() << "): " << input << std::endl;
|
|
|
295890 |
}
|
|
|
295890 |
|
|
|
295890 |
- CXCursor cursor = clang_getTranslationUnitCursor(translation_unit);
|
|
|
295890 |
+ indirect_structs.clear();
|
|
|
295890 |
+ unvisited_indirect_structs.clear();
|
|
|
295890 |
|
|
|
295890 |
- clang_visitChildren(
|
|
|
295890 |
- cursor,
|
|
|
295890 |
- [](CXCursor c, CXCursor parent, CXClientData client_data)
|
|
|
295890 |
- {
|
|
|
295890 |
+ CXCursor cursor = clang_getTranslationUnitCursor(translation_unit);
|
|
|
295890 |
|
|
|
295890 |
- if (clang_getCursorKind(parent) != CXCursor_StructDecl &&
|
|
|
295890 |
- clang_getCursorKind(parent) != CXCursor_UnionDecl)
|
|
|
295890 |
- return CXChildVisit_Recurse;
|
|
|
295890 |
+ bool iterate = true;
|
|
|
295890 |
|
|
|
295890 |
- if (clang_getCursorKind(c) == CXCursor_FieldDecl)
|
|
|
295890 |
+ do {
|
|
|
295890 |
+ clang_visitChildren(
|
|
|
295890 |
+ cursor,
|
|
|
295890 |
+ [](CXCursor c, CXCursor parent, CXClientData client_data)
|
|
|
295890 |
{
|
|
|
295890 |
- auto &structs = static_cast<BPFtrace*>(client_data)->structs_;
|
|
|
295890 |
- auto struct_name = get_parent_struct_name(c);
|
|
|
295890 |
- auto ident = get_clang_string(clang_getCursorSpelling(c));
|
|
|
295890 |
- auto offset = clang_Cursor_getOffsetOfField(c) / 8;
|
|
|
295890 |
- auto type = clang_getCanonicalType(clang_getCursorType(c));
|
|
|
295890 |
+ if (clang_getCursorKind(parent) != CXCursor_StructDecl &&
|
|
|
295890 |
+ clang_getCursorKind(parent) != CXCursor_UnionDecl)
|
|
|
295890 |
+ return CXChildVisit_Recurse;
|
|
|
295890 |
|
|
|
295890 |
auto ptype = clang_getCanonicalType(clang_getCursorType(parent));
|
|
|
295890 |
auto ptypestr = get_clang_string(clang_getTypeSpelling(ptype));
|
|
|
295890 |
auto ptypesize = clang_Type_getSizeOf(ptype);
|
|
|
295890 |
|
|
|
295890 |
- if(clang_Cursor_isAnonymous(parent))
|
|
|
295890 |
- offset = get_indirect_field_offset(c);
|
|
|
295890 |
+ if (clang_getCursorKind(c) == CXCursor_StructDecl ||
|
|
|
295890 |
+ clang_getCursorKind(c) == CXCursor_UnionDecl) {
|
|
|
295890 |
+ auto struct_name = get_clang_string(clang_getTypeSpelling(clang_getCanonicalType(clang_getCursorType(c))));
|
|
|
295890 |
+ indirect_structs[struct_name] = c;
|
|
|
295890 |
+ unvisited_indirect_structs.insert(struct_name);
|
|
|
295890 |
|
|
|
295890 |
- if (struct_name == "")
|
|
|
295890 |
- struct_name = ptypestr;
|
|
|
295890 |
- remove_struct_prefix(struct_name);
|
|
|
295890 |
+ return CXChildVisit_Continue;
|
|
|
295890 |
+ }
|
|
|
295890 |
|
|
|
295890 |
- structs[struct_name].fields[ident].offset = offset;
|
|
|
295890 |
- structs[struct_name].fields[ident].type = get_sized_type(type);
|
|
|
295890 |
- structs[struct_name].size = ptypesize;
|
|
|
295890 |
- }
|
|
|
295890 |
+ if (clang_getCursorKind(c) == CXCursor_FieldDecl)
|
|
|
295890 |
+ {
|
|
|
295890 |
+ auto &structs = static_cast<BPFtrace*>(client_data)->structs_;
|
|
|
295890 |
+ auto struct_name = get_parent_struct_name(c);
|
|
|
295890 |
+ auto ident = get_clang_string(clang_getCursorSpelling(c));
|
|
|
295890 |
+ auto offset = clang_Cursor_getOffsetOfField(c) / 8;
|
|
|
295890 |
+ auto type = clang_getCanonicalType(clang_getCursorType(c));
|
|
|
295890 |
+ auto typestr = get_clang_string(clang_getTypeSpelling(type));
|
|
|
295890 |
|
|
|
295890 |
- return CXChildVisit_Recurse;
|
|
|
295890 |
- },
|
|
|
295890 |
- &bpftrace);
|
|
|
295890 |
+ if (indirect_structs.count(typestr))
|
|
|
295890 |
+ indirect_structs.erase(typestr);
|
|
|
295890 |
+
|
|
|
295890 |
+ if(indirect_structs.count(ptypestr))
|
|
|
295890 |
+ offset = get_indirect_field_offset(c);
|
|
|
295890 |
+
|
|
|
295890 |
+ if (struct_name == "")
|
|
|
295890 |
+ struct_name = ptypestr;
|
|
|
295890 |
+ remove_struct_prefix(struct_name);
|
|
|
295890 |
+
|
|
|
295890 |
+ structs[struct_name].fields[ident].offset = offset;
|
|
|
295890 |
+ structs[struct_name].fields[ident].type = get_sized_type(type);
|
|
|
295890 |
+ structs[struct_name].size = ptypesize;
|
|
|
295890 |
+ }
|
|
|
295890 |
+
|
|
|
295890 |
+ return CXChildVisit_Recurse;
|
|
|
295890 |
+ },
|
|
|
295890 |
+ &bpftrace);
|
|
|
295890 |
+ if (unvisited_indirect_structs.size()) {
|
|
|
295890 |
+ cursor = indirect_structs[*unvisited_indirect_structs.begin()];
|
|
|
295890 |
+ unvisited_indirect_structs.erase(unvisited_indirect_structs.begin());
|
|
|
295890 |
+ } else {
|
|
|
295890 |
+ iterate = false;
|
|
|
295890 |
+ }
|
|
|
295890 |
+ } while (iterate);
|
|
|
295890 |
|
|
|
295890 |
clang_disposeTranslationUnit(translation_unit);
|
|
|
295890 |
clang_disposeIndex(index);
|
|
|
295890 |
--
|
|
|
295890 |
2.20.1
|
|
|
295890 |
|