How to invoke math functions from dbx?
Is there an easy way to invoke math functions from dbx? If I try, for example, to call sqrt I get meaningless results:
(dbx) print sqrt(4.0)
sqrt(4) = 1074790400
(dbx)
This is from code which uses sqrt, so sqrt should be accessible. Does this need some kind of cast?
# 1
No, no cast is required. It looks like wrong sqrt is called or bug in dbx. I just tried it on Solaris 10 x64 machine and dbx 7.6:
(dbx:main) p sqrt(4.0)
sqrt(4) = 2.0
What is your configuration (OS, arch, dbx)?
# 2
And we need to make sure that sqrt() is actually what you expect it to be: please issue
whatis sqrt
which sqrt
in dbx and post output here.
# 3
This happens with dbx 7.5 on Solaris 10, Sparc (the dbx version from Studio 11).
Output of dbx -V:
Sun Dbx Debugger 7.5 Patch 121023-01 2006/02/09
Output of uname -a:
SunOS fiji 5.10 Generic_118833-36 sun4u sparc SUNW,Sun-Blade-1500
The output of whereis/whatis/which:
(dbx) whereis sqrt
function:`libm.so.2`sqrt
(dbx) whatis sqrt
sqrt (0x0):
(dbx) which sqrt
`libm.so.2`sqrt
(dbx)
# 4
This is not right:
(dbx) whatis sqrt
sqrt (0x0):
And I guess its the reason why call gives strange result: dbx doesn't know this function prototype and treats return value as int (presumably).
Ah, now I understand what's going on: apparently, you don't _use_ sqrt in your code, which resulted in sqrt prototype missing from a.out's debug info. I don't know if that can be helped, though other than making a fake call to sqrt in your program.
# 5
No, this can't be the reason; I invoke sqrt in a small test program on the very line where sqrt is used.
But I just found that it depends on the fact that this is C++ code (sorry, I forgot to mention this). If I compile the same small test program with cc, I can invoke sqrt and get correct results. With CC, i.e. as C++ code, this does not work, and the obvious idea to use std::sqrt does not work either:
(dbx) print std::sqrt(4.0)
dbx: "sqrt" is not defined as a function or procedure in std
dbx: see `help scope' for details
(dbx)
BTW: this seems to be the same with CC/dbx from Studio 12.
# 6
Yeah, it is definitely C++-specific.
As a workaround, try using __sqrtf and __sqrtl instead of sqrt; they both work:
(dbx:main) p __sqrtf(4.0)
__sqrtf(4) = 2.0
(dbx:main) p __sqrtl(4.0)
__sqrtl(4) = 2.00000000000000000000000000000000000e+00
Apparently, C and C++ compilers generate different debug info:
$ cc -g -lm a.c
$ dwarfdump a.out | grep sqrt
DW_AT_namesqrt
and
$ CC -g -lm a.c
$ dwarfdump a.out | grep sqrt
DW_AT_SUN_part_link_namei__sqrtf
DW_AT_name__sqrtf
DW_AT_SUN_part_link_namei__sqrtl
DW_AT_name__sqrtl
As you can see, when compiled with C++ compiler, sqrt is not mentioned in debug information and thus dbx can't see it.
The question is why...
This is probably because, when compiled with CC, math.h defines sqrt as 'extern "C++" inline ...', but this needs more investigation. I'll try to ask around.
# 7
Thanks for the investigation. I tried myself with dumpstabs (CC from Studio 11 uses stabs), and arrived at the same conclusion. Strangely, fabs and pow are present in the debug info, as well as these float and long double variants with leading "__", but sqrt is not. fabs and pow consequently can be used from dbx.
Out of curiosity: would it be possible to coerce dbx into calling sqrt, with sqrt being casted to a "function pointer with argument type double, returning double"? I tried, but I only manage to produce syntax errors:
(dbx) print ((double)(*)(double))sqrt)(4.0)
dbx: syntax error on "((double)(*)"
Does dbx not support this kind of feature, or did I somehow get the cast wrong?
This would be very useful for functions compiled without debug info.
# 8
> Out of curiosity: would it be possible to coerce dbx into calling sqrt, with sqrt being casted
> to a "function pointer with argument type double, returning double"? I tried, but I only
> manage to produce syntax errors:
I tried that, too, in the first place and I think function pointers are not supported by dbx. That's (partly) understandable -- dbx is not a compiler. But I'd suggest you file an RFE (Request For Enhancement) through bugs.sun.com since it would indeed be a useful feature.
Thanks for reporting this problem, by the way.
I managed to create smaller testcase that demonstrates problem with sqrt and will probably file a bug if no one convince me that this is expected behaviour. Test looks like this:
$ cat test.c
namespace MY
{
extern double sqrt ( double );
}
using MY::sqrt;
void foo()
{
double d = 0;
d = sqrt(4);
}
There are two key words: namespace and extern. If either of them is omitted, sqrt appears in debug info all right.
# 9
>
> I tried that, too, in the first place and I think
> function pointers are not supported by dbx. That's
> (partly) understandable -- dbx is not a compiler. But
> I'd suggest you file an RFE (Request For Enhancement)
> through bugs.sun.com since it would indeed be a
> useful feature.
>
For the record: I got the cast wrong (of course). Trying again:
(dbx) print (( double (*)(double))sqrt)(4.0)
((double (*)(double)) sqrt)(4) = &(noname) at 0x40100000
(dbx)
Now the syntax is accepted, but the output is useless.
gcc/gdb, on the other hand, apparently support this feature. I tried, just to try out my cast syntax, the same small example on a linux box and got, with the same expression (with gdb 6.1)
(gdb) p (( double (*)(double))sqrt)(4.0)
$1 = 2
(gdb)
Plain "p sqrt(4.0)" does not work there either:
(gdb) whatis sqrt
type = <text variable, no debug info>
(gdb) p sqrt(4.0)
$3 = 0
(gdb)
Is it really possible that such a time proven tool like dbx can't invoke a function by function pointer? If so, I will indeed file a RFE.
# 10
> If so, I will indeed file a RFE.
Please, do.
As to missing sqrt die (debug info entry), I'll file a bug in an hour or so and post its ID here.
# 11
Okay, bug 6580813 (external symbols declared in non-global namespace is not present in debug info) has been filed. It should become visible on bugs.sun.com in a day or so.
# 12
It turns out that this is a bit different than it looks: dbx is indeed able to invoke functions invoked in this way correctly; dbx just fails to print a sensible return value.
I tried with the following small function:
#include <stdio.h>
int printme(double x) {
printf("This is %g\n",x);
return (int)2*x;
}
Compiling this without -g, linking this with some hello world program and invoking the function from dbx gives
(dbx) print ((int (*)(double))printme)(4.0)
This is 4
((int (*)(double)) printme)(4) = &(noname)(double) at 0x8
(dbx)
The line "This is 4" clearly indicates that the function has been invoked correctly. Just the printed return value is meaningless. In this case, it is even possible to construct expressions with the return value:
(dbx) print 5 + ((int (*)(double))printme)(4.0)
This is 4
5+((int (*)(double)) printme)(4) = 13
i.e. dbx "knows" the correct return value 8. This does, however, apparently not work with return values of type double (i.e. in the original sqrt-Example).
I have therefore submitted a bug report with bugs.sun.com; I will post the BugID when (and if) this has been accepted.
# 13
The last item became Bug Id 6584396.