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));
}
Related
I have tried working with the command line arguments in a small C++ program on Amiga 1200 (Workbench 3.1.4).
I have compiled with the use of bebbo’s cross-compiler g++ (m68k-amigaos-g++) (see https://github.com/bebbo/amiga-gcc) a simple CLI app that just outputs the arguments. While it works fine when compiled with 'normal' g++ in Windows, it failed in AmigaShell in Amiga Forever emulator and Amiga 1200 machine as well.
I have found on some forums that the preprocessor symbol __stdargs should be used, which as I understand instructs the compiler to handle the generated assembler as if the function was called with the parameters passed on stack and not with the use of registers. Is that correct understanding?
Is the normal that Amiga (and g++) by default use registers and it needs to be overridden for AmigaShell? I added that to __stdargs to the main() function. Anyway, that did not help.
Next, I have read, again on some forum, that -mcrt parameter has to be used when compiler output is linked. I have struggled to find the purpose do the parameter. It seems it specifies which standard C library (similar to glibc) to be linked? According the Google the following possible variants of the parameter (-mcrt=nix13, -mcrt=nix20, and mcrt=clib2) (see e.g. https://github.com/adtools/libnix).
The only one that works fine was nix20 (nix13 did not link and clib2 linked, but the program did not work on Amiga. Why in a first-place we need the standard C library?
I have used this with -mcrt: m68k-amigaos-g++ args.o -mcrt=nix20 -o args and it finally worked:
Can anybody describe to me as a newbie a bit more background details of all this?
Here is my test program:
#include <iostream>
using std::cout;
#if defined (__AMIGA__)
#define MAIN_FNC __stdargs
#else
#define MAIN_FNC
#endif
MAIN_FNC int main( int argc, char *argv[] )
{
cout << "Arguments count:" << argc << " \n";
for ( int i = 0; i < argc; i ++ )
cout << i << ". [" << argv[i] << "]\n";
return 0;
}
You don't need any MAIN_FNC, remove it. Also don't need to play with -mcrt=xxx. Just link with -noixemul option.
m68k-amigaos-g++ args.o -noixemul -o args
By default ixemul.library is used/linked (in short and very simply the ixemul.library emulate some unix behavior, see here). That cause your problem.
More info about -noixemul related to gcc & AmigaOS here:
GCC and ixemul.library
I was trying to compile my c++ program using the command g++ program.cpp -o program in order to create an executable with the same name as the actual program but used g++ program.cpp -o program.cpp and now my code looks like gibberish. Is there anyway to reverse it?
Reversing this process is semi-possible, but I do not recommend it. It is easier to just rewrite the program, as the compilation loses a ton of info. If you had compiled it with -g I believe it would be possible to recover the source (I have no idea though how one would do that).
If you have to reverse it you need to use a decompiler such as Cutter/Ghidra, but the result will need to be cleaned up. Example:
#inlcude <iostream>
#include <string>
int main(){
std::string a = "Hey";
a += '\n';
std::cout << a;
return 0;
}
Compiling with g++ test.cc -o test, and then decompiling with Ghidra, gets us:
undefined8 main(void){
long in_FS_OFFSET;
allocator<char> local_49;
basic_string<char,std::char_traits<char>,std::allocator<char>> local_48 [40];
long local_20;
local_20 = *(long *)(in_FS_OFFSET + 0x28);
std::allocator<char>::allocator();
/* try { // try from 001012a3 to 001012a7 has its CatchHandler # 001012fc */
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string
((char *)local_48,(allocator *)&DAT_00102005);
std::allocator<char>::~allocator(&local_49);
/* try { // try from 001012c2 to 001012d9 has its CatchHandler # 0010131a */
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator+=
(local_48,"\n");
std::operator<<((basic_ostream *)std::cout,(basic_string *)local_48);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string
(local_48);
if (local_20 != *(long *)(in_FS_OFFSET + 0x28)) {
/* WARNING: Subroutine does not return */
__stack_chk_fail();
}
return 0;
}
Pretty far gone, huh. The original program was only a few lines, but this seems a monstrosity. By knowing what to look for you can ignore things the compiler placed there to be safe like __stack_chk_fail(), and the anything that has in_FS_OFFSET or local_20 in it. But it is extremely laboursome in general. With some code it might be easier, but parts of it might be optimised away etc. so it is generally not recommended.
Note: I did not paste it here but at DAT_00102005, the string "Hey" is contained.
For example, suppose we have a string like:
string x = "for(int i = 0; i < 10; i++){cout << \"Hello World!\n\";}"
What is the simplest way to complete the following function definition:
void do_code(string x); /* given x that's valid c++ code, executes that code as if it were written inside of the function body */
The standard C++ libraries do not contain a C++ parser/compiler. This means that your only choice is to either find and link a C++ compiler library or to simply output your string as a file and launch the C++ compiler with a system call.
The first thing, linking to a C++ compiler, would actually be quite doable in something like Visual Studio for example, that does indeed have DLL libraries for compiling C++ and spitting out a new DLL that you could link at runtime.
The second thing, is pretty much what any IDE does. It saves your text-editor stuff into a C++ file, compile it by system-executing the compiler and run the output.
That said, there are many languages with build-in interpreter that would be more suitable for runtime code interpretation.
Not directly as you're asking for C++ to be simultaneously compiled and interpreted.
But there is LLVM, which is a compiler framework and API. That would allow you to take in this case a string containing valid C++, invoke the LLVM infrastructure and then afterwards use a LLVM-based just in time compiler as described at length here. Keep in mind you must also support the C++ library. You should also have some mechanism to map variables into your interpreted C++ and take data back out.
A big but worthy undertaking, seems like someone might have done something like this already, and maybe Cling is just that.
Use the Dynamic Linking Loader (POSIX only)
This has been tested in Linux and OSX.
#include<fstream>
#include<string>
#include<cstdlib>
#include<dlfcn.h>
void do_code( std::string x ) {
{ std::ofstream s("temp.cc");
s << "#include<iostream>\nextern \"C\" void f(){" << x << '}'; }
std::system( "g++ temp.cc -shared -fPIC -otemp.o" );
auto h = dlopen( "./temp.o", RTLD_LAZY );
reinterpret_cast< void(*)() >( dlsym( h, "f" ) )();
dlclose( h );
}
int main() {
std::string x = "for(int i = 0; i < 10; i++){std::cout << \"Hello World!\\n\";}";
do_code( x );
}
Try it online! You'll need to compile with the -ldl parameter to link libdl.a. Don't copy-paste this into production code as this has no error checking.
Works for me:
system("echo \"#include <iostream> \nint main() { for(int i = 0; i < 10; i++){std::cout << i << std::endl;} }\" >temp.cc; g++ -o temp temp.cc && ./temp");
Is there some "default function" to print an object like a string on the GDB when we are debugging C++ applications? Something like: toString();
Or my class have to implement something like that?
You could always have printed std::string (or anything else for that matter) using print command. However, struggling with C++ template container internals might not be pleasant. In the recent versions of toolchains (GDB + Python + Pretty Printers that are usually installed together as part of the development packages on most user-friendly Linux distros), those are automatically recognized and printed (pretty!). For example:
$ cat test.cpp
#include <string>
#include <iostream>
int main()
{
std::string s = "Hello, World!";
std::cout << s << std::endl;
}
$ g++ -Wall -ggdb -o test ./test.cpp
$ gdb ./test
(gdb) break main
Breakpoint 1 at 0x400ae5: file ./test.cpp, line 6.
(gdb) run
Starting program: /tmp/test
Breakpoint 1, main () at ./test.cpp:6
6 std::string s = "Hello, World!";
Missing separate debuginfos, use: debuginfo-install glibc-2.16-28.fc18.x86_64 libgcc-4.7.2-8.fc18.x86_64 libstdc++-4.7.2-8.fc18.x86_64
(gdb) next
7 std::cout << s << std::endl;
(gdb) p s
$1 = "Hello, World!"
(gdb)
As #111111 pointed out, check out http://sourceware.org/gdb/wiki/STLSupport for instructions on how to get this installed yourself.
You can call any member functions from Standard Library or your own data type during debug session. This is sometimes the easiest way to output object state in gdb. For std::string you could call it's c_str() member which returns const char*:
(gdb) p str.c_str()
$1 = "Hello, World!"
Though this will work only for debugging live process, but not for core dump debugging.
gdb has a built-in print command that you can call in gdb on any variable or expression to see its value. You should look at the gdb documentation for details. You can find the full manual here and a decent intro guide can be found here
Define operator<< and call it from GDB
C++ equivalent of Java's toString? was mentioned in the comments, and operator<< is the most common way of defining a to string method on a class.
This is likely the sanest approach because the resulting string method will be part of the codebase itself, and so:
it is less to stop compiling (one would hope!)
it is readily available without any GDB setup
it can be called from C++ itself when needed
Unfortunately I haven't found a completely sane way of calling operator<< from GDB, what a mess: calling operator<< in gdb
This has worked on my hello world test:
(gdb) call (void)operator<<(std::cerr, my_class)
MyClass: i = 0(gdb)
There is no newline at the end, but I can live with that.
main.cpp
#include <iostream>
struct MyClass {
int i;
MyClass() { i = 0; }
};
std::ostream& operator<<(std::ostream &oss, const MyClass &my_class) {
return oss << "MyClass: i = " << my_class.i;
}
int main() {
MyClass my_class;
std::cout << my_class << std::endl;
}
Compiled with:
g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o main.out main.cpp
Tested in GDB 8.1.0, Ubuntu 18.04.
I want to call a function from C++ library on linux. I have a shared object of that library.
I want to call method getAge() that return an int from ydmg library.
Following is the code that I have written:
testydmg.cpp
#include "ydmg/bd.h"
#include "yut/hash.h"
#include "dlfcn.h"
extern "C" int getAge();
class testydmg{
public:
testydmg::testydmg(const yutHash& user){
}
testydmg::testydmg(){
}
testydmg::~testydmg(){
}
int testydmg::getFunction(){
void *handle;
int (*voidfnc)();
handle = dlopen("ydmg.so",RTLD_LAZY);
if(handle == NULL){
printf("error in opening ydmg lib");
} else {
voidfnc = (int (*)())dlsym(handle, "getAge");
(*voidfnc)();
printf("class loaded");
}
ydmgBd obj;
obj.getAge();
printf("Inside getFunction()...");
dlclose(handle);
}
};
I compile and link the code as below:
gcc -fPIC -shared -l stdc++ -I/home/y/libexec64/jdk1.6.0/include -I/home/y/libexec64/jdk1.6.0/include/linux -I/home/y/include testydmg.cpp -o libTestYdmg.so libydmg.so
Then I check for the method in the new shared object i.e. libTestYdmg.so
nm -C libTestYdmg.so | egrep getAge
I get nothing by running the above command.
Does it mean that it did not get the method getAge() from the library.
Could you please correct where I am going wrong ?
You want to use ydmgDB::getAge() but you are asking to the library for getAge(). This is not correct, just simply create a ydmgDBobject and invoke it's method getAge() without loading the library that is linked with your compile command line.
You don't need to dlopen the library.
Besides, getAge is not really included in libTestYdmg.so. You must look for it in libydmg.so using:
nm -C libydmg.so | grep getAge
If you're interested in actually using dlopen in C++ code, take a look at the
C++ dlopen mini HOWTO, which includes example code and some possibly important
warnings.