Forum > Unix

Dynamically linked executables...possible?

(1/2) > >>

TCH:
In C there is the option (-Wl,--export-dynamic or -rdynamic) to link a binary dynamically. I found no option for this in the manual and according to this topic, it was not possible 3 years ago. Is it possible now?

marcov:
The FPC equivalent of -Wl is -k. So  -k--export-dynamic should do the same.

The question of course is if the object files are compatible with that, but that needs digging into the linker and its options

TCH:
Thank you. Unfortunately this did not work, but i might done it wrong. To be precise: i've made a simple test library, which is dynamically loaded by the test executable, but one of library's functions calls another one which resides in the executable and not the library. The statical approach (passing the address of that function to the library) works perfectly, but i am curious if the same dynamical approach can be applied in Pascal as in C.

The library code:
--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---library mylib; {$mode objfpc}{$H+} type TCaller = function (ptr: pinteger): integer; cdecl; var caller: TCaller; external name 'caller'; function mylib_a(a: integer): integer; cdecl;begin        result := a - 5;end; procedure mylib_b(b: pinteger); cdecl;begin        b^ := b^ - 5;end; function mylib_c(c: pinteger): integer; cdecl;begin        c^ := c^ - 5;        result := c^ - 5;end; function mylib_d(d: pinteger): integer; cdecl;begin        d^ := d^ + 5;        result := caller(d);end; exports mylib_a, mylib_b, mylib_c, mylib_d; end.The unit code:
--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---unit mylib; {$mode objfpc}{$H+} interface type        Tmylib_a = function (a: integer): integer; StdCall;        Tmylib_b = procedure (b: pinteger); StdCall;        Tmylib_c = function (c: pinteger): integer; StdCall;        Tmylib_d = function (d: pinteger): integer; StdCall; var        mylib_a: Tmylib_a;        mylib_b: Tmylib_b;        mylib_c: Tmylib_c;        mylib_d: Tmylib_d; procedure close_mylib();function init_mylib(path: string): integer; implementation uses dynlibs; const        MYLIB_ERROR_ALREADY_OPEN =      1;        MYLIB_ERROR_CANNOT_OPEN =       2;        MYLIB_ERROR_MISSING_SYMBOL =    3; var mylibhnd: TLibHandle; procedure close_mylib();begin        if (mylibhnd <> DynLibs.NilHandle) then        begin                FreeLibrary(mylibhnd);                mylibhnd := DynLibs.NilHandle;        end;end; function init_mylib(path: string): integer;begin        if (mylibhnd <> DynLibs.NilHandle) then        begin                result := MYLIB_ERROR_ALREADY_OPEN;                exit;        end;         mylibhnd := LoadLibrary(path);        if (mylibhnd = DynLibs.NilHandle) then        begin                result := MYLIB_ERROR_CANNOT_OPEN;                exit;        end;         mylib_a := Tmylib_a(GetProcedureAddress(mylibhnd, 'mylib_a'));        if (mylib_a = Tmylib_a(DynLibs.NilHandle)) then        begin                close_mylib();                result := MYLIB_ERROR_MISSING_SYMBOL;                exit;        end;         mylib_b := Tmylib_b(GetProcedureAddress(mylibhnd, 'mylib_b'));        if (mylib_b = Tmylib_b(DynLibs.NilHandle)) then        begin                close_mylib();                result := MYLIB_ERROR_MISSING_SYMBOL;                exit;        end;         mylib_c := Tmylib_c(GetProcedureAddress(mylibhnd, 'mylib_c'));        if (mylib_c = Tmylib_c(DynLibs.NilHandle)) then        begin                close_mylib();                result := MYLIB_ERROR_MISSING_SYMBOL;                exit;        end;         mylib_d := Tmylib_d(GetProcedureAddress(mylibhnd, 'mylib_d'));        if (mylib_d = Tmylib_d(DynLibs.NilHandle)) then        begin                close_mylib();                result := MYLIB_ERROR_MISSING_SYMBOL;                exit;        end;         result := 0;end; end.The main program's code:
--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---program mytest; {$mode objfpc}{$H+} uses mylib, SysUtils; function caller(ptr: pinteger): integer; cdecl;begin        ptr^ := ptr^ + 5;        result := ptr^ + 5;end; const libname = './libmylib.so';var e, a, b, c, c2, d, d2: integer; begin        e := init_mylib(libname);        if (e <> 0) then        begin                WriteLn(StdErr, 'Cannot open "' + libname + ' - error ' + IntToStr(e) + '.');                Halt(1);        end;         a := mylib_a(9);        b := 10;        mylib_b(@b);        c := 11;        c2 := mylib_c(@c);        d := 12;        d2 := mylib_d(@d);        WriteLn(StdOut, 'a = ' + IntToStr(a) + ', b = ' + IntToStr(b) + ', c = ' + IntToStr(c) + ', c2 = ' + IntToStr(c2) + ', d = ' + IntToStr(d) + ', d2 = ' + IntToStr(d2));         close_mylib();end.Compiling the library:
--- Code: Bash  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---#!/bin/shcd libfpc -CX -Xs -XX mylib.pasrm mylib.omv libmylib.so ../Compiling the executable:
--- Code: Bash  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---#!/bin/shfpc -CX -Xs -XX -k--export-dynamic mytest.pasrm mylib.o mylib.ppu mytest.ochmod +x mytestThis very same approach works if there is no calling of the main program's function, or if it is done by passing it's address to the library. Introducing the
--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---type TCaller = function (ptr: pinteger): integer; cdecl; var caller: TCaller; external name 'caller';part resulted in LoadLibrary being unable to open the library. If i do `objdump -T libmylib.so`, the symbols are seem to be in their place and the library's name is correct too:
--- Code: ---libmylib.so:     file format elf64-x86-64

DYNAMIC SYMBOL TABLE:
0000000000000ae0 g    DF .text  0000000000000005 mylib_d
0000000000000ab0 g    DF .text  0000000000000005 mylib_a
0000000000000ac0 g    DF .text  0000000000000005 mylib_b
0000000000000000      D  *UND*  0000000000000000 caller
0000000000000ad0 g    DF .text  0000000000000005 mylib_c
--- End code ---

trev:
I don't have time to go through your code or understand the issue and you do not mention the OS, but you can look at what I wrote with code examples for macOS (UNIX) in this Wiki article.

alpine:

--- Quote from: TCH on October 12, 2021, 10:12:15 pm ---*snip*
This very same approach works if there is no calling of the main program's function, or if it is done by passing it's address to the library. Introducing the
--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---type TCaller = function (ptr: pinteger): integer; cdecl; var caller: TCaller; external name 'caller';part resulted in LoadLibrary being unable to open the library. If i do `objdump -T libmylib.so`, the symbols are seem to be in their place and the library's name is correct too:
--- Code: ---libmylib.so:     file format elf64-x86-64

DYNAMIC SYMBOL TABLE:
0000000000000ae0 g    DF .text  0000000000000005 mylib_d
0000000000000ab0 g    DF .text  0000000000000005 mylib_a
0000000000000ac0 g    DF .text  0000000000000005 mylib_b
0000000000000000      D  *UND*  0000000000000000 caller
0000000000000ad0 g    DF .text  0000000000000005 mylib_c
--- End code ---

--- End quote ---

Isn't it that the 'caller' variable was declared as pointer to fn in mylib, while the 'caller' in mytest is just a function, not a var?
Have you set the LD_LIBRARY_PATH env variable?

Navigation

[0] Message Index

[#] Next page

Go to full version