dlsym() returns 'symbol not found' - c++

I'm using OS X 10.7 (Lion), XCode 4.6.3 and libstdc++ as the C++ Standard Library.
I have this code in my main project:
shared.cpp:
extern "C" int sharedFun()
{
return 5;
}
And this in my side project, that needs to dynamically load the main one:
loader.cpp:
#include <dlfcn.h>
int main(int argc, const char * argv[])
{
void* mainApp = dlopen("mainApp.dylib", RTLD_LAZY);
char* error;
dlsym(mainApp, "sharedFun");
if ((error = dlerror()) != nullptr)
{
....
}
}
nm output:
nm -gU mainApp.dylib | grep sharedFun
002a3a10 - 01 0000 FUN _sharedFun
002a3a10 T _sharedFun
dlopen loads the library just fine, but dlsym returns "symbol not found".
Any ideas?
Thanks.

Related

Boost::stacktrace a specific thread

I want to debug an application where some threads seem to go into a deadlock situation in a production environment (I cannot debug, thus I need a meaningful log). I found boost::stacktrace::stacktrace(), but it dumps info for all threads.
Is it possible to limit the output to a specific thread?
If it is Linux specific you can use backtrace and backtrace_symbols to retrieve the backtrace for that specific thread.
I adapted this example from man backtrace to include a thread.
#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <thread>
#define BT_BUF_SIZE 100
void printbt(void)
{
int j, nptrs;
void *buffer[BT_BUF_SIZE];
char **strings;
nptrs = backtrace(buffer, BT_BUF_SIZE);
printf("backtrace() returned %d addresses\n", nptrs);
/* The call backtrace_symbols_fd(buffer, nptrs, STDOUT_FILENO)
would produce similar output to the following: */
strings = backtrace_symbols(buffer, nptrs);
if (strings == NULL) {
perror("backtrace_symbols");
exit(EXIT_FAILURE);
}
for (j = 0; j < nptrs; j++)
printf("%s\n", strings[j]);
free(strings);
}
static void myfunc2(void)
{
printbt();
}
void myfunc(int ncalls)
{
if (ncalls > 1)
myfunc(ncalls - 1);
else
myfunc2();
}
int main(int argc, char *argv[])
{
if (argc != 2) {
fprintf(stderr, "%s num-calls\n", argv[0]);
return 0;
}
std::thread th( myfunc, atoi(argv[1]) );
th.join();
}
You have to compile with -rdynamic to work
$ g++ -g3 -rdynamic test2.cpp -o /tmp/test2 -lpthread
Running it provides
$ /tmp/test2 3
backtrace() returned 13 addresses
/tmp/test2(_Z7printbtv+0x32) [0x55e2dbe5d37b]
/tmp/test2(+0x4451) [0x55e2dbe5d451]
/tmp/test2(_Z6myfunci+0x29) [0x55e2dbe5d47d]
/tmp/test2(_Z6myfunci+0x22) [0x55e2dbe5d476]
/tmp/test2(_Z6myfunci+0x22) [0x55e2dbe5d476]
/tmp/test2(_ZSt13__invoke_implIvPFviEJiEET_St14__invoke_otherOT0_DpOT1_+0x36) [0x55e2dbe5e0af]
/tmp/test2(_ZSt8__invokeIPFviEJiEENSt15__invoke_resultIT_JDpT0_EE4typeEOS3_DpOS4_+0x4a) [0x55e2dbe5dffd]
/tmp/test2(_ZNSt6thread8_InvokerISt5tupleIJPFviEiEEE9_M_invokeIJLm0ELm1EEEEvSt12_Index_tupleIJXspT_EEE+0x47) [0x55e2dbe5df4d]
/tmp/test2(_ZNSt6thread8_InvokerISt5tupleIJPFviEiEEEclEv+0x2b) [0x55e2dbe5deef]
/tmp/test2(_ZNSt6thread11_State_implINS_8_InvokerISt5tupleIJPFviEiEEEEE6_M_runEv+0x20) [0x55e2dbe5dec0]
/lib/x86_64-linux-gnu/libstdc++.so.6(+0xd6de4) [0x7f306312ede4]
/lib/x86_64-linux-gnu/libpthread.so.0(+0x8609) [0x7f3063242609]
/lib/x86_64-linux-gnu/libc.so.6(clone+0x43) [0x7f3062f6a133]
You can use __cxa_demangle to automatically demangle the symbols or you can simply use c++filt from gcc for that.
$ echo _ZSt13__invoke_implIvPFviEJiEET_St14__invoke_otherOT0_DpOT1_+0x36 | c++filt
void std::__invoke_impl<void, void (*)(int), int>(std::__invoke_other, void (*&&)(int), int&&)+0x36
$ echo _Z6myfunci+0x29 | c++filt
myfunc(int)+0x29
You can then go into gdb and look what line the offset 0x29 corresponds to inside the function myfunc(int)

