Skip to content

Commit

Permalink
Refactor to look up target blocks via parse data and remove block-lev…
Browse files Browse the repository at this point in the history
…el locks associated with that lookup.
  • Loading branch information
wrwilliams committed Aug 16, 2017
1 parent dc335d0 commit b00c212
Show file tree
Hide file tree
Showing 12 changed files with 64 additions and 33 deletions.
4 changes: 2 additions & 2 deletions dyninstAPI/src/parse-cfg.h
Expand Up @@ -191,8 +191,8 @@ class image_edge : public ParseAPI::Edge {
// MSVC++ 2003 does not properly support covariant return types
// in overloaded methods
#if !defined _MSC_VER || _MSC_VER > 1310
virtual parse_block * src() const { return (parse_block*)_source; }
virtual parse_block * trg() const { return (parse_block*)_target; }
virtual parse_block * src() const { return (parse_block*)src(); }
virtual parse_block * trg() const { return (parse_block*)trg(); }
#endif

const char * getTypeString();
Expand Down
8 changes: 6 additions & 2 deletions parseAPI/h/CFG.h
Expand Up @@ -61,6 +61,7 @@ class LoopAnalyzer;
class dominatorCFG;
class CodeObject;
class CFGModifier;
class ParseData;

enum EdgeTypeEnum {
CALL = 0,
Expand Down Expand Up @@ -146,7 +147,8 @@ class PARSER_EXPORT Edge : public allocatable {
friend class CFGModifier;
protected:
Block * _source;
Block * _target;
ParseData* index;
Offset _target_off;

private:

Expand Down Expand Up @@ -176,7 +178,7 @@ class PARSER_EXPORT Edge : public allocatable {
virtual ~Edge();

Block * src() const { return _source; }
Block * trg() const { return _target; }
Block * trg() const;
EdgeTypeEnum type() const {
return static_cast<EdgeTypeEnum>(_type._type_enum);
}
Expand Down Expand Up @@ -297,6 +299,8 @@ class PARSER_EXPORT Block :
public:
typedef std::map<Offset, InstructionAPI::InstructionPtr> Insns;
typedef std::list<Edge*> edgelist;
public:
static Block * sink_block;

Block(CodeObject * o, CodeRegion * r, Address start);
virtual ~Block();
Expand Down
1 change: 1 addition & 0 deletions parseAPI/h/CodeObject.h
Expand Up @@ -154,6 +154,7 @@ class CodeObject {
* Hacky "for insertion" method
*/
PARSER_EXPORT Address getFreeAddr() const;
ParseData* parse_data();

private:
void process_hints();
Expand Down
20 changes: 15 additions & 5 deletions parseAPI/src/Block.C
Expand Up @@ -70,7 +70,7 @@ bool
Block::consistent(Address addr, Address & prev_insn)
{
InstructionSource * isrc;
if(!_obj->cs()->regionsOverlap())
if(_obj && !_obj->cs()->regionsOverlap())
isrc = _obj->cs();
else
isrc = region();
Expand All @@ -94,6 +94,7 @@ Block::consistent(Address addr, Address & prev_insn)
void
Block::getFuncs(vector<Function *> & funcs)
{
if(!_obj) return; // universal sink
set<Function *> stab;
_obj->findFuncs(region(),start(),stab);
set<Function *>::iterator sit = stab.begin();
Expand Down Expand Up @@ -147,13 +148,13 @@ SingleContextOrInterproc::pred_impl(Edge * e) const
}

int Block::containingFuncs() const {
_obj->finalize();
if(_obj) _obj->finalize();
return _func_cnt;
}

void Block::removeFunc(Function *)
{
if (0 == _func_cnt) {
if ((0 == _func_cnt) && _obj) {
_obj->finalize();
}
assert(0 != _func_cnt);
Expand All @@ -162,6 +163,7 @@ void Block::removeFunc(Function *)

void Block::updateEnd(Address addr)
{
if(!_obj) return;
_obj->cs()->addCounter(PARSE_BLOCK_SIZE, -1*size());
_end = addr;
_obj->cs()->addCounter(PARSE_BLOCK_SIZE, size());
Expand All @@ -180,7 +182,7 @@ void Edge::install()
void Edge::uninstall()
{
mal_printf("Uninstalling edge [%lx]->[%lx]\n",
_source->lastInsnAddr(), _target->start());
_source->lastInsnAddr(), _target_off);
// if it's a call edge, it's cached in the function object, remove it
if (CALL == type()) {
vector<Function*> srcFs;
Expand All @@ -203,13 +205,21 @@ void Edge::uninstall()
}
// remove from source and target blocks
_source->removeTarget(this);
_target->removeSource(this);
trg()->removeSource(this);
}

void Edge::destroy(Edge *e, CodeObject *o) {
o->destroy(e);
}

Block* Block::sink_block = new Block(NULL, NULL, std::numeric_limits<Address>::max());

Block *Edge::trg() const {
Block* found = index->findBlock(_source->region(), _target_off);
if(found) return found;
return Block::sink_block;
}

std::string format(EdgeTypeEnum e) {
switch(e) {
case CALL: return "call";
Expand Down
4 changes: 3 additions & 1 deletion parseAPI/src/CFGFactory.C
Expand Up @@ -34,6 +34,7 @@
#include "CFG.h"
#include <iostream>

#include "ParseData.h"
using namespace std;
using namespace Dyninst;
using namespace Dyninst::ParseAPI;
Expand Down Expand Up @@ -73,7 +74,8 @@ std::string ParseAPI::format(EdgeTypeEnum e) {

Edge::Edge(Block *source, Block *target, EdgeTypeEnum type)
: _source(source),
_target(target),
index(source->obj()->parse_data()),
_target_off(target->low()),
_type(type,false) {

}
Expand Down
2 changes: 1 addition & 1 deletion parseAPI/src/CFGModifier.C
Expand Up @@ -103,7 +103,7 @@ bool CFGModifier::redirect(Edge *edge, Block *target) {
edge->_type._sink = 0;
}

edge->_target = target;
edge->_target_off = target->low();
target->addSource(edge);
target->obj()->_pcb->addEdge(target, edge, ParseCallback::source);
edge->src()->obj()->_pcb->modifyEdge(edge, target, ParseCallback::target);
Expand Down
8 changes: 8 additions & 0 deletions parseAPI/src/CodeObject.C
Expand Up @@ -115,35 +115,41 @@ CodeObject::findFuncByEntry(CodeRegion * cr, Address entry)
int
CodeObject::findFuncs(CodeRegion * cr, Address addr, set<Function*> & funcs)
{
assert(parser);
return parser->findFuncs(cr,addr,funcs);
}
int
CodeObject::findFuncs(CodeRegion * cr, Address start, Address end, set<Function*> & funcs)
{
assert(parser);
return parser->findFuncs(cr,start,end,funcs);
}

Block *
CodeObject::findBlockByEntry(CodeRegion * cr, Address addr)
{
assert(parser);
return parser->findBlockByEntry(cr, addr);
}

Block *
CodeObject::findNextBlock(CodeRegion * cr, Address addr)
{
assert(parser);
return parser->findNextBlock(cr, addr);
}

int
CodeObject::findBlocks(CodeRegion * cr, Address addr, set<Block*> & blocks)
{
assert(parser);
return parser->findBlocks(cr,addr,blocks);
}

// find without parsing.
int CodeObject::findCurrentBlocks(CodeRegion * cr, Address addr, set<Block*> & blocks)
{
assert(parser);
return parser->findCurrentBlocks(cr,addr,blocks);
}

Expand Down Expand Up @@ -397,3 +403,5 @@ Address CodeObject::getFreeAddr() const {
}
return hi;
}

ParseData *CodeObject::parse_data() { return parser->parse_data(); }
1 change: 0 additions & 1 deletion parseAPI/src/ParseData.C
Expand Up @@ -372,7 +372,6 @@ OverlappingParseData::record_block(CodeRegion *cr, Block *b)
rd = rmap[cr];

}
boost::lock_guard<Block> block_guard(*b);
boost::lock_guard<region_data> g(*rd);
rd->blocksByAddr[b->start()] = b;
rd->blocksByRange.insert(b);
Expand Down
5 changes: 2 additions & 3 deletions parseAPI/src/ParseData.h
Expand Up @@ -92,6 +92,7 @@ class ParseFrame : public boost::lockable_adapter<boost::recursive_mutex> {

void pushWork(ParseWorkElem * elem) {
boost::lock_guard<ParseFrame> g(*this);
parsing_printf("\t pushing work element for block %p, edge %p, target %p\n", elem->cur(), elem->edge(), elem->target());
worklist.push(elem);
}
ParseWorkElem * popWork() {
Expand Down Expand Up @@ -345,9 +346,7 @@ inline void StandardParseData::record_func(Function *f)
}
inline void StandardParseData::record_block(CodeRegion * /* cr */, Block *b)
{
boost::lock(b->lockable(), _rdata.lockable());
boost::lock_guard<Block> block_guard(*b, boost::adopt_lock);
boost::lock_guard<region_data> g(_rdata, boost::adopt_lock);
boost::lock_guard<region_data> g(_rdata);
_rdata.blocksByAddr[b->start()] = b;
_rdata.blocksByRange.insert(b);
}
Expand Down
34 changes: 20 additions & 14 deletions parseAPI/src/Parser.C
Expand Up @@ -77,7 +77,6 @@ Parser::Parser(CodeObject & obj, CFGFactory & fact, ParseCallbackManager & pcb)
_cfgfact(fact),
_pcb(pcb),
_parse_data(NULL),
_sink(NULL),
_parse_state(UNPARSED),
_in_parse(false),
_in_finalize(false)
Expand Down Expand Up @@ -105,7 +104,6 @@ Parser::Parser(CodeObject & obj, CFGFactory & fact, ParseCallbackManager & pcb)
sort(copy.begin(),copy.end(),less_cr());

// allocate a sink block -- region is arbitrary
_sink = _cfgfact._mksink(&_obj,copy[0]);

bool overlap = false;
CodeRegion * prev = copy[0], *cur = NULL;
Expand Down Expand Up @@ -1023,7 +1021,7 @@ Parser::parse_frame(ParseFrame & frame, bool recursive) {
// check for system call FT
Edge* edge = work->edge();
Block::Insns blockInsns;
boost::lock_guard<Block> src_guard(*edge->src());
// boost::lock_guard<Block> src_guard(*edge->src());
edge->src()->getInsns(blockInsns);
auto prev = blockInsns.rbegin();
InstructionAPI::InstructionPtr prevInsn = prev->second;
Expand Down Expand Up @@ -1403,12 +1401,12 @@ Parser::parse_frame(ParseFrame & frame, bool recursive) {
} else if ( ahPtr->isAbort() ) {
// 4. `abort-causing' instructions
end_block(cur,ahPtr);
//link(cur, _sink, DIRECT, true);
//link(cur, sink_block, DIRECT, true);
break;
} else if ( ahPtr->isInvalidInsn() ) {
// 4. Invalid or `abort-causing' instructions
end_block(cur,ahPtr);
link(cur, _sink, DIRECT, true);
link(cur, Block::sink_block, DIRECT, true);
break;
} else if ( ahPtr->isInterruptOrSyscall() ) {
// 5. Raising instructions
Expand Down Expand Up @@ -1450,7 +1448,7 @@ Parser::parse_frame(ParseFrame & frame, bool recursive) {
_pcb.foundWeirdInsns(func);
end_block(cur,ahPtr);
// allow invalid instructions to end up as a sink node.
link(cur, _sink, DIRECT, true);
link(cur, Block::sink_block, DIRECT, true);
break;
} else if (ahPtr->isNopJump()) {
// patch the jump to make it a nop, and re-set the
Expand Down Expand Up @@ -1491,7 +1489,7 @@ Parser::parse_frame(ParseFrame & frame, bool recursive) {

end_block(cur,ahPtr);
// We need to tag the block with a sink edge
link(cur, _sink, DIRECT, true);
link(cur, Block::sink_block, DIRECT, true);
break;
} else if (!cur->region()->contains(ahPtr->getNextAddr())) {
parsing_printf("[%s] next address %lx is outside [%lx,%lx)\n",
Expand All @@ -1500,7 +1498,7 @@ Parser::parse_frame(ParseFrame & frame, bool recursive) {
cur->region()->offset()+cur->region()->length());
end_block(cur,ahPtr);
// We need to tag the block with a sink edge
link(cur, _sink, DIRECT, true);
link(cur, Block::sink_block, DIRECT, true);
break;
}
ahPtr->advance();
Expand Down Expand Up @@ -1653,6 +1651,8 @@ Parser::add_edge(
EdgeTypeEnum et,
Edge * exist)
{
// adjust anything pointing to zero to force it to sink
if(dst == 0) { dst = -1; }
Block * split = NULL;
Block * ret = NULL;
Edge * newedge = NULL;
Expand Down Expand Up @@ -1913,7 +1913,7 @@ Parser::link(Block *src, Block *dst, EdgeTypeEnum et, bool sink)
Edge*
Parser::link_tempsink(Block *src, EdgeTypeEnum et)
{
Edge * e = factory()._mkedge(src,_sink,et);
Edge * e = factory()._mkedge(src,Block::sink_block,et);
e->_type._sink = true;
src->_trglist.push_back(e);
return e;
Expand All @@ -1922,23 +1922,29 @@ Parser::link_tempsink(Block *src, EdgeTypeEnum et)
void
Parser::relink(Edge * e, Block *src, Block *dst)
{
assert(e);
boost::lock_guard<ParseData> guard(*_parse_data);
bool addSrcAndDest = true;
if(src != e->src()) {
assert(e);
e->src()->removeTarget(e);
_pcb.removeEdge(e->src(), e, ParseCallback::target);
assert(e);
e->_source = src;
src->addTarget(e);
_pcb.addEdge(src, e, ParseCallback::target);
addSrcAndDest = false;
}
if(dst != e->trg()) {
if(e->trg() != _sink) {
e->trg()->removeSource(e);
if(dst != e->trg()) {
assert(e);
if(e->trg() != Block::sink_block) {
assert(e);
if(e->trg()) {
e->trg()->removeSource(e);
}
_pcb.removeEdge(e->trg(), e, ParseCallback::source);
addSrcAndDest = false;
}
e->_target = dst;
dst->addSource(e);
_pcb.addEdge(dst, e, ParseCallback::source);
if (addSrcAndDest) {
Expand All @@ -1949,7 +1955,7 @@ Parser::relink(Edge * e, Block *src, Block *dst)
}
}

e->_type._sink = (dst == _sink);
e->_type._sink = (dst == Block::sink_block);
}

ParseFrame::Status
Expand Down
1 change: 1 addition & 0 deletions parseAPI/src/Parser.h
Expand Up @@ -154,6 +154,7 @@ class Parser {
void init_frame(ParseFrame & frame);

void finalize(Function *f);
ParseData* parse_data() { return _parse_data; }

private:
void parse_vanilla();
Expand Down

0 comments on commit b00c212

Please sign in to comment.