Recent

Author Topic: [SOLVED] How to call a FPC compiled shared library under Alpine?  (Read 9874 times)

engkin

  • Hero Member
  • *****
  • Posts: 2871
Re: [SOLVED] How to call a FPC compiled shared library under Alpine?
« Reply #15 on: June 13, 2021, 08:00:23 pm »
Can you share the ppas.sh and link.res produced by FPC on your system?

MarkMLl

  • Hero Member
  • *****
  • Posts: 2875
Re: [Solved] How to call a FPC compiled shared library under Alpine?
« Reply #16 on: June 13, 2021, 08:29:21 pm »
If it is the case, imho, fpc should add a {$ifdef ALPINE} define (like MarkMLI proposed).

I didn't propose anything! Keep my name out of it!! :-)

But more seriously... noting OP's most recent comment, I was tinkering with something a year or so ago which had a frontend/backend architecture connected in /both/ /directions/ by explicitly-loaded dynamic entry points, and having problems on 64-bit Debian. There might, possibly, be a fundamental OS problem lurking, since 32-bit was OK... I didn't report it as a problem pending more investigation and making sure I had exactly the same FPC and library versions.

MarkMLl
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

rarnu

  • New Member
  • *
  • Posts: 13
Re: [Solved] How to call a FPC compiled shared library under Alpine?
« Reply #17 on: June 13, 2021, 09:05:49 pm »
Could you check if there is a /usr/lib/libdl.so in your system?

Maybe you will have to create a symlink that point to the installed libdl.so.x of your system.

[EDIT] Other maybe: It could be that in Alpine dlopen is part of a other library than libdl.so.x .

If it is the case, imho, fpc should add a {$ifdef ALPINE} define (like MarkMLI proposed).

There is no "libdl.so" or something like that in Alpine, and even no so file contains the dlopen function.

I have use these command to find:

Code: Pascal  [Select][+][-]
  1. # cd /
  2. # find . - name "*.so.*" | xargs echo | xargs nm
  3.  

But I find that there is a "libdl.a" under /usr/lib, and I tried this:

Code: Pascal  [Select][+][-]
  1. program host;
  2.  
  3. {$mode objfpc}{$H+}
  4. {$linklib /usr/lib/libdl.a}
  5.  
  6. uses classes, Sysutils;
  7.  
  8. function dlopen(Name : PChar; Flags : longint) : Pointer; cdecl; external;
  9. function dlsym(Lib : Pointer; Name : Pchar) : Pointer; cdecl; external;
  10.  
  11. type
  12.   TAdd = function (x: Integer; y: Integer): Integer; cdecl;
  13.  
  14. var
  15.   libPath: string;
  16.   lib: Pointer;
  17.   mAdd: TAdd;
  18. begin
  19.   libPath:= ExtractFilePath(ParamStr(0)) + 'libmylib.so';
  20.   lib := dlopen(PChar(libPath), 2);
  21.   mAdd := TAdd(dlsym(lib, 'add'));
  22.   writeln(mAdd(1, 2));
  23. end.
  24.  

still crash when calling dlopen. It seems that dlopen is not contains in that static library (many many libraries in Alpine has no symbol exported, seems stripped).

and the same C code is here, can't work for the same reason

Code: C  [Select][+][-]
  1. #include <stdio.h>
  2. #include <dlfcn.h>
  3.  
  4. #define LIB_PATH "./libmylib.so"
  5.  
  6. typedef int (*add) (int, int);
  7.  
  8. int main() {
  9.   void* handle = dlopen(LIB_PATH, RTLD_NOW);
  10.   add mAdd = (add)dlsym(handle, "add");
  11.   int n = mAdd(1, 2);
  12.   printf("%d\n", n);
  13.   return 0;
  14. }
  15.  

build executable with:
Code: Pascal  [Select][+][-]
  1. $ gcc host.c -ldl
  2.  

the command executed successfully and generated a.out .

Then, I use ldd for checking the libraries, both FPC & C executables returns the same:

Code: Pascal  [Select][+][-]
  1. /lib/ld-musl-x86_64.so.1 (0x7f6e73691000)
  2. libc.musl-x86_64.so.1 => /lib/ld-musl-x86_64.so.1 (0x7f6e73691000)
  3.  

checked ld-musl-x86_64.so.1 and no dlopen in it.  :o


rarnu

  • New Member
  • *
  • Posts: 13
