PS. Yes, I know that a forum post is not a blog. This is something I'm "starting small" to see if there is need and value for other from these kind of articles. They will cover all projects I work on (ABiv0, ABIv11 and AxRuntime). Please share your opinion!
----------
The next update on AxRuntime will allow creation of dual-run executables. This means the same executable can be started from Linux, either from desktop or from console, and from within "running" AxRuntime program. The second case is the case of using RunCommand() or System() APIs in your application or simply running commands and script from AROS-Shell. A command is nothing else than an executable "loaded" into shell, executed and unloaded.
Current version of AxRuntime, the 2.0 does not have the dual-run capability. It generates plain Linux ELF executables that can only be started from Linux side. On the other hand the libraries, like dos.library or intuition.library are actually ELF shared objects which are dynamically loaded uses dlopen() API. This already works great, for example AROS MPlayer compiled for AxRuntime is fully usable under Linux.
On AROS/Amiga side, loading of every binary follows the same path. Binary is loaded using LoadSeg(), control jumps to entry point function and once control returns, binary is unloaded. That's of course simplified description - in reality a few more things are happening. The AROS/Amiga entry point function has three standard arguments
(STRPTR argstr, LONG argsize, struct ExecBase *SysBase)
Knowing this, the first approach to dual-run was simple. Let's dlopen() a linux binary, execute code, and dlclose() it, mirroring AROS/Amiga behavior. The problems appeared already on first step. Since a couple of years it is no longer possible to dlopen() an ELF executable - this can only be done with ELF shared object. I didn't dive into understanding the reasons, but that's the situation right now. This meant that simplest approach failed.
Second approach then was the opposite - since ELF shared objects can be dynamically loaded to support AROS/Amiga needs, can a ELF shared object be made to be executed on Linux side? Good news is that it can! It is obviously not standard, but possible and supported. For example you can "run" Linux C library
$ /usr/lib/x86_64-linux-gnu/libc.so.6
and it will display its version and license information.
The process of achieving this is simple, once you get to understand it of course. First, the shared object needs to have a link to program interpreter placed in a specific section. This is achieved by following code:
const char dl_loader[] __attribute__((section(".interp"))) = "/lib64/ld-linux-x86-64.so.2";
Next, during building the linker needs to be informed what will be entry point that should be executed. There is a convenient linker option for this that is now embedded in axrt.specs file use during building of Ax executables. For reference, the standardized, Linux-side entry is called _axrt_start and can be viewed at
https://github.com/deadw00d/AROS/blob/alt-runtime/arch/all-runtime/axrt/startup/startup.c#L127. Last thing, that is important for debugging is to add DEBUG symbols in .dynamic section of ELF shared object. GDB uses that symbols to communicated with program interpret - without it, resolving symbols doesn't work and you are left with debuggin assembler.
Last thing to cover is AROS/Amiga-side startup. As mentioned earlier this is a function with standardized arguments and in AxRuntim case it name is standardized to __startup_entry and can be seen at
https://github.com/deadw00d/AROS/blob/alt-runtime/arch/all-runtime/axrt/startup/startup.c#L58. The name standardization is important for AxRuntime modules loader to locate it. Since the shared-object-executable can now be opened by dlopen(), dlsym() can be used to find __startup_entry function because it is exported from the ELF object.
And that's it. When executing from Linux, _axrt_start takes care of runtime initialization and eventually jumps to __startup_entry. When executing from already initialized runtime, control jumps directly to __startup_entry. Effect is for example AROS-Shell which can load and run commands!