GDB: show arguments for function before calling it - gdb

In gdb is there a command that will show me the arguments for a function that I can call? I'd like to enter info functions to discover what functions are available, then discover what arguments one of those functions expects. (I'm looking for a solution for the most generic case, where I can't count on having the source code or an executable compiled with debug info.)
I realise that you can enter info args in gdb to view the args for the current function. My question is unrelated to that.
I also realise that you can enter disassemble <function> to view the assembly and thereby reverse-engineer the arguments. I hope that there's a faster, more readable alternative.

I'd like to enter info functions to discover what functions are available, then discover what arguments one of those functions expects.
That is exactly what info functions does, provided you have compiled code with debug info. For example:
// foo.c
int foo(int x, int y)
{
return x + y;
}
int main(int argc, char *argv[])
{
return foo(1, -1);
}
Compile with gcc -g foo.c and:
(gdb) info functions
File foo.c:
1: int foo(int, int);
6: int main(int, char **);
...
Without debug info, GDB can't tell you anything about C functions -- it would have to disassemble the target function and reverse-engineer the arguments, and it's not that smart.
For C++, it can do a little bit better: after g++ foo.c:
0x0000000000001125 foo(int, int)
0x0000000000001139 main
Here main has extern "C" linkage, so its arguments aren't mangled. But foo() has C++ linkage, so the argument types can be deduced from the mangled name even without the debug info.

Related

GDB doesn't list member functions or namespace functions in GHS compiled ELF

I'm attempting to use GDB to debug a PowerPC ELF image compiled by the Green Hills GHS compiler from C++ source. The GHS MULTI debugger uses a proprietary debugging format, but the compiler provides a -dwarf2 option to produce native DWARF-2 debugging information as well. GDB is able to read at least some information from the DWARF-2, and can do things like map line numbers to addresses and find the addresses of symbols, but many things such printing local variables in member functions do not work.
I compiled this very simple program with g++ targeting x86 and GHS targeting PowerPC to compare the two. The -dwarf2 and -G flags were set in the top level .gpj for GHS to produce DWARF-2 debug information. I did a readelf --debug-dump and confirmed that GHS did generate what looks like reasonably correct DWARF-2.
class ClassA {
public:
int Method(bool arg) {
int local_1 = arg * 2;
member_var_ = local_1;
return local_1;
}
int member_var_;
};
int FuncA(int arg) {
int local_2 = arg * 2;
return local_2;
}
double global_a = 1;
namespace NamespaceA {
int FuncB(int arg) {
int local_3 = arg * 2;
return local_3;
}
}
int main(int argc, char *argv[]) {
ClassA a;
return a.Method(true);
}
GDB is able to list all the functions from the g++ compiled ELF:
gdb hello
...
Reading symbols from hello...done.
(gdb) info func
All defined functions:
File hello.cc:
int ClassA::Method(bool);
int FuncA(int);
int NamespaceA::FuncB(int);
int main(int, char**);
GDB does not list the member function or the function declared inside a namespace from the GHS compiled ELF:
gdb hello
...
Reading symbols from hello...done.
(gdb) info func
All defined functions:
File src/hello.cc:
int FuncA(int);
int main(int, char**);
Non-debugging symbols:
...
Is there an incompatibility between GHS generated DWARF-2 and GDB?
For namespaces support you need at least DWARF3 format. It looks like DWARF2 is unable to represent C++ namespaces because it was completed before C++ namespaces were even considered, see DWARF3 features:
3 Major New Features
3.1 C++ , including Namespaces
DWARF2 was completed before the C++ Standard and before C++ namespaces were even considered. DWARF3
provides a complete set of features using DW TAG namespace, DW TAG
imported declaration, DW AT import, and DW AT extension that enables
an implementation to represent the visible namespaces correctly in
every function. Implementations may choose to emit a single namespace
declaration showing the complete namespace at the end of the
compilation unit as this is simpler, though it loses some of the
details of some uses of C++ Namespaces.

Redirecting system() function call using LD_PRELOAD

