Commit fdfcae7f authored by Jason Hiser's avatar Jason Hiser 🚜

cleaning up thanos plugin interface

parent 96f34d5e
Pipeline #2557 failed with stages
in 7 minutes and 18 seconds
......@@ -24,34 +24,50 @@
using namespace IRDB_SDK;
using namespace std;
// constructor
KillDeads::KillDeads(FileIR_t *p_variantIR)
:
Transform(p_variantIR)
Transform(p_variantIR) // init transform class for insertAssembly and getFileIR
{
}
int KillDeads::execute()
bool KillDeads::execute()
{
// init statistics variables
auto killed_flags=0L;
auto killed_regs=0L;
// seed RNG and choose a random kill value.
srand(time(0));
int kill_val=rand();
// declare and construct a deep analysis engine
auto de=DeepAnalysis_t::factory(getFileIR());
auto reg_mapp=de->getDeadRegisters();
auto &reg_map=*reg_mapp;
cout<<"Using random_value: "<<dec<<kill_val<<endl;
// and get the dead regs
auto reg_map_ptr=de->getDeadRegisters();
// for syntactical convenience, we deref the pointer once and make a reference to it.
auto &reg_map=*reg_map_ptr;
// log
cout<<"Using random kill value: "<<dec<<kill_val<<endl;
for(auto &insn : getFileIR()->getInstructions())
// the insertAssembly family modifies what getInstructions(), and the range-based for loop
// may go crazy. Copy first so we only check the original instructions
const auto old_insn=getFileIR()->getInstructions();
// for each instruction
for(auto &insn : old_insn)
{
// find the dead registers for the instruction
const auto &regset=reg_map[insn];
// each register that's dead
for(auto reg : regset)
{
// if it's the flags, kill the flags with a cmp
if (reg==rn_EFLAGS)
{
// for flags, do a random compare to change them
......@@ -61,25 +77,35 @@ int KillDeads::execute()
insertAssemblyBefore(insn, buf);
killed_flags++;
}
// check if it's an integer register
if(is64bitRegister(reg) || is32bitRegister(reg) || is16bitRegister(reg) || is8bitRegister(reg))
{
// other integer registers can be killed with a mov
char buf[100];
sprintf(buf," mov %s, %d", registerToString(reg).c_str(), kill_val);
cout<<"Inserting '"<<buf<<"' before '"<<insn->getDisassembly()<<"'"<<endl;
insertAssemblyBefore(insn, buf);
killed_regs++;
}
// Future work: kill float registers
}
}
//
// SELF_VALIDATE is used for nightly tseting to make sure we are finding at least some dead registers.
//
assert(getenv("SELF_VALIDATE")==nullptr || killed_flags > 5);
assert(getenv("SELF_VALIDATE")==nullptr || killed_regs > 15);
//
// Output stats to log using #ATTRIBUTE convention
//
cout<<"#ATTRIBUTE killed_flags="<<dec<<killed_flags<<endl;
cout<<"#ATTRIBUTE killed_regs="<<dec<<killed_regs<<endl;
return 1;
// success!
return true;
}
......@@ -29,8 +29,9 @@ class KillDeads : public IRDB_SDK::Transform
{
public:
KillDeads(IRDB_SDK::FileIR_t *p_variantIR);
int execute();
bool execute();
private:
// no class member data or methods yet.
};
#endif
......@@ -28,80 +28,97 @@
using namespace std;
using namespace IRDB_SDK;
void usage(char* name)
//
// kill_deads is a Thanos-enabled transform. Thanos-enabled transforms must implement the TransfromStep_t abstract class.
//
// For convenience, since this class is simple and shouldn't be used elsewhere, we just implement the class in the .cpp file
//
class KillDeadsDriver_t : public IRDB_SDK::TransformStep_t
{
cerr<<"Usage: "<<name<<" <variant_id>\n";
}
int main(int argc, char **argv)
{
if(argc != 2)
{
usage(argv[0]);
exit(1);
}
string programName(argv[0]);
int variantID = atoi(argv[1]);
/* setup the interface to the sql server */
auto pqxx_interface=pqxxDB_t::factory();
BaseObj_t::setInterface(pqxx_interface.get());
auto pidp=VariantID_t::factory(variantID);
assert(pidp->isRegistered()==true);
cout<<"kill_deads_driver.exe started\n";
bool one_success = false;
for(set<File_t*>::iterator it=pidp->getFiles().begin();
it!=pidp->getFiles().end();
++it)
{
File_t* this_file = *it;
auto firp = FileIR_t::factory(pidp.get(), this_file);
cout<<"Transforming "<<this_file->getURL()<<endl;
assert(firp && pidp);
try
{
KillDeads kill_deads(firp.get());
int success=kill_deads.execute();
if (success)
{
cout<<"Writing changes for "<<this_file->getURL()<<endl;
one_success = true;
firp->writeToDB();
}
else
public:
//
// required override: how to parse your options
//
int parseArgs(const vector<string> step_args) override
{
// must get at least the variant ID to work on as the first parameter.
if(step_args.size() != 0)
{
cout<<"Skipping (no changes) "<<this_file->getURL()<<endl;
usage(program_name);
return 2; // error
}
}
catch (DatabaseError_t pnide)
{
cerr << programName << ": Unexpected database error: " << pnide << "file url: " << this_file->getURL() << endl;
return 1;
}
catch (...)
{
cerr << programName << ": Unexpected error file url: " << this_file->getURL() << endl;
return 1;
}
} // end file iterator
// if any integer transforms for any files succeeded, we commit
if (one_success)
{
cout<<"Commiting changes...\n";
pqxx_interface->commit();
}
return 0; // success (bash-style 0=success, 1=warnings, 2=errors)
}
return 0;
//
// required override: how to achieve the actual transform
//
int executeStep() override
{
auto url=getMainFile()->getURL() ;
try
{
// load the fileIR (or, get the handle to an already loaded IR)
auto firp = getMainFileIR();
// declare and execute a transform
KillDeads kill_deads(firp);
auto success=kill_deads.execute();
// check for success
if (success)
{
cout << "Success! Thanos will write back changes for " << url << endl;
return 0; // success (bash-style 0=success, 1=warnings, 2=errors)
}
// failure
cout << "Failure! Thanos will report error to user for " << url << endl;
return 2; // error
}
catch (DatabaseError_t db_err)
{
cerr << program_name << ": Unexpected database error: " << db_err << "file url: " << url << endl;
return 2; // error
}
catch (...)
{
cerr << program_name << ": Unexpected error file url: " << url << endl;
return 2; // error
}
assert(0); // unreachable
}
//
// required override: report the step name
//
string getStepName(void) const override
{
return program_name;
}
private:
const string program_name = string("kill_deads");
int variantID = BaseObj_t::NOT_IN_DATABASE;
//
// optional: print arguments for this class
// very simple args: only the variant ID
//
void usage(const string& p_name)
{
cerr << "Usage: " << p_name << endl;
}
};
//
// Required interface: a factory for creating the interface object for this transform.
//
extern "C"
shared_ptr<TransformStep_t> getTransformStep(void)
{
return shared_ptr<TransformStep_t>(new KillDeadsDriver_t());
}
......@@ -37,43 +37,20 @@ using namespace IRDB_SDK;
class StackStampDriver_t : public IRDB_SDK::TransformStep_t
{
private:
const string programName=string("libstack_stamp.so");
int variantID = BaseObj_t::NOT_IN_DATABASE;
bool verbose=false;
Stamper::StampValue_t stamp_value=-1;
public:
void usage(const string& name)
{
cerr<<"Usage: "<<name<<" <variant_id>\n";
cerr<<"\t--stamp-value <value> Set the stamp value that will be used. "<<endl;
cerr<<"\t-s <value> (as parsed by by strtoul) "<<endl;
cerr<<"\t--verbose Verbose mode. "<<endl;
cerr<<"\t-v "<<endl;
cerr<<"--help,--usage,-?,-h Display this message "<<endl;
}
public:
int parseArgs(const vector<string> step_args)
int parseArgs(const vector<string> step_args) override
{
/* convert to argv format for esay parsing wth getopts */
auto argv = vector<char*>();
transform(ALLOF(step_args), back_inserter(argv), [](const string &s) -> char* { return const_cast<char*>(s.c_str()); } );
const auto argc=step_args.size();
variantID = atoi(argv[0]);
srand(getpid()+time(NULL));
stamp_value=rand();
if(argc < 1)
{
usage(programName);
return 1;
}
// declare getopts values
const auto short_opts="s:v?h";
struct option long_options[] = {
......@@ -114,44 +91,49 @@ class StackStampDriver_t : public IRDB_SDK::TransformStep_t
return 0;
}
int executeStep(IRDBObjects_t *const irdb_objects)
int executeStep() override
{
/* setup the interface to the sql server */
auto &pqxx_interface=*irdb_objects->getDBInterface();;
BaseObj_t::setInterface(&pqxx_interface);
const auto pidp = irdb_objects->addVariant(variantID);
assert(pidp->isRegistered()==true);
auto success = false;
auto this_file=pidp->getMainFile();
auto firp = irdb_objects->addFileIR(variantID, this_file->getBaseID());
cout<<"Transforming "<<this_file->getURL()<<endl;
auto url=getMainFile()->getURL();
try
{
auto firp=getMainFileIR();
Stamper::StackStamp_t ss(firp, stamp_value, verbose);
success=ss.execute();
const auto success=ss.execute();
return success ? 0 : 2; // bash-style, 0=success, 1=warnings, 2=errors
}
catch (DatabaseError_t pnide)
catch (DatabaseError_t dberr)
{
cerr << programName << ": Unexpected database error: " << pnide << "file url: " << this_file->getURL() << endl;
cerr << programName << ": Unexpected database error: " << dberr << "file url: " << url << endl;
return 2; // error
}
catch (...)
{
cerr << programName << ": Unexpected error file url: " << this_file->getURL() << endl;
cerr << programName << ": Unexpected error file url: " << url << endl;
return 2; // error
}
return success ? 0 : 2;
}
string getStepName(void) const override
{
return string("stack_stamp");
}
private:
const string programName = string("libstack_stamp.so");
bool verbose = false;
Stamper::StampValue_t stamp_value=-1;
void usage(const string& name)
{
cerr<<"Usage: "<<name<<endl;
cerr<<"\t--stamp-value <value> Set the stamp value that will be used. "<<endl;
cerr<<"\t-s <value> (as parsed by by strtoul) "<<endl;
cerr<<"\t--verbose Verbose mode. "<<endl;
cerr<<"\t-v "<<endl;
cerr<<"--help,--usage,-?,-h Display this message "<<endl;
}
};
extern "C"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment