Hi all,
I'm trying to use the new loop API to find the head basic
block for loops in the applications we are doing performance
analysis on.
The old api had a function for that:
BPatch_basicBlock* head = loop->getLoopHead();
but now, we need to figure it out on our own.
I must be doing something wrong because I never get any source
lines returned from the
bool linesFound = module->getSourceLines(
bbstartAddr, filesAndlines);
call below. The new code is bracketed by the #if
DyninstAPI_VERSION_MAJOR >= 9 line below.
Does anyone see anything obvious that I'm doing wrong?
I checked for the presence of the dwarf information via
dwarfdump and there appears to be statement information
present.
This is the function from DyninstSymbols.cxx from our
OpenSpeedShop code, that I'm working on to get loop info:
/** Get the loops containing the specified
address. */
std::vector<LoopInfo> getLoopsAt(const Address&
address, BPatch_image& image)
{
std::vector<LoopInfo> retval;
// Iterate over each module within the specified image
BPatch_Vector<BPatch_module*>* modules =
image.getModules();
if (modules == NULL)
{
return retval;
}
for (unsigned int m = 0; m < modules->size();
++m)
{
BPatch_module* module = (*modules)[m];
if (module == NULL)
{
continue;
}
Address module_base =
(uint64_t)module->getBaseAddr();
// Find the function(s) containing the specified
address
BPatch_Vector<BPatch_function*> functions;
module->findFunctionByAddress(
(void*)((module_base + address).getValue()),
functions, false, false
);
for (unsigned int f = 0; f < functions.size();
++f)
{
BPatch_function* function = functions[f];
if (function == NULL)
{
continue;
}
// Find the loops containing the specified
address
BPatch_flowGraph* cfg = function->getCFG();
if (cfg == NULL)
{
continue;
}
BPatch_Vector<BPatch_basicBlockLoop*>
loops;
cfg->getLoops(loops);
for (unsigned int l = 0; l < loops.size();
++l)
{
BPatch_basicBlockLoop* loop = loops[l];
if ((loop == NULL) ||
!loop->containsAddressInclusive(
(module_base + address).getValue()
))
{
continue;
}
// A loop containing this address has been
found! Rejoice!
// And, of course, obtain the loop's head
address and basic
// block address ranges...
#if DyninstAPI_VERSION_MAJOR >= 9
// Need to use the new dyninst API for
finding the head of the loop
// One possibility - from wdh - might be
to call getLoopEntries() to
// get the basic block of each entry.
Then, for each of these, take
// the first address of that basic block
and query the source
// file/line containing that address.
Assuming that all line numbers are within
// a single source file, the minimum line
number is probably reasonably the
// loop definition. And the first address
in that basic block would be the one
// to use for “addr_head” in the Open|SS
database.
BPatch_basicBlock* head;
std::vector<BPatch_basicBlock*>
entries;
loop->getLoopEntries(entries);
std::cerr << " entries.size()="
<< entries.size() << std::endl;
// bbe: Loop through the basic block
entries
std::vector<BPatch_basicBlock*>::iterator bbe;
std::cerr << "entries.begin() !=
entries.end()=" << (entries.begin() != entries.end())
<< std::endl;
// filesAndlines: Return value file names
and line numbers from getSourceLines
std::vector<BPatch_statement >
filesAndlines ;
// Loop through the loops basic blocks,
get the starting address of the block
// Then use that address to get the
filename and line number for that address
// We are looking for the minimum line
number for the blocks in the loop to use
// as the loop head basic block.
head = entries[0]; // give an intial
value to the loop head
for (bbe = entries.begin(); bbe !=
entries.end(); ++bbe) {
unsigned long bbstartAddr =
(*bbe)->getStartAddress();
std::cerr << "module=" <<
module << " bbe=" << (*bbe) << "
bbstartAddr=" << std::hex << bbstartAddr
<< std::endl;
bool linesFound =
module->getSourceLines( bbstartAddr, filesAndlines);
std::cerr << "linesFound="
<< linesFound << std::endl;
std::cerr << "
filesAlines.size()=" << filesAndlines.size() <<
std::endl;
if (linesFound) {
std::cerr << "
filesAlines.size()=" << filesAndlines.size() <<
std::endl;
std::vector<BPatch_statement>::iterator lf_dx;
for (lf_dx = filesAndlines.begin();
lf_dx != filesAndlines.end(); ++lf_dx) {
std::cerr << "fileName="
<< (*lf_dx).fileName() << " lineNumber="
<< (*lf_dx).lineNumber() << std::endl;
}
} // linesFound
} // entries
#else
BPatch_basicBlock* head =
loop->getLoopHead();
#endif
if (head == NULL)
{
continue;
}
// Use the loop head basic block to create
the necessary loop information to return
LoopInfo
info(Address(head->getStartAddress()) - module_base);
BPatch_Vector<BPatch_basicBlock*>
blocks;
loop->getLoopBasicBlocks(blocks);
for (unsigned int i = 0; i <
blocks.size(); ++i)
{
BPatch_basicBlock* block = blocks[i];
if (block != NULL)
{
info.dm_ranges.push_back(
AddressRange(
Address(block->getStartAddress()) - module_base,
Address(block->getEndAddress()) - module_base
)
);
}
}
retval.push_back(info);
} // l
} // f
} // m
return retval;
}
I never get any lines returned from getSourceLines even though
I can see them in the dwarfdump output.
I attached the full dwarfdump output and the smg2000 run with
the debug output (snippet below).
[openss]: Converting raw data from /opt/shared/offline-oss
into temp file X.0.openss
Processing raw data for smg2000 ...
Processing processes and threads ...
Processing performance data ...
Processing symbols ...
Resolving symbols for
/home/jeg/DEMOS/demos/mpi/openmpi-1.8.2/smg2000/test/smg2000
entries.size()=1
entries.begin() != entries.end()=1
module=0x1bd6810 bbe=0x200f980 bbstartAddr=4020d3
linesFound=0
filesAlines.size()=0
entries.size()=1
entries.begin() != entries.end()=1
module=0x1bd6810 bbe=0x20111e0 bbstartAddr=40215f
linesFound=0
filesAlines.size()=0
entries.size()=1
entries.begin() != entries.end()=1
module=0x1bd6810 bbe=0x2012b70 bbstartAddr=4021f3
linesFound=0
filesAlines.size()=0
entries.size()=1
entries.begin() != entries.end()=1
module=0x1bd6810 bbe=0x20464a0 bbstartAddr=4036a9
linesFound=0
...
...