Hi all,
I'm still not able to get source line information for use with the new
Dyninst 9.0.x loop interface change for finding the head node of the
loop in order to give the users the start line number for the loop.
That simple dyninst interface was removed in 9.0.x.
I'm computing an address from the basic blocks in the loop and passing
that to the module class getSourceLines function:
bool getSourceLines( unsigned long addr,
std::vector<BPatch_statement> & lines )
I've tried passing the basic block starting address as the address for
the above call
Then I tried taking the module base address off the starting address and
tried that.
Those two address tries didn't produce any line info.
So, the big picture is:
BPatch_Vector<BPatch_module*>* modules = image.getModules();
BPatch_Vector<BPatch_function*> functions;
module->findFunctionByAddress(
(void*)((module_base + address).getValue()), functions,
false, false
);
BPatch_flowGraph* cfg = function->getCFG();
BPatch_Vector<BPatch_basicBlockLoop*> loops;
cfg->getLoops(loops);
for .... loop through all the loops
BPatch_basicBlockLoop* loop = loops[l];
std::vector<BPatch_basicBlock*> entries;
loop->getLoopEntries(entries);
for (bbe = entries.begin(); bbe != entries.end();
++bbe) {
unsigned long module_base =
(uint64_t)module->getBaseAddr();
unsigned long bbstartAddr =
(*bbe)->getStartAddress() - module_base;
bool linesFound = module->getSourceLines(
bbstartAddr, filesAndlines);
/* never find any lines */
This is the full function (below). Am I using the correct API calls to
get the line information? Does anyone have a suggestion?
Thanks,
Jim G
/** 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;
// 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 initial value to the
loop head
for (bbe = entries.begin(); bbe != entries.end();
++bbe) {
unsigned long module_base =
(uint64_t)module->getBaseAddr();
unsigned long bbstartAddr =
(*bbe)->getStartAddress() - module_base;
bool linesFound = module->getSourceLines(
bbstartAddr, filesAndlines);
if (linesFound) {
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;
}
On 09/11/2015 02:42 PM, Jim Galarowicz wrote:
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
...
...
_______________________________________________
Dyninst-api mailing list
Dyninst-api@cs.wisc.edu
https://lists.cs.wisc.edu/mailman/listinfo/dyninst-api