Lazarus

Programming => Operating Systems => Linux => Topic started by: rarnu on June 11, 2021, 07:36:43 pm

Title: [SOLVED] How to call a FPC compiled shared library under Alpine?
Post by: rarnu on June 11, 2021, 07:36:43 pm
I'm now using Alpine Linux for some development. I find that the shared library compiled with FPC can't be loaded by other programs.

here's my library's code:

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

These code compiled by command:
Code: Text  [Select][+][-]
  1. $ fpc mylib.lpr -FL/lib/libc.musl-x86_64.so.1
  2.  

There is no "ld-linux-x86-64.so.2" in Alpine Linux, even glibc is also not included. Only musl-libc can be used.

and here's my app for calling the lib:

Code: Pascal  [Select][+][-]
  1. program host;
  2. {$mode objfpc}{$H+}
  3.  
  4. uses
  5.   Classes, SysUtils, dynlibs;
  6.  
  7. type
  8.   TAdd = function (x: integer; y: integer): integer; cdecl;
  9.  
  10. var
  11.   libPath: string;
  12.   lib: TLibHandle;
  13.   mAdd: TAdd;
  14. begin
  15.   libPath:= ExtractFilePath(ParamStr(0)) + 'libmylib.so';
  16.   lib := loadLibrary(libPath);
  17.   mAdd := TAdd(GetProcAddress(lib, 'add'));
  18.   WriteLn(mAdd(1, 2));
  19. end;
  20.  

These code compiled by command:
Code: Pascal  [Select][+][-]
  1. $ fpc host.lpr -FL/lib/libc.musl-x86_64.so.1
  2.  

now I get "libmylib.so" and "host" files, and I try to run "host", it crashed with the message:

Code: Pascal  [Select][+][-]
  1. An unhandled exception occurred at $00007F4E99259B40:
  2. EAccessViolation:
  3.   $00007F4E99259B40
  4.   $0000000000422D84
  5.   $0000000000422D84
  6.   $0000000000422D84
  7.   $0000000000422D84
  8.   $0000000000422D84
  9.   $0000000000422D84
  10.   $0000000000422D84
  11.   $0000000000422D84
  12.   $0000000000422D84
  13.   $0000000000422D84
  14.   $0000000000422D84
  15.   $0000000000422D84
  16.   $0000000000422D84
  17.   $0000000000422D84
  18.   $0000000000422D84
  19.   $0000000000422D84
  20.  
  21. Segmentation fault
  22.  

I can't solve the problem with the given message, needs help.

And I have also tried, write these code with C and compiled with gcc, it works fine!!

I want to know the reason and how to make it work.

Help me please. thank you.
Title: Re: How to call a FPC compiled shared library under Alpine?
Post by: MarkMLl on June 11, 2021, 10:00:03 pm
There is no "ld-linux-x86-64.so.2" in Alpine Linux, even glibc is also not included. Only musl-libc can be used.

That's pretty weird, since generally speaking ld-linux-something.so is a prerequisite for a standard .elf file.

Without volunteering that I have a solution but to keep the ball rolling, what is the output of this command

$ readelf -d `which gcc`

MarkMLl
Title: Re: How to call a FPC compiled shared library under Alpine?
Post by: Fred vS on June 11, 2021, 10:00:43 pm
Hello Ramu.

Not sure it could help but what about to use for export code in "mylib" ?:

Code: Pascal  [Select][+][-]
  1. ...
  2. exports
  3.   add name 'add';
  4.  

And for fpc command line (added "-fPIC") ?:

Code: Bash  [Select][+][-]
  1. $ fpc mylib.lpr -fPIC -FL/lib/libc.musl-x86_64.so.1

And in "host" program, to localize the error ?:

Code: Pascal  [Select][+][-]
  1. ...
  2.  lib := loadLibrary(libPath);
  3.  if lib = nilhandle then
  4.   WriteLn(libpath + ' not loaded')
  5. else
  6. begin
  7.   mAdd := TAdd(GetProcAddress(lib, 'add'));
  8.   if assigned(mAdd)
  9.   WriteLn(mAdd(1, 2)) else
  10.   WriteLn('mAdd  not assigned')
  11. end;

Title: Re: How to call a FPC compiled shared library under Alpine?
Post by: rarnu on June 12, 2021, 03:02:25 am
There is no "ld-linux-x86-64.so.2" in Alpine Linux, even glibc is also not included. Only musl-libc can be used.

That's pretty weird, since generally speaking ld-linux-something.so is a prerequisite for a standard .elf file.

Without volunteering that I have a solution but to keep the ball rolling, what is the output of this command

$ readelf -d `which gcc`

MarkMLl

Thank you MarkMLI, here is my command result:

