Sharyathi Nagesh wrote:
Since I was not able to find a good documentation I was not able
to
validate the code design. If some one can review and provide me guidance
it will help me immensely.
Challenges are
a. Efficient way of accessing the function/subprogram DIE (Debug
Information Entry) in an executable that contains multiple Complier
Units (CU)
b. Is the sequence of dwarf API calls appropriate
I think you shouldn't be using <libdwarf.h>, but rather <libdw.h>.
In fact, you might want to look at libdwfl, which might be a better
match for what you do. I know it supports common core files directly,
but I don't how and if vmcore files differ from that, so you may end up
having to write some support code yourself. I don't know much about
this library though, so will stick with <libdw.h>.
Also, use <gelf.h>, it will let you handle 32bit as well as 64bit ELF
data structures transparently.
dwarf_begin_elf will give you Dwarf *dbg that you can work with further.
You can that use dwarf_nextcu to iterate CUs and dwarf_offdie to get
CU DIE of each CU:
Dwarf_Off cu_off = 0, next_off;
size_t header_size;
while (!dwarf_nextcu (dbg, cu_off, &next_off, &header_size,
NULL, NULL, NULL)) {
Dwarf_Die cudie;
if (!dwarf_offdie (dbg, cu_off + header_size, &cudie))
return 0;
/* per-CU processing here, for example: */
int each_fun (Dwarf_Die *die, void *spaces) {
Dwarf_Attribute attr;
if (dwarf_attr (die, DW_AT_name, &attr) != NULL)
printf ("%s%s\n", spaces,
dwarf_formstring (&attr)
?: "???");
return DWARF_CB_OK;
}
each_fun (&cudie, "");
dwarf_getfuncs (&cudie, each_fun, " ", 0);
cu_off = next_off;
}
The example above will list names of all CUs and for each of them give a
list of functions defined therein. each_fun is a callback, which I
abuse to also print out CU names. You would put your per-function
processing there and likely not call it for CU DIE itself.
c. Scalability of the application, especially architecture
dependency
The above should work pretty much everywhere.
2. Converting the address mentioned in DW_AT_location to actual
address
of the local variable/arguments. System tap function
literal_stmt_for_local() has an implementation for this, I am going
thorough this some help in this direction will help me immensly.
I don't know any deep secrets about this. dwarf_getlocation_addr looks
to me like the right function to call to get hands on stream of location
operands for given DIE. The address argument that it needs is, I think,
the instruction pointer (the location of the variable changes depending
on where in code you are; it can be a register here, stack over there,
etc.)
dwfl_module_return_value_location from libdwfl looks like an interesting
alternative to me.
You would still need to write evaluator for DW_AT_location. I think
some things in that are pretty easy, namely general arithmetic, but most
of the interesting stuff involves reading register values, and that's
pretty specific for your problem domain. That's actually something that
peeking in systemtap sources might help with.
3. Converting the address generated from DW_AT_location to actual
address in vmcore dump. I am assuming the address we get from the dwarf
tag will be a virtual address and that needs to be mapped to a location
at vmocre file. crash tool has a routine readmem(), I am currently
looking into it for probable solution.
That's something I can't help with at all.
As a sidenote, in your code you seem to be doing a lookup by name. If
you are trying to annotate a stack trace (which I don't know if you do),
I would think that you would do lookup by address. That is, given stack
trace of PCs that you have somehow obtained from the core file, call
dwarf_addrdie to get CU DIE that covers given PC, and then use that with
dwarf_getscopes to get "stack" of DIEs around that PC. Then find
closest function DIE in that stack, iterate its arguments, evaluate
their location expressions to find values, etc.
Hope that helps,
PM