|
From: Christian P. <tr...@ge...> - 2005-04-06 12:33:26
|
Hi,
I wonder how valgrind does this. Well, I already took a look into stacktrac=
e.c=20
of SVN trunk's repository - but (how wonder) this is very valgrind specific.
My goal is to generate my own stacktrace within my program, e.g. when I=20
receive a certain signal (SIGSEGFAULT) or, when a C++ exception is to be=20
instanciated (so the constructor could do this for a better error tracking).
Suppose we've a funktion like this:
std::vector<std::string> getStackTrace() {
std::vector<std::string> stacktrace;
// magic here
return stacktrace;
}
and any function, like this:
void foo() {
if (errorOccured)
printStacktrace("An error just happened", getStackTrace());
}
which would then print out the stack trace up to from top-of-stack (e.g.=20
main()) down to foo().
I'm obviousely *not* able to google for it, as I didn't find any good docs=
=20
about :(
All I know is, that other apps (like ut2004-bin) is doing the same.
I'd be really very very happy if someone could point out me to the right=20
direction here.
p.s.: my arch: amd64/linux and x86/linux.
Thanks in advance,
Christian Parpart.
=2D-=20
Netiquette: http://www.ietf.org/rfc/rfc1855.txt
14:26:13 up 14 days, 3:32, 0 users, load average: 0.05, 0.12, 0.14
|
|
From: Nicholas N. <nj...@cs...> - 2005-04-06 12:42:12
|
On Wed, 6 Apr 2005, Christian Parpart wrote: > I wonder how valgrind does this. Well, I already took a look into stacktrace.c > of SVN trunk's repository - but (how wonder) this is very valgrind specific. I don't think it's very Valgrind-specific. Basically you just need to find the return addresses on the stack, and use those addresses to look up debugging information (which you have to read separately) to find the function names. That's pretty much what the code in stacktrace.c does. > All I know is, that other apps (like ut2004-bin) is doing the same. Can you find source code for these other apps, for comparison? N |
|
From: Christian P. <tr...@ge...> - 2005-04-06 13:06:22
|
On Wednesday 06 April 2005 2:42 pm, Nicholas Nethercote wrote:
> On Wed, 6 Apr 2005, Christian Parpart wrote:
> > I wonder how valgrind does this. Well, I already took a look into
> > stacktrace.c of SVN trunk's repository - but (how wonder) this is very
> > valgrind specific.
>
> I don't think it's very Valgrind-specific. Basically you just need to
> find the return addresses on the stack, and use those addresses to look up
> debugging information (which you have to read separately) to find the
> function names. That's pretty much what the code in stacktrace.c does.
Of course, this is not valgrind-specific. BUT I know that valgrind is creat=
ing=20
stack traces on the fly as well. Except, that it doesn't to for itself but=
=20
for its guest process (the one to be observed).
In the kernel sources, I actually found, that they're using something like=
=20
this [arch/x86-64/kernel/traps.c]:
void dump_stack(void) { // ARCH independant
unsigned long dummy;
show_trace(&dummy);
}
void show_trace(unsigned long *stack) { // x86-64 dependant.
// ....
int i =3D 0;
while (((long)stack & (THREAD_SIZE - 1)) !=3D 0) {
unsigned long addr =3D *stack++;
if (__kernel_text_address(addr)) {
i +=3D printk_address(addr);
i +=3D printk(" ");
if (i > 50) {
printk("\n ");
i =3D 0;
}
}
}
printk("\n");
}
__kernel_text_address() returns true in case it got passed an address withi=
n=20
the kernel address space (or any module address space).
printk_address then prints the symbol address, module name and symbolname.
So, I guess I got it (not quite sure yet), but one question remains, how to=
=20
get the symbol names I want the addresses for.
Why do they (in the kernel) something like (((long)stack & (THREAD_SIZE -=20
1)) !=3D 0). How's this adoptable to a userspace process (generically).
demangling isn't a problem. Here I already got some source code (from gcc :=
=2DD)
> > All I know is, that other apps (like ut2004-bin) is doing the same.
>
> Can you find source code for these other apps, for comparison?
I'd be happy if. But at least ut2004-bin is binary-only (no sources).
=2D-=20
Netiquette: http://www.ietf.org/rfc/rfc1855.txt
14:45:35 up 14 days, 3:52, 0 users, load average: 0.13, 0.20, 0.22
|
|
From: Michael R. <val...@no...> - 2005-04-06 12:49:50
|
Hi. Christian Parpart wrote: > My goal is to generate my own stacktrace within my program, You should have a look at: http://www.gnu.org/software/libc/manual/html_node/Backtraces.html#Backtraces In a current project I have a function like this: void stack_print_trace(void) { int num_frames = 0; void *stack[64]; num_frames = backtrace(stack, 64); fprintf(stderr, "stack trace:\n"); backtrace_symbols_fd(stack, num_frames, 2); return; } which is called within the SIGSEGV handler. hth. Bye, Mike |
|
From: Christian P. <tr...@ge...> - 2005-04-06 13:16:18
|
On Wednesday 06 April 2005 2:49 pm, Michael Renzmann wrote: > Hi. > > Christian Parpart wrote: > > My goal is to generate my own stacktrace within my program, > > You should have a look at: > http://www.gnu.org/software/libc/manual/html_node/Backtraces.html#Backtra= ce >s That - obviousely - saves me alot of time :) Lets see how I can integrate this. Although, I'm very curious what the libc= =20 sources will tell me soon :) Regards, Christian Parpart. =2D-=20 Netiquette: http://www.ietf.org/rfc/rfc1855.txt 15:14:38 up 14 days, 4:21, 0 users, load average: 0.23, 0.17, 0.16 |
|
From: Christian P. <tr...@ge...> - 2005-04-06 15:52:25
|
On Wednesday 06 April 2005 3:16 pm, Christian Parpart wrote: > On Wednesday 06 April 2005 2:49 pm, Michael Renzmann wrote: > > Hi. > > > > Christian Parpart wrote: > > > My goal is to generate my own stacktrace within my program, > > > > You should have a look at: > > http://www.gnu.org/software/libc/manual/html_node/Backtraces.html#Backt= ra > >ce s > > That - obviousely - saves me alot of time :) > > Lets see how I can integrate this. Although, I'm very curious what the li= bc > sources will tell me soon :) #include <cxxabi.h> #include <execinfo.h> #define GNU_SOURCE #include <dlfcn.h> TStringArray getCallTrace(int skip =3D 0) { TStringArray result; const int BT_SIZE =3D 256; void *stack[BT_SIZE]; size_t size =3D backtrace(stack, BT_SIZE); Dl_info info; for (size_t i =3D skip; i < size; ++i) { if (dladdr(stack[i], &info) !=3D 0) { char buf[256]; size_t len =3D sizeof(buf); int status =3D 0; result.add(String::format("{0} {1} [0x{2:X}]", args(info.dli_fn= ame, abi::__cxa_demangle(info.dli_sname, buf, &len, &status), st= ack[i]))); } else result.add(String::format("0x{0:X}", args(stack[i]))); } return result; } Just to share my experiences - This function generates a backtrace using=20 the backtrace() function and reformats each calling function using=20 __cxa_demangle() (GNU C++ ABI function) and puts everything into a vector. I call this function in my exception constructor, so, that when I catch som= e,=20 I can do the following: catch (const TException& e) { // ... FServer->logger().debug("Call Trace:"); for (int i =3D 0, k =3D e.callTrace().size(); i < k; ++i) FServer->logger().debug(String::format("[{0}] {1}", args(i, e.callT= race()[i]))); } That's really nice. Thanks. Regards, Christian Parpart. =2D-=20 Netiquette: http://www.ietf.org/rfc/rfc1855.txt 17:44:24 up 14 days, 6:50, 0 users, load average: 0.52, 0.60, 0.41 |
>>>http://www.gnu.org/software/libc/manual/html_node/Backtraces.html#Backtraces > > size_t size = backtrace(stack, BT_SIZE); > > Dl_info info; > for (size_t i = skip; i < size; ++i) { > if (dladdr(stack[i], &info) != 0) { > char buf[256]; > size_t len = sizeof(buf); > int status = 0; > result.add(String::format("{0} {1} [0x{2:X}]", args(info.dli_fname, > abi::__cxa_demangle(info.dli_sname, buf, &len, &status), stack[i]))); > } else > result.add(String::format("0x{0:X}", args(stack[i]))); > } For cases where the in-memory symbol tables are not enough, but the on-disk symbol tables are better: [Redirect the output to a file, if necessary.] #include <stdio.h> #include <stdlib.h> #include <unistd.h> char str[100+4096]; char path[4096]; path[readlink("/proc/self/exe", path, -1+ sizeof(path))] = '\0'; sprintf(str, "echo 'bt\ndetach\nquit\n' | gdb -batch -x /dev/stdin %s %d\n", path, (int)getpid() ); system(str); -- John Reiser, jreiser@BitWagon.com |
|
From: Robert W. <rj...@du...> - 2005-04-06 18:12:19
|
As well as the glibc stuff, there's also VALGRIND_PRINTF_BACKTRACE, which only gets invoked when you're running under Valgrind and converts backtrace information to source file/line number information, if it can. Regards, Robert. --=20 Robert Walsh Amalgamated Durables, Inc. - "We don't make the things you buy." Email: rj...@du... |
|
From: <jp...@mu...> - 2005-04-07 17:18:28
|
Is there a way to get the full file/line info without valgrind running? I added the gnu backtrace functions to my exception, assert, and segv, but it's only of limited utility with just function names. -- Jason Weber On Wed, April 6, 2005 11:12 am, Robert Walsh said: > As well as the glibc stuff, there's also VALGRIND_PRINTF_BACKTRACE, > which only gets invoked when you're running under Valgrind and converts > backtrace information to source file/line number information, if it can. > > Regards, > Robert. > > -- > Robert Walsh > Amalgamated Durables, Inc. - "We don't make the things you buy." > Email: rj...@du... > |
|
From: Robert W. <rj...@du...> - 2005-04-07 17:32:23
|
> Is there a way to get the full file/line info without valgrind running? Yes, assuming you're using DWARF. Look at libdwarf - you can use the code in there to do a reverse map from symbol+offset to file+line. It's not super trivial to do, but it is doable: http://reality.sgi.com/davea Another similar package is the DWARF library that comes with elfutils. It's called libdw, and the advantages over libdwarf is that it comes with Fedora (and probably earlier releases) and already has a function to do this. The disadvantage with this is that I can't find a web page or documentation, so the only way I could learn how to use it was to download the spec file, extract the sources and read through the test cases it came with. libdw is OSL'd, if I remember correctly. libdwarf is LGPL'd. If you're using COFF or stabs, you're on your own - I don't know anything that can help you there. Regards, Robert. |
|
From: Avery P. <ape...@ni...> - 2005-04-07 18:09:07
|
On Thu, Apr 07, 2005 at 10:17:07AM -0700, jp...@mu... wrote: > Is there a way to get the full file/line info without valgrind running? > > I added the gnu backtrace functions to my exception, assert, and > segv, but it's only of limited utility with just function names. We have a gdb script that does a file/line lookup of the gnu backtrace output: http://open.nit.ca/wiki/?AnonymousCvs The file you want from CVS is wvstreams/utils/wvcrashread.sh. Have fun, Avery |
|
From: Crispin F. <val...@fl...> - 2005-04-07 19:30:24
|
On Thu, 2005-04-07 at 10:17 -0700, jp...@mu... wrote: > Is there a way to get the full file/line info without valgrind running? > > I added the gnu backtrace functions to my exception, assert, and > segv, but it's only of limited utility with just function names. You should be able to get the file and line number using the 'addr2line' program (in binutils). Crispin |
|
From: <jp...@mu...> - 2005-04-08 01:33:39
|
It seems to work on plain executables, but not on dynamic libraries. I'm not really sure how it would. Is this the expected behavior? -- Jason Weber On Thu, April 7, 2005 12:32 pm, Crispin Flowerday said: > On Thu, 2005-04-07 at 10:17 -0700, jp...@mu... wrote: >> Is there a way to get the full file/line info without valgrind running? >> >> I added the gnu backtrace functions to my exception, assert, and >> segv, but it's only of limited utility with just function names. > > You should be able to get the file and line number using the 'addr2line' > program (in binutils). > > Crispin > > > > ------------------------------------------------------- > SF email is sponsored by - The IT Product Guide > Read honest & candid reviews on hundreds of IT Products from real users. > Discover which products truly live up to the hype. Start reading now. > http://ads.osdn.com/?ad_id=6595&alloc_id=14396&op=click > _______________________________________________ > Valgrind-users mailing list > Val...@li... > https://lists.sourceforge.net/lists/listinfo/valgrind-users > |