Re: [SOLVED] How to call a FPC compiled shared library under Alpine?
« Reply #18 on: June 13, 2021, 09:10:51 pm »
Can you share the ppas.sh and link.res produced by FPC on your system?

yes, attached.

rarnu

  • New Member
  • *
  • Posts: 13
Re: [SOLVED] How to call a FPC compiled shared library under Alpine?
« Reply #19 on: June 13, 2021, 09:21:55 pm »
And up to now, I have recompiled FPC 3.3.1 from SVN under Alpine 3.12

But the "dynamic load" problem is still.


Fred vS

  • Hero Member
  • *****
  • Posts: 2312
    • StrumPract is the musicians best friend
Re: [SOLVED] How to call a FPC compiled shared library under Alpine?
« Reply #20 on: June 13, 2021, 09:53:57 pm »
Hello.

I am not (yet) a Alpine guru, but there it seems that dlopen is in package libtool:
https://pkgs.alpinelinux.org/contents?file=&path=&name=libtool&branch=edge&repo=main&arch=x86

Quote
/usr/share/libtool/loaders/dlopen.c
« Last Edit: June 13, 2021, 10:31:55 pm by Fred vS »
I use Lazarus 2.0.6 32/64 and FPC 3.2.0 32/64 on Debian 10.2 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64 and Mac OS X Snow Leopard 32.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt, Carbon.

https://github.com/fredvs
https://gitlab.com/fredvs

Fred vS

  • Hero Member
  • *****
  • Posts: 2312
    • StrumPract is the musicians best friend
Re: [SOLVED] How to call a FPC compiled shared library under Alpine?
« Reply #21 on: June 13, 2021, 10:23:25 pm »
Re-hello.

I think that dlopen() is in libltdl.so library.

https://pkgs.alpinelinux.org/package/edge/main/x86/libltdl

Maybe you  may create a a symlink /usr/lib/libdl.so > /usr/lib/libltdl.so (or where is the library).
I use Lazarus 2.0.6 32/64 and FPC 3.2.0 32/64 on Debian 10.2 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64 and Mac OS X Snow Leopard 32.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt, Carbon.

https://github.com/fredvs
https://gitlab.com/fredvs

engkin

  • Hero Member
  • *****
  • Posts: 2871
Re: [SOLVED] How to call a FPC compiled shared library under Alpine?
« Reply #22 on: June 13, 2021, 11:03:00 pm »
In reply #4 you indicated that the problem is in the library generated by FPC because a gcc generated library did work:
Now I get a library named "libmylib.so" and this library can be loaded by FPC's "loadLibrary" and it works fine.

what's the difference between C's library and FPC's library?

Can you share the output of:
Code: Text  [Select][+][-]
  1. gcc -v -shared -o libmylib.so add.c

and the assembly files generated from FPC when you add -al switch.

Edit:
I noticed from the files you shared the code is stripped. Probably it is a good idea to deactivate stripping for now:
Code: Text  [Select][+][-]
  1. ...
  2. /usr/bin/strip --discard-all --strip-debug libmylib.so
  3. ...

Also, while it probably will not work, try to remove the initialization call:
Quote
/usr/bin/ld -b elf64-x86-64 -m elf_x86_64  -init FPC_SHARED_LIB_START -fini FPC_LIB_EXIT -soname libmylib.so   -shared  -L. -o libmylib.so -T link4764.res
« Last Edit: June 13, 2021, 11:13:06 pm by engkin »

rarnu

  • New Member
  • *
  • Posts: 13
Re: [SOLVED] How to call a FPC compiled shared library under Alpine?
« Reply #23 on: June 14, 2021, 05:05:48 am »
In reply #4 you indicated that the problem is in the library generated by FPC because a gcc generated library did work:
Now I get a library named "libmylib.so" and this library can be loaded by FPC's "loadLibrary" and it works fine.

what's the difference between C's library and FPC's library?

Can you share the output of:
Code: Text  [Select][+][-]
  1. gcc -v -shared -o libmylib.so add.c

and the assembly files generated from FPC when you add -al switch.

Edit:
I noticed from the files you shared the code is stripped. Probably it is a good idea to deactivate stripping for now:
Code: Text  [Select][+][-]
  1. ...
  2. /usr/bin/strip --discard-all --strip-debug libmylib.so
  3. ...