Reset dlmopen namespace

I have a small program that loads 2 modules (X11, and my own):
#include <fcntl.h>
#include <dlfcn.h>
#include <stdlib.h>
#include <stdio.h>
int main(int c, char* argv[])
{
pid_t PID = c > 1 ? atoi(argv[1]) : -1;
if (PID <= 0)
{
fprintf(stderr, "Invalid PID\n");
return -1;
}
const char* path = "/home/brandon/Desktop/mylib.so";
void* x11 = dlmopen(LM_ID_NEWLM, "libX11.so.6", RTLD_NOW);
/*Lmid_t id = 0;
dlinfo(dl, RTLD_DI_LMID, &id);
dl = dlmopen(id, path, RTLD_LAZY);*/
void* dl = dlopen(path, RTLD_LAZY);
if (dl)
{
printf("Loading dll\n");
void (*ptrace_info)(pid_t pid) = (decltype(ptrace_info))dlsym(dl, "ptrace_info");
if (ptrace_info)
{
ptrace_info(PID);
}
dlclose(dl);
printf("Unloaded\n");
}
return 0;
}
If I use dlopen(path, RTLD_*) my module fails to ptrace the specified pid. However, if I uncommented the code above that uses dlmopen everything works fine (even if I create a new namespace, it works)..
If I do not dlmopen(.., X11, ..), it works fine. The only time it does NOT work is if I dlmopen anything and then try to dlopen something else.
Seeing as the only difference is the namespace, is there a way I can use dlopen after using dlmopen?

g++ Qt link issues

I'm having trouble (dynamically) linking with the Qt libraries whilst compiling a C++ project with g++ 4.5.3:
g++ -Wall XMLInOut.cpp tinyxml2.cpp -I"C:\Qt\4.7.1\include" -I"$ADTF_ADDONS\adtf-device-toolbox\include" -L"C:\Qt\4.7.1\lib" -lQtCore4 -DtUInt32=uint -o xmltest.exe
The output is the following :
/tmp/cclJqe9S.o:XMLInOut.cpp:(.text+0x1db): undefined reference to `QString::toUInt(bool*, int) const'
/tmp/cclJqe9S.o:XMLInOut.cpp:(.text$_ZN7QStringC1EPKc[QString::QString(char const*)]+0x15): undefined reference to QString::fromAscii_helper(char const*, int)
/usr/lib/gcc/i686-pc-cygwin/4.5.3/../../../../i686-pc-cygwin/bin/ld: /tmp/cclJqe9S.o: bad reloc address 0x15 in section `.text$_ZN7QStringC1EPKc[QString::QString(char const*)]'
If I understand correctly, the -l option will link against a dynamic library. in the Qt/libs I have the QtCore4.dll
What am I doing wrong?
Cheers
EDIT :
Although I believe the problem lies fully in the linkage, I will post my code :
#include "XMLInOut.h"
#include "tinyxml2.h"
#include <iostream>
#include "ModelToInterfaceWrapper.h"
//#define __DEBUG_OUT_
#ifdef __DEBUG_OUT_
#define out(A) cout<<A
#else
#define out(A)
#endif
using namespace std;
using namespace tinyxml2;
void XMLInOut::readAndParseFile(const char* pFilename){
XMLDocument doc;
doc.LoadFile( "config.xml" );
XMLElement *service = doc.FirstChildElement( "root" )->FirstChildElement( "Service" );
for( service; service; service=service->NextSiblingElement() )
{// Iterating Services
out(endl<<service->FirstAttribute()->Value());
QString serviceName;
tUInt32 signalValue ;
const XMLAttribute* description = ((const XMLElement *)service)->FindAttribute("description");
if((const XMLAttribute*)0 != description){
out(" ("<<description->Value()<<")");
serviceName = description->Value();
}else {
serviceName = service->FirstAttribute()->Value();
}
for(XMLElement *signal = service->FirstChildElement( "Signal" ); signal; signal=signal->NextSiblingElement() ){
out(endl<<" "<<signal->GetText());
signalValue = (new QString (signal->GetText()))->toUInt();
}
}
}
int main(int argc, char **argv) {
XMLInOut xmlinOut;
xmlinOut.readAndParseFile("config.xml");
}

Calling Lua function from string_t

