This is the mail archive of the java@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: RFC: stack trace generation


Casey Marshall wrote:

What I'm trying now is making the file/line number lookup code do so
for the stack as a whole -- each `lookup' method in NameFinder would
receive the entire stack trace and an array of objects to store the
info it finds for each frame, skipping frames that have already been
filled in. Then I call each in a precedence order -- interpreted,
DWARF-2 info, dladdr, and finally (not implemented yet) addr2line.

This makes the DWARF-2 part much faster, since it can optimize out of
having to read things more than once. It also has room for inserting
other methods for finding debug info; it isn't "pluggable", but it
could be.


Perhaps the best thing to do would be to make Dwarf2NameFinder a class, and have it remember whatever information/state about each .so is necessary to speed up repeated lookups. This would work better than passing an entire stack trace to the NameFinder, because different types of NameFinder are required for different frames - eg interpreted frames, and the logic to determine which name finder to use doesn't belong in the NameFinder itself. I'd like to keep NameFinder's role simple.

What I do currently (not necessarily the best solution) is to instantiate a NameFinder once for every Throwable.printStackTrace() call. The NameFinder.lookup() method is then called once for each frame with the IP for that frame. The namefinder determines which binary contains the address, using dladdr(), and starts an addr2line instance for that binary if necessary. The addr2line instances are kept open until close() is called on the namefinder once the bottom of the stack is reached. This means that the repeated lookup() calls do not each cause a new addr2line instance to be started if there is one already running for that binary.

Caching some data about each .so is presumably much less of a problem than keeping around a huge (50MB+ !) addr2line instance, so we could probably just keep the namefinder instance around for the lifetime of the application, after the first printStackTrace() call? Perhaps we can keep the mmap'ed .debug_line sections open too - presumably they can be mapped read-only, so the overall effect on application memory usage shouldn't be too significant?

Bryce> I think reading the .debug_line info directly is definitely the
Bryce> right solution. My only concern is this: + * DWARF-2 reading by
Bryce> Casey Marshall <csm@gnu.org>. ELF info reading + * based on
Bryce> elf/sprof.c from glibc-2.3.2, written by Ulrich Drepper + * and
Bryce> Copyright (C) 1997-2002, 2003 Free Software Foundation, Inc.

Bryce> Are we allowed to use this ELF code? Do we need to get special
Bryce> permission from the FSF to use/relicense it?

Maybe, that was one of my open questions about this. The code I used
from glibc was very small -- basically a cluestick about how to mmap
the ELF headers, and how to find and inspect section names.

I could rewrite this part if need be, since I have a better grasp of
ELF than when I started this.


I think this may be necessary, unfortunately.

Regards

Bryce


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]