Skip to content

Commit

Permalink
Merge branch 'master' into export_symcc_runtime
Browse files Browse the repository at this point in the history
  • Loading branch information
rmalmain committed Apr 21, 2024
2 parents 296db08 + c89b6cc commit 7a7dcfe
Show file tree
Hide file tree
Showing 8 changed files with 55 additions and 32 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/run_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
runs-on: ubuntu-22.04
strategy:
matrix:
llvm_version: [16, 17]
llvm_version: [16, 17, 18]
steps:
- uses: actions/checkout@v3
with:
Expand Down
10 changes: 10 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,16 @@ if (${TARGET_32BIT})
set(SYMCC_RUNTIME_32BIT_DIR ${BINARY_DIR})
endif()

find_package(LLVM REQUIRED CONFIG)

message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message(STATUS "Using LLVMConfig.cmake from ${LLVM_DIR}")

if (${LLVM_VERSION_MAJOR} LESS 8 OR ${LLVM_VERSION_MAJOR} GREATER 18)
message(WARNING "The software has been developed for LLVM 8 through 18; \
it is unlikely to work with other versions!")
endif()

add_definitions(${LLVM_DEFINITIONS})
include_directories(SYSTEM ${LLVM_INCLUDE_DIRS})

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ program. The actual computation happens through calls to the support library at
run time.

To build the pass and the support library, install LLVM (any version between 8
and 17) and Z3 (version 4.5 or later), as well as a C++ compiler with support
and 18) and Z3 (version 4.5 or later), as well as a C++ compiler with support
for C++17. LLVM lit is only needed to run the tests; if it's not packaged with
your LLVM, you can get it with `pip install lit`.

