{"id":24369975,"url":"https://github.com/unikraft/run-app-elfloader","last_synced_at":"2025-04-10T17:33:20.311Z","repository":{"id":40240536,"uuid":"485128961","full_name":"unikraft/run-app-elfloader","owner":"unikraft","description":"Run Unikraft ELF Loader app on Linux executables","archived":false,"fork":false,"pushed_at":"2023-10-19T07:42:08.000Z","size":18583,"stargazers_count":14,"open_issues_count":3,"forks_count":12,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-03-24T15:11:13.976Z","etag":null,"topics":["elf","elf-loader","executable","static-pie","unikraft"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/unikraft.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-04-24T20:08:59.000Z","updated_at":"2025-03-07T15:55:18.000Z","dependencies_parsed_at":"2023-02-12T04:15:48.790Z","dependency_job_id":"2883a42c-c35b-423c-a6f2-b9035b6f6367","html_url":"https://github.com/unikraft/run-app-elfloader","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unikraft%2Frun-app-elfloader","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unikraft%2Frun-app-elfloader/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unikraft%2Frun-app-elfloader/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unikraft%2Frun-app-elfloader/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/unikraft","download_url":"https://codeload.github.com/unikraft/run-app-elfloader/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248261993,"owners_count":21074229,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["elf","elf-loader","executable","static-pie","unikraft"],"created_at":"2025-01-19T04:11:13.463Z","updated_at":"2025-04-10T17:33:20.277Z","avatar_url":"https://github.com/unikraft.png","language":"Shell","readme":"# Run App ELF Loader\n\nRun Linux ELF binaries, i.e. binary compatibility mode, using [`app-elfloader`](https://github.com/unikraft/app-elfloader).\nELFs must be PIE (*position-independent executables*).\nBoth static and dynamic PIE ELFs are supported.\nThe common built for Linux distributions is dynamic PIE ELFs.\n\nA list of pre-built Linux executables are located in:\n\n* the [`dynamic-apps` repository](https://github.com/unikraft/dynamic-apps): dynamic ELFs\n* the [`static-pie-apps` repository](https://github.com/unikraft/static-pie-apps): static PIE ELFs\n\nPre-built `app-elfloader` Unikraft images for KVM,  are provided:\n\n* `app-elfloader_qemu-x86_64`: This is the default image.\n  It prints out `strace`-like messages for each system call.\n* `app-elfloader_qemu-x86_64_plain`: This is the least verbose image, without `strace`-like messages.\n* `app-elfloader_qemu-x86_64_full-debug`: This image prints out extensive debugging information, including the `strace`-like messages.\n* `app-elfloader_qemu-x86_64_full-debug.dbg`: This is the above image with debugging symbols, used for debugging.\n  See more on debugging [below](#running-in-debugging-mode).\n\nOther files are:\n\n* `run_app.sh`: The prime script used to run applications.\n  See more in the [`Run Applications` section below](#run-applications).\n* `run.sh`: The back end script used to run applications and configure networking, filesystems and debugging.\n  See more in the [`Custom Runs` section below](#custom-runs).\n* `defaults`: The file with default configuration options used by `run.sh`.\n* `scripts/`: Network-configuration scripts used by `run.sh`.\n* `rootfs/`: Placeholder directory used as 9pfs root filesystem for applications that don't have a specific one.\n* `utils/`, `out/`: Old files that may be removed at some point.\n\n## Run Applications\n\n## Custom Runs\n\nIn order to have more control over the running of ELFs, such as configuring networking, filesystems and debugging, use the `run.sh` script:\n\n```console\n$ ./run.sh ../static-pie-apps/small/socket/call_socket\n\n$ ./run.sh ../static-pie-apps/sqlite3/sqlite3\n```\n\nThe default script options for the script are defined in the `defaults` file.\nThis file is sourced in the `run.sh` script.\n\nTo list all script options run it without arguments or with the `-h` argument:\n\n```console\n$ ./run.sh\nStart QEMU/KVM for ELF Loader app\n\n./run.sh [-h] [-g] [-n] [-r path/to/9p/rootfs] [-k path/to/kvm/image] path/to/exec/to/load [args]\n    -h - show this help message\n    -g - start in debug mode\n    -n - add networking support\n    -d - disable KVM\n    -r - set path to 9pfs root filesystem\n    -k - set path unikraft image\n```\n\n### Using a Root Filesystem\n\nThe `rootfs/` folder stores the filesystem that will be used by the loaded ELF via 9pfs.\nIt may require being populated with corresponding files.\nThe files to be used by each particular ELF file are located in:\n\n* the `rootfs/` subdirectory for application directory for [`static PIE ELFs`](https://github.com/unikraft/static-pie-apps)\n* the application directory for [`dynamic ELFs`](https://github.com/unikraft/dynamic-apps)\n\nFor example, to run the `sqlite3` static PIE ELF, use:\n\n```console\n$ ./run.sh -k app-elfloader_qemu-x86_64_plain -r ../static-pie-apps/sqlite3/rootfs/ ../static-pie-apps/sqlite3/sqlite3\n[...]\nPowered by\no.   .o       _ _               __ _\nOo   Oo  ___ (_) | __ __  __ _ ' _) :_\noO   oO ' _ `| | |/ /  _)' _` | |_|  _)\noOo oOO| | | | |   (| | | (_) |  _) :_\n OoOoO ._, ._:_:_,\\_._,  .__,_:_, \\___)\n             Epimetheus 0.12.0~5bd4b94d\n-- warning: cannot find home directory; cannot read ~/.sqliterc\nSQLite version 3.38.2 2022-03-26 13:51:10\nEnter \".help\" for usage hints.\nConnected to a transient in-memory database.\nUse \".open FILENAME\" to reopen on a persistent database.\nsqlite\u003e .open chinook.db\nsqlite\u003e select * from ALBUM limit 5;\n1|For Those About To Rock We Salute You|1\n2|Balls to the Wall|2\n3|Restless and Wild|2\n4|Let There Be Rock|1\n5|Big Ones|3\nsqlite\u003e\n```\n\nIn the command above, we used the `-k` option to use the `plain` ELF loader image, with minimal debugging information printed.\n\nTo run the dynamic `sqlite3` PIE ELF, use:\n\n```console\n$ ./run.sh -k app-elfloader_qemu-x86_64_plain -r ../dynamic-apps/sqlite3/ ../dynamic-apps/sqlite3/lib64/ld-linux-x86-64.so.2 /usr/bin/sqlite3\n[...]\nPowered by\no.   .o       _ _               __ _\nOo   Oo  ___ (_) | __ __  __ _ ' _) :_\noO   oO ' _ `| | |/ /  _)' _` | |_|  _)\noOo oOO| | | | |   (| | | (_) |  _) :_\n OoOoO ._, ._:_:_,\\_._,  .__,_:_, \\___)\n             Epimetheus 0.12.0~5bd4b94d\n[    0.800341] CRIT: [appelfloader] \u003cbrk.c @   60\u003e Cannot handle multiple user space heaps: Not implemented!\n-- warning: cannot find home directory; cannot read ~/.sqliterc\nSQLite version 3.22.0 2018-01-22 18:45:57\nEnter \".help\" for usage hints.\nConnected to a transient in-memory database.\nUse \".open FILENAME\" to reopen on a persistent database.\nsqlite\u003e .open chinook.db\nsqlite\u003e select * from ALBUM limit 5;\n1|For Those About To Rock We Salute You|1\n2|Balls to the Wall|2\n3|Restless and Wild|2\n4|Let There Be Rock|1\n5|Big Ones|3\nsqlite\u003e\n```\n\nFor dynamic ELFs, the ELF Loader loads the Linux dynamic linker / loader (`ld-linux-x86-64.so.2`) that, in its turn, loads the actual dynamic ELF.\n\n### Using Networking\n\nWhen running a server / network application, networking is required.\nThe `-n` option creates a bridge (`virbr0`) and runs the specific actions to provide networking support.\n\nYou can run a simple dynamic ELF server written in C using:\n\n```console\n$ ./run.sh -k app-elfloader_qemu-x86_64_plain -r ../dynamic-apps/lang/c/ ../dynamic-apps/lang/c/lib64/ld-linux-x86-64.so.2 /server\n[...]\nPowered by\no.   .o       _ _               __ _\nOo   Oo  ___ (_) | __ __  __ _ ' _) :_\noO   oO ' _ `| | |/ /  _)' _` | |_|  _)\noOo oOO| | | | |   (| | | (_) |  _) :_\n OoOoO ._, ._:_:_,\\_._,  .__,_:_, \\___)\n             Epimetheus 0.12.0~5bd4b94d\nListening on port 3333...\n```\n\nFor a more complex scenario, below is the command to run the dynamic `redis-server` ELF:\n\n```console\n$ ./run.sh -k app-elfloader_qemu-x86_64_plain -r ../dynamic-apps/redis/ ../dynamic-apps/redis/lib64/ld-linux-x86-64.so.2 /usr/bin/redis-server /etc/redis/redis.conf\n[...]\nPowered by\no.   .o       _ _               __ _\nOo   Oo  ___ (_) | __ __  __ _ ' _) :_\noO   oO ' _ `| | |/ /  _)' _` | |_|  _)\noOo oOO| | | | |   (| | | (_) |  _) :_\n OoOoO ._, ._:_:_,\\_._,  .__,_:_, \\___)\n             Epimetheus 0.12.0~5bd4b94d\n0:M 09 Apr 18:02:50.068 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo\n0:M 09 Apr 18:02:50.069 # Redis version=4.0.9, bits=64, commit=00000000, modified=0, pid=0, just started\n0:M 09 Apr 18:02:50.071 # Configuration loaded\n[    0.173187] ERR:  [libposix_process] \u003cdeprecated.c @  348\u003e Ignore updating resource 7: cur = 10032, max = 10032\n0:M 09 Apr 18:02:50.075 * Increased maximum number of open files to 10032 (it was originally set to 1024).\n0:M 09 Apr 18:02:50.078 # Fatal: Can't initialize Background Jobs.\n```\n\n`redis-server` currently block due to some issues with futexes.\n\n### Running in Debugging Mode\n\nIt is often the case you want to debug the unikernel running image using a debugger such as GDB.\nThis is enabled by the `-g` option of the `run.sh` script, together with the use of the `.dbg` image and the `debug.sh` script.\n\nNote that GDB does not load ELF symbols automatically.\nTo load those symbols, we need to know the start address which the ELF is loaded to.\nRun `run.sh` to find the start address and use the `app-elfloader_qemu-x86_64_full-debug` image.\nThis differs depending on whether running a static PIE ELF or a dynamic ELF.\n\n#### Load Address for Static PIE ELFs\n\nFor a static PIE ELF, we need the to know where `app-elfloader` loads the ELF.\nSo we do a full run of the `..._full-debug` variant of the `app-elfloader` and extract the corresponding debug message:\n\n```console\n$ ./run.sh -k app-elfloader_qemu-x86_64_full-debug ../static-pie-apps/lang/c/helloworld\n[...]\n[    0.351701] Info: [appelfloader] \u003cmain.c @  122\u003e ELF program loaded to 0x400101000-0x4001d0860 (850016 B), entry at 0x40010afa0\n[...]\n```\n\nHere the load address is `0x400101000`.\n\n#### Load Address for Static PIE ELFs\n\nFor a dynamic ELF, we need the to know where the Linux dynamic linker / loader loads the dynamic ELF.\nSimilar to the static case, we do a full run of the `..._full-debug` variant of the `app-elfloader` and extract the corresponding debug message:\n\n```console\n$ ./run.sh -k app-elfloader_qemu-x86_64_full-debug -r ../dynamic-apps/lang/c/ ../dynamic-apps/lang/c/lib64/ld-linux-x86-64.so.2 /helloworld\n[...]\nopenat(AT_FDCWD, \"/helloworld\", O_RDONLY|O_CLOEXEC) = fd:3\nread(fd:3, \u003cout\u003e\"\\x7FELF\\x02\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x03\\x00\u003e\\x00\\x01\\x00\\x00\\x00\"..., 832) = 832\nfstat(fd:3, va:0x40004f650) = OK\nmmap(NULL, 2101272, PROT_EXEC|PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, fd:3, 0) = va:0x1000002000\n[...]\n```\n\nThe final `mmap` system call, used to map the `.text` section of the `helloworld` executable (see `PROT_EXEC|PROT_READ`) provides the address for it is loaded: `0x1000002000`.\n\n#### Starting a Debugging Session\n\nTo start a debugging session, run the `run.sh` script with the `-g` option.\nWe show the case for a dynamic ELF, the same would apply for debugging static PIE ELF:\n\n```console\n$ ./run.sh -g -k app-elfloader_qemu-x86_64_full-debug -r ../dynamic-apps/lang/c/ ../dynamic-apps/lang/c/lib64/ld-linux-x86-64.so.2 /helloworld\n```\n\nIt will hang waiting for debugging inputs.\n\nOn another console, start the actual debugging interface with GDB by running the `debug.sh` script with the following arguments:\n\n* the path to the ELF being loaded\n* the memory address where the ELF is loaded (found above)\n* the `.dbg` image of the ELF Loader\n\n```console\n$ ./debug.sh -e ../dynamic-apps/lang/c/helloworld -o 0x1000002000 app-elfloader_qemu-x86_64_full-debug.dbg\n+ gdb -ex 'set confirm off' -ex 'set pagination off' -ex 'set arch i386:x86-64:intel' -ex 'target remote localhost:1234' -ex 'add-symbol-file ../dynamic-apps/lang/c/helloworld -o 0x10\n00002000' -ex 'hbreak _ukplat_entry' -ex continue -ex 'delete 1' app-elfloader_qemu-x86_64_full-debug.dbg\nGNU gdb (Ubuntu 10.2-0ubuntu1~18.04~2) 10.2\n[...]\nReading symbols from app-elfloader_qemu-x86_64_full-debug.dbg...\nThe target architecture is set to \"i386:x86-64:intel\".\nRemote debugging using localhost:1234\n0x000000000000fff0 in ?? ()\nadd symbol table from file \"../dynamic-apps/lang/c/helloworld\" with all sections offset by 0x1000002000\nReading symbols from ../dynamic-apps/lang/c/helloworld...\n(No debugging symbols found in ../dynamic-apps/lang/c/helloworld)\nHardware assisted breakpoint 1 at 0x10f790: file /home/razvan/projects/unikraft/scripts/workdir/unikraft/plat/kvm/x86/setup.c, line 300.\nContinuing.\nBreakpoint 1, _ukplat_entry (lcpu=lcpu@entry=0x210040 \u003clcpus\u003e, bi=bi@entry=0x1c0148 \u003cbi_bootinfo_sec\u003e) at /home/razvan/projects/unikraft/scripts/workdir/unikraft/plat/kvm/x86/setup.c:300\n300             _libkvmplat_init_console();\n(gdb)\n```\n\nThe `./debug.sh` sets a hardware breakpoint at the unikernel entry point (`_ukplat_entry`).\nAnd then it deletes it to make room for other hardware breakpoints.\n\nNote that you need to use hardware breakpoints when first breaking into the newly loaded executable (afterwards you can use simple software breakpoints - using `break`).\n\nWhen waiting at `_ukplat_entry` you can list the `main` symbols by running `info function main`;\nthe `main` symbol for the newly loaded executable typically starts with `0x100...` for dynamic ELFs and with `0x400...` for static PIE ELFs.\nUse `hbreak` to break.\n\n```console\n(gdb) info function main\n[...]\nNon-debugging symbols:\n0x0000001000002615  main\n(gdb) hbreak *0x0000001000002615\nHardware assisted breakpoint 2 at 0x1000002615\n(gdb) c\nContinuing.\n\nBreakpoint 2, 0x0000001000002615 in main ()\n(gdb) bt\n#0  0x0000001000002615 in main ()\n#1  0x0000001000225c87 in ?? ()\n#2  0x0000000000008000 in ?? ()\n#3  0x000000040004fe50 in ?? ()\n#4  0x0000000100000000 in ?? ()\n#5  0x0000001000002615 in frame_dummy ()\n#6  0x0000000000000000 in ?? ()\n(gdb) disass\nDump of assembler code for function main:\n=\u003e 0x0000001000002615 \u003c+0\u003e:     push   %rbp\n   0x0000001000002616 \u003c+1\u003e:     mov    %rsp,%rbp\n   0x0000001000002619 \u003c+4\u003e:     lea    0x94(%rip),%rdi        # 0x10000026b4\n   0x0000001000002620 \u003c+11\u003e:    call   0x1000002510 \u003cputs@plt\u003e\n   0x0000001000002625 \u003c+16\u003e:    mov    $0x0,%eax\n   0x000000100000262a \u003c+21\u003e:    pop    %rbp\n   0x000000100000262b \u003c+22\u003e:    ret\nEnd of assembler dump.\n(gdb)\n```\n\nTypically, you would want to break on different system calls by using `break uk_syscall_r_...` (you can use Tab-Tab to list system call symbols).\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funikraft%2Frun-app-elfloader","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Funikraft%2Frun-app-elfloader","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funikraft%2Frun-app-elfloader/lists"}