Code: Pascal  [Select][+][-]
  1. Dynamic section at offset 0xf49f8 contains 21 entries:
  2.   Tag        Type                         Name/Value
  3.  0x0000000000000001 (NEEDED)             Shared library: [libc.musl-x86_64.so.1]
  4.  0x000000000000000c (INIT)               0x403000
  5.  0x000000000000000d (FINI)               0x479e6f
  6.  0x0000000000000019 (INIT_ARRAY)         0x4f31d0
  7.  0x000000000000001b (INIT_ARRAYSZ)       112 (bytes)
  8.  0x000000006ffffef5 (GNU_HASH)           0x4002c8
  9.  0x0000000000000005 (STRTAB)             0x401090
  10.  0x0000000000000006 (SYMTAB)             0x400328
  11.  0x000000000000000a (STRSZ)              1097 (bytes)
  12.  0x000000000000000b (SYMENT)             24 (bytes)
  13.  0x0000000000000015 (DEBUG)              0x0
  14.  0x0000000000000003 (PLTGOT)             0x4f5b98
  15.  0x0000000000000002 (PLTRELSZ)           3144 (bytes)
  16.  0x0000000000000014 (PLTREL)             RELA
  17.  0x0000000000000017 (JMPREL)             0x4015b8
  18.  0x0000000000000007 (RELA)               0x4014e0
  19.  0x0000000000000008 (RELASZ)             216 (bytes)
  20.  0x0000000000000009 (RELAENT)            24 (bytes)
  21.  0x0000000000000018 (BIND_NOW)          
  22.  0x000000006ffffffb (FLAGS_1)            Flags: NOW
  23.  0x0000000000000000 (NULL)               0x0
  24.  
  25.  
Title: Re: How to call a FPC compiled shared library under Alpine?
Post by: rarnu on June 12, 2021, 03:08:25 am
Hello Ramu.

Not sure it could help but what about to use for export code in "mylib" ?:

Code: Pascal  [Select][+][-]
  1. ...
  2. exports
  3.   add name 'add';
  4.  

And for fpc command line (added "-fPIC") ?:

Code: Bash  [Select][+][-]
  1. $ fpc mylib.lpr -fPIC -FL/lib/libc.musl-x86_64.so.1

And in "host" program, to localize the error ?:

Code: Pascal  [Select][+][-]
  1. ...
  2.  lib := loadLibrary(libPath);
  3.  if lib = nilhandle then
  4.   WriteLn(libpath + ' not loaded')
  5. else
  6. begin
  7.   mAdd := TAdd(GetProcAddress(lib, 'add'));
  8.   if assigned(mAdd)
  9.   WriteLn(mAdd(1, 2)) else
  10.   WriteLn('mAdd  not assigned')
  11. end;

Thank you Fred, I have tried your code.

I find the crash happens when calling "loadLibrary", I also tried "SafeLoadLibrary" still not work.

And then I tried the C code like:

Code: C  [Select][+][-]
  1. // add.h
  2. int add(int x, int y);
  3.  

Code: C  [Select][+][-]
  1. // add.c
  2. #include "add.h"
  3.  
  4. int add(int x, int y) {
  5.   return x + y;
  6. }
  7.  

and compiled with command

Code: Text  [Select][+][-]
  1. $ gcc -shared -o libmylib.so add.c
  2.  

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?
Title: Re: How to call a FPC compiled shared library under Alpine?
Post by: PierceNg on June 12, 2021, 04:28:55 am
There is no "ld-linux-x86-64.so.2" in Alpine Linux, even glibc is also not included. Only musl-libc can be used.

There is a libc-compat package on Alpine. All it does is to create a link to musl-libc. I've used this to run Ubuntu-compiled FPC programs on Alpine.

Try installing libc-compat package and re-run your program. If that fails, try rebuilding your shared library and program on Ubuntu, say, then run on Alpine with libc-compat installed.

If still doesn't work, glibc is also available as an Alpine package.
Title: Re: How to call a FPC compiled shared library under Alpine?
Post by: rarnu on June 12, 2021, 05:49:28 am
There is no "ld-linux-x86-64.so.2" in Alpine Linux, even glibc is also not included. Only musl-libc can be used.

There is a libc-compat package on Alpine. All it does is to create a link to musl-libc. I've used this to run Ubuntu-compiled FPC programs on Alpine.

Try installing libc-compat package and re-run your program. If that fails, try rebuilding your shared library and program on Ubuntu, say, then run on Alpine with libc-compat installed.

If still doesn't work, glibc is also available as an Alpine package.

Thank you PierceNg, I have tried to install a compat lib of glibc. here's the results:

