Systemtap can access program variables in a probe. By using dwarf it
knows a variable will be at, say [sp, #12], so it uses a cached set of
registers, does the address evaluation and fetches the value. For the
dyninst backend we load the cache with the register values pulled via
BPatch_registerExpr. For x8664 this works fine; we can load the cache
with the register values in one call. Since ppcle and aarch64 are
limited to the number of arguments that will fit in registers; it is
done in chunks. This is fine on ppcle, but on aarch64 I am seeing
ARCH64::emitCall(opCode, codeGen&, const
std::vector<boost::shared_ptr<AstNode> >&, bool, func_instance*):
Assertion `scratch != REG_NULL && "cannot get a scratch register"' failed.
With the attached program, uncommenting the line at "This fails" fails
the same way.
PS Is there a way to grab sp (r31 depended on usage) because in some
cases, especially without optimization the variable value is at sp+offset
#include <cstdlib>
#include <cstdio>
#include <string>
#include <vector>
#include <iostream>
// dyninst libraries
#include <dyninst/BPatch.h>
#include <dyninst/BPatch_addressSpace.h>
#include <dyninst/BPatch_process.h>
#include <dyninst/BPatch_function.h>
#include <dyninst/BPatch_point.h>
using namespace std;
BPatch bpatch;
static void
usage (bool ok)
{
if (!ok)
{
cerr << "Usage mutator [-static] [-dynamic] PID|FILE.\n";
exit (1);
}
}
bool is_number(const std::string& s)
{
std::string::const_iterator it = s.begin();
while (it != s.end() && std::isdigit(*it)) ++it;
return !s.empty() && it == s.end();
}
// Create and insert a printf snippet
bool insert_printf_snippet(BPatch_addressSpace* app,
std::vector<BPatch_point*>* points)
{
vector<BPatch_register> bpregs;
app->getRegisters(bpregs);
ostream& debug_reg = cerr;
debug_reg << bpregs.size() << " registers available:";
for (size_t i = 0; i < bpregs.size(); ++i)
debug_reg << " " << bpregs[i].name();
debug_reg << endl;
BPatch_image* appImage = app->getImage();
std::vector<BPatch_snippet*> printfArgs;
BPatch_snippet* fmt = new BPatch_constExpr("In main %#lx %#lx %#lx %#lx %#lx %#lx %#lx\n");
printfArgs.push_back(fmt);
printfArgs.insert(printfArgs.end(), 7, new BPatch_constExpr(0));
std::vector<BPatch_function*> printfFuncs;
appImage->findFunction("printf", printfFuncs);
if (printfFuncs.size() == 0)
{
fprintf(stderr, "Could not find printf\n");
return false;
}
// This is the goal:
// int first_reg [] = {7, 14, 21, 28, 31};
// This fails
// int first_reg [] = {0, 7, 14, 21, 28};
// This works
int first_reg [] = {0, 7, 14, 21};
int pfarg;
for (int i = 0; i < (sizeof(first_reg)/sizeof(int))-1; i++)
{
pfarg = 1;
for (int r = first_reg[i]; r < first_reg[i+1]; r++)
{
printf("arg[%d]=reg[%d] ",pfarg,r);
printfArgs[pfarg++] = (new BPatch_registerExpr(bpregs[r]));
}
printf("\n");
BPatch_funcCallExpr printfCall(*(printfFuncs[0]), printfArgs);
if (!app->insertSnippet(printfCall, *points))/*, BPatch_callBefore, BPatch_firstSnippet))*/
{
fprintf(stderr, "insertSnippet failed\n");
return false;
}
}
return true;
}
int main(int argc, char **argv)
{
int pid;
// BPatch_binaryEdit *app_bin;
BPatch_addressSpace *app_bin;
BPatch_addressSpace *aspace;
BPatch_image *image;
enum {dyn_static, dyn_dynamic} dyn_type;
char * p ;
int argn = 1;
usage (argn < argc);
if (strncmp (argv[argn], "-h", 2) == 0)
usage (0);
else if (strcmp (argv[argn], "-static") == 0)
{
dyn_type = dyn_static;
argn += 1;
}
else if (strcmp (argv[argn], "-dynamic") == 0)
{
dyn_type = dyn_dynamic;
argn += 1;
}
usage (argn < argc);
if (is_number (argv[argn]))
{
pid = atoi(argv[1]);
if (pid == 0)
{
cerr << "ERROR ## Wrong PID " << pid << ", please use another.\n";
return 2;
}
app_bin = bpatch.processAttach(NULL, pid);
dyn_type = dyn_dynamic;
}
else
{
const char* prog_argv[] = {argv[argn], "-v", "5", NULL};
if (dyn_type == dyn_dynamic)
app_bin = bpatch.processCreate(argv[argn], prog_argv);
else /* assume dyn_static */
app_bin = bpatch.openBinary(argv[argn]);
}
aspace = app_bin;
image = aspace->getImage();
const char *inst_library = "libc.so.6";
if (!app_bin->loadLibrary (inst_library)) {
cerr << "Failed to open libc" << endl;
return EXIT_FAILURE;
}
vector<BPatch_function *> main_function;
image->findFunction("main", main_function);
std::vector<BPatch_point*>* main_entry_point = main_function[0]->findPoint(BPatch_entry);
if (!main_entry_point || main_entry_point->size() == 0) {
fprintf(stderr, "No entry points for main\n");
exit(1);
}
if (!insert_printf_snippet(aspace, main_entry_point))
{
fprintf(stderr, "insert_printf_snippet failed\n");
exit(1);
}
if (dyn_type == dyn_static)
{
string exefile = argv[argn];
std::size_t found = exefile.find_last_of(".");
if (found == string::npos)
exefile += "-mutated";
else
exefile = exefile.substr(0,found) + "-mutated" + exefile.substr(found);
cout << "Mutation done. Created " + exefile << endl;
BPatch_binaryEdit* appbined = dynamic_cast<BPatch_binaryEdit*>(app_bin);
appbined->writeFile(exefile.c_str());
}
else if (dyn_type == dyn_dynamic)
{
cout << "Mutation done. Running mutatee\n";
BPatch_process* appproc = dynamic_cast<BPatch_process*>(app_bin);
appproc->continueExecution();
appproc->detach(true);
}
return 0;
}
|