Difference between revisions of "OS aware RTL"
Line 71: | Line 71: | ||
initialization | initialization | ||
if VersionToInt(LinuxVersion()) > VersionToInt('2.5.66') then | if VersionToInt(LinuxVersion()) > VersionToInt('2.5.66') then | ||
− | epoll_create_func:= | + | epoll_create_func:=Epoll.epoll_create // assign as it's there |
else | else | ||
epoll_create_func:=@Epoll.epoll_create_dummy; | epoll_create_func:=@Epoll.epoll_create_dummy; |
Revision as of 09:00, 10 March 2006
The problem
Currently there's a runtime problem with binaries created by FPC. The problem lies in libC/syscall numbers but it spans to userland as I'll explain later.
I'll talk mostly about the Linux RTL since it's the most chaotic OS out there but this really applies to any OS including Windows.
1. Syscall number changes
2. LibC functions missing
It's a known fact that syscall numbers change. This happens on all unices out there more or less frequently. The problem with FPC RTL is that it's smartlinked into the binary. Altho this is also a big advantage, the drawback is that things like syscall numbers are hardcoded. This means one of two things for ABI compatibility:
a: Old syscalls will be used on new OSes if the binary was compiled on old ones
b: Non-existing syscalls will be used on old OSes if the binary was compiled on new ones
There's more: as an example I'll use the newly added epoll* functions in linux.pp. These are used as syscalls if {$FPC_USE_LIBC} is false. This way the binaries will compile even on 2.4 kernel where epoll doesn't exist. The problem comes if someone tries to create a libfprtl.so on these systems (or use one from 2.6) since smartlinking cannot "hide" the missing functions anymore.
The proposal
Currently the only thing used to alleviate this is {$ifdef} and good luck. This won't last forever and if fpc wants to both use latest features and be backwards ABI compatible, something which I call "OS aware binaries" must be created.
Lets say we change the unit which defines syscall numbers on Linux to something like this: (note: I know it's chopped up to include file but let's keep it simple)
unit Syscalls; interface var syscall_nr_epoll_create: Integer; // defined them as variables ... implementation uses Linux, Kernel24, Kernel26; initialization if VersionToInt(LinuxVersion()) > VersionToInt('2.5.66') then begin sycall_nr_epoll_create:=...; end else begin ... end; end.
Another solution which applies to the epoll/libC problem is this:
unit Linux; interface ... function epoll_create(size: cint): cint; ... implementation uses Syscalls, Epoll; var epoll_create_func: TEpoll_CreateFunction; function epoll_create(size: cint): cint; begin epoll_create_func(size); end; initialization if VersionToInt(LinuxVersion()) > VersionToInt('2.5.66') then epoll_create_func:=Epoll.epoll_create // assign as it's there else epoll_create_func:=@Epoll.epoll_create_dummy; end.
And epoll would look something like:
unit Epoll; interface type TEpollCreateFunction = function(cint): cint; ... function epoll_create_dummy(size: cint): cint; ... var epoll_create: TEpollCreateFuncion; ... implementation {$ifndef FPC_USE_LIBC} function epoll_create_syscall(size: cint): cint; begin // do syscall stuff end; {$endif} function epoll_create_dummy(size: cint): cint; begin raise TOSMismatchException.Create; // we don't have this one here... end; initialization {$ifndef FPC_USE_LIBC} epoll_create:=dlopen(); {$else} epoll_create:=@epoll_create_syscall; {$endif} end.
This should enable libfprtl.so to be compilable and linkable on any Linux version. Ofcourse it should be compiled on latest possible so all "features" are there.
Ofcourse there are cons and pros, and inherited problems in this solution.
The pros:
- ABI compatible binaries
- Fixes certain future problems (epoll/FPC_USE_LIBC)
- It would be just cool since FPC would be the only compiler with proper ABI compat. on linux
The cons:
- Overhead both memory and CPU (initialization slows down, smartlinking would be useless on these things)
- Detection of OS version is more than tricky even with standardizef POSIX.1 functions like uname