Commit 79a21f3e authored by otawa's avatar otawa

Merge branch 'dev' into beta

parents fda5eb01 fd8fcde5
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
# configuration
set(PLUGIN "lrusecurity") # plugin name
set(NAMESPACE "") # namespace
set(SOURCES "src/lrusecurity.cpp"
"src/lrusecurity_SecurityCatBuilder.cpp"
"src/Prev/lrusecurity_ExistHitPrevAnalysis.cpp"
"src/Prev/lrusecurity_ExistHitPrevDomain.cpp"
"src/Prev/lrusecurity_ExistHitPrevAdapter.cpp"
"src/Prev_Over/lrusecurity_ExistHitPrevOAnalysis.cpp"
"src/Prev_Over/lrusecurity_ExistHitPrevOAdapter.cpp"
"src/Prev_Over/lrusecurity_ExistHitPrevODomain.cpp"
"src/Prev_Under/lrusecurity_ExistHitPrevUAnalysis.cpp"
"src/Prev_Under/lrusecurity_ExistHitPrevUDomain.cpp"
"src/Prev_Under/lrusecurity_ExistHitPrevUAdapter.cpp"
"src/lrusecurity_Displayer.cpp"
"src/Graphic/AccMatching.cpp" # Modification for Dot
"src/Graphic/DotModificator.cpp"
)
# script
project(${PLUGIN})
# look for OTAWA
if(NOT OTAWA_CONFIG)
find_program(OTAWA_CONFIG otawa-config DOC "path to otawa-config")
if(NOT OTAWA_CONFIG)
message(FATAL_ERROR "ERROR: otawa-config is required !")
endif()
endif()
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${PLUGIN}.eld DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/)
message(STATUS "otawa-config found at ${OTAWA_CONFIG}")
execute_process(COMMAND "${OTAWA_CONFIG}" --cflags
OUTPUT_VARIABLE OTAWA_CFLAGS
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND "${OTAWA_CONFIG}" --libs --make-plug ${PLUGIN} -r
OUTPUT_VARIABLE OTAWA_LDFLAGS
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND "${OTAWA_CONFIG}" --prefix
OUTPUT_VARIABLE OTAWA_PREFIX
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
OUTPUT_STRIP_TRAILING_WHITESPACE)
# plugin definition
set(ORIGIN $ORIGIN)
add_library(${PLUGIN} SHARED ${SOURCES})
set_property(TARGET ${PLUGIN} PROPERTY PREFIX "")
set_property(TARGET ${PLUGIN} PROPERTY COMPILE_FLAGS "${OTAWA_CFLAGS} --std=c++11 -g -Wall -Wextra")
target_include_directories(${PLUGIN} PUBLIC "${CMAKE_SOURCE_DIR}/include")
target_link_libraries(${PLUGIN} ${OTAWA_LDFLAGS})
# installation
set(PLUGIN_PATH "${OTAWA_PREFIX}/lib/otawa/${NAMESPACE}")
install(TARGETS ${PLUGIN} LIBRARY DESTINATION ${PLUGIN_PATH})
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/lrusecurity" DESTINATION "${OTAWA_PREFIX}/include/")
install(FILES ${PLUGIN}.eld DESTINATION ${PLUGIN_PATH})
#ifndef LRUSECURITY_ACSSECURITY_H_H_
#define LRUSECURITY_ACSSECURITY_H_H_
#include <otawa/icache/features.h>
#include <otawa/icat3/features.h>
#include <otawa/base.h>
#include <set>
namespace lrusecurity
{
/*
struct Compa_access
{
bool operator()(const otawa::icache::Access a, const otawa::icache::Access b) const {return &a < &b;}
};
*/
class ACSSecurity : public elm::AllocArray<std::set <const otawa::icache::Access *>>
{
public:
ACSSecurity() = default;
ACSSecurity(int n) : elm::AllocArray<std::set <const otawa::icache::Access *>>(n){
for (int i = 0; i < n; i++)
(*this)[i] = std::set <const otawa::icache::Access *>();
}
ACSSecurity(int n, const otawa::icache::Access* access) : elm::AllocArray<std::set <const otawa::icache::Access *>>(n) {
for (int i = 0; i < n; i++){
(*this)[i] = std::set <const otawa::icache::Access *>();
(*this)[i].insert(access);
}
}
void print(int set, const otawa::icat3::LBlockCollection& coll, elm::io::Output& out= elm::cout) const;
};
}// namespace lrusecurity
#endif //LRUSECURITY_ACSSECURITY_H_H_
#ifndef LRUSECURITY_FEATURES_H_
#define LRUSECURITY_FEATURES_H_
#include <string>
#include <elm/data/Array.h>
#include <otawa/proc/AbstractFeature.h>
#include <otawa/icat3/features.h>
#include <lrusecurity/ACSSecurity.h>
namespace lrusecurity {
// Exist-Hit with previous access
extern otawa::p::feature EXIST_HIT_PREV_ANALYSIS_FEATURE;
extern otawa::p::id<otawa::icat3::Container<ACSSecurity> > EXIST_HIT_PREV_INIT;
extern otawa::p::id<otawa::icat3::Container<ACSSecurity> > EXIST_HIT_PREV_IN;
enum class SecurityCategory{
SAFE,
UNSAFE
};
class CacheState;
class ACSSManager
{
public:
ACSSManager(otawa::WorkSpace *ws);
~ACSSManager(void);
void start(otawa::Block *b);
void update(const otawa::icache::Access& acc);
int existHitAge(const otawa::icat3::LBlock *lb);
void print(const otawa::icat3::LBlock *lb, elm::io::Output& out = elm::cout);
private:
CacheState& use(int set);
const otawa::icat3::LBlockCollection& coll;
elm::Vector<int> used;
otawa::Block *_b;
CacheState **_states;
};
//Specifying which calls are making the program unsafe
extern otawa::p::feature SECURITY_CATEGORY_FEATURE;
extern otawa::p::id<SecurityCategory> SECURITY_CATEGORY;
} // namespace lrusecurity
#endif // LRUMC_FEATURES_H
[elm-plugin]
name=lrusecurity
deps=otawa/icat3;lruzdd;lrumc;lrupreanalysis
description=Information Leakage Cache Analysis for LRU policy
author=Valentin Touzeau, Maeva Ramarijaona
#ifndef LRUSECURITY_ACSSECURITY_H_H_
#define LRUSECURITY_ACSSECURITY_H_H_
#include <otawa/icache/features.h>
#include <otawa/icat3/features.h>
#include <otawa/base.h>
namespace lrusecurity
{
class ACSSecurity : public AllocArray<otawa::Address>
{
public:
ACSSecurity();
ACSSecurity(int n){
for (int i = 0; i < n; i++)
(*this)[i] = otawa::Address();
};
void print(int set, const otawa::icat3::LBlockCollection& coll, io::Output& out=cout) const;
};
}
#endif //LRUSECURITY_ACSSECURITY_H_H_
#ifndef LRUSECURITY_CACHE_STATE_H_
#define LRUSECURITY_CACHE_STATE_H_
#include "Prev/ExistHitPrevDomain.h"
namespace lrusecurity
{
class CacheState
{
public:
CacheState(const otawa::icat3::LBlockCollection& coll, int set) :
_existHitPrevDomain(coll, set, nullptr),
_PrevState(nullptr),
{
}
~CacheState()
{
if(_existHitState)
delete _PrevState;
}
ExistHitPrevDomain _existHitPrevDomain;
typename ExistHitPrevDomain::t* _PrevState;
};
} // namespace lrusecurity
#endif // LRUSECURITY_CACHE_STATE_H_
#include "AccMatching.h"
using namespace otawa;
namespace lrusecurity
{
void AccMatcher::setupCFG(CFG *cfg)
{
/* Parcours du CFG pour ajouter les BB au dictionnaire */
CFG::BlockIter iter_block;
for (iter_block = cfg->blocks(); iter_block(); iter_block++){
Block *b = *iter_block;
if (b->isBasic()){
BasicBlock *bb = b->toBasic();
const Bag<icache::Access>& bag = otawa::icache::ACCESSES(bb);
for (int i = 0; i < bag.size(); i++){
insert(&bag[i], bb);
}
}
}
}
void AccMatcher::setupColl(const CFGCollection *collection)
{
for(auto cfg: *collection) {
AccMatcher::setupCFG(cfg);
}
}
otawa::BasicBlock* AccMatcher::match_access(const otawa::icache::Access *access)
{
/* On cherche le BB associé à l'accès*/
auto search = this->_match.find(access);
if (search != _match.end())
return search->second;
else
cerr << "Unable to find access\n";
cerr << access->address();
cerr << "\n";
return NULL;
}
} // namespace lrusecurity
#ifndef LRUSECURITY_ACC_MATCHING_H
#define LRUSECURITY_ACC_MATCHING_H
#include <otawa/cfg/features.h>
#include <otawa/cfg/CFG.h>
#include <otawa/prog/Inst.h>
#include <otawa/icache/features.h>
#include <map>
namespace lrusecurity
{
class AccMatcher
{
/* Cette classe permet de créer un dictionnaire entre Access et BasicBlock auquel appartient cet accès*/
public:
AccMatcher(void){};
void setupColl(const otawa::CFGCollection *coll);
void setupCFG(otawa::CFG *cfg);
inline void insert(const otawa::icache::Access *acc, otawa::BasicBlock *bb){_match.insert({acc, bb});};
otawa::BasicBlock *match_access(const otawa::icache::Access *access);
inline void clean(void){_match = std::map<const otawa::icache::Access *, otawa::BasicBlock *>();};
private:
std::map<const otawa::icache::Access *, otawa::BasicBlock *> _match;
};
} // namespace lrusecurity
#endif /* ifndef LRUSECURITY_ACC_MATCHING_H */
#include <iostream>
#include <fstream>
#include <string>
#include "DotModificator.h"
namespace lrusecurity
{
void displayString(string str, std::ofstream *flux)
{
/* Cette fonction permet de placer une string elm dans std::ofstream*/
for (String::Iter i = str.begin(); i!= str.end(); i++)
*flux << *i;
}
void DotModificator::modify(otawa::CFG *cfg, const otawa::icache::Access *access, otawa::Address address)
{
std::ofstream flux(_filename, std::ios::app);
if (flux){
// Permet de mettre des nodes au même niveau
if (isFirst()) {
flux << "rankdir = TB;" << io::endl;
}
//Copie de l'addresse pour affichage
string addr = _ << address;
if (access){
// On récupère le bloc correspondant à l'accès grâce à l'InstMatcher
otawa::BasicBlock *bb_match = getMatcher()->match_access(access);
if (bb_match != NULL) {
// Copie de l'adresse de l'accès pour affichage
string acc_addr = _ << access->address();
// Creation du node UNSAFE
flux << "Unsafe_" << _count << " [label=\"{UNSAFE ";
displayString(acc_addr, &flux);
flux <<"|Lead to a hit @ ";
displayString(addr, &flux);
flux <<"}\", color = red];" << io::endl;
// On met au même niveau le node Unsafe et le BB auquel il correspond
flux << "{rank = same; Unsafe_" << _count << "; ";
displayString(bb_match->cfg()->name(), &flux);
flux << "_" << bb_match->cfg()->index() << "_" << bb_match->index() <<";}" << io::endl; //TODO: à optimisé (1 par BB)
}
} else { // UNSAFE au début
flux << "Unsafe_" << _count << " [label=\"{UNSAFE at the ENTRY|Can lead to a hit @ ";
displayString(addr, &flux);
flux << "|In function ";
displayString(cfg->name(), &flux);
flux << "}\", color = red];" << io::endl;
}
// On incrémente le compteur qui permet de nommer les nodes Unsafe
_count++;
} else {
cerr << "ERROR: Unable to open the file" << io::endl;
}
}
void DotModificator::finish(void)
{
std::ofstream flux(_filename);
if (flux){
flux << "}" << io::endl;
} else {
cerr << "ERROR: Unable to open the file" << io::endl;
}
}
}
#ifndef LRUSECURITY_DOT_MODIFICATOR_H
#define LRUSECURITY_DOT_MODIFICATOR_H
#include <otawa/icache/features.h>
#include <otawa/base.h>
#include <otawa/cfg/CFG.h>
#include "AccMatching.h"
namespace lrusecurity
{
class DotModificator
{
/* Cette classe permet de modifier un fichier DOT pour ajouter les résultats de l'analyse de sécurité*/
public:
DotModificator(const char *dot_file, AccMatcher *match):_filename(dot_file), _accM(match), _count(0){};
void modify(otawa::CFG *cfg, const otawa::icache::Access *access, otawa::Address address);
void finish(void);
inline AccMatcher *getMatcher(void){return _accM;};
inline bool isFirst(void){return _count == 0;};
private:
const char *_filename;
AccMatcher *_accM;
int _count;
};
}
#endif /* ifndef LRUSECURITY_DOT_MODIFICATOR_H */
#ifndef LRUSECURITY_EXIST_HIT_PREV_ADAPTER_H_
#define LRUSECURITY_EXIST_HIT_PREV_ADAPTER_H_
#include <otawa/ai/ArrayStore.h>
#include <otawa/icat3/features.h>
#include <otawa/cfg/CompositeCFG.h>
#include <otawa/cfg/features.h>
#include <lrupreanalysis/features.h>
#include "ExistHitPrevDomain.h"
namespace lrusecurity
{
class ExistHitPrevAdapter
{
public:
using domain_t = ExistHitPrevDomain;
using t = typename domain_t::t;
using graph_t = otawa::CompositeCFG;
using store_t = otawa::ai::ArrayStore<domain_t, graph_t>;
ExistHitPrevAdapter(int set, const t* init, const otawa::icat3::LBlockCollection& coll, const otawa::CFGCollection& cfgs, otawa::WorkSpace* ws);
inline domain_t& domain(void) { return _domain; }
inline graph_t& graph(void) { return _graph; }
inline store_t& store(void) { return _store; }
void update(const otawa::Bag<otawa::icache::Access>& accs, t& d);
void update(otawa::Block *v, t& d);
private:
lrumc::ACSManager _ehManager;
domain_t _domain;
graph_t _graph;
store_t _store;
};
} // namespace lrusecurity
#endif // LRUSECURITY_EXIST_HIT_ADAPTER_H_
#ifndef LRUSECURITY_EXIST_HIT_ANALYSIS_H_
#define LRUSECURITY_EXIST_HIT_ANALYSIS_H_
#include <otawa/proc/Processor.h>
#include <otawa/icat3/features.h>
#include <otawa/cfg/features.h>
#include <lrusecurity/ACSSecurity.h>
namespace lrusecurity
{
class ExistHitPrevAnalysis: public otawa::Processor
{
public:
static otawa::p::declare reg;
ExistHitPrevAnalysis(otawa::p::declare& r = reg);
protected:
void configure(const otawa::PropList& props) override;
void setup(otawa::WorkSpace* ws) override;
void processWorkSpace(otawa::WorkSpace* ws) override;
void destroy(otawa::WorkSpace* ws) override;
private:
void processSet(int i, otawa::WorkSpace* ws);
const otawa::icat3::Container<ACSSecurity>* _initExistHitPrev;
const otawa::icat3::LBlockCollection* _coll;
const otawa::CFGCollection* _cfgs;
};
/**
* Perform the ACS analysis for the Exist-Hit domain. For cache block, it associates an upper bound on block age that holds on at least on path
* @par Properties
* @li @ref EXIST_HIT_PREV_IN
*
* @par Configuraiton
* @li @ref EXIST_HIT_PREV_INIT
*
* @par Implementation
* @li @ref ExistHitPrevAnalysis
*
* @ingroup lrusecurity
*/
extern otawa::p::feature EXIST_HIT_PREV_ANALYSIS_FEATURE;
/**
* ACSSecurity for the Exist-Hit analysis at the entry of the corresponding block or edge.
*
* @par Feature
* @li @ref EXIST_HIT_ANALYSIS_PREV_FEATURE
*
* @par Hooks
* @li @ref Block
* @li @ref Edge
*
* @ingroup lrusecurity
*/
extern otawa::p::id<otawa::icat3::Container<ACSSecurity> > EXIST_HIT_PREV_IN;
/**
* Initial state for Exist-Miss instruction cache analysis.
*
* @par Hook
* @li Feature configuration.
*
* @par Feature
* @li @ref EXIST_HIT_ANALYSIS_PREV_FEATURE
*
* @ingroup lrusecurity
*/
extern otawa::p::id<otawa::icat3::Container<ACSSecurity> > EXIST_HIT_PREV_INIT;
}; // namespace lrusecurity
#endif // LRUSECURITY_EXIST_HIT_ANALYSIS_H_
#ifndef LRUSECURITY_EXIST_HIT_DOMAIN_H_
#define LRUSECURITY_EXIST_HIT_DOMAIN_H_
#include <otawa/icat3/features.h>
#include <otawa/icache/features.h>
#include <elm/io/Output.h>
#include <lrumc/features.h>
#include <lrumc/ACSManager.h>
#include <lrupreanalysis/features.h>
#include <lrusecurity/ACSSecurity.h>
namespace lrusecurity
{
class ExistHitPrevDomain {
public:
using t = ACSSecurity;
ExistHitPrevDomain(const otawa::icat3::LBlockCollection& coll, int set, const t* init);
inline const t& bot(void) const { return _bot; }
inline const t& top(void) const { return _top; }
inline const t& init(void) const { return _init; }
inline void print(const t& a, otawa::io::Output& out) const { a.print(_set, _coll, out); }
inline elm::io::Printable<t, ExistHitPrevDomain> print(const t& a) const { return elm::io::p(a, *this); }
inline bool contains(const t& a, int i) { return(!a[i].empty()); }
inline void copy(t& d, const t& s) { d.copy(s); }
bool equals(const t& a, const t& b) const;
void join(t& d, const t& s);
void fetch(t& a, const otawa::icache::Access& ac, lrumc::ACSManager& ehManager);
void update(const otawa::icache::Access& access, t& a, lrumc::ACSManager& ehManager);
private:
int _n;
t _bot, _top;
otawa::hard::Cache::set_t _set;
const otawa::icat3::LBlockCollection& _coll;
int _A;
const t& _init;
t _tmp;
};
} // namespace lrusecurity
#endif // LRUSECURITY_EXIST_HIT_DOMAIN_H_
#include "ExistHitPrevAdapter.h"
using namespace otawa;
namespace lrusecurity
{
ExistHitPrevAdapter::ExistHitPrevAdapter(
int set,
const t* init,
const icat3::LBlockCollection& coll,
const CFGCollection& cfgs,
otawa::WorkSpace* ws) :
_ehManager(ws),
_domain(coll, set, init),
_graph(cfgs),
_store(_domain, _graph)
{
}
void ExistHitPrevAdapter::update(const Bag<icache::Access>& accs, t& d)
{
for(int i = 0; i < accs.count(); i++) {
_domain.update(accs[i], d, _ehManager);
_ehManager.update(accs[i]);
}
}
void ExistHitPrevAdapter::update(Block *v, t& d)
{
_domain.copy(d, _domain.bot());
t s;
// update and join along edges
for(auto e = _graph.preds(v); e(); e++) {
Block *w = e->source();
_domain.copy(s, _store.get(w));
_ehManager.start(w);
// apply block
{
const Bag<icache::Access>& accs = icache::ACCESSES(w);
if(accs.count() > 0)
update(accs, s);
}
// apply edge
{
const Bag<icache::Access>& accs = icache::ACCESSES(*e);
if(accs.count() > 0)
update(accs, s);
}
// merge result
_domain.join(d, s);
}
}
} // namespace lrusecurity
#include "ExistHitPrevAnalysis.h"
#include <chrono>
#include <otawa/ai/ArrayStore.h>
#include <otawa/ai/SimpleAI.h>
#include <otawa/icache/features.h>
#include <otawa/icat3/features.h>
#include <lrusecurity/features.h>
#include "ExistHitPrevAdapter.h"