Expand Down
2 changes: 1 addition & 1 deletion compiler/Runtime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ SymFnT import(llvm::Module &M, llvm::StringRef name, llvm::Type *ret,
Runtime::Runtime(Module &M) {
IRBuilder<> IRB(M.getContext());
auto *intPtrType = M.getDataLayout().getIntPtrType(M.getContext());
auto *ptrT = IRB.getInt8PtrTy();
auto *ptrT = IRB.getInt8Ty()->getPointerTo();
auto *int8T = IRB.getInt8Ty();
auto *int1T = IRB.getInt1Ty();
auto *voidT = IRB.getVoidTy();
Expand Down
21 changes: 12 additions & 9 deletions compiler/Symbolizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ void Symbolizer::shortCircuitExpressionUses() {

// Build the check whether any input expression is non-null (i.e., there
// is a symbolic input).
auto *nullExpression = ConstantPointerNull::get(IRB.getInt8PtrTy());
auto *nullExpression =
ConstantPointerNull::get(IRB.getInt8Ty()->getPointerTo());
std::vector<Value *> nullChecks;
for (const auto &input : symbolicComputation.inputs) {
nullChecks.push_back(
Expand Down Expand Up @@ -149,7 +150,7 @@ void Symbolizer::shortCircuitExpressionUses() {
Value *finalArgExpression;
if (needRuntimeCheck) {
IRB.SetInsertPoint(symbolicComputation.firstInstruction);
auto *argPHI = IRB.CreatePHI(IRB.getInt8PtrTy(), 2);
auto *argPHI = IRB.CreatePHI(IRB.getInt8Ty()->getPointerTo(), 2);
argPHI->addIncoming(originalArgExpression, argCheckBlock);
argPHI->addIncoming(newArgExpression, newArgExpression->getParent());
finalArgExpression = argPHI;
Expand All @@ -165,10 +166,10 @@ void Symbolizer::shortCircuitExpressionUses() {
// if short-circuiting wasn't possible.
if (!symbolicComputation.lastInstruction->use_empty()) {
IRB.SetInsertPoint(&tail->front());
auto *finalExpression = IRB.CreatePHI(IRB.getInt8PtrTy(), 2);
auto *finalExpression = IRB.CreatePHI(IRB.getInt8Ty()->getPointerTo(), 2);
symbolicComputation.lastInstruction->replaceAllUsesWith(finalExpression);
finalExpression->addIncoming(ConstantPointerNull::get(IRB.getInt8PtrTy()),
head);
finalExpression->addIncoming(
ConstantPointerNull::get(IRB.getInt8Ty()->getPointerTo()), head);
finalExpression->addIncoming(
symbolicComputation.lastInstruction,
symbolicComputation.lastInstruction->getParent());
Expand Down Expand Up @@ -384,7 +385,7 @@ void Symbolizer::handleFunctionCall(CallBase &I, Instruction *returnPoint) {
// previous function call. (If the function is instrumented, it will just
// override our null with the real expression.)
IRB.CreateCall(runtime.setReturnExpression,
ConstantPointerNull::get(IRB.getInt8PtrTy()));
ConstantPointerNull::get(IRB.getInt8Ty()->getPointerTo()));
IRB.SetInsertPoint(returnPoint);
symbolicExpressions[&I] = IRB.CreateCall(runtime.getReturnExpression);
}
Expand Down Expand Up @@ -826,11 +827,13 @@ void Symbolizer::visitPHINode(PHINode &I) {

IRBuilder<> IRB(&I);
unsigned numIncomingValues = I.getNumIncomingValues();
auto *exprPHI = IRB.CreatePHI(IRB.getInt8PtrTy(), numIncomingValues);
auto *exprPHI =
IRB.CreatePHI(IRB.getInt8Ty()->getPointerTo(), numIncomingValues);
for (unsigned incoming = 0; incoming < numIncomingValues; incoming++) {
exprPHI->addIncoming(
// The null pointer will be replaced in finalizePHINodes.
ConstantPointerNull::get(cast<PointerType>(IRB.getInt8PtrTy())),
ConstantPointerNull::get(
cast<PointerType>(IRB.getInt8Ty()->getPointerTo())),
I.getIncomingBlock(incoming));
}

Expand Down Expand Up @@ -909,7 +912,7 @@ void Symbolizer::visitSwitchInst(SwitchInst &I) {

// Build a check whether we have a symbolic condition, to be used later.
auto *haveSymbolicCondition = IRB.CreateICmpNE(
conditionExpr, ConstantPointerNull::get(IRB.getInt8PtrTy()));
conditionExpr, ConstantPointerNull::get(IRB.getInt8Ty()->getPointerTo()));
auto *constraintBlock = SplitBlockAndInsertIfThen(haveSymbolicCondition, &I,
/* unreachable */ false);

Expand Down
4 changes: 2 additions & 2 deletions compiler/Symbolizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ class Symbolizer : public llvm::InstVisitor<Symbolizer> {
Input(llvm::Value *concrete, unsigned idx, llvm::Instruction *user)
: concreteValue(concrete), operandIndex(idx), user(user) {
assert(getSymbolicOperand()->getType() ==
llvm::Type::getInt8PtrTy(user->getContext()));
llvm::Type::getInt8Ty(user->getContext())->getPointerTo());
}

llvm::Value *getSymbolicOperand() const {
Expand Down Expand Up @@ -215,7 +215,7 @@ class Symbolizer : public llvm::InstVisitor<Symbolizer> {
auto *expr = getSymbolicExpression(V);
if (expr == nullptr)
return llvm::ConstantPointerNull::get(
llvm::IntegerType::getInt8PtrTy(V->getContext()));
llvm::IntegerType::getInt8Ty(V->getContext())->getPointerTo());
return expr;
}

Expand Down
2 changes: 1 addition & 1 deletion util/symcc_fuzzing_helper/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ fn process_new_testcase(
)
})? {
AflShowmapResult::Success(testcase_bitmap) => {
let interesting = state.current_bitmap.merge(&testcase_bitmap);
let interesting = state.current_bitmap.merge(*testcase_bitmap)?;
if interesting {
symcc::copy_testcase(&testcase, &mut state.queue, parent).with_context(|| {
format!(
Expand Down
44 changes: 27 additions & 17 deletions util/symcc_fuzzing_helper/src/symcc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,13 @@ fn insert_input_file<S: AsRef<OsStr>, P: AsRef<Path>>(

/// A coverage map as used by AFL.
pub struct AflMap {
data: [u8; 65536],
data: Option<Vec<u8>>,
}

impl AflMap {
/// Create an empty map.
pub fn new() -> AflMap {
AflMap { data: [0; 65536] }
AflMap { data: None }
}

/// Load a map from disk.
Expand All @@ -60,31 +60,41 @@ impl AflMap {
path.as_ref().display()
)
})?;
Ok(AflMap { data: Some(data) })
}

/// Merge two coverage maps in place.
fn merge_vec(data: &mut Vec<u8>, new_data: Vec<u8>) -> Result<bool> {
let mut interesting = false;
ensure!(
data.len() == 65536,
"The file to load the coverage map from has the wrong size ({})",
data.len()
data.len() == new_data.len(),
"Coverage maps must have the same size ({} and {})",
data.len(),
new_data.len(),
);

let mut result = AflMap::new();
result.data.copy_from_slice(&data);
Ok(result)
for (known, new) in data.iter_mut().zip(new_data.iter()) {
if *known != (*known | new) {
*known |= new;
interesting = true;
}
}
Ok(interesting)
}

/// Merge with another coverage map in place.
///
/// Return true if the map has changed, i.e., if the other map yielded new
/// coverage.
pub fn merge(&mut self, other: &AflMap) -> bool {
let mut interesting = false;
for (known, new) in self.data.iter_mut().zip(other.data.iter()) {
if *known != (*known | new) {
*known |= new;
interesting = true;
pub fn merge(&mut self, other: AflMap) -> Result<bool> {
match (&mut self.data, other.data) {
(Some(data), Some(new_data)) => AflMap::merge_vec(data, new_data),
(Some(_), None) => Ok(false),
(None, Some(new_data)) => {
self.data = Some(new_data);
Ok(true)
}
(None, None) => Ok(false),
}

interesting
}
}

Expand Down

0 comments on commit 7a7dcfe

Please sign in to comment.