with official libc6-compat, FPC library can't load, and the app with mysql(needs official libmysqlclient.so) inside works fine.
with 3rd-party glibc 2.33, FPC library works fine, but the libmysqlclient.so can't load.

I want my FPC library and mysql both work, but ...
Title: Re: How to call a FPC compiled shared library under Alpine?
Post by: Fred vS on June 12, 2021, 06:09:59 am
Hello Rarnu.

What do you get with this console command to check the methods of the fpc library?

Code: Bash  [Select][+][-]
  1. $ nm -D libmylib.so
Title: Re: How to call a FPC compiled shared library under Alpine?
Post by: rarnu on June 12, 2021, 07:09:05 am
Hello Rarnu.

What do you get with this console command to check the methods of the fpc library?

Code: Bash  [Select][+][-]
  1. $ nm -D libmylib.so

yep, I think this is the key point. FPC's library's exported methods is different with C's

Code: Pascal  [Select][+][-]
  1. 00000000000470a0 T add
  2.  

FPC exports only one method, but C's library exports more:

Code: Pascal  [Select][+][-]
  1.                  w _ITM_deregisterTMCloneTable
  2.                  w _ITM_registerTMCloneTable
  3.                  w __cxa_finalize
  4.                  w __deregister_frame_info
  5.                  w __register_frame_info
  6. 0000000000001175 T _fini
  7. 0000000000001000 T _init
  8. 000000000000113f T add
  9.  

here are "_init" and "_fini", I think my lib must have them exported, but how?
Title: Re: How to call a FPC compiled shared library under Alpine?
Post by: Fred vS on June 12, 2021, 02:57:11 pm
Quote
here are "_init" and "_fini", I think my lib must have them exported, but how?

Hum, I think you will need a guru.

Maybe you can try to add those "_init" and "_fini" in your lib and export it.

https://docs.oracle.com/cd/E88353_01/html/E37854/u-fini-9e.html

Sorry, I dont use Alpine so I cannot test.

Fre;D
Title: [Solved] How to call a FPC compiled shared library under Alpine?
Post by: rarnu on June 13, 2021, 04:51:36 am
Thank you all for the help. I find the final solution.

first of all, official libc6-compat must be installed into Alpine. Do NEVER install the 3rd-party glibc, it will override ld-linux-x86-64.so.2 and break other packages in Alpine because almost all packages in Alpine are built by musl-libc, and the original ld-linux-x86-64.so.2 is a symlink from libc.musl-x86_64.so .

so my solution is to remove the dependency of ld-linux-x86-64.so.2 from my lib.

use the command for make a like.res:

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

It will generate the link.res and ppas.sh. Open link.res, find "INPUT (ld-linux-x86-64.so.2)" and then remove it. run ppas.sh for build a shared library.

Code: Pascal  [Select][+][-]
  1. $ ./ppas.sh
  2.  

here can get a libmylib.so without ld-linux-x86-64.so.2 required. use "readelf -d libmylib.so" to check it.

And one more step is to remove "dynlibs" from host app. In Alpine can't use that.

I added a compile switch to it:

Code: Pascal  [Select][+][-]
  1. uses Classes, SysUtils {$IFNDEF ALPINE}, dynlibs {$ENDIF};
  2.  

and compile host app with the command:

Code: Pascal  [Select][+][-]
  1. $ fpc -dALPINE host.lpr
  2.  

well, the problem is solved.  :D

Title: Re: [SOLVED] How to call a FPC compiled shared library under Alpine?
Post by: MarkMLl on June 13, 2021, 09:53:54 am
Congratulations on fixing it and thanks for keeping us updated.

