Skip to content

Commit

Permalink
Adds basic sfpf binary
Browse files Browse the repository at this point in the history
sfpf is the Static Function Property Finder and it utilizes a modified deduction
engine, which propigates information from library functions through defined
functions. This is the reverse direction compared to the deductions used in
sfpv, thus the ReverseDedutions class. The ideal use of sfpf would be to quickly
obtain whitelists and blacklists from a library.

- Adds basic sfpf binary
- Moves main.cpp to sfpv.cpp
- Adds simple internal blacklist in sfpf
  • Loading branch information
fundamental committed Jun 5, 2012
1 parent bfb2e85 commit 7e2bbaf
Show file tree
Hide file tree
Showing 7 changed files with 400 additions and 7 deletions.
8 changes: 6 additions & 2 deletions CMakeLists.txt
Expand Up @@ -22,9 +22,13 @@ set (CMAKE_CXX_COMPILER clang++)

add_definitions (-DVERSION="${sfpv_VERSION_MAJOR}.${sfpv_VERSION_MINOR}")
add_executable (sfpv src/Errors.cpp src/GraphBuilder.cpp src/Deductions.cpp
src/TranslationUnit.cpp src/FuncCalls.cpp src/FuncEntries.cpp src/main.cpp)
src/TranslationUnit.cpp src/FuncCalls.cpp src/FuncEntries.cpp src/sfpv.cpp)
target_link_libraries (sfpv ${CLANG_LIBRARIES} ${LLVM_LIBRARIES})

add_executable (sfpf src/Errors.cpp src/GraphBuilder.cpp src/ReverseDeductions.cpp
src/TranslationUnit.cpp src/FuncCalls.cpp src/FuncEntries.cpp src/sfpf.cpp)
target_link_libraries (sfpf ${CLANG_LIBRARIES} ${LLVM_LIBRARIES})

######################################################################
# Tests to verify it works #
######################################################################
Expand All @@ -38,7 +42,7 @@ set_property (TEST test-one
"error: Realtime safety violation, baz called from a safe function.*Function undefined_function was deduced to need to be safe")

#Verify that nothing dies with very complex headers
add_test (header-includes sfpv -C "-D__STDC_CONSTANT_MACROS=1 -D__STDC_FORMAT_MACROS=1 __STDC_LIMIT_MACROS=1" ${SRC}/src/main.cpp)
add_test (header-includes sfpv -C "-D__STDC_CONSTANT_MACROS=1 -D__STDC_FORMAT_MACROS=1 __STDC_LIMIT_MACROS=1" ${SRC}/src/sfpv.cpp)

#Check that information is translated over multiple translation units
add_test (multi-translation-unit sfpv ${SRC}/test/test-input.cpp ${SRC}/test/test-input2.cpp)
Expand Down
2 changes: 1 addition & 1 deletion src/FuncEntries.cpp
Expand Up @@ -40,7 +40,7 @@ bool FuncEntries::has(std::string fname)
void FuncEntries::add(std::string fname, class TranslationUnit *tu, class clang::FunctionDecl *fdecl)
{
if(impl->fmap.find(fname) == impl->fmap.end())
impl->fmap[fname] = FuncEntry(fname, tu, fdecl);
impl->fmap.insert(std::pair<std::string, FuncEntry>(fname,FuncEntry(fname, tu, fdecl)));
}

FuncEntry &FuncEntries::operator[](std::string fname)
Expand Down
9 changes: 5 additions & 4 deletions src/FuncEntries.h
Expand Up @@ -13,18 +13,18 @@ class FuncEntry
public:
FuncEntry(void)
:name("I_HAVE_A_BUG...@" __FILE__)
{
}
{}
FuncEntry(std::string str, class TranslationUnit *tu, class clang::FunctionDecl *fdecl)
:name(str),TU(tu),FDECL(fdecl),RT(false),ext_RT(false),nRT(false), defined(false)
:name(str),TU(tu),FDECL(fdecl),RT(false),ext_RT(false),nRT(false), ext_nRT(false), defined(false)
{}

void display(void) const;
void realtime(void) { RT = true; }
void ext_realtime(void) {ext_RT = true;}
void ext_not_realtime(void) {ext_nRT = true;}
void not_realtime(void) { nRT = true; }
bool realtime_p(void) {return RT|ext_RT;}
bool not_realtime_p(void) {return nRT;}
bool not_realtime_p(void) {return nRT|ext_nRT;}
void define(void) {defined = true;}
bool defined_p(void) {return defined;}

