{"id":20126025,"url":"https://github.com/mahdisafsafi/azote","last_synced_at":"2026-03-01T08:34:46.905Z","repository":{"id":24423007,"uuid":"101286085","full_name":"MahdiSafsafi/Azote","owner":"MahdiSafsafi","description":"Fast and lightweight AArch64 disassembler.","archived":false,"fork":false,"pushed_at":"2021-12-06T15:50:48.000Z","size":359,"stargazers_count":30,"open_issues_count":3,"forks_count":11,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-08-18T03:40:04.048Z","etag":null,"topics":["aarch64","arm","disassembler","opcodes"],"latest_commit_sha":null,"homepage":null,"language":"Pascal","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MahdiSafsafi.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}},"created_at":"2017-08-24T11:06:02.000Z","updated_at":"2024-12-22T19:29:29.000Z","dependencies_parsed_at":"2022-07-25T14:02:19.368Z","dependency_job_id":null,"html_url":"https://github.com/MahdiSafsafi/Azote","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/MahdiSafsafi/Azote","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MahdiSafsafi%2FAzote","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MahdiSafsafi%2FAzote/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MahdiSafsafi%2FAzote/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MahdiSafsafi%2FAzote/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MahdiSafsafi","download_url":"https://codeload.github.com/MahdiSafsafi/Azote/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MahdiSafsafi%2FAzote/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29965406,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-01T06:55:38.174Z","status":"ssl_error","status_checked_at":"2026-03-01T06:53:04.810Z","response_time":124,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["aarch64","arm","disassembler","opcodes"],"created_at":"2024-11-13T20:12:41.459Z","updated_at":"2026-03-01T08:34:46.857Z","avatar_url":"https://github.com/MahdiSafsafi.png","language":"Pascal","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Azote\nAzote is the faster and lightweight disassembler for AArch64.\n\n# TODO\n- Add **AArch32** support.\n- Add **x86** support.\n- Possibly **SVE extension** support ? \n\n# Features\n- Extremely fast and tinny in size.\n- Supports all instructions of **ARMv8.3** including (SIMD, NEON, FP16,...).\n- No dependencies on platform specific APIs (it should run on all platforms).\n- Supports switching to aliases instructions.\n- Supports FPC and Delphi. \n- For each decoded instruction, it provides all the necessary info for a good analysis. \n- Built with unique feature \"**Patches**\" which explains why it's fast and lightweight.\n\n# Fast \u0026 lightweight\n## ADT\nAzote decodes instructions based on highly optimized arbitrary decision tree (ADT) which was generated using the same algorithm uses by GNU Binutils. However, I improved it to fits Azote needs as follow:\n- Uses single instruction for testing (only test) rather than three instruction (mov,shift and test). As a result, the generated code remains small and faster.\n- When the last node is not sealed, the tree shots the instruction that has the highest number of set bits of its mask. As a result, the disasm guarantees that it will never confuse between two similar instruction. Also, when disassembling, it will never waste time to do semantic checks that allow to distinguish between those two instructions.\n- The same rules above applies to aliases instructions.\n\n## Patches\nWhile current available solutions push instructions variants into their tables and decode operands based on a search of pattern match between the instruction and the variant. Azote does not do that! Azote decodes operands against the standard decoder and applies patches to fix the result (patches were already generated on the fly). As a result:\n- Azote's table remains small because it does not contain instruction variants.\n- Operands decoding is highly faster because it never wastes time to iterate through variants and tries to match variant's pattern.\n\n# Analys\nVery suitable for analysis. For example, we decode ```0x8B348331``` opcode.\n```pas\nvar \n  Insn: TA64Instruction;\nbegin\n  FillChar(Insn, SizeOf(TA64Instruction), #00);\n  Insn.OpCode := $8B348331;\n  DecodeInstruction(Insn);\nend;\n```\nAfter decoding it, it outputs the following info:\n```pas\nIID           = INSN_ADD\nOpCode        = 2335474481 {$8B348331}\nCondition     = cdNone\nIClass        = c_addsub_ext\nSyntax        = 'add x17, x25, w20, sxtb'\nOperandCount  = 3\nOperands[0]   = {Flags:[ofDestination]; OperandType:otRegister; Register:REG_X17}\nOperands[1]   = {Flags:[]; OperandType:otRegister; Register:REG_X25}\nOperands[2]   = {Flags:[ofShifter]; OperandType:otRegister; Register:REG_W20; Shifter:sfSxtb; Amount:0}\nOptions       = []\nUserTag       = 0\n```\n\n# Command line tool\n- **Usage**: Azote [Command] [Options] [\u003cOpCode\u003e...]\n- **Command**:\n  - -h = Display help.\n  - -d = Disasm.\n- **Options**:\n  - -L = Little Endian.\n  - -B = Big Endian.\n- **e.g**: ```Azote -d -B \"0x0B8754C5 0x8B2D6074 0xCB3333F4 0x4D4079EF 0x4CDF6C20 0x4E608400\"```\n# Benchmarks\n\nDecoding 7 million random instructions without printing:\n![bm1](https://github.com/MahdiSafsafi/Azote/blob/master/ss/bm1.PNG)\n\nDecoding 7 million random instructions with printing:\n![bm2](https://github.com/MahdiSafsafi/Azote/blob/master/ss/bm2.PNG)\n\nAs you can see, it's very fast to decode instructions. However, printing instructions slow down the process and that because Azote uses Delphi string instead of PChar. I believe I can improve the process up to [40%-60%] if I switch to PChar. But for now, I will stick with string type.\n\n# Tests\nWhile Azote currently is in beta phase, it was able to validate mostly all **LLVM** tests (95%). Because tests were automatically converted from **LLVM** to **DUnitX**, some of them escaped from the patterns match. Also, I got some false positive result with few of them (e.g: ins vs mov instruction where Azote always decodes the preferred form 'mov').\n\n# Supported compilers and platforms.\n- Azote was designed to be a cross-platform library. For now, I tested it only on windows.\n- It compiles under **Delphi** and **FPC**: Tested on FPC(3.0.2) and Delphi(10.2).\n\nPlease give feedback on this area. \n\n# Docs\nPlease refer to the [Wiki](https://github.com/MahdiSafsafi/Azote/wiki) page. And take a look to the included [demos](https://github.com/MahdiSafsafi/Azote/tree/master/demos).\n\n# Credits\n- ARM (for opening their specification).\n- LLVM (for tests).\n- Binutils (for ADT).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmahdisafsafi%2Fazote","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmahdisafsafi%2Fazote","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmahdisafsafi%2Fazote/lists"}