Since what you did involved changing FPC-generated files (i.e. wasn't just a fix to your Alpine configuration) I suggest it would be worthwhile posting it on Mantis so that the core developers are aware... not so much because they're expected to do support what can only be described as a minority platform but in case this could usefully be handled in a more general and widely-applicable way.

MarkMLl
Title: Re: [Solved] How to call a FPC compiled shared library under Alpine?
Post by: Fred vS on June 13, 2021, 12:57:28 pm
Code: Pascal  [Select][+][-]
  1. uses Classes, SysUtils {$IFNDEF ALPINE}, dynlibs {$ENDIF};
  2.  

well, the problem is solved.  :D

Wow, congrats!

May I ask you how do you load the library if you dont use dynlibs (LoadLibrary) ?
Do you use instead "external" (and then no dynamic loading)?

Fre;D

Title: Re: [Solved] How to call a FPC compiled shared library under Alpine?
Post by: rarnu on June 13, 2021, 06:09:26 pm
Wow, congrats!

May I ask you how do you load the library if you dont use dynlibs (LoadLibrary) ?
Do you use instead "external" (and then no dynamic loading)?

Fre;D

I have not found the way to use a library dynamically. Just the simplest code:

Code: Pascal  [Select][+][-]
  1. program host;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. uses classes, Sysutils{$IFNDEF ALPINE}, dynlibs {$ENDIF};
  6.  
  7. function add(x: integer; y: integer): integer; cdecl; external 'mylib';
  8.  
  9. begin
  10.   writeln(add(1, 2));
  11. end.
  12.  

and execute it by:

Code: Pascal  [Select][+][-]
  1. $ LD_LIBRARY_PATH=. ./host
  2.  

or make libmylib.so a symlink to "/usr/lib" is also worked.

And, I have tried something else to make it dynamic but failed. here is the code:

Code: Pascal  [Select][+][-]
  1. program host;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. uses Classes, Sysutils, dl;
  6.  
  7. type
  8.   TAdd = function (x: Integer; y: Integer): Integer; cdecl;
  9.  
  10. var
  11.   libPath: string;
  12.   lib: Pointer;
  13.   mAdd: TAdd;
  14. begin
  15.   libPath:= ExtractFilePath(ParamStr(0)) + 'libmylib.so';
  16.   lib := dlopen(PChar(libPath), RTLD_NOW);
  17.   mAdd := TAdd(dlsym(lib, 'add'));
  18.   writeln(mAdd(1, 2));
  19. end.
  20.  

this code works on my ubuntu and manjaro. But on Alpine it crashes when calling "dlopen" and no solution now.

on Alpine, even the C code with "dlopen" is also not work. Strange...
Title: Re: [Solved] How to call a FPC compiled shared library under Alpine?
Post by: Fred vS on June 13, 2021, 06:31:55 pm
Code: Pascal  [Select][+][-]
  1. program host;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. uses Classes, Sysutils, dl;
  6.  
  7. type
  8.   TAdd = function (x: Integer; y: Integer): Integer; cdecl;
  9.  
  10. var
  11.   libPath: string;
  12.   lib: Pointer;
  13.   mAdd: TAdd;
  14. begin
  15.   libPath:= ExtractFilePath(ParamStr(0)) + 'libmylib.so';
  16.   lib := dlopen(PChar(libPath), RTLD_NOW);
  17.   mAdd := TAdd(dlsym(lib, 'add'));
  18.   writeln(mAdd(1, 2));
  19. end.
  20.  

this code works on my ubuntu and manjaro. But on Alpine it crashes when calling "dlopen" and no solution now.

on Alpine, even the C code with "dlopen" is also not work. Strange...

Hum, strange indeed.

In dl.pas, "dlopen" has this code:

Code: Pascal  [Select][+][-]
  1. function dlopen(Name : PChar; Flags : longint) : Pointer; cdecl; external libdl;  

And libdl is defined as:

Code: Pascal  [Select][+][-]
  1. const
  2. {$ifdef BSD}   // dlopen is in libc on FreeBSD.
  3.   LibDL = 'c';
  4. {$else}
  5.   {$ifdef HAIKU}
  6.     LibDL = 'root';
  7.   {$else}
  8.     LibDL = 'dl';
  9.   {$endif}
  10. {$endif}        

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 somebody insinuated).

Fre;D
Title: Re: [SOLVED] How to call a FPC compiled shared library under Alpine?
Post by: engkin on June 13, 2021, 08:00:23 pm
Can you share the ppas.sh and link.res produced by FPC on your system?
Title: Re: [Solved] How to call a FPC compiled shared library under Alpine?
Post by: MarkMLl 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
Title: Re: [Solved] How to call a FPC compiled shared library under Alpine?
Post by: rarnu 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

Title: Re: [SOLVED] How to call a FPC compiled shared library under Alpine?
Post by: rarnu 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.
Title: Re: [SOLVED] How to call a FPC compiled shared library under Alpine?
Post by: rarnu 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.

Title: Re: [SOLVED] How to call a FPC compiled shared library under Alpine?
Post by: Fred vS 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
Title: Re: [SOLVED] How to call a FPC compiled shared library under Alpine?
Post by: Fred vS 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).
Title: Re: [SOLVED] How to call a FPC compiled shared library under Alpine?
Post by: engkin 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
Title: Re: [SOLVED] How to call a FPC compiled shared library under Alpine?
Post by: rarnu 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.  
Title: Re: [SOLVED] How to call a FPC compiled shared library under Alpine?
Post by: rarnu 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.
Title: Re: [SOLVED] How to call a FPC compiled shared library under Alpine?
Post by: rarnu 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.
Title: Re: [SOLVED] How to call a FPC compiled shared library under Alpine?
Post by: Fred vS 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
Title: Re: [SOLVED] How to call a FPC compiled shared library under Alpine?
Post by: MarkMLl 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
TinyPortal © 2005-2018