Libicu, undefined reference while compiling - linux

I'm trying to use the lib icu in my shared library.
So i generate my .so who use libicu functions, this parts works well.
Then i try to compile my main program, using the shared library that i created before. But i get the following error:
release//libstring.so: undefined reference to `u_errorName_53'
release//libstring.so: undefined reference to `ucnv_toUnicode_53'
release//libstring.so: undefined reference to `ucnv_close_53'
release//libstring.so: undefined reference to `ucnv_fromUChars_53'
release//libstring.so: undefined reference to `udat_open_53'
release//libstring.so: undefined reference to `udat_parse_53'
release//libstring.so: undefined reference to `udat_format_53'
release//libstring.so: undefined reference to `ucnv_toUChars_53'
release//libstring.so: undefined reference to `ucnv_open_53'
release//libstring.so: undefined reference to `udat_close_53'
I have installed the libicu with this help.
I compile my shared library with -licuuc, as well as my main program compile only with -l:libstring.so and -licuuc.
When i do ldd libstring.so, i don't have the .so of the libicu on the list of dependencies.
The problem probably come from this.
Thx
EDIT: I have create a little test:
icu.h:
#pragma once
#include <iostream>
#include <string>
#include <unicode/ucnv.h>
class c_icu
{
private:
void * p_priv;
public:
c_icu();
void open(const wchar_t *name);
void to_local(std::wstring &, std::wstring &);
void from_local(std::wstring &, std::wstring &);
void close(void);
~c_icu();
};
icu.cpp:
#include "icu.h"
c_icu::c_icu()
{
p_priv = NULL;
}
c_icu::~c_icu()
{
if (p_priv)
close();
}
void c_icu::open(const wchar_t *name)
{
UErrorCode status = U_ZERO_ERROR;
char conv_name[256];
if (wcstombs(conv_name, name, 256) == (size_t)-1)
{
std::cout << "ERROR: wcstombs failed" << std::endl;
exit(0);
}
if ((p_priv = (UConverter *)ucnv_open(conv_name, &status)) == NULL)
{
std::cout << "ERROR: ucnv_open failed" << std::endl;
exit(0);
}
}
void c_icu::to_local(std::wstring &src, std::wstring &dst)
{
UErrorCode status = U_ZERO_ERROR;
int32_t len;
len = ucnv_toUChars((UConverter *)p_priv, (UChar *)NULL, 0, (const char *)src.c_str(), src.size(), &status);
if (status == U_BUFFER_OVERFLOW_ERROR)
{
status = U_ZERO_ERROR;
dst.resize(len);
len = ucnv_toUChars((UConverter *)p_priv, (UChar *)dst.c_str(), dst.size(), (const char *)src.c_str(), src.size(), &status);
if (U_FAILURE(status))
{
std::cout << "ERROR: to_local failed" << std::endl;
exit(0);
}
}
}
void c_icu::from_local(std::wstring &src, std::wstring &dst)
{
UErrorCode status = U_ZERO_ERROR;
int32_t len;
len = ucnv_fromUChars((UConverter *)p_priv, (char *)NULL, 0, (const UChar *)src.c_str(), src.size(), &status);
if (status == U_BUFFER_OVERFLOW_ERROR)
{
status = U_ZERO_ERROR;
dst.reserve(len);
len = ucnv_fromUChars((UConverter *)p_priv, (char *)dst.c_str(), dst.size(), (const UChar *)src.c_str(), -1, &status);
}
}
void c_icu::close(void)
{
ucnv_close((UConverter *)p_priv);
p_priv = NULL;
}
test.cpp:
#include "icu.h"
int main(void)
{
c_icu converter;
std::wstring src = L"";
std::wstring dst;
const wchar_t add[11] = L"Just a test";
const wchar_t *unicode = L"koi8-r";
for (unsigned int i = 0; i < 1000; i++)
src.append(add, 11);
converter.open(unicode);
converter.from_local(src, dst);
converter.close();
}
Makefile:
NAME= test
LIB_NAME= libicutest.so
FLAGS= -W -Wall -Wextra
all: lib $(NAME)
$(NAME):
#echo "Main programm compiling ..."
g++ -c test.cpp -o test.o $(FLAGS)
g++ -o $(NAME) test.o -Wl,-rpath,'$$ORIGIN/' -licui18n -L. -licutest
#echo "Main programm compiled"
lib:
#echo "Lib Compiling ..."
g++ -std=gnu++11 -c -fPIC icu.cpp -o icu.o $(FLAGS)
g++ -shared -Wl,-soname,$(LIB_NAME) -o $(LIB_NAME) icu.o -licui18n
#echo "Lib Compiled"
Note: even with -licuuc instead of -licui18n i got the same error.
Output:
$> make
Lib Compiling ...
g++ -std=gnu++11 -c -fPIC icu.cpp -o icu.o -W -Wall -Wextra
g++ -shared -Wl,-soname,libicutest.so -o libicutest.so icu.o -licui18n
Lib Compiled
Main programm compiling ...
g++ -c test.cpp -o test.o -W -Wall -Wextra
g++ -o test test.o -Wl,-rpath,'$ORIGIN/' -licui18n -L. -licutest
./libicutest.so: undefined reference to `ucnv_close_53'
./libicutest.so: undefined reference to `ucnv_fromUChars_53'
./libicutest.so: undefined reference to `ucnv_toUChars_53'
./libicutest.so: undefined reference to `ucnv_open_53'
collect2: error: ld returned 1 exit status
make: *** [test] Error 1
If i do ldd on my shared library:
$> ldd libicutest.so
linux-vdso.so.1 => (0x00007ffd5eb7f000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f092b5e6000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f092b221000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f092af1a000)
/lib64/ld-linux-x86-64.so.2 (0x00007f092bb00000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f092ad04000)
EDIT2:
Ok, seems that the problem is easier to solve than expected. My program need function in icu_53, but i got icu_48 installed on my computer dunno why.
$> locate libicu
/usr/lib/x86_64-linux-gnu/libicudata.so.48
/usr/lib/x86_64-linux-gnu/libicudata.so.48.1.1
/usr/lib/x86_64-linux-gnu/libicui18n.so.48
/usr/lib/x86_64-linux-gnu/libicui18n.so.48.1.1
/usr/lib/x86_64-linux-gnu/libicuio.so.48
/usr/lib/x86_64-linux-gnu/libicuio.so.48.1.1
/usr/lib/x86_64-linux-gnu/libicule.so.48
/usr/lib/x86_64-linux-gnu/libicule.so.48.1.1
/usr/lib/x86_64-linux-gnu/libiculx.so.48
/usr/lib/x86_64-linux-gnu/libiculx.so.48.1.1
/usr/lib/x86_64-linux-gnu/libicutest.so.48
/usr/lib/x86_64-linux-gnu/libicutest.so.48.1.1
/usr/lib/x86_64-linux-gnu/libicutu.so.48
/usr/lib/x86_64-linux-gnu/libicutu.so.48.1.1
/usr/lib/x86_64-linux-gnu/libicuuc.so.48
/usr/lib/x86_64-linux-gnu/libicuuc.so.48.1.1
Does anyone know how to upgrade the version from icu_48 to icu_53 at least ?

Seems 'udat_parse_53' is located inside libicui18n.so.53 library. Try to compile your project with '-licui18n' option.

Related

G++: Undefined reference to class::method

I am trying to create an interface for my program using SDL2. The problem is that when I include my .h file, the compiler can't find the .cpp even tough I linked everything. None of the methods I found on the internet work and when compiling in visual studio, the code works perfectly fine. What is more strange is that when I try to make my classes inherit from others, I get the same error from the parent class. I am also using the latest version of Ubuntu. Furthermore, I installed all the libraries required for SDL2.
This is the error:
/usr/bin/ld: /tmp/ccWHZ70h.o: in function `interface::init(char const*)':
interface.cpp:(.text+0xd6): undefined reference to `interface::renderer'
/usr/bin/ld: interface.cpp:(.text+0xdd): undefined reference to `interface::renderer'
/usr/bin/ld: interface.cpp:(.text+0x106): undefined reference to `interface::renderer'
/usr/bin/ld: /tmp/ccWHZ70h.o: in function `interface::LoadTexture(char const*)':
interface.cpp:(.text+0x1bd): undefined reference to `interface::renderer'
/usr/bin/ld: /tmp/ccWHZ70h.o: in function `interface::DrawTexture(SDL_Texture*, SDL_Rect, SDL_Rect)':
interface.cpp:(.text+0x20d): undefined reference to `interface::renderer'
collect2: error: ld returned 1 exit status
make: *** [MakeFile:2: all] Error 1
I compile using make -f on this file:
all:
g++ mainClient.cpp client.cpp interface.cpp -lSDL2main -lSDL2 -lSDL2_image -lSDL2_mixer -lSDL2_ttf -o client.exe
clean:
rm -f *~client-exe
The code works perfectly fine without the interface class.
This is the inteface.h code:
#pragma once
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_mixer.h>
#include <SDL2/SDL_ttf.h>
#include <SDL2/SDL_render.h>
#include <iostream>
class interface
{
private:
int width, height;
SDL_Window* window;
bool state;
static SDL_Renderer* renderer;
public:
interface(int w,int h);
~interface(){};
int init(const char* titlu);
void loop();
void render();
SDL_Texture* LoadTexture(const char* filename);
void DrawTexture(SDL_Texture* tex, SDL_Rect imgRect, SDL_Rect destRect);
};
And this is the interface.cpp code:
#include "interface.h"
interface::interface(int w, int h)
{
width = w;
height = h;
state = true;
}
int interface::init(const char* title)
{
if(SDL_Init(SDL_INIT_EVERYTHING) == 0)
{
window = SDL_CreateWindow(title,SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,width,height,0);
if(window == NULL)
{
std::cout<<"Eroare la crearea ferestrei!\n";
state = false;
}
renderer = SDL_CreateRenderer(window,-1,0);
if(renderer == NULL)
{
std::cout<<"Eroare la crearea rendererului!\n";
state = false;
}
else
{
SDL_SetRenderDrawColor(renderer,255,255,255,255);
}
}
else
{
std::cout<<"ERROR AT INIT EVERYTHING\n";
state = false;
}
}
SDL_Texture* interface::LoadTexture(const char* filename)
{
SDL_Surface* tempSurface = IMG_Load(filename);
if(!tempSurface)
{
std::cout<<"Eroare la imaginea: "<<filename<<SDL_GetError<<std::endl;
}
SDL_Texture* tex = SDL_CreateTextureFromSurface(renderer,tempSurface);
SDL_FreeSurface(tempSurface);
return tex;
}
void interface::DrawTexture(SDL_Texture* tex, SDL_Rect imgRect,SDL_Rect destRec)
{
SDL_RenderCopyEx(renderer,tex,&imgRect,&destRec,0,NULL,SDL_FLIP_NONE);
}
This is the code of mainClient.cpp where I include interface.h:
#include "client.h"
#include "interface.h"
int main()
{
client *Client = new client;
interface *screen = new interface(800,600);
screen->init("ReadsProfiler");
Client->init();
Client->loop();
}
I get the same error if I don't use client.h, so I'm not gonna add the code to that as well.
Because rendereris static, you also need to declare it in the .cpp file.
Add it to interface.cpp, for example under #include "interface.h":
SDL_Renderer* interface::renderer;