Also, while it probably will not work, try to remove the initialization call:
Quote
/usr/bin/ld -b elf64-x86-64 -m elf_x86_64  -init FPC_SHARED_LIB_START -fini FPC_LIB_EXIT -soname libmylib.so   -shared  -L. -o libmylib.so -T link4764.res

Thank you engkin, the problem of static load is solved by remove ld-linux-x86-64.so.2 from link.res.

and as you say, remove FPC's init and fini will be more friendly for C callers. I will do that then.

result of command "gcc -v -shared -o libmylib.so add.c" is here:

Code: Pascal  [Select][+][-]
  1. Using built-in specs.
  2. COLLECT_GCC=gcc
  3. COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-alpine-linux-musl/9.3.0/lto-wrapper
  4. Target: x86_64-alpine-linux-musl
  5. Configured with: /home/buildozer/aports/main/gcc/src/gcc-9.3.0/configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --build=x86_64-alpine-linux-musl --host=x86_64-alpine-linux-musl --target=x86_64-alpine-linux-musl --with-pkgversion='Alpine 9.3.0' --enable-checking=release --disable-fixed-point --disable-libstdcxx-pch --disable-multilib --disable-nls --disable-werror --disable-symvers --enable-__cxa_atexit --enable-default-pie --enable-default-ssp --enable-cloog-backend --enable-languages=c,c++,d,objc,fortran,ada --disable-libssp --disable-libmpx --disable-libmudflap --disable-libsanitizer --enable-shared --enable-threads --enable-tls --with-system-zlib --with-linker-hash-style=gnu
  6. Thread model: posix
  7. gcc version 9.3.0 (Alpine 9.3.0)
  8. COLLECT_GCC_OPTIONS='-v' '-shared' '-o' 'libmylib.so' '-mtune=generic' '-march=x86-64'
  9.  /usr/libexec/gcc/x86_64-alpine-linux-musl/9.3.0/cc1 -quiet -v add.c -quiet -dumpbase add.c -mtune=generic -march=x86-64 -auxbase add -version -o /tmp/ccpbCFBd.s
  10. GNU C17 (Alpine 9.3.0) version 9.3.0 (x86_64-alpine-linux-musl)
  11.         compiled by GNU C version 9.3.0, GMP version 6.2.0, MPFR version 4.0.2, MPC version 1.1.0, isl version isl-0.18-GMP
  12.  
  13. GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
  14. ignoring nonexistent directory "/usr/local/include"
  15. ignoring nonexistent directory "/usr/lib/gcc/x86_64-alpine-linux-musl/9.3.0/../../../../x86_64-alpine-linux-musl/include"
  16. #include "..." search starts here:
  17. #include <...> search starts here:
  18.  /usr/include/fortify
  19.  /usr/include
  20.  /usr/lib/gcc/x86_64-alpine-linux-musl/9.3.0/include
  21. End of search list.
  22. GNU C17 (Alpine 9.3.0) version 9.3.0 (x86_64-alpine-linux-musl)
  23.         compiled by GNU C version 9.3.0, GMP version 6.2.0, MPFR version 4.0.2, MPC version 1.1.0, isl version isl-0.18-GMP
  24.  
  25. GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
  26. Compiler executable checksum: 501c05d615d8f797a5937479b6573636
  27. COLLECT_GCC_OPTIONS='-v' '-shared' '-o' 'libmylib.so' '-mtune=generic' '-march=x86-64'
  28.  /usr/lib/gcc/x86_64-alpine-linux-musl/9.3.0/../../../../x86_64-alpine-linux-musl/bin/as -v --64 -o /tmp/ccbClpjJ.o /tmp/ccpbCFBd.s
  29. GNU assembler version 2.34 (x86_64-alpine-linux-musl) using BFD version (GNU Binutils) 2.34
  30. COMPILER_PATH=/usr/libexec/gcc/x86_64-alpine-linux-musl/9.3.0/:/usr/libexec/gcc/x86_64-alpine-linux-musl/9.3.0/:/usr/libexec/gcc/x86_64-alpine-linux-musl/:/usr/lib/gcc/x86_64-alpine-linux-musl/9.3.0/:/usr/lib/gcc/x86_64-alpine-linux-musl/:/usr/lib/gcc/x86_64-alpine-linux-musl/9.3.0/../../../../x86_64-alpine-linux-musl/bin/
  31. LIBRARY_PATH=/usr/lib/gcc/x86_64-alpine-linux-musl/9.3.0/:/usr/lib/gcc/x86_64-alpine-linux-musl/9.3.0/../../../../x86_64-alpine-linux-musl/lib/../lib/:/usr/lib/gcc/x86_64-alpine-linux-musl/9.3.0/../../../../lib/:/lib/../lib/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-alpine-linux-musl/9.3.0/../../../../x86_64-alpine-linux-musl/lib/:/usr/lib/gcc/x86_64-alpine-linux-musl/9.3.0/../../../:/lib/:/usr/lib/
  32. COLLECT_GCC_OPTIONS='-v' '-shared' '-o' 'libmylib.so' '-mtune=generic' '-march=x86-64'
  33.  /usr/libexec/gcc/x86_64-alpine-linux-musl/9.3.0/collect2 -plugin /usr/libexec/gcc/x86_64-alpine-linux-musl/9.3.0/liblto_plugin.so -plugin-opt=/usr/libexec/gcc/x86_64-alpine-linux-musl/9.3.0/lto-wrapper -plugin-opt=-fresolution=/tmp/ccPjfibM.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --eh-frame-hdr --hash-style=gnu -m elf_x86_64 --as-needed -shared -z relro -z now -o libmylib.so /usr/lib/gcc/x86_64-alpine-linux-musl/9.3.0/../../../../lib/crti.o /usr/lib/gcc/x86_64-alpine-linux-musl/9.3.0/crtbeginS.o -L/usr/lib/gcc/x86_64-alpine-linux-musl/9.3.0 -L/usr/lib/gcc/x86_64-alpine-linux-musl/9.3.0/../../../../x86_64-alpine-linux-musl/lib/../lib -L/usr/lib/gcc/x86_64-alpine-linux-musl/9.3.0/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-alpine-linux-musl/9.3.0/../../../../x86_64-alpine-linux-musl/lib -L/usr/lib/gcc/x86_64-alpine-linux-musl/9.3.0/../../.. /tmp/ccbClpjJ.o -lssp_nonshared -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /usr/lib/gcc/x86_64-alpine-linux-musl/9.3.0/crtendS.o /usr/lib/gcc/x86_64-alpine-linux-musl/9.3.0/../../../../lib/crtn.o
  34. COLLECT_GCC_OPTIONS='-v' '-shared' '-o' 'libmylib.so' '-mtune=generic' '-march=x86-64'
  35.  
« Last Edit: June 14, 2021, 08:00:47 am by rarnu »

rarnu

  • New Member
  • *
  • Posts: 13
Re: [SOLVED] How to call a FPC compiled shared library under Alpine?
« Reply #24 on: June 14, 2021, 05:10:35 am »
Re-hello.

I think that dlopen() is in libltdl.so library.

https://pkgs.alpinelinux.org/package/edge/main/x86/libltdl

Maybe you  may create a a symlink /usr/lib/libdl.so > /usr/lib/libltdl.so (or where is the library).

Yes, there is a "lt_dlopen" in libltdl.so, in "ltdl.h" there are some exports:
Code: C  [Select][+][-]
  1. LT_SCOPE lt_dlhandle lt_dlopen          (const char *filename);          
  2. LT_SCOPE lt_dlhandle lt_dlopenext       (const char *filename);        
  3. LT_SCOPE lt_dlhandle lt_dlopenadvise    (const char *filename,  lt_dladvise advise);          
  4. LT_SCOPE void *     lt_dlsym            (lt_dlhandle handle, const char *name);
  5. LT_SCOPE const char *lt_dlerror         (void);                                
  6. LT_SCOPE int        lt_dlclose          (lt_dlhandle handle);            
  7.  

here is my C code with ltdl:

Code: C  [Select][+][-]
  1. #include <stdio.h>
  2. #include <ltdl.h>
  3.  
  4. #define LIB_PATH "./libmylib.so"
  5.  
  6. typedef int (*add) (int, int);
  7.  
  8. int main() {
  9.   lt_dlinit();
  10.   lt_dlhandle handle = lt_dlopen(LIB_PATH);
  11.   add mAdd = (add)lt_dlsym(handle, "add");
  12.   int n = mAdd(1, 2);
  13.   printf("%d\n", n);
  14.   return 0;
  15. }
  16.  

compiled with:

Code: C  [Select][+][-]
  1. $ gcc host.c -lltdl
  2.  

if the so is compiled by C, it works, and if not, it crashes.
« Last Edit: June 14, 2021, 08:04:59 am by rarnu »

rarnu

  • New Member
  • *
  • Posts: 13
Re: [SOLVED] How to call a FPC compiled shared library under Alpine?
« Reply #25 on: June 14, 2021, 08:36:37 am »
Again, thanks for all helps. Now I find the final worked solution.

here all the code must be compiled under Alpine, no other linux.

the lib's code:
Code: Pascal  [Select][+][-]
  1. library mylib;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. uses Classes, Sysutils;
  6.  
  7. function add(x: integer; y: integer): integer; cdecl;
  8. begin
  9.   Exit(x + y);
  10. end;
  11.  
  12. exports
  13.   add;
  14.  
  15. end.
  16.  

compile it with command:
Code: Pascal  [Select][+][-]
  1. $ fpc -Cn mylib.lpr
  2.  

remove "ld-linux-x86-64.so.2" in link.res or linkxxx.res

open "ppas.sh" and change the /usr/bin/ld line to:

Code: Pascal  [Select][+][-]
  1. /usr/bin/ld -b elf64-x86-64 -m elf_x86_64 -soname libmylib.so   -shared  -L. -o libmylib.so -T link.res
  2.  

now execute ppas.sh and get the libmylib.so

-------------------------------------------------------------------------

here's my host app's code:
Code: Pascal  [Select][+][-]
  1. program host;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. {$linklib ltdl}
  6. {$linklib c}
  7.  
  8. uses classes, Sysutils;
  9.  
  10. const
  11.   LIB_PATH = './libmylib.so';
  12.  
  13. function lt_dlinit(): integer; cdecl; external;
  14. function lt_dlopen(const filename : PChar) : Pointer; cdecl; external;
  15. function lt_dlsym(Lib : Pointer; const name : Pchar) : Pointer; cdecl; external;
  16.  
  17. type
  18.   TAdd = function (x: Integer; y: Integer): Integer; cdecl;
  19.  
  20. var
  21.   r: integer;
  22.   lib: Pointer;
  23.   mAdd: TAdd;
  24. begin
  25.   lt_dlinit();
  26.   lib := lt_dlopen(LIB_PATH);
  27.   mAdd := TAdd(lt_dlsym(lib, 'add'));
  28.   writeln(mAdd(1, 2));
  29. end.
  30.  

compile it with command:
Code: Pascal  [Select][+][-]
  1. $ fpc -Cn host.lpr
  2.  

open "ppas.sh" and change the param "--dynamic-linker" from "ld-linux-x86-64.so.2" to "ld-musl-x86_64.so.1"

now execute ppas.sh and get host executable.

-------------------------------------------------------------------------

that's all, now I can run host to load libmylib.so dynamically.

and the previous way for static load is also worked.

Thanks you all, a lot.

Fred vS

  • Hero Member
  • *****
  • Posts: 2312
    • StrumPract is the musicians best friend
Re: [SOLVED] How to call a FPC compiled shared library under Alpine?
« Reply #26 on: June 14, 2021, 01:43:38 pm »
Hello Rarnu.

Wow, congrats and thanks for your perseverance (I love 'no giving-up' people').

Your last post should be transferred into a fpc wiki page.

Fre;D
I use Lazarus 2.0.6 32/64 and FPC 3.2.0 32/64 on Debian 10.2 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64 and Mac OS X Snow Leopard 32.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt, Carbon.

https://github.com/fredvs
https://gitlab.com/fredvs

MarkMLl

  • Hero Member
  • *****
  • Posts: 2875
Re: [SOLVED] How to call a FPC compiled shared library under Alpine?
« Reply #27 on: June 14, 2021, 03:08:13 pm »
Wow, congrats and thanks for your perseverance (I love 'no giving-up' people').

I agree. However I think there's a lesson to be learned here: some of the initial problems were caused by a demi-borked system, and assuming that the distro maintainers are competent that can only have been caused by a part-successful installation of an "alien" package.

Assuming that's correct, I'd mention that it's the second problem of this nature in a week: I'd suggest that however much we are repelled by the "string and chewinggum" implementation of Docker it really is quite serviceable at providing a sandbox in which slightly-suspect apps can be run.

MarkMLl
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

 

TinyPortal © 2005-2018