{"id":47577489,"url":"https://github.com/gashap0n/elfy.zig","last_synced_at":"2026-04-15T03:01:04.245Z","repository":{"id":300779905,"uuid":"1007154272","full_name":"gashap0n/elfy.zig","owner":"gashap0n","description":"Tiny and fast ELF parsing library for Zig.","archived":false,"fork":false,"pushed_at":"2026-03-26T15:16:09.000Z","size":228,"stargazers_count":18,"open_issues_count":2,"forks_count":2,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-03-27T06:09:01.307Z","etag":null,"topics":["elf","linux","parser","zig-library"],"latest_commit_sha":null,"homepage":"","language":"Zig","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gashap0n.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-06-23T14:43:24.000Z","updated_at":"2026-03-26T15:17:24.000Z","dependencies_parsed_at":"2025-08-22T15:27:28.312Z","dependency_job_id":"a0fce6dd-bcb9-4c16-914a-8402b50e78a4","html_url":"https://github.com/gashap0n/elfy.zig","commit_stats":null,"previous_names":["rawc1nnamon/zig.elfy","rawc1nnamon/elfy.zig","gashap0n/elfy.zig"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/gashap0n/elfy.zig","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gashap0n%2Felfy.zig","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gashap0n%2Felfy.zig/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gashap0n%2Felfy.zig/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gashap0n%2Felfy.zig/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gashap0n","download_url":"https://codeload.github.com/gashap0n/elfy.zig/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gashap0n%2Felfy.zig/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31824118,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-14T18:05:02.291Z","status":"online","status_checked_at":"2026-04-15T02:00:06.175Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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","linux","parser","zig-library"],"created_at":"2026-03-31T06:00:36.086Z","updated_at":"2026-04-15T03:01:04.211Z","avatar_url":"https://github.com/gashap0n.png","language":"Zig","funding_links":[],"categories":["Zig"],"sub_categories":[],"readme":"# Elfy\n\n**Elfy** is an ELF parsing library that uses **mmap** (multi-platform) to map files into memory for reading. It supports both 32-bit and 64-bit ELF formats and handles little/big-endian byte ordering.\n\n## Install\n\nFirst, you must fetch the `elfy` library for your project:\n\n```bash\nzig fetch --save git+https://github.com/gashap0n/zig.elfy#master\n```\n\nThen, after `b.addExecutable(...)`, add the following code to your `build.zig`:\n\n```zig\nconst elfy = b.dependency(\"elfy\", .{\n    .target = target,\n    .optimize = optimize,\n});\n\n// Where 'exe' is your project executable\nexe.root_module.addImport(\"elfy\", elfy.module(\"elfy\"));\n```\n\n## Basic Usage\n\nElfy offers a rich API that supports parsing the most relevant ELF data. The binary can be initialized in two modes: `.ReadOnly` or `.ReadWrite`. The latter allows basic section content modification and the creation of a new ELF with these changes.\n\n```zig\nconst std = @import(\"std\");\nconst elfy = @import(\"elfy\");\n\npub fn main() !void {\n    const allocator = std.heap.page_allocator;\n\n    // The binary must be a variable\n    var binary = try elfy.Elf.init(\"/bin/cat\", .ReadOnly, allocator);\n    defer binary.deinit();\n\n    const header = binary.getHeader();\n    std.debug.print(\"Entry {x}, Machine: {s}\\n\", .{ header.getEntryPoint(), @tagName(header.getMachine()) });\n\n    // Iterator return values must also be variables\n    var sections = try binary.getIterator(elfy.ElfSection);\n    while (try sections.next()) |section| {\n        const name = try binary.getSectionName(section);\n        const section_type = section.getType();\n        std.debug.print(\"Name: {s}, Type: {s}\\n\", .{ name, @tagName(section_type) });\n    }\n}\n```\n\n## Elf\n\n`Elf` is the struct that contains the API and can be accessed this way: `elfy.Elf`. You must initialize the binary using the `init` function: `Elf.init(path: []const u8, mode: MapMode, allocator: Allocator)` (make sure to `deinit` the binary using `defer binary.deinit()`).\n\nElfy uses a hybrid parsing method (lazy and eager). Lightweight data, such as sections, string tables, and symbol names, are processed during `init`. On the other hand, data like symbol content, dynamic symbols, and relocations are lazily parsed using an `Iterator`, which you can obtain with the following function: `try binary.getIterator(...)`. This function accepts iterable data structures, which include:\n\n* `ElfProgram`: Program/segment headers.  \n* `ElfSection`: Section headers. \n* `ElfSymbol`: Symbol sections.\n* `ElfDynamic`: Dynamic symbol sections.\n* `ElfRelocation`: Relocation sections.  \n\n```zig\n// elfy.ElfProgram, elfy.ElfSection, elfy.ElfSymbol ...\nvar sections = try binary.getIterator(elfy.ElfSection);\nwhile (try sections.next()) |section| {\n    // ...\n}\n```\n\nThe **iterator** returned by `getIterator(...)` contains a `next()` function to retrieve the next data structure (you should use a `while` loop to iterate) and a `reset()` function to reset the iterator. Additionally, the iterator includes flow control fields like `index`, `remaining`, `count`, etc. Avoid modifying these fields.\n\nLastly, the **binary** instance returned by `init(...)` contains useful functions that facilitate parsing complex structures:\n\n* `createElf(name: []const u8) ElfError!void`\n* `getHeader() ElfHeader`\n* `getIterator(comptime T: type) ElfError!Iterator(T)`\n* `getSectionName(section: ElfSection) ElfError![]const u8`\n* `getSectionData(section: ElfSection) ElfError![]const u8`\n* `getSectionByIndex(index: u64) ElfError!ElfSection`\n* `getSectionByName(name: []const u8) ElfError!ElfSection`\n* `getSectionByType(section_type: SectionType) ElfError!ElfSection`\n* `getSectionDataByName(name: []const u8) ElfError![]const u8`\n* `modifySectionData(section: ElfSection, data: []const u8) ElfError!void`\n* `getSymbolName(symbol: ElfSymbol) ElfError![]const u8`\n* `getDynName(dynamic: ElfDynamic) ElfError!?[]const u8`\n* `getRelocationLinkedSymbol(relocation: ElfRelocation, reloc_index: u64) ElfError!ElfSymbol`\n\n## ELF Structures\n\nElfy contains six data structures: `ElfHeader`, `ElfProgram`, `ElfSection`, `ElfSymbol`, `ElfDynamic`, and `ElfRelocation`. These are tagged unions that contain both 32-bit and 64-bit fields, but you don't need to use `switch (...)` to access the content. Each data structure has methods to retrieve information (see [types](src/types.zig)). For example:\n\n```zig\nvar symbols = try binary.getIterator(elfy.ElfSymbol);\nwhile (try symbols.next()) |symbol| {\n    _ = symbol.getInfo();\n    _ = symbol.getSize();\n    _ = symbol.getBind();\n    _ = symbol.getType();\n    _ = symbol.getVisibility();\n    // ...\n}\n```\n\nThere is one special case: `relocation.getType(...)` receives a machine value as a parameter (for example, `header.getMachine()`) and returns a tagged union containing the relocation type for each architecture. You must use `switch (reloc_type)` to unpack it. For example:\n\n```zig\nconst header = binary.getHeader();\nvar relocations = try binary.getIterator(elfy.ElfRelocation);\nwhile (try relocations.next()) |relocation| {\n    // relocation.getType() receives the ELF machine as parameter\n    const linked_symbol = try binary.getRelocationLinkedSymbol(relocation, relocations.index);\n    const symbol_name = try binary.getSymbolName(linked_symbol);\n    const reloc_type = try relocation.getType(header.getMachine());\n    \n    switch (reloc_type) {\n         .X86_64 =\u003e |t| std.debug.print(\"Type: {s}, Symbol Name: {s}\\n\", .{ @tagName(t), symbol_name }),\n        // You can add more architectures if needed (ARM, RISCV, SPARC, etc.)\n        else =\u003e std.debug.print(\"[!] Unsupported architecture\", .{}),\n    }\n}\n```\n\nSupported relocation types are:\n\n* `@\"386\"`\n* `S390`\n* `ARM`\n* `PPC`\n* `PPC64`\n* `MIPS`\n* `ALPHA`\n* `AARCH64`\n* `LOONGARCH`\n* `RISCV`\n* `SPARC`\n* `X86_64`\n\n## Modify Section Content\n\nWith the binary opened in `.ReadWrite` mode, you can modify the content of a section as long as the new content has a length less than or equal to the original buffer. For example:\n\n```zig\nconst buf: []const u8 = \u0026[_]u8{\n    0x48, 0xc7, 0xc0, 0x01, 0x00, 0x00, 0x00,\n    0x48, 0xc7, 0xc7, 0x01, 0x00, 0x00, 0x00,\n    0x48, 0x8d, 0x35, 0x0a, 0x00, 0x00, 0x00,\n    0x48, 0xc7, 0xc2, 0x0c, 0x00, 0x00, 0x00,\n    0x0f, 0x05, 0x48, 0xc7, 0xc0, 0x3c, 0x00,\n    0x00, 0x00, 0x48, 0xc7, 0xc7, 0x00, 0x00,\n    0x00, 0x00, 0x0f, 0x05, 0x48, 0x65, 0x6c,\n    0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c,\n    0x64,\n    0x0a,\n    // ...\n};\n\nconst text = try binary.getSectionByName(\".text\");\ntry binary.modifySectionData(text, buf);\ntry binary.createElf(\"new_binary\");\n```\n\n## What If I Need Other Data Structures?\n\nI created this library with the features I needed. If you're looking for a data structure that this parser doesn't contain (e.g., `ElfNote`, `relr`, etc.), you can create custom functions to parse it more easily. For example, if you want to parse notes:\n\n```zig\nfn parseNote(note: []const u8) !elf.Elf64_Nhdr { ... }\n// ...\n\nvar sections = try binary.getIterator(elfy.ElfSection);\nwhile (try sections.next()) |section| {\n    const raw_note = if (section.getType() == .SHT_NOTE) try binary.getSectionData(section);\n    const note = try parseNote(raw_note);\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgashap0n%2Felfy.zig","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgashap0n%2Felfy.zig","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgashap0n%2Felfy.zig/lists"}