help needed to call c++ method with dbx

i have a c++ method defined:

const CArgValue &operator[] (const string &name) const

and i would like to call it in dbx - i tried:

o print X.operator[]("name") - but the "char *" doesn't match "const string" - so i tried to create a string

o print X.operator[](string.operator new[]("p")) - but string was not in scope

o print X.operator[](std::string.operator new[]("p")) - but string was not in scope

whatis -t std::string shows that it is a typedef to: class std::basic_string<...>

o print X.operator[](std::basic_string.operator new[]("p")) - i get a huge list to select from - twice - i tried to pick the one that matched the typedef - but i get: syntax error. even if iget this to work - selecting from that long list twice is not feasible for debugging.

what is the correct way to call this function from dbx?

[885 byte] By [autohanda] at [2007-11-27 4:49:46]
# 1

i wrote a simple c++ function to convert a char* to a string - how do i load and call this function in dbx without actually calling it in the program being debugged? i tried to load the ".o" file - using "loadobject -load X.o" - but it is not mapped so i can't call it. this is also true if i embed it in another executable and load that one as well using loadobject.

autohanda at 2007-7-12 10:02:54 > top of Java-index,Development Tools,Solaris and Linux Development Tools...
# 2

You have to link the object file into a .so file and then use LD_PRELOAD

to put that shared library into your program when you run it.

# create test.so

(dbx) export LD_PRELOAD

(dbx) LD_PRELOAD=/home/user/test.so

(dbx) stop in main

(dbx) run

(dbx) whereis testfunc

(dbx) print testfunc()

ChrisQuenellea at 2007-7-12 10:02:54 > top of Java-index,Development Tools,Solaris and Linux Development Tools...
# 3

perfect - life is good again - any idea if i should have been able to do this with dbx directly?

btw - any idea how was i supposed to figure LD_PRELOAD without asking? and why didn't "loadobject -load" do the dlopen and map in the code - should i have known this wasn't going to work?

anyway - thanks for helping me - no way i would have moved on without help - thanks.

autohanda at 2007-7-12 10:02:54 > top of Java-index,Development Tools,Solaris and Linux Development Tools...
# 4

There are two things going on here:

Normally, dbx can only call functions that are somehow linked into

the program somehow. This part is described in the manual and

the help file.

The LD_PRELOAD trick is a way (on any UNIX-style system) to

add new code into a program *after* the program was already linked.

Are you accustomed to a different system that works differently?

Is this feature something that works automatically (or more easily)

in other systems? Tell me more if you can.

In theory the code you want to add might require special compiler

and linker options, so dbx can't really build the library automatically for you

in a reliable way.

You could also have simply included the 'debug' functions inside your

original program, and rebuilt it. The C++ compiler will sometimes

leave out bits of code that your program doesn't seem to be using.

Was that the problem here?

--chris

ChrisQuenellea at 2007-7-12 10:02:54 > top of Java-index,Development Tools,Solaris and Linux Development Tools...
# 5

i knew if i put it the code i could call it - but i wanted to do something that did not modify the existing code.

mostly my question was more along the lines of: if i scan the dbx manual, i didn't see any hint about LD_PRELOAD, so maybe my search strategy is off - and i could do better the next time - or maybe there is a section i should brush up on - that sort of thing.

actually this isn't working for me - i convert the char* to a string in my code - and pass the string to the c++ code - the c++ code tries to get the address of the string and can't - i guess it is in dbx's address space - my dbx call was:

X.operator[](asString("text"))

shoot, maybe i will have to recompile after all.

but, i still would have been messing around trying to use loadobject if you had not helped me - so still: thanks.

autohanda at 2007-7-12 10:02:54 > top of Java-index,Development Tools,Solaris and Linux Development Tools...
# 6

i finally got this to work in a routine with a string reference parameter. i had to return a string address in the conversion routine - e.g.

extern const string *asStringRef(const char *C) {return new string(C)}

load the conversion routine as described using LD_PRELOAD - and dereference the address in dbx - e.g.

(dbx) print X.operator[](*asStringRef("text"))

i had address/segmentation faults in operator[] doing anything else - including dereferencing in the conversion routine.

autohanda at 2007-7-12 10:02:54 > top of Java-index,Development Tools,Solaris and Linux Development Tools...
# 7

Dbx isn't really a C++ compiler. It's not very sophisticated when it comes to

creating temporary C++ objects for purposes of expression evaluation.

The safest way to create an object with one function call, and pass that

object to another function call is to create the object on the heap.

Another common technique is to create global variables to use

in place of temporaries. The global is not directly used by the program.

Example:

(dbx) get_string_object( & __global_string_obj , "test")

(dbx) print other_function ( & __global_string_obj )

This kinds of things fall into the category of "techniques" rather

than documented features of dbx. It's hard to figure out where they

would fit in the dbx manual.

ChrisQuenellea at 2007-7-12 10:02:54 > top of Java-index,Development Tools,Solaris and Linux Development Tools...
# 8

the dbx manual that i looked in had a section for c++ debugging - and it sure would have helped me out if there was an indication that not all methods in a class can be called using print. of course, the manual might have said exactly that, and in a hurry, i overlooked it. the manual could have also helped me with a mental model of which methods will fail: e.g. calling a method which creates a temporary will fail, and here is why.

thanks for that great global hint - i'll give it a try.

