forked from iovisor/bcc
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
cc: Rewrite probe functions that refer to tracepoint structures
When a probe function refers to a tracepoint arguments structure, such as `struct tracepoint__irq__irq_handler_entry`, add that structure on-the-fly using a Clang frontend action that runs before any other steps take place. Typically, the user will create tracepoint probe functions using the TRACEPOINT_PROBE macro, which avoids the need for specifying the tracepoint category and event twice in the signature of the probe function.
- Loading branch information
Showing
7 changed files
with
270 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
/* | ||
* Copyright (c) 2016 Sasha Goldshtein | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http:https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
#include <linux/bpf.h> | ||
#include <linux/version.h> | ||
#include <sys/utsname.h> | ||
#include <unistd.h> | ||
|
||
#include <fstream> | ||
#include <regex> | ||
|
||
#include <clang/AST/ASTConsumer.h> | ||
#include <clang/AST/ASTContext.h> | ||
#include <clang/AST/RecordLayout.h> | ||
#include <clang/Frontend/CompilerInstance.h> | ||
#include <clang/Frontend/MultiplexConsumer.h> | ||
#include <clang/Rewrite/Core/Rewriter.h> | ||
|
||
#include "tp_frontend_action.h" | ||
|
||
namespace ebpf { | ||
|
||
using std::map; | ||
using std::set; | ||
using std::string; | ||
using std::to_string; | ||
using std::unique_ptr; | ||
using std::vector; | ||
using std::regex; | ||
using std::smatch; | ||
using std::regex_search; | ||
using std::ifstream; | ||
using namespace clang; | ||
|
||
TracepointTypeVisitor::TracepointTypeVisitor(ASTContext &C, Rewriter &rewriter) | ||
: C(C), diag_(C.getDiagnostics()), rewriter_(rewriter), out_(llvm::errs()) { | ||
} | ||
|
||
string TracepointTypeVisitor::GenerateTracepointStruct( | ||
SourceLocation loc, string const& category, string const& event) { | ||
static regex field_regex("field:([^;]*);.*size:\\d+;"); | ||
string format_file = "/sys/kernel/debug/tracing/events/" + | ||
category + "/" + event + "/format"; | ||
ifstream input(format_file.c_str()); | ||
if (!input) | ||
return ""; | ||
|
||
string tp_struct = "struct tracepoint__" + category + "__" + event + " {\n"; | ||
tp_struct += "\tu64 __do_not_use__;\n"; | ||
for (string line; getline(input, line); ) { | ||
smatch field_match; | ||
if (!regex_search(line, field_match, field_regex)) | ||
continue; | ||
|
||
string field = field_match[1]; | ||
auto pos = field.find_last_of("\t "); | ||
if (pos == string::npos) | ||
continue; | ||
|
||
string field_type = field.substr(0, pos); | ||
string field_name = field.substr(pos + 1); | ||
if (field_type.find("__data_loc") != string::npos) | ||
continue; | ||
if (field_name.find("common_") == 0) | ||
continue; | ||
|
||
tp_struct += "\t" + field_type + " " + field_name + ";\n"; | ||
} | ||
|
||
tp_struct += "};\n"; | ||
return tp_struct; | ||
} | ||
|
||
bool TracepointTypeVisitor::VisitFunctionDecl(FunctionDecl *D) { | ||
static regex type_regex("(?:struct|class)\\s+tracepoint__(\\S+)__(\\S+)"); | ||
if (D->isExternallyVisible() && D->hasBody()) { | ||
// If this function has a tracepoint structure as an argument, | ||
// add that structure declaration based on the structure name. | ||
for (auto arg : D->params()) { | ||
auto type = arg->getType(); | ||
if (type->isPointerType() && | ||
type->getPointeeType()->isStructureOrClassType()) { | ||
auto type_name = QualType::getAsString(type.split()); | ||
smatch type_match; | ||
if (regex_search(type_name, type_match, type_regex)) { | ||
string tp_cat = type_match[1], tp_evt = type_match[2]; | ||
string tp_struct = GenerateTracepointStruct( | ||
D->getLocStart(), tp_cat, tp_evt); | ||
|
||
// Get the actual function declaration point (the macro instantiation | ||
// point if using the TRACEPOINT_PROBE macro instead of the macro | ||
// declaration point in bpf_helpers.h). | ||
auto insert_loc = D->getLocStart(); | ||
insert_loc = rewriter_.getSourceMgr().getFileLoc(insert_loc); | ||
rewriter_.InsertText(insert_loc, tp_struct); | ||
} | ||
} | ||
} | ||
} | ||
return true; | ||
} | ||
|
||
TracepointTypeConsumer::TracepointTypeConsumer(ASTContext &C, Rewriter &rewriter) | ||
: visitor_(C, rewriter) { | ||
} | ||
|
||
bool TracepointTypeConsumer::HandleTopLevelDecl(DeclGroupRef Group) { | ||
for (auto D : Group) | ||
visitor_.TraverseDecl(D); | ||
return true; | ||
} | ||
|
||
TracepointFrontendAction::TracepointFrontendAction(llvm::raw_ostream &os) | ||
: os_(os), rewriter_(new Rewriter) { | ||
} | ||
|
||
void TracepointFrontendAction::EndSourceFileAction() { | ||
rewriter_->getEditBuffer(rewriter_->getSourceMgr().getMainFileID()).write(os_); | ||
os_.flush(); | ||
} | ||
|
||
unique_ptr<ASTConsumer> TracepointFrontendAction::CreateASTConsumer( | ||
CompilerInstance &Compiler, llvm::StringRef InFile) { | ||
rewriter_->setSourceMgr(Compiler.getSourceManager(), Compiler.getLangOpts()); | ||
return unique_ptr<ASTConsumer>(new TracepointTypeConsumer( | ||
Compiler.getASTContext(), *rewriter_)); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
/* | ||
* Copyright (c) 2016 Sasha Goldshtein | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http:https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
#include <map> | ||
#include <memory> | ||
#include <set> | ||
#include <string> | ||
#include <vector> | ||
|
||
#include <clang/AST/RecursiveASTVisitor.h> | ||
#include <clang/Frontend/FrontendAction.h> | ||
#include <clang/Rewrite/Core/Rewriter.h> | ||
|
||
namespace clang { | ||
class ASTConsumer; | ||
class ASTContext; | ||
class CompilerInstance; | ||
} | ||
|
||
namespace llvm { | ||
class raw_ostream; | ||
class StringRef; | ||
} | ||
|
||
namespace ebpf { | ||
|
||
// Visit functions that have a tracepoint argument structure in their signature | ||
// and automatically generate the structure on-the-fly. | ||
class TracepointTypeVisitor : | ||
public clang::RecursiveASTVisitor<TracepointTypeVisitor> { | ||
public: | ||
explicit TracepointTypeVisitor(clang::ASTContext &C, | ||
clang::Rewriter &rewriter); | ||
bool VisitFunctionDecl(clang::FunctionDecl *D); | ||
|
||
private: | ||
std::string GenerateTracepointStruct(clang::SourceLocation loc, | ||
std::string const& category, std::string const& event); | ||
|
||
clang::ASTContext &C; | ||
clang::DiagnosticsEngine &diag_; | ||
clang::Rewriter &rewriter_; | ||
llvm::raw_ostream &out_; | ||
}; | ||
|
||
class TracepointTypeConsumer : public clang::ASTConsumer { | ||
public: | ||
explicit TracepointTypeConsumer(clang::ASTContext &C, | ||
clang::Rewriter &rewriter); | ||
bool HandleTopLevelDecl(clang::DeclGroupRef Group) override; | ||
private: | ||
TracepointTypeVisitor visitor_; | ||
}; | ||
|
||
class TracepointFrontendAction : public clang::ASTFrontendAction { | ||
public: | ||
TracepointFrontendAction(llvm::raw_ostream &os); | ||
|
||
void EndSourceFileAction() override; | ||
|
||
std::unique_ptr<clang::ASTConsumer> | ||
CreateASTConsumer(clang::CompilerInstance &Compiler, llvm::StringRef InFile) override; | ||
|
||
private: | ||
llvm::raw_ostream &os_; | ||
std::unique_ptr<clang::Rewriter> rewriter_; | ||
}; | ||
|
||
} // namespace visitor |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters