I am trying to compile an open source library using Emscripten and after making a few minor changes I have it compiling and running, but when I try to actually use it too much I am getting:
segmentation fault, exceeded the top of the available dynamic heap when loading 1 bytes from address 1869770797. STATICTOP=184544, DYNAMICTOP=21213184 melt.html:1246:11
exception thrown: abort("segmentation fault, exceeded the top of the available dynamic heap when loading 1 bytes from address 1869770797. STATICTOP=184544, DYNAMICTOP=21213184") at jsStackTrace#http://localhost:6931/melt.js:1603:13
stackTrace#http://localhost:6931/melt.js:1620:12
abort#http://localhost:6931/melt.js:52047:44
SAFE_HEAP_LOAD#http://localhost:6931/melt.js:926:51
_strcmp#http://localhost:6931/melt.wasm:wasm-function[912]:0x67c58
But I really don't think it should be using that much memory? What is the best way to debug memory issues like this with Emscripten in the browser?
I can't seem to even find the exact "strcmp" call it is failing on as the stack information kinda sucks.
If I compile without -s SAFE_HEAP=1 the error comes through as:
exception thrown: RuntimeError: index out of bounds,_strcmp#http://localhost:6931/melt.wasm:wasm-function[771]:0x34dcf
Module._strcmp#http://localhost:6931/melt.js:50463:10
The library I am trying to compile is MLT framework (https://github.com/mltframework/mlt)
It's a bit complicated as well as it uses dynamic linking to load most of its features - right now I am just trying to get it working with the absolute minimum - mltframework itself (statically linked into the executable), libmltcore (loaded via dlload), libmltsdl2 (loaded via dlload)
Compile flags are as follows, for MLT itself (using WASM=0 but it doesn't seem to make a difference WASM or not):
emcc -g -s WASM=0 -dynamiclib -current_version 6.14.0
-compatibility_version 6
-o ../../../lib/libmlt.bc
mlt_frame.o mlt_version.o mlt_geometry.o mlt_deque.o mlt_property.o mlt_properties.o mlt_events.o mlt_parser.o mlt_service.o mlt_producer.o mlt_multitrack.o mlt_playlist.o mlt_consumer.o mlt_filter.o mlt_transition.o mlt_field.o mlt_tractor.o mlt_factory.o mlt_repository.o mlt_pool.o mlt_tokeniser.o mlt_profile.o mlt_log.o mlt_cache.o mlt_animation.o mlt_slices.o
-lpthread -lm
libmltcore:
emcc -g -s EXPORT_ALL=1 -s WASM=0 -s SIDE_MODULE=1 -dynamiclib
-o ../../../../lib/mlt/libmltcore.js
factory.o producer_colour.o producer_consumer.o producer_hold.o producer_loader.o producer_melt.o producer_noise.o producer_timewarp.o producer_tone.o filter_audiochannels.o filter_audiomap.o filter_audioconvert.o filter_audiowave.o filter_brightness.o filter_channelcopy.o filter_crop.o filter_data_feed.o filter_data_show.o filter_fieldorder.o filter_gamma.o filter_greyscale.o filter_imageconvert.o filter_luma.o filter_mirror.o filter_mono.o filter_obscure.o filter_panner.o filter_region.o filter_rescale.o filter_resize.o filter_transition.o filter_watermark.o transition_composite.o transition_luma.o transition_mix.o transition_region.o transition_matte.o consumer_multi.o consumer_null.o
-L../../framework -lmlt -lm -lpthread
litmltsdl2:
emcc -g -s EXPORT_ALL=1 -s SIDE_MODULE=1 -s WASM=0 -dynamiclib
-o ../../../../lib/mlt/libmltsdl2.js
factory.o common.o consumer_sdl2.o consumer_sdl2_audio.o
-L../../framework -lmlt -lpthread -lm -s USE_SDL=2
And finally my executable:
emcc -g -s SAFE_HEAP=1 -s WASM=0 -s TOTAL_MEMORY=1024MB -s EXIT_RUNTIME=1 -s EXPORT_ALL=1 -s MAIN_MODULE=1
-O2 -I$(pwd)/dist/include/mlt $(pwd)/dist/lib/libmlt.bc
--preload-file lib/mlt
--preload-file lib/share
melt.c -o melt.html --pre-js melt_pre.js
I've tried various other flags:
ALIASING_FUNCTION_POINTERS=0
SAFE_HEAP=1
STACK_OVERFLOW_CHECK=1
EMULATE_FUNCTION_POINTER_CASTS=1
ASSERTIONS=2
-g4 seems like it might be helpful but tt fails to find the source files when building the libraries.
It worth taking a look at the full list and descriptions of emcc compiler options. You will realize all of other flags you mentioned won't help your case after reading the description from the link.
Firstly I'm pretty sure that you can't use MB notations for -s TOTAL_MEMORY= flag, since as you can see above, -s flags are actually JavaScript. Try using a plain integer instead. Also -s ALLOW_MEMORY_GROWTH=1 will let the heap grow automatically as you need.
Note that pthread is not available in some browsers by default, since it (SharedArrayBuffer precisely) was affected by Meltdown vulnerability so it is disabled in the browsers.
I am trying to create executable using some libraries.
My GCC command is :-
gcc -fPIC -DLINUX testdenpli /verilog/libdenpli.so -L/local/test/dir/ testpli.c
I have my library with symbols at path '/local/test/dir/'
Error:-
libdenpli.so: undefined reference to `ktlTcl_InitStubs'
libdenpli.so: undefined reference to `ktlitclStubsPtr'
I have the libraries with above symbols at path "'/local/test/dir/" .. But still seeing the issue.
Any one please help.
The error message says that libdenpli.so requires linking another shared library that provides symbols ktlTcl_InitStubs and ktlitclStubsPtr.
Find the shared library that provides those symbols using the following command:
for so in $(find /local/test/dir -name "*.so" -o -name "*.so.*"); do
nm --defined-only --dynamic $so 2>/dev/null | grep -q 'ktlTcl_InitStubs|ktlitclStubsPtr' && echo $so;
done
Then add that library into your linker command line:
gcc -Wall -Wextra -fPIC -DLINUX -o testdenpli testpli.c /verilog/libdenpli.so <full-path-to-found-library>
What is the name of the library containing the symbols? You need to include -lNAME to your compilation.
In general,
gcc file.c -o file -L/path/to/libs -lNAME
Note, the prefix "lib" and the suffix ".so" needn't be mentioned.
I'm trying to compile my code with a DLL i made and I get the error below when i write ./prog
./prog: error while loading shared libraries: libctest.so.1: cannot open shared object file: No such file or directory
I followed the tutorial here and my mono app has no problem loading the dll and calling the functions. The key parts of the tutorial were
gcc -Wall -fPIC -c *.c
gcc -shared -Wl,-soname,libctest.so.1 -o libctest.so.1.0 *.o
mv libctest.so.1.0 /opt/lib
ln -sf /opt/lib/libctest.so.1.0 /opt/lib/libctest.so.1
ln -sf /opt/lib/libctest.so.1.0 /opt/lib/libctest.so
My C# code does
[DllImport("path/to/CDLL", CallingConvention = CallingConvention.Cdecl)]
public static extern void test();
I built with
gcc -Wall -L/opt/lib main.c -lctest -o prog
This is the first thing i changed. prog.c to main.c. From there I simply run with ./prog to get the error at the top of this question. I do this as root so there shouldn't be permission issues. I also chmod 755 the so's. What am I doing wrong? This is opensuse. I had to create the /opt/lib so I am thinking this path isn't registered where it should be
The dynamic linker ld.so will not look in /opt/lib by default when attempting to resolve library dependencies. You have to tell the linker about the non-standard library directories or add the /opt/lib path to your prog binary.
eg
LD_LIBRARY_PATH=/opt/lib ./prog
or, link prog with the -rpath linker option. This provides an additional path for the linker to search when resolving locations of shared objects.
gcc -Wall -L/opt/lib -Wl,-rpath,/opt/lib main.c -lctest -o prog
You can use the ldd command on a binary to show the locations of shared libraries.
ldd prog
This will currently show that libctest.so cannot be found. With an additional search path, the following command should show that all libraries are resolved:
LD_LIBRARY_PATH=/opt/lib ldd prog
I'm trying to compile a C program under Linux. However, out of curiosity, I'm trying to execute some steps by hand: I use:
the gcc frontend to produce assembler code
then run the GNU assembler to get an object file
and then link it with the C runtime to get a working executable.
Now I'm stuck with the linking part.
The program is a very basic "Hello world":
#include <stdio.h>
int main() {
printf("Hello\n");
return 0;
}
I use the following command to produce the assembly code:
gcc hello.c -S -masm=intel
I'm telling gcc to quit after compiling and dump the assembly code with Intel syntax.
Then I use th GNU assembler to produce the object file:
as -o hello.o hello.s
Then I try using ld to produce the final executable:
ld hello.o /usr/lib/libc.so /usr/lib/crt1.o -o hello
But I keep getting the following error message:
/usr/lib/crt1.o: In function `_start':
(.text+0xc): undefined reference to `__libc_csu_fini'
/usr/lib/crt1.o: In function `_start':
(.text+0x11): undefined reference to `__libc_csu_init'
The symbols __libc_csu_fini/init seem to be a part of glibc, but I can't find them anywhere! I tried linking against libc statically (against /usr/lib/libc.a) with the same result.
What could the problem be?
/usr/lib/libc.so is a linker script which tells the linker to pull in the shared library /lib/libc.so.6, and a non-shared portion, /usr/lib/libc_nonshared.a.
__libc_csu_init and __libc_csu_fini come from /usr/lib/libc_nonshared.a. They're not being found because references to symbols in non-shared libraries need to appear before the archive that defines them on the linker line. In your case, /usr/lib/crt1.o (which references them) appears after /usr/lib/libc.so (which pulls them in), so it doesn't work.
Fixing the order on the link line will get you a bit further, but then you'll probably get a new problem, where __libc_csu_init and __libc_csu_fini (which are now found) can't find _init and _fini. In order to call C library functions, you should also link /usr/lib/crti.o (after crt1.o but before the C library) and /usr/lib/crtn.o (after the C library), which contain initialisation and finalisation code.
Adding those should give you a successfully linked executable. It still won't work, because it uses the dynamically linked C library without specifying what the dynamic linker is. You'll need to tell the linker that as well, with something like -dynamic-linker /lib/ld-linux.so.2 (for 32-bit x86 at least; the name of the standard dynamic linker varies across platforms).
If you do all that (essentially as per Rob's answer), you'll get something that works in simple cases. But you may come across further problems with more complex code, as GCC provides some of its own library routines which may be needed if your code uses certain features. These will be buried somewhere deep inside the GCC installation directories...
You can see what gcc is doing by running it with either the -v option (which will show you the commands it invokes as it runs), or the -### option (which just prints the commands it would run, with all of the arguments quotes, but doesn't actually run anything). The output will be confusing unless you know that it usually invokes ld indirectly via one of its own components, collect2 (which is used to glue in C++ constructor calls at the right point).
I found another post which contained a clue: -dynamic-linker /lib/ld-linux.so.2.
Try this:
$ gcc hello.c -S -masm=intel
$ as -o hello.o hello.s
$ ld -o hello -dynamic-linker /lib/ld-linux.so.2 /usr/lib/crt1.o /usr/lib/crti.o hello.o -lc /usr/lib/crtn.o
$ ./hello
hello, world
$
Assuming that a normal invocation of gcc -o hello hello.c produces a working build, run this command:
gcc --verbose -o hello hello.c
and gcc will tell you how it's linking things. That should give you a good idea of everything that you might need to account for in your link step.
In Ubuntu 14.04 (GCC 4.8), the minimal linking command is:
ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 \
/usr/lib/x86_64-linux-gnu/crt1.o \
/usr/lib/x86_64-linux-gnu/crti.o \
-L/usr/lib/gcc/x86_64-linux-gnu/4.8/ \
-lc -lgcc -lgcc_s \
hello.o \
/usr/lib/x86_64-linux-gnu/crtn.o
Although they may not be necessary, you should also link to -lgcc and -lgcc_s, since GCC may emit calls to functions present in those libraries for operations which your hardware does not implement natively, e.g. long long int operations on 32-bit. See also: Do I really need libgcc?
I had to add:
-L/usr/lib/gcc/x86_64-linux-gnu/4.8/ \
because the default linker script does not include that directory, and that is where libgcc.a was located.
As mentioned by Michael Burr, you can find the paths with gcc -v. More precisely, you need:
gcc -v hello_world.c |& grep 'collect2' | tr ' ' '\n'
This is how I fixed it on ubuntu 11.10:
apt-get remove libc-dev
Say yes to remove all the packages but copy the list to reinstall after.
apt-get install libc-dev
If you're running a 64-bit OS, your glibc(-devel) may be broken. By looking at this and this you can find these 3 possible solutions:
add lib64 to LD_LIBRARY_PATH
use lc_noshared
reinstall glibc-devel
Since you are doing the link process by hand, you are forgetting to link the C run time initializer, or whatever it is called.
To not get into the specifics of where and what you should link for you platform, after getting your intel asm file, use gcc to generate (compile and link) your executable.
simply doing gcc hello.c -o hello should work.
Take it:
$ echo 'main(){puts("ok");}' > hello.c
$ gcc -c hello.c -o hello.o
$ ld hello.o -o hello.exe /usr/lib/crt1.o /usr/lib/crti.o /usr/lib/crtn.o \
-dynamic-linker /lib/ld-linux.so.2 -lc
$ ./hello.exe
ok
Path to /usr/lib/crt*.o will when glibc configured with --prefix=/usr
I know that LD_LIBRARY_PATH is evil and it's a good habit to avoid using it.
I have a program called server.c on a remote Solaris 9 server that holds two versions of openssl library (0.9.8 and 1.0.0) and I'm using gcc 3.4.6. My program need to link to 1.0.0a version. Because it's work environment, I don't have the right to modify anything in the openssl library directory. I figured out to compile my program with both -L and -R options without setting LD_LIBRARY_PATH and it worked fine. (I noticed it won't work without setting -R option) But the compiled program kept linking to /usr/local/ssl/lib/libssl.so.0.9.8 instead of /.../libssl.so.1.0.0. Is there a work-around for this?
BTW, please correct me if I'm wrong: is it the -R option that actually "link" the shared libraries at runtime and -L option only "load" shared libraries at compile time?
Any help will be much appreciated!
Z.Zen
//////////////////////////////////////////////
Here is my Makefile:
CC = gcc
OPENSSLDIR = /usr/local/ssl
CFLAGS = -g -Wall -W -I${OPENSSLDIR}/include -O2 -D_REENTRANT -D__EXTENSIONS__
RPATH = -R${OPENSSLDIR}/lib
LD = ${RPATH} -L${OPENSSLDIR}/lib -lssl -lcrypto -lsocket -lnsl -lpthread
OBJS = common.o
PROGS = server
all: ${PROGS}
server: server.o ${OBJS}
${CC} server.o ${OBJS} -o server ${LD}
clean:;
${RM} ${PROGS} *.ln *.BAK *.bak *.o
I figured out that I can include the absolute path of the specific library that I want to link to and it worked fine for me:
LD = ${RPATH} -lsocket -lnsl -lpthread ${OPENSSLDIR}/lib/libssl.so.1.0.0 \
${OPENSSLDIR}/lib/libcrypto.so.1.0.0
If you are using g++, Piotr Lesnicki pointed out that -l:libssl.so.1.0.0 also works. See more at the original post.
Do you have any links to the SSL lib?
If not, can you create a link to the the desired SSL lib like
ln -s libssl.so.1.0.0 libssl.so
in the ssl directory and try it