Re: [DynInst_API:] Type conflict building parseAPI example


Date: Wed, 6 Feb 2013 15:29:39 +0000
From: "E.Robbins" <er209@xxxxxxxxxx>
Subject: Re: [DynInst_API:] Type conflict building parseAPI example
Okay, I really should have checked this better before I sent it out!

I've added a last fix which is purely cosmetic - fixes the indentation in the final output, which was a bit messy in previous versions.

Sorry for 3 separate mails!

________________________________________
From: dyninst-api-bounces@xxxxxxxxxxx [dyninst-api-bounces@xxxxxxxxxxx] on behalf of E.Robbins [er209@xxxxxxxxxx]
Sent: 06 February 2013 15:15
Cc: dyninst-api@xxxxxxxxxxx
Subject: Re: [DynInst_API:] Type conflict building parseAPI example

Urr, one last tiny update - add start addresses as well as names to function nodes.

Ed
________________________________________
From: dyninst-api-bounces@xxxxxxxxxxx [dyninst-api-bounces@xxxxxxxxxxx] on behalf of E.Robbins [er209@xxxxxxxxxx]
Sent: 06 February 2013 15:09
To: Andrew Bernat
Cc: dyninst-api@xxxxxxxxxxx
Subject: Re: [DynInst_API:] Type conflict building parseAPI example

Ok, I have now also made the example a lot nicer - no dot errors and nodes are always printed in the right place. You can find it attached.

Cheers,
Ed
________________________________________
From: Andrew Bernat [bernat@xxxxxxxxxxx]
Sent: 05 February 2013 18:58
To: E.Robbins
Cc: dyninst-api@xxxxxxxxxxx
Subject: Re: [DynInst_API:] Type conflict building parseAPI example

On Feb 5, 2013, at 12:52 PM, E.Robbins <er209@xxxxxxxxxx<mailto:er209@xxxxxxxxxx>> wrote:

I do have valgrind - I'll check it out tomorrow. Did you want me to do some particular check (I mostly use it for leak checking)?

The default run will identify memory errors. I'd like to know what we're double-deleting, since it seems to vary by platform. Odd.

I find it a bit strange that when the control flow recovery runs into a call it creates an edge to the called function *and* one to the following block (the one starting immediately after the call site). Shouldn't it make an edge going to the call and then an edge from the return block of the called function to the following block? Otherwise you are assuming that the function will return. I am sure there is a good reason for this (probably because you can't always find the return of a function?) but I just wondered what the reasoning was?

It's to make intra-function analysis easier. We create a virtual edge with a type of CALL_FT to link the call to where execution will return. We check for non-returning functions and omit CALL_FT if we find them, though that analysis turns out to be remarkably difficult.

Basically, it's to make life easy for people that don't want full interprocedural analysis.

Drew


Cheers,
Ed

________________________________________
From: Andrew Bernat [bernat@xxxxxxxxxxx<mailto:bernat@xxxxxxxxxxx>]
Sent: 05 February 2013 18:01
Subject: Re: [DynInst_API:] Type conflict building parseAPI example

Thanks, this is very nice.

WRT the crash - do you have valgrind on your system? If so, could you run it and send me the output? I'd be interested to know why delete isn't working. Not that I'm at all surprised - memory management is a pain.

Drew

On Feb 5, 2013, at 8:14 AM, E.Robbins <er209@xxxxxxxxxx<mailto:er209@xxxxxxxxxx><mailto:er209@xxxxxxxxxx>> wrote:

Hi again,
I added a couple of lines to your example and now it groups nodes from the same function into clusters and labels function nodes with the name of the function... makes it a bit clearer what is going on. Give it a try! I've attached it.

BTW, I commented out the deletes at the end because one of them causes a crash, at least on my system.

Cheers,
Ed

--
Andrew Bernat
Paradyn Project
bernat@xxxxxxxxxxx<mailto:bernat@xxxxxxxxxxx><mailto:bernat@xxxxxxxxxxx>
http://www.cs.wisc.edu/~bernat





--
Andrew Bernat
Paradyn Project
bernat@xxxxxxxxxxx<mailto:bernat@xxxxxxxxxxx>
http://www.cs.wisc.edu/~bernat




#include <stdio.h>
#include <map>
#include "CodeObject.h"
#include "CFG.h"

using namespace std;
using namespace Dyninst;
using namespace ParseAPI;

int main(int argc, char * argv[])
{
	map<Address, bool> seen;
	vector<Function *> funcs;
	SymtabCodeSource *sts;
	CodeObject *co;

	// Create a new binary code object from the filename argument
	sts = new SymtabCodeSource( argv[1] );
	co = new CodeObject( sts );

	// Parse the binary
	co->parse();
	printf("digraph G {\n");

	// Print the control flow graph
	CodeObject::funclist all = co->funcs();
	CodeObject::funclist::iterator fit = all.begin();
	for(int i = 0; fit != all.end(); ++fit, i++) { // i is index for clusters
		Function *f = *fit;

		// Make a cluster for nodes of this function
		printf("\t subgraph cluster_%d {label=\"%s\";\n\t\tcolour=blue;\n", i, f->name().c_str());

		if(f->retstatus() == NORETURN)
			printf("\t\t\"%lx\" [shape=box,color=red]\n",f->addr());
		else
			printf("\t\t\"%lx\" [shape=box]\n",f->addr());
		// Label functions by name
		printf("\t\t\"%lx\" [label=\"%s\\n%lx\"];\n", f->addr(), f->name().c_str(), f->addr());

		// For some reason not doing this seems to make prettier graphs
		// seen[f->addr()] = true;

		char *edgeoutput = NULL, *temp = NULL;
		asprintf(&edgeoutput, "");

		Function::blocklist::const_iterator bit = f->blocks().begin();
		for( ; bit != f->blocks().end(); ++bit) {
			Block *b = *bit;
			// Donâ??t revisit blocks in shared code
			if(seen.find(b->start()) != seen.end())
				continue;

			seen[b->start()] = true;

			// Label block
			printf("\t\t\"%lx\";\n", b->start());

			Block::edgelist::const_iterator it = b->targets().begin();
			for( ; it != b->targets().end(); ++it) {
				char * s = "";
				if((*it)->type() == CALL)
					s = " [color=blue]";
				else if((*it)->type() == RET)
					s = " [color=green]";
				// Store the edges somewhere to be printed outside of the cluster
				temp = edgeoutput;
				asprintf(&edgeoutput, "%s\t\"%lx\" -> \"%lx\"%s\n", temp, (*it)->src()->start(), (*it)->trg()->start(),s);
				free(temp);
			}
		}
		// End cluster
		printf("\t}\n");
		// Print edges
		printf("%s", edgeoutput);
		free(edgeoutput);
	}
	printf("}\n");

	delete co;
	//delete sts;
}
[← Prev in Thread] Current Thread [Next in Thread→]