Issue with dlopen and weak symbols

I have the following sequence
executable (main) ---- (dlopen)---> libapp.so ---(dynamically linked)--> libfoo.so
libfoo.so in turn dynamically links to libfoo_strong.so. libfoo.so invokes a function from
libfoo_strong.so, but also has a weak definition (within foo.c which is compiled into libfoo.so).
Now, libapp.so invokes a function from libfoo.so (say invoke_foo_func_ptr() and this function >invokes a function pointer which stores the symbol that is defined as weak. My expectation is that >invokes_foo_func_ptr invokes the strong symbol, but it always goes to the weak symbol. Pls see the >code below for details.
PS: Dont ask me to explain the reason particular sequence of execution, but I am open to >workarounds.
foo_strong.c --> gcc -g -fPIC -shared -rdynamic foo_strong.o -o libfoo_strong.so
foo.c: --> gcc -g -fPIC -shared -rdynamic -L/users/ardesiga/cprogs/ld_r foo.o -o libfoo.so
app.c: --> gcc -g -fPIC -shared -rdynamic -L/users/ardesiga/cprogs/ld_r -lfoo -lfoo_strong app.o -o > libapp.so
/* foo_strong.c */
int
foo_weak_func (char *msg)
{
printf("[%s:%s] Reached strong, with msg: %s\n", __FILE__, __FUNCTION__, msg);
}
/* foo.c */
#include <stdio.h>
#include <stdlib.h>
#include "foo_ext.h"
#include "foo_weak.h"
int __attribute__ ((weak)) foo_weak_func (char *msg)
{
printf("[%s:%s], Reached weak, with msg: %s\n", __FILE__, __FUNCTION__, msg);
}
typedef int (*func_ptr_t) (char *msg);
func_ptr_t foo_func_ptr = foo_weak_func;
void
invoke_foo_func_ptr (char *msg)
{
printf("Inside %s\n", __FUNCTION__);
if (foo_func_ptr) {
(*foo_func_ptr)(msg);
} else {
printf("foo_func_ptr is NULL\n");
}
}
/* app.c */
#include "foo.h"
int
app_init_func (char *msg)
{
printf("Inside %s:%s\n", __FILE__, __FUNCTION__);
invoke_foo_func_ptr(msg);
}
/* main.c */
int main (int argc, char *argv[])
{
void *dl_handle;
char *lib_name;
app_init_func_t app_init_func;
if (!(argc > 1)) {
printf("Library is not supplied, loading libapp.so\n");
lib_name = strdup("libapp.so");
} else {
lib_name = strdup(argv[2]);
}
printf("Loading library: %s\n", lib_name);
dl_handle = dlopen(lib_name, RTLD_LAZY);
if (!dl_handle) {
printf("Failed to dlopen on %s, error: %s\n", lib_name, dlerror());
exit(1);
}
app_init_func = dlsym(dl_handle, "app_init_func");
if (app_init_func) {
(*app_init_func)("Called via dlsym");
} else {
printf("dlsym did not file app_init_func");
}
return (0);
}
My expectation is that invokes_foo_func_ptr invokes the strong symbol, but it always goes to the weak symbol.
Your expectation is incorrect and everything is working as designed.
Weak symbols lose to strong symbols when you link a single ELF binary. If you were to link a normal (strong) function foo and a weak foo into libfoo.so, the the strong definition would have won.
When you have multiple ELF images, some with strong foo, and some with weak foo, the first ELF image to define foo (regardless of whether weak or strong) wins. The loader will simply not look for any additional ELF images in its search scope once it finds the first image that does provide a definition for foo.
Dont ask me to explain the reason particular sequence of execution
That is quite an obnoxious thing to say.
I have a guess as to what your reason may be, and a solution for it, but you'll have to provide your reason first.

C++ 11 threading error

I have a C++11 program that gives me this error:
terminate called after throwing an instance of 'std::system_error'
what(): Operation not permitted
Code:
const int popSize=100;
void initializePop(mt3dSet mt3dPop[], int index1, int index2, std::string ssmName, std::string s1, std::string s2, std::string s3, std::string s4, std::string mt3dnam, std::string obf1, int iNSP, int iNRM, int iNCM, int iNLY, int iOPT, int iNPS, int iNWL, int iNRO, int ssmPosition, int obsPosition ){
if((index1 >= index2)||index1<0||index2>popSize){
std::cout<<"\nInitializing population...\nIndex not valid..\nQuitting...\n";
exit(1);
}
for(int i=index1; i<index2; i++){
mt3dPop[i].setSSM(ssmName, iNSP, iNRM, iNCM, iNLY);
mt3dPop[i].setNam(toString(s1,s3,i));
mt3dPop[i].setObsName(toString(s1,s4,i));
mt3dPop[i].setSsmName(toString(s1,s2,i));
mt3dPop[i].getSSM().generateFl(toString(s1,s2,i),iOPT,iNPS);
mt3dPop[i].generateNam(mt3dnam, ssmPosition, obsPosition);
mt3dPop[i].setFitness(obf1, iNWL, iNRO);
}}
void runPackage(ifstream& inFile){
//all variables/function parameters for function call are read from inFile
unsigned int numThreads = std::thread::hardware_concurrency();// =4 in my computer
std::vector<std::thread> vt(numThreads-1);//three threads
for(int j=0; j<numThreads-1; j++){
vt[j]= std::thread(initializePop,mt3dPop,j*popSize/numThreads, (j+1)*popSize/numThreads, ssmName, s1,s2, s3, s4, mt3dnam,obf1,iNSP, iNRM, iNCM, iNLY, iOPT, iNPS, iNWL, iNRO, ssmPosition, obsPosition ); //0-24 in thread 1, 25-49 in thread 2, 50-74 in thread 3
}
//remaining 75 to 99 in main thread
initializePop(mt3dPop,(numThreads-1)*popSize/numThreads, popSize, ssmName, s1,s2, s3, s4, mt3dnam,obf1,iNSP, iNRM, iNCM, iNLY, iOPT, iNPS, iNWL, iNRO, ssmPosition, obsPosition);
for(int j=0; j<numThreads-1; j++){
vt[j].join();
}}
What does the error mean and how do I fix it?
You need to link correctly, and compile with -std=c++11 - see this example.
I'm guessing you had the same problem as me! (I compiled with -pthread and -std=c++11 rather than linking with those two. (But you will need to compile with std=c++11 as well as linking with it.))
Probably you want to do something like this:
g++ -c <input_files> -std=c++11
then
g++ -o a.out <input_files> -std=c++11 -pthread
... at least I think that's right. (Someone to confirm?)
How to reproduce these errors:
#include <iostream>
#include <stdlib.h>
#include <string>
using namespace std;
void task1(std::string msg){
cout << "task1 says: " << msg;
}
int main() {
std::thread t1(task1, "hello");
t1.join();
return 0;
}
Compile and run:
el#defiant ~/foo4/39_threading $ g++ -o s s.cpp
s.cpp: In function ‘int main()’:
s.cpp:9:3: error: ‘thread’ is not a member of ‘std’
s.cpp:9:15: error: expected ‘;’ before ‘t1’
You forgot to #include <thread>, include it and try again:
#include <iostream>
#include <stdlib.h>
#include <string>
#include <thread>
using namespace std;
void task1(std::string msg){
cout << "task1 says: " << msg;
}
int main() {
std::thread t1(task1, "hello");
t1.join();
return 0;
}
Compile and run:
el#defiant ~/foo4/39_threading $ g++ -o s s.cpp -std=c++11
el#defiant ~/foo4/39_threading $ ./s
terminate called after throwing an instance of 'std::system_error'
what(): Operation not permitted
Aborted (core dumped)
More errors, as you defined above, because you didn't specify -pthread in the compile:
el#defiant ~/foo4/39_threading $ g++ -o s s.cpp -pthread -std=c++11
el#defiant ~/foo4/39_threading $ ./s
task1 says: hello
Now it works.

Dynamically loading Linux shared libraries?

I want to create a shared library which can be loaded in two different ways into targets:
LD_PRELOAD
Dynamic loading via dlsym
My shared library looks like this:
#include "stdio.h"
void __attribute__ ((constructor)) my_load(void);
void my_load(void) {
printf("asdf");
}
void someFunc(void) {
printf("someFunc called");
}
I am compiling it like so:
all:
gcc -fPIC -g -c -Wall MyLib.c
gcc -shared -W1,-soname,MyLib.so.1 -o MyLib.so.1.0.1 -lc
I do not wish to install it with ldconfig, etc. The target process looks like this:
#include <stdio.h>
#include <dlfcn.h>
void func1() {
printf("%d\n", 1);
}
void func2() {
printf("%d\n", 2);
}
void func3() {
printf("%d\n", 3);
}
int main() {
void* lib_handle = dlopen("/home/mike/Desktop/TargetProcess/MyLib.so.1.0.1",
RTLD_NOW|RTLD_GLOBAL);
if(lib_handle == NULL) {
printf("Failed loading lib\n");
} else {
printf("Loaded lib successfully\n");
void (*some_func)() = dlsym(lib_handle, "someFunc");
printf("%p\n", some_func);
dlclose(lib_handle);
}
func1();
func2();
func3();
return 0;
}
The target is compiled as so:
all:
gcc TestProg.c -ldl -o TestProg
My questions are:
With the dynamic loading with dlopen as above, why does my_load not appear to be called?
With the same method, why does dlsym always return nil even though dlopen returns non-null? Similarly, nm doesn't list either my_load or someFunc as symbols of the .so.
Is it possible to use LD_PRELOAD to load the library? I tried copying the .so into the same directory as the target then invoking LD_PRELOAD="./MyLib.so.1.0.1" ./TestProg but again my_load seems not to be being called.
Your object files was no linked into your library:
gcc -shared -W1,-soname,MyLib.so.1 -o MyLib.so.1.0.1 -lc
Change it to include your object file MyLib.o:
gcc MyLib.o -shared -W1,-soname,MyLib.so.1 -o MyLib.so.1.0.1 -lc
UPDATE: just tryed your command locally (without any MyLib.c or MyLib.o):
$ gcc -shared -W1,-soname,MyLib.so.1 -o MyLib.so.1.0.1 -lc && echo ok
ok
$ nm MyLib.so.1.0.1
xxxxxxxx a _DYNAMIC
xxxxxxxx a _GLOBAL_OFFSET_TABLE_
w _Jv_RegisterClasses
xxxxxxxx A __bss_start
w __cxa_finalize##xxxxxxxxxxx
xxxxxxxx d __dso_handle
w __gmon_start__
xxxxxxxx t __i686.get_pc_thunk.bx
xxxxxxxx A _edata
xxxxxxxx A _end
xxxxxxxx T _fini
xxxxxxxx T _init
It is an empty dynamic library.

How can dlsym successfully import function from stripped binary library?

It's weird that dlsym can import functions from stripped binaries.
Can anyone tell me why/how?
=== FILE: a.c ===
int a1() { return 1; }
int a2() { return 2; }
=== end of a.c ===
=== FILE: b.c ===
#include <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>
typedef int (*fint)();
fint dlsym_fint(void *handle, char *name)
{
fint x = (fint)dlsym(handle, name);
char *err = NULL;
if ((err = dlerror()) != NULL) {
printf("dlsym: %s\n", err);
exit(1);
}
return x;
}
int main()
{
void *dl = dlopen("a.so", RTLD_NOW);
fint a = NULL;
a = dlsym_fint(dl, "a1");
printf("%p: %d\n", a, a());
a = dlsym_fint(dl, "a2");
printf("%p: %d\n", a, a());
return 0;
}
=== end of b.c ===
$ gcc -shared -fPIC -o a.so a.c
$ nm a.so
...
00000000000004ec T a1
00000000000004f7 T a2
...
$ strip a.so
$ nm a.so
nm: a.so: no symbols
$ gcc -o b b.c -ldl
$ ./b
0x2aaaaaac74ec: 1
0x2aaaaaac74f7: 2
Try readelf -s a.so. The dynamic symbols are still there after that strip.
(Or just switch to nm -D a.so.)
strip removes debugging symbol tables, not the dynamic symbol tables used by the dynamic linker. To remove those symbols as well, use -fvisibility=hidden, and the symbol visibility function/variable attributes to select which functions you want to expose.

Resources