-
Notifications
You must be signed in to change notification settings - Fork 45
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add `dec2hex` tool * Turn it into an API * Print integers as hex in `rellic-xref`
- Loading branch information
Showing
6 changed files
with
216 additions
and
1 deletion.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
/* | ||
* Copyright (c) 2021-present, Trail of Bits, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed in accordance with the terms specified in | ||
* the LICENSE file found in the root directory of this source tree. | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <clang/AST/ASTContext.h> | ||
#include <llvm/ADT/APInt.h> | ||
#include <llvm/Support/raw_ostream.h> | ||
|
||
#include <functional> | ||
#include <memory> | ||
|
||
namespace rellic { | ||
// Converts integer literals in `ast_ctx` to hexadecimal form when | ||
// `shouldConvert` return true. | ||
// | ||
// Note: the context should have valid source range information, i.e. cannot be | ||
// the one directly generated by Rellic. To obtain a context with valid source | ||
// range information, serialize the AST to a string and parse it back into a | ||
// context. | ||
void ConvertIntegerLiteralsToHex( | ||
clang::ASTContext& ast_ctx, llvm::raw_ostream& os, | ||
std::function<bool(const llvm::APInt&)> shouldConvert); | ||
} // namespace rellic |
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,98 @@ | ||
/* | ||
* Copyright (c) 2022-present, Trail of Bits, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed in accordance with the terms specified in | ||
* the LICENSE file found in the root directory of this source tree. | ||
*/ | ||
|
||
#include <clang/AST/Expr.h> | ||
#include <clang/ASTMatchers/ASTMatchFinder.h> | ||
#include <clang/ASTMatchers/ASTMatchers.h> | ||
#include <clang/Basic/SourceManager.h> | ||
#include <clang/Rewrite/Core/Rewriter.h> | ||
#include <clang/Tooling/Tooling.h> | ||
#include <llvm/Support/MemoryBuffer.h> | ||
#include <llvm/Support/raw_ostream.h> | ||
|
||
namespace rellic { | ||
namespace { | ||
using namespace clang; | ||
using namespace clang::ast_matchers; | ||
|
||
StatementMatcher intlit = integerLiteral().bind("intlit"); | ||
|
||
class IntegerReplacer : public MatchFinder::MatchCallback { | ||
Rewriter &rw; | ||
std::function<bool(const llvm::APInt &)> shouldConvert; | ||
|
||
public: | ||
IntegerReplacer(Rewriter &rw, | ||
std::function<bool(const llvm::APInt &)> shouldConvert) | ||
: rw(rw), shouldConvert(shouldConvert) {} | ||
virtual void run(const MatchFinder::MatchResult &Result) { | ||
if (auto lit = Result.Nodes.getNodeAs<IntegerLiteral>("intlit")) { | ||
if (!shouldConvert(lit->getValue())) { | ||
return; | ||
} | ||
|
||
llvm::SmallString<40> str; | ||
lit->getValue().toString( | ||
str, /*radix=*/16, /*isSigned=*/lit->getType()->isSignedIntegerType(), | ||
/*formatAsCLiteral=*/true); | ||
std::string res; | ||
llvm::raw_string_ostream OS(res); | ||
OS << str; | ||
switch (lit->getType()->castAs<BuiltinType>()->getKind()) { | ||
default: | ||
llvm_unreachable("Unexpected type for integer literal!"); | ||
case BuiltinType::Char_S: | ||
case BuiltinType::Char_U: | ||
OS << "i8"; | ||
break; | ||
case BuiltinType::UChar: | ||
OS << "Ui8"; | ||
break; | ||
case BuiltinType::Short: | ||
OS << "i16"; | ||
break; | ||
case BuiltinType::UShort: | ||
OS << "Ui16"; | ||
break; | ||
case BuiltinType::Int: | ||
break; // no suffix. | ||
case BuiltinType::UInt: | ||
OS << 'U'; | ||
break; | ||
case BuiltinType::Long: | ||
OS << 'L'; | ||
break; | ||
case BuiltinType::ULong: | ||
OS << "UL"; | ||
break; | ||
case BuiltinType::LongLong: | ||
OS << "LL"; | ||
break; | ||
case BuiltinType::ULongLong: | ||
OS << "ULL"; | ||
break; | ||
} | ||
rw.ReplaceText(lit->getSourceRange(), res); | ||
} | ||
} | ||
}; | ||
} // namespace | ||
|
||
void ConvertIntegerLiteralsToHex( | ||
clang::ASTContext &ast_ctx, llvm::raw_ostream &os, | ||
std::function<bool(const llvm::APInt &)> shouldConvert) { | ||
auto &sm{ast_ctx.getSourceManager()}; | ||
clang::Rewriter rewriter{sm, ast_ctx.getLangOpts()}; | ||
clang::ast_matchers::MatchFinder finder; | ||
IntegerReplacer replacer{rewriter, shouldConvert}; | ||
|
||
finder.addMatcher(intlit, &replacer); | ||
finder.matchAST(ast_ctx); | ||
rewriter.getRewriteBufferFor(sm.getMainFileID())->write(os); | ||
} | ||
} // namespace rellic |
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,65 @@ | ||
/* | ||
* Copyright (c) 2022-present, Trail of Bits, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed in accordance with the terms specified in | ||
* the LICENSE file found in the root directory of this source tree. | ||
*/ | ||
|
||
#include <clang/Tooling/Tooling.h> | ||
#include <gflags/gflags.h> | ||
#include <glog/logging.h> | ||
#include <llvm/ADT/APInt.h> | ||
#include <llvm/Support/MemoryBuffer.h> | ||
#include <llvm/Support/raw_ostream.h> | ||
#include <rellic/Dec2Hex.h> | ||
|
||
#include <iostream> | ||
#include <sstream> | ||
#include <system_error> | ||
|
||
DEFINE_string(input, "-", "Input C file."); | ||
DEFINE_string(output, "", "Output C file."); | ||
|
||
int main(int argc, char *argv[]) { | ||
std::stringstream usage; | ||
usage << std::endl | ||
<< std::endl | ||
<< " " << argv[0] << " \\" << std::endl | ||
<< " --input INPUT_C_FILE \\" << std::endl | ||
<< " --output OUTPUT_C_FILE \\" << std::endl | ||
<< std::endl; | ||
|
||
google::InitGoogleLogging(argv[0]); | ||
google::InstallFailureSignalHandler(); | ||
google::SetUsageMessage(usage.str()); | ||
google::ParseCommandLineFlags(&argc, &argv, true); | ||
|
||
auto input_file = llvm::MemoryBuffer::getFileOrSTDIN(FLAGS_input); | ||
if (!input_file) { | ||
LOG(FATAL) << input_file.getError().message(); | ||
} | ||
auto ast_unit{clang::tooling::buildASTFromCodeWithArgs( | ||
input_file.get()->getBuffer(), {}, FLAGS_input, "rellic-dec2hex")}; | ||
auto &ast_ctx{ast_unit->getASTContext()}; | ||
|
||
auto heuristic = [](const llvm::APInt &value) { | ||
return value.getZExtValue() >= 16; | ||
}; | ||
|
||
if (FLAGS_output.empty()) { | ||
rellic::ConvertIntegerLiteralsToHex(ast_ctx, llvm::outs(), heuristic); | ||
} else { | ||
std::error_code ec; | ||
llvm::raw_fd_ostream os(FLAGS_output, ec); | ||
if (ec) { | ||
LOG(FATAL) << ec.message(); | ||
} | ||
rellic::ConvertIntegerLiteralsToHex(ast_ctx, os, heuristic); | ||
} | ||
|
||
google::ShutDownCommandLineFlags(); | ||
google::ShutdownGoogleLogging(); | ||
|
||
return EXIT_SUCCESS; | ||
} |
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