Expand All @@ -35,6 +35,7 @@ class FuncEntry
bool RT;
bool ext_RT;
bool nRT;
bool ext_nRT;
bool defined;
};

Expand Down
159 changes: 159 additions & 0 deletions src/ReverseDeductions.cpp
@@ -0,0 +1,159 @@
#include "ReverseDeductions.h"
#include "Errors.h"
#include "GraphBuilder.h"
#include "FuncCalls.h"
#include "FuncEntries.h"
#include "TranslationUnit.h"

#include <string>
#include <vector>
#include <cstdio>

#pragma clang diagnostic ignored "-Wc++11-extensions"

typedef CallPair Deduction;
class ReverseDeductionsImpl
{
public:
int length(void) const;
void print(void) const;
void print_whitelist(void) const;
bool rt_p(std::string fname) const;
bool nrt_p(std::string fname) const;
void deduce_rt(std::string d);
void deduce_nrt(Deduction d);
void perform_deductions(GraphBuilder *gb);
void find_all(GraphBuilder *gb);
bool known(FuncEntry e) const;

GraphBuilder *gb;
private:
std::vector<std::string> rt_deductions;
std::vector<Deduction> nrt_deductions;
};

ReverseDeductions::ReverseDeductions(GraphBuilder *gb)
:impl(new ReverseDeductionsImpl)
{
impl->gb = gb;
impl->find_all(gb);
}

ReverseDeductions::~ReverseDeductions(void)
{
delete impl;
}

void ReverseDeductions::print(void)
{
impl->print();
}

void ReverseDeductions::print_whitelist(void)
{
impl->print_whitelist();
}

int ReverseDeductionsImpl::length(void) const
{
return rt_deductions.size() + nrt_deductions.size();
}

void ReverseDeductionsImpl::print(void) const
{
printf("Deduced Safe Functions\n");
for(std::string s: rt_deductions)
printf("%30s\n", s.c_str());

printf("Deduced Unsafe Functions\n");
for(Deduction d: nrt_deductions)
printf("%30s :=> %30s\n", d.first.c_str(), d.second.c_str());
}

void ReverseDeductionsImpl::print_whitelist(void) const
{
for(std::string s: rt_deductions)
printf("%s\n", s.c_str());
}

bool ReverseDeductionsImpl::rt_p(std::string fname) const
{
FuncEntries &fe = gb->getFunctions();
if(fe.has(fname) && fe[fname].realtime_p())
return true;

for(std::string d: rt_deductions)
if(d == fname)
return true;
return false;
}

bool ReverseDeductionsImpl::nrt_p(std::string fname) const
{
FuncEntries &fe = gb->getFunctions();
if(fe.has(fname) && fe[fname].not_realtime_p())
return true;

for(auto d: nrt_deductions)
if(d.first == fname)
return true;
return false;
}

void ReverseDeductionsImpl::deduce_nrt(Deduction d)
{
nrt_deductions.push_back(d);
}
void ReverseDeductionsImpl::deduce_rt(std::string d)
{
rt_deductions.push_back(d);
}

void ReverseDeductionsImpl::perform_deductions(GraphBuilder *gb)
{
FuncEntries &entries = gb->getFunctions();
for(auto pair:entries) {
FuncEntry e = pair.second;

//Don't bother with functions with deduced safety
if(known(e) || !e.defined_p())
continue;

//Try to deduce non-realtime
//If any call is to an unsafe function, this function is unsafe
for(CallPair c:gb->getCalls()) {
if(c.first == e.name && nrt_p(c.second)) {
deduce_nrt(c);
goto next;
}
}


//Try to deduce realtime
//If all calls are to safe functions, this function is safe
//FIXME to postpone complexity recursion is hardcoded
for(CallPair c:gb->getCalls()) {
if(c.first == e.name && c.first != c.second &&!rt_p(c.second)) {
goto next;
}
}
deduce_rt(e.name);
next:
;
}
}

void ReverseDeductionsImpl::find_all(GraphBuilder *gb)
{
int len = 0;
do {
len = length();
perform_deductions(gb);
} while(len != length());
}

bool ReverseDeductionsImpl::known(FuncEntry e) const
{
return rt_p(e.name)||nrt_p(e.name);
}

13 changes: 13 additions & 0 deletions src/ReverseDeductions.h
@@ -0,0 +1,13 @@
class GraphBuilder;

class ReverseDeductions
{
public:
ReverseDeductions(GraphBuilder *gb);
~ReverseDeductions(void);
void print(void);
void print_whitelist(void);
private:
class ReverseDeductionsImpl *impl;
};

0 comments on commit 7e2bbaf

Please sign in to comment.