{"id":17187992,"url":"https://github.com/icculus/mojoelf","last_synced_at":"2025-04-13T19:09:42.525Z","repository":{"id":53882931,"uuid":"381158221","full_name":"icculus/mojoelf","owner":"icculus","description":"Load ELF binaries from a memory buffer.","archived":false,"fork":false,"pushed_at":"2021-07-02T19:05:50.000Z","size":254,"stargazers_count":39,"open_issues_count":0,"forks_count":9,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-27T09:46:23.306Z","etag":null,"topics":["elf"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"zlib","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/icculus.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"github":["icculus"],"patreon":"icculus"}},"created_at":"2021-06-28T20:51:12.000Z","updated_at":"2025-03-24T01:37:00.000Z","dependencies_parsed_at":"2022-09-11T10:50:33.016Z","dependency_job_id":null,"html_url":"https://github.com/icculus/mojoelf","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/icculus%2Fmojoelf","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/icculus%2Fmojoelf/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/icculus%2Fmojoelf/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/icculus%2Fmojoelf/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/icculus","download_url":"https://codeload.github.com/icculus/mojoelf/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248766736,"owners_count":21158301,"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"],"created_at":"2024-10-15T01:07:49.806Z","updated_at":"2025-04-13T19:09:42.502Z","avatar_url":"https://github.com/icculus.png","language":"Python","funding_links":["https://github.com/sponsors/icculus","https://patreon.com/icculus"],"categories":[],"sub_categories":[],"readme":"# MojoELF\n\nMojoELF is an ELF binary loader that runs in your application instead of\nas part of the C runtime. The most useful feature of this is that, unlike\nthe standard `dlopen()`, it can load an ELF file from a place other than\nthe filesystem. Notably, it can load one from a buffer in memory.\n\n## To use this nonsense:\n\n- Add mojoelf.c to your build.\n- Compile with these #defines, or change the top of mojoelf.c:\n  ```c\n  #define MOJOELF_SUPPORT_DLERROR 0  // remove MOJOELF_dlerror() + lots of strings.\n  #define MOJOELF_SUPPORT_DLOPEN_FILE 0 // remove MOJOELF_dlopen_file()\n  #define MOJOELF_REDUCE_LIBC_DEPENDENCIES 0  // use less libc calls. Scary!\n  #define NDEBUG 1  // Turns off assert, which removes libc dependencies.\n  ```\n- Your calling code should `#include mojoelf.h` ...\n- Put your ELF library in memory, and call `MOJOELF_dlopen_mem()` with the\n  address of the memory buffer, the size of the buffer, and (optionally),\n  callbacks that handle symbol resolution (they can be NULL). Details on\n  the resolver callbacks are at the end of this document.\n- If `MOJOELF_dlopen_mem()` returns non-NULL, the library is ready to use. If\n  it returns NULL, there was a problem (`MOJOELF_dlerror()` will give you a\n  human-readable error message). On success, you can free your buffer; we\n  don't need it after `MOJOELF_dlopen_mem()` returns.\n- `MOJOELF_dlopen_file()` does the same thing, but takes a filename instead of\n  a memory buffer. Internally, it just loads the file into a malloc()'d\n  buffer and calls `MOJOELF_dlopen_mem()`.\n- To request entry points into the library, use MOJOELF_dlsym():\n  ```c\n  int (*my_function)(int argument) = MOJOELF_dlsym(lib, \"AwesomeFunc\");\n  if (my_function == NULL) {\n      printf(\"couldn't find AwesomeFunc!\\n\");\n  } else {\n      printf(\"AwesomeFunc() returns %d\\n\", my_function(123));\n  }\n  ```\n- When you are done with a library, call `MOJOELF_dlclose()` to free any\n  resources. All pointers returned by `MOJOELF_dlsym()` for this library are\n  invalid after this call.\n- Other fun stuff: `MOJOELF_getentry()` gets you the entry point for the\n  ELF file (which isn't useful on shared libraries, but is how you eventually\n  get to main() in an executable).\n\n\n## Callbacks:\n\nYou supply a handful of callbacks when calling `MOJOELF_dlopen_*()`. Any given\ncallback is allowed to be NULL, as is the pointer to the MOJOELF_callbacks if\nyou don't care about these at all. The function pointers get copied, so you\ncan free the MOJOELF_Callbacks struct as soon as `MOJOELF_dlopen_*()` returns.\n\n```c\ntypedef struct MOJOELF_Callbacks\n{\n    MOJOELF_LoaderCallback loader;\n    MOJOELF_SymbolCallback resolver;\n    MOJOELF_UnloaderCallback unloader;\n} MOJOELF_Callbacks;\n```\n\nNote that `MOJOELF_dlopen_*()` does not make any attempt to resolve dependencies\non its own, so if you want to implement something like Linux's dynamic loader,\nyou'll need to parse `LD_LIBRARY_PATH`, or whatever, on your own using these\ncallbacks. By default, without callbacks, any dependency (including libc.so)\nor unresolved symbol will cause `MOJOELF_dlopen_*()` to fail.\n\nThe \"loader\" callback doesn't necessarily load anything. All it does it tell\nMojoELF that it's claiming a specific dependency. For example, if you want to\nload an ELF that depends on libFoo.so.3, but you plan to override this\nlibrary without it actually existing, you can write a callback like this...\n\n```c\nvoid *my_loader(const char *soname, const char *rpath, const char *runpath)\n{\n    return (void *) (strcmp(soname, \"libFoo.so.3\") == 0);\n}\n```\n\n...and MojoELF will not try to load libFoo itself, and assumes you will\nprovide any needed symbols from it via your resolver callback.\n\nNote that your loader can be way more complex...it could actually _load_\nsomething, for example, but in many cases, this is all that's needed.\n\nThe loader callback is provided with any `RPATH` or `RUNPATH` entries in the\ncurrently-loading ELF. Please refer to Linux's `dlopen()` manpage for details\non these strings.\n\nThe value returned from the loader callback is opaque data. It will be passed\nto your resolver callback, and is expected to be free'd in the unloader\ncallback, if you like.\n\nThe resolver callback looks like this:\n\n```c\nextern int my_function(int argument);\n\nvoid *my_resolver(void *handle, const char *sym)\n{\n    if (strcmp(sym, \"my_function\") == 0)\n        return my_function;\n    // this also works for data, not just functions.\n    return NULL;  /* can't help you. */\n}\n```\n\nThe callback is called once for each non-NULL value that your loader\npreviously returned, in the other they were returned, until one succeeds. If\nnone succeeds, the callback fires one more time with the handle set to NULL.\nIf this still doesn't return a non-NULL value, MojoELF will fail to load the\nELF file, due to missing dependencies.\n\n\nThe unloader callback is like this:\n\n```c\nvoid my_unloader(void *handle)\n{\n    // if (handle) is something you allocated in your loader callback,\n    //  you can free it here.\n}\n```\n\n## If you have problems:\n\nAsk Ryan: icculus@icculus.org\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ficculus%2Fmojoelf","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ficculus%2Fmojoelf","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ficculus%2Fmojoelf/lists"}