I want to replace the calls to system() function made by my program using LD_PRELOAD.
So I created the following wrapper functions in a shared library for testing.
// syshook.c
int system(const char * command)
{
printf("system() called for %s ************************************\n", command);
return 55;
}
char * getenv (const char* name)
{
printf("my getenv() *********************");
return 0;
}
And compiled and linked to a shared object libsyshook.so with gcc.
gcc -Wall -fPIC -c *.c
gcc -shared -Wl,-soname,libsyshook.so -o libsyshook.so.1.0
ln -s libsyshook.so libsyshook.so.1.0
However, when I run the program with with LD_PRELOAD as shown below, my wrapper function for system() is not called, but the wrapper for getenv() called.
LD_PRELOAD="libsyshook.so" myprog
When I attach the debugger, I can see that system() call, calls the implementation in libpthread.so. So why is redirecting system() not working. I don't think there is any limitation on that ??
Edit:
My test program compiled to myprog above looks like this. Comments indicate my observations.
void TestClass::testMethod()
{
string cmdLine = "date";
if (!mainWin) cmdLine = "time";
int retFromSys = system(cmdLine.c_str()); // goes into libpthread when stepped in.
cout << "return from system " << retFromSys << endl; // prints 0, not 55
getenv("DEBUG_SYS"); // Wrapper function called for this. Prints "my getenv ****** ..."
The most usual case of bad linking with LD_PRELOAD is when GCC replace your function by another one, when he think it can make your code faster to execute.
For instance, if GCC read this line in your code :
printf("%d", strlen("toto"));
It will replace with this line before compiling it :
puts("4");
Because it knows the printf and strlen functions, and think the output would be the same with puts function.
In this example, if you made your own printf or strlen function in a library loaded with LD_PRELOAD, your function won't be called after compilation, because GCC would have replaced function calls.
I think your problem is for the same reason. system is a very heavy function, and GCC may replaced your function call by another. For instance, if you tried :
system("ls");
GCC might replaced your line by :
execlp("ls", "ls");
That would do the same, but in less heavy. It couldn't know that you wanted to use your own system function. Try to disassemble your code to check if this is the problem.
As solution, I suggest you to try to call system with a more "random" parameter, to make GCC think it should not try to replace it. Maybe something like :
int main(int argc, char** argv)
{
char* line = NULL;
// Useless condition to make GCC think the parameter is variable
if (argc == 1)
line = "ls";
return (system(line));
}

int main(void) giving error

Hello programming world.
I am currently doing my first programming course at university and our instructor said the function
int main (); //without the curly braces// is valid.
I may have misheard him/misinterpreted him, as when I try and run a console with that, it gives an error. But when I do int main() {}; it runs fine.
So:
1. Are the curly braces needed regardless of the content in the body?
How did the function run without the return 0.
Using this, what is the shortest possible int main / void main function possible?
as requested, here is the error:
Undefined symbols for architecture x86_64:
"_main", referenced from:
implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Thank you so much :)
In C++, there are two correct definitions for main:
int main() {
// ...
}
and
int main(int argc, char *argv[]) {
// ...
}
or equivalent. (Other implementation-defined forms are possible, but we can ignore those. And the return type is always int, at least for hosted implementations; void main() is wrong.)
The braces { and } are part of the syntax of a function definition; they're not optional.
You can provide a declaration for main, such as
int main();
but there's no real point in doing so. That's a declaration, not a definition -- and you still need to have a definition somewhere.
A return 0; at the end is not required. This is a special case that applies only to main, not to other functions: if execution reaches the closing }, it does an implicit return 0;.
The shortest legal program would probably be:
int main(){}
Thats the difference between a function definition and declaration (see What is the difference between a definition and a declaration?
Basically int main(); is a prototype telling the compiler that you will have a function called main, which returns an int, but you do not implement it yet.
the int main() {} is the implementation of the function, thus the curly braces, giving it a function body and full implementation.
I'd like to clarify a few things.
int main();
is a function declaration, i.e. it lets other functions / classes know about it.
However, it does not define main, meaning it says nothing about what main actually does.
Since every C++ program must define main, as it is run first, your compiler will definitely give a compile error.
By writing
int main() {}
You are defining main by specifying that main does nothing, so it will run.
Finally, C++ compilers will implicitly add a return 0; statement if you do not return anything, as it is an indicator to the operating system that the program ran successfully.
For more information, see https://stackoverflow.com/a/204483/2512775 on what main should return.
Your error code means that you have not declared the main() function properly. What you should do is add the curly braces to signify the block of code that your application will run in.
Although the compiler will add a return statement if it isn't given one, just add one to make sure.

Assembly Function calling x64 VC++

So I am writing a wrapper for main and still provide a main like functionality, so user can define int main() or int main(argc, argv) and both works fine. I am able to do that for some compilers with inline assembly with pushing argc & argv onto stack before calling the user's main. However for x64 VC++, there is no inline assembly, so any suggestions on how I can achieve this?
Thanks!
I see two obvious choices: either write your code in assembly language, contained in an assembly language file, or else write your code in C++ without any inline assembly:
void my_entry_point() {
int argc = foo();
int argv = bar();
int ret = main(argc, argv);
exit_to_os(ret);
}

VC++: non-global old-style function declarations?

In Visual Studio 2003 using pure C, old-style function
declarations do not show as global member
i.e. void func(blah) int blah;{...}
This shows as a global member in the members dropdown:
void func(int blah)
{
...
}
This compiles, but old-style does not appear in the global
members dropdown:
void func(blah)
int blah;
{
...
}
I am trying to use the new 'Calling Graph' functionality to
analyse code, but as most of our legacy code uses the
old-style function parameters, those functions are not
recognized are not shown as Global Members, and therefore do
not appear in the 'Calling Graph'.
Is there any way to let the "call graph" analysis process
old-style function declarations correctly?
Maybe you want to consider to just change the old style function signatures. There shouldn't be any issues with that.
EDIT:
For an automatic conversion of your source files from old style syntax to ANSI-C style, take a look at the cproto tool. Maybe that could save you some time if you decide to go that direction.
This is an excerpt from the docs:
-f n
Set the style of generated function prototypes where n is a
number from 0 to 3. For example,
consider the function definition
main (argc, argv)
int argc;
char *argv[];
{
}
If the value is 0, then no prototypes are generated. When set to
1, the output is:
int main(/*int argc, char *argv[]*/);
For a value of 2, the output has the form:
int main(int /*argc*/, char */*argv*/[]);
The default value is 3. It produces the full function prototype:
int main(int argc, char *argv[]);
I'm not sure but maybe the engine uses regexs to trace routine signatures and the old C style isn't implemented.