autohanda at 2007-7-12 10:02:54 > top of Java-index,Development Tools,Solaris and Linux Development Tools...
# 9
Could you do me a favor and post a short example that showsthe problem? I think it should have worked the first way you tried it,but it's hard to be sure without a test case.
ChrisQuenellea at 2007-7-12 10:02:54 > top of Java-index,Development Tools,Solaris and Linux Development Tools...
# 10
i can give it a try - which of these is the 1st way that should have worked?
autohanda at 2007-7-12 10:02:54 > top of Java-index,Development Tools,Solaris and Linux Development Tools...
# 11

I think the theory is that dbx is supposed to be able to do anything

the C++ compiler will accept as an expression. (But we don't

have a huge amount of testing).

If all of the three expressions in your first post here are accepted

inside a C++ program, then include all of them in the test case,

and I'll claim they are supposed to work in dbx.

ChrisQuenellea at 2007-7-12 10:02:54 > top of Java-index,Development Tools,Solaris and Linux Development Tools...
# 12

ok - wow - that is unexpected. i just unloaded version 11 and installed 12 because of some other errors, so give me a few days to get settled again - and i'll try to create a test case. i gave:

print X.operator[]("name")

a quick try and it failed with:

dbx: found 2 functions named "operator[]" in CLASS, but none of them match argument specification - so at least the 1st problem is still there - i'll get on a test case shortly.

thanks for getting back to me and trying to help out-

autohanda at 2007-7-12 10:02:54 > top of Java-index,Development Tools,Solaris and Linux Development Tools...
# 13

$more testLoad.cpp

#include <iostream>

#include <string>

using namespace std;

const void printString(const string &theString) {

cout << "theString=<" << theString << ">\n";

}

main(){}

$dbx testLoad

For information about new features see `help changes'

To remove this message, put `dbxenv suppress_startup_message 7.6' in your .dbxrcReading testLoad

Reading ld.so.1

Reading libCstd.so.1

Reading libCrun.so.1

Reading libm.so.2

Reading libc.so.1

Reading libCstd_isa.so.1

(dbx) stop in main

(2) stop in main

(dbx) run

Running: testLoad

(process id 12563)

Reading libc_psr.so.1

stopped in main at line 9 in file "testLoad.cpp"

9main(){}

(dbx) call printString("test")

dbx: found 2 functions named "printString" in the scope `testLoad`testLoad.cpp`main`, but none of them match argument specification

dbx: see `help scope' for details

dbx: Bad call statement

(dbx) call printString(string.new[]("test"))

dbx: "string" is not defined in the scope `testLoad`testLoad.cpp`main`

dbx: Bad call statement

(dbx) call printString(std::string.new[]("test"))

dbx: "string" is not defined in std

dbx: Bad call statement

(dbx) whatis string

dbx: "string" is not defined in the scope `testLoad`testLoad.cpp`main`

dbx: warning: `whatis' (without flags) will look for non-type names only. Use `help whatis' for details.

(dbx) whatis -t string

typedef class std::basic_string<char,std::char_traits><char>,std::allocator<ch ar> > string;

(dbx) call printString(std::basic_string.new[]("test"))

More than one identifier 'basic_string'.

Select one of the following:

0) Cancel

1) `libCstd.so.1`#__1cDstdMbasic_string4Cwn0ALchar_traits4Cw__n0AJallocator4Cw2 t6Mrkn0C__v_ [non -g, demangles to: std::basic_string<wchar_t,std::char_traits><wchar_t>,std::allocator <wchar_t> >::basic_string(const std::allocator<wchar_t>&)]

...

16) `libCstd.so.1`#__1cDstdMbasic_string4Ccn0ALchar_traits4Cc__n0AJallocator4Cc2 t6MIcrkn0C__v_[non -g, demangles to: std::basic_string<char,std::char_traits><char>,std::allocator<ch ar> >::basic_string(unsigned,char,const std::allocator<char>&)]

> 16

More than one identifier 'basic_string'.

Select one of the following:

0) Cancel

1) `libCstd.so.1`#__1cDstdMbasic_string4Cwn0ALchar_traits4Cw__n0AJallocator4Cw2 t6Mrkn0C__v_ [non -g, demangles to: std::basic_string<wchar_t,std::char_traits><wchar_t>,std::allocator <wchar_t> >::basic_string(const std::allocator<wchar_t>&)]

...

16) `libCstd.so.1`#__1cDstdMbasic_string4Ccn0ALchar_traits4Cc__n0AJallocator4Cc2 t6MIcrkn0C__v_[non -g, demangles to: std::basic_string<char,std::char_traits><char>,std::allocator<ch ar> >::basic_string(unsigned,char,const std::allocator<char>&)]

> 16

dbx: syntax error

dbx: Bad call statement

(dbx)

autohanda at 2007-7-12 10:02:54 > top of Java-index,Development Tools,Solaris and Linux Development Tools...
# 14

I filed this bug:

6572106 can't pass C++ string reference arguments in dbx

It should be visible on bugs.sun.com in a few days.

Here is my modified test case:

#include <iostream>

#include <string>

using namespace std;

const void printString(const string &theString) {

cout << "theString=<" << theString << ">\n";

}

main(){

printString("test");

printString(string("test"));

}

The dbx commands that I said should work are:

call printString("test");

call printString(string("test"));

The other dbx command examples you gave aren't valid

C++ exactly, so it's not fair to claim they are supposed to work

inside dbx. We'll see what the dbx/C++ guy says. Stay tuned.

ChrisQuenellea at 2007-7-12 10:02:54 > top of Java-index,Development Tools,Solaris and Linux Development Tools...
# 15
thanks buddy - for taking the time to help me out - i'm staying tuned.
autohanda at 2007-7-21 21:14:06 > top of Java-index,Development Tools,Solaris and Linux Development Tools...