I have some functions declared and initialized in .lua file. Then, when I receive signal, I read string_t variable with the name of function to call from file. The problem is that I don't know how to push function to stack by its name or call it.
For example:
test.lua
function iLoveVodka()
--some text
end
function iLoveFish()
--another text
end
C File:
string_t a = "iLoveVodka()"
How can i call function from C/C++ code iLoveVodka() only by having its name?
Here is some sample code that does two things:
Loads the file "test.lua" from the same directory.
Tries to call the function iLoveVodka(), if it can be found.
You should be able to build this easily enough:
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#include <stdio.h>
#include <stdlib.h>
int main( int argc, char *argv[])
{
lua_State *l = luaL_newstate ();
luaL_openlibs (l);
int error = luaL_dofile (l, "test.lua");
if (error)
{
printf( "Error loading test.lua: %s\n",luaL_checkstring (l, -1) );
exit(1);
}
/**
* Get the function and call it
*/
lua_getglobal(l, "iLoveVodka");
if ( lua_isnil(l,-1) )
{
printf("Failed to find global function iLoveVodka\n" );
exit(1);
}
lua_pcall(l,0,0,0);
/**
* Cleanup.
*/
lua_close (l);
return 0;
}
This can be compiled like this:
gcc -O -o test `pkg-config --libs --cflags lua5.1` test.c
Just define your iLoveVodka() function inside test.lua, and you should be OK.

boost test case from dll access violation

I want to start Boost test case from dll under Windows RT. I built test case as dll via the Visual Studio command prompt using the following comandline:
cl.exe /EHsc /D_USRDLL /D_WINDLL /LDd ~location\testcase.cpp ~library location\libboost_unit_test_framework-vc110-mt-sgd-1_53.lib /link /DLL /OUT:~output directory\testcase.dll
placed it into my application’s folder and set property "Content" to "true". After launching of my application I have the following error:
Unhadled exception at the 0x00B9AF16 in TestApp.exe: 0xC0000005: Access violation reading location 0x00000000
Top of the call stack is below:
> TestApp.exe!boost::unit_test::framework::get(unsigned long id, boost::unit_test::test_unit_type t) Line 388 C++
TestApp.exe!boost::unit_test::framework::get(unsigned long id) Line 73 C++
TestApp.exe!boost::unit_test::traverse_test_tree(unsigned long id, boost::unit_test::test_tree_visitor & V) Line 232 C++
TestApp.exe!boost::unit_test::traverse_test_tree(const boost::unit_test::test_suite & suite, boost::unit_test::test_tree_visitor & V) Line 207 C++
TestApp.exe!boost::unit_test::traverse_test_tree(unsigned long id, boost::unit_test::test_tree_visitor & V) Line 234 C++
TestApp.exe!boost::unit_test::framework::run(unsigned long id, bool continue_test) Line 403 C++
TestApp.exe!boost::unit_test::unit_test_main(boost::unit_test::test_suite * (int, char * *) * init_func, int argc, char * * argv) Line 185 C++
Here is the dll code (NOTE: If I place the same code directly into my source, it works fine):
void test_stat()
{
//some code there
}
extern "C" {
__declspec (dllexport) test_suite* init_unit_test_suite( int argc, char* argv[] )
{
test_suite *test = BOOST_TEST_SUITE("test name");
test->add(BOOST_TEST_CASE(&test_stat));
return test;
}
}
Code of the application for launching of the test case:
boost::unit_test::test_suite* main_global_test_suite;
test_suite* init_unit_test_suite( int argc, char* argv[] ) {
return NULL; }
test_suite* run_global_test_suite (int, char* []) {
return main_global_test_suite;
}
HINSTANCE hMyDll;
typedef test_suite* (*PFN_MyFunction)(int,const char*);
PFN_MyFunction pfnMyFunction;
test_suite* rPtr;
if((hMyDll=::LoadPackagedLibrary(L"testcase", 0))==NULL)
{
return;
}
pfnMyFunction=(PFN_MyFunction)GetProcAddress(hMyDll,"init_unit_test_suite");
if (pfnMyFunction != NULL)
{
//just create fake arguments for the boost::unit_test::unit_test_main function call
char* argv[1024];
argv[0] = "Text";
rPtr = pfnMyFunction(1, NULL);
main_global_test_suite = rPtr;
const int error =
boost::unit_test::unit_test_main(&run_global_test_suite, 1, argv );
}
else
{
//handling code
}
FreeLibrary(hMyDll);
Is there any ideas how to solve the problem?
Check what console_test_runner is doing. This is command line application (part of Boost.Test), which intended to do just that - load and execute test units implemented in shared library. Also please make sure you tell UTF that you want to build dll: define BOOST_TEST_DYN_LINK.