{"id":23103698,"url":"https://github.com/n0thhhing/ts-capstone","last_synced_at":"2025-10-09T08:34:34.695Z","repository":{"id":229293944,"uuid":"776100132","full_name":"n0thhhing/ts-capstone","owner":"n0thhhing","description":"capstone bindings for typescript","archived":false,"fork":false,"pushed_at":"2025-01-07T23:03:01.000Z","size":19976,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-09-20T06:19:15.960Z","etag":null,"topics":["arm","arm64","assembly","bindings","capstone","dissassembler","emscripten","javascript","mips","risc-v","typescript","x86"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/n0thhhing.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}},"created_at":"2024-03-22T17:22:16.000Z","updated_at":"2025-08-11T06:27:20.000Z","dependencies_parsed_at":"2025-01-07T21:31:45.720Z","dependency_job_id":null,"html_url":"https://github.com/n0thhhing/ts-capstone","commit_stats":null,"previous_names":["n0thhhing/capstone-wrapper","n0thhhing/ts-capstone"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/n0thhhing/ts-capstone","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/n0thhhing%2Fts-capstone","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/n0thhhing%2Fts-capstone/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/n0thhhing%2Fts-capstone/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/n0thhhing%2Fts-capstone/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/n0thhhing","download_url":"https://codeload.github.com/n0thhhing/ts-capstone/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/n0thhhing%2Fts-capstone/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279001055,"owners_count":26082991,"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","status":"online","status_checked_at":"2025-10-09T02:00:07.460Z","response_time":59,"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":["arm","arm64","assembly","bindings","capstone","dissassembler","emscripten","javascript","mips","risc-v","typescript","x86"],"created_at":"2024-12-17T00:22:52.009Z","updated_at":"2025-10-09T08:34:34.680Z","avatar_url":"https://github.com/n0thhhing.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ts-capstone\nThis module provides bindings for the Capstone disassembly framework.\n\n## Quick Start\n```bash\nnpm i ts-capstone\n# note that if your using bun, you need\n# to be on version 1.1.42 canary, otherwise\n# you will get a Segmentation fault.\n# see https://github.com/oven-sh/bun/issues/15527\nbun i ts-capstone\n```\n\n## Example\n\n```typescript\nimport CS, { cs_arch, cs_mode, cs_insn, ARM64 } from './path/to/capstone.ts';\n\nconst arch: cs_arch = CS.ARCH_ARM64; // or CS.ARCH_AARCH64.\nconst mode: cs_mode = CS.MODE_ARCH;\n\nconst code: Array\u003cnumber\u003e = [\n  0x00, 0x00, 0x80, 0xd2, // 0x1000: mov x0, #0\n  0xfd, 0xfb, 0xff, 0x17, // 0x1004: b #0xfffffffffffffff8\n  0x88, 0x02, 0x40, 0xb9, // 0x1008: ldr w8, [x20]\n  0x20, 0x00, 0x02, 0x8b, // 0x100c: add x0, x1, x2\n  0x20, 0x00, 0x00, 0xf9, // 0x1010: str x0, [x1]\n  0x20, 0x00, 0x42, 0xf8, // 0x1014: ldur x0, [x1, #0x20]\n  0x20, 0x88, 0x82, 0x4f, // 0x1018: mul v0.4s, v1.4s, v2.s[2]\n];\n\nconst cs = new CS.CAPSTONE(arch, mode);\n\nconst instructions: Array\u003ccs_insn\u003e = cs.disasm(\n  code,\n  0x1000 /* optional length */,\n);\n\n// An instruction can be found in this basic format\nconst example_insn: cs_insn = {\n  id: 664, // Instruction ID (a numeric ID for the instruction mnemonic)\n  address: 4104, // Address (EIP) of this instruction\n  size: 4, // Size of this instruction\n  mnemonic: 'msr', // Ascii text of instruction mnemonic\n  op_str: 'dbgdtrtx_el0, x12', // Ascii text of instruction operands\n  bytes: [12, 5, 19, 213], // Machine bytes of this instruction, with number of bytes indicated by size above\n  // If you have detail enabled you will have\n  // a object called detail, most of it depends on\n  // the chosen architecture or the instruction\n  detail: {\n    regs_write: [], // list of implicit registers modified by this insn\n    groups: [6], // list of group this instruction belong to\n    regs_read: [], // list of implicit registers read by this insn\n    regs_read_count: 0, // number of implicit registers read by this insn\n    regs_write_count: 0, // number of implicit registers modified by this insn\n    groups_count: 1, // number of groups this insn belongs to\n    writeback: false, // Instruction has writeback operands.\n    // The detail object will have information\n    // specific to your chosen architecture, this\n    // contains things like operands, registers,\n    // and other details involving the instruction.\n    // So... Anything in the object is specific\n    // to cs_arch and the instruction itself.\n    arm64: {\n      operands: [\n        {\n          vector_index: -1,\n          vas: 0,\n          shift: { type: 0, value: 0 },\n          ext: 0,\n          access: 2,\n          type: 68, // ARM64.OP_SYS\n          sys: 38952,\n        },\n        {\n          vector_index: -1,\n          vas: 0,\n          shift: { type: 0, value: 0 },\n          ext: 0,\n          access: 1,\n          type: 1, // ARM64.OP_REG\n          reg: 230,\n        },\n      ],\n      cc: 0,\n      update_flags: false,\n      writeback: false,\n      post_index: false,\n      op_count: 2,\n    },\n  },\n};\n\nfor (const insn of instructions)\n  console.log(\n    `0x${insn.address.toString(16)}\\t${insn.mnemonic}\\t${insn.op_str}`,\n  );\n\n// if you want to iterate one at a time\n// you can use the disasm_iter method,\n// this is actually faster than using\n// cs.disasm() due to set memory allocation.\nconst data = {\n  // the input will have to be an object\n  // because primitive values like booleans,\n  // Numbers, strings, ect, are read only\n  // (The function copies the value).\n  buffer: code,\n  addr: 0x1000,\n  insn: {}, // or null, this will be filled once you call disasm_iter.\n};\n\n// this returns a boolean, which will become\n// false either when it is done iterating,\n// or if it comes upon an invalid instruction.\nwhile (cs.disasm_iter(data)) {\n  // every iteration this function goes through,\n  // it will edit the data object with the new\n  // instruction. also if the current instruction\n  // is valid and there are still instructions\n  // to go through, the data object will be\n  // updated with the next iterations bytes\n  // and address, so after the first loop,\n  // the buffer will be changed to the next set\n  // of bytes and the address will be iterated as well.\n  const insn: cs_insn = data.insn;\n  console.log(\n    `0x${insn.address.toString(16)}\\t${insn.mnemonic}\\t${insn.op_str}`,\n  );\n}\n\n// options\n\n// OPT_MNEMONIC\n\n// every time disasm (or disasm_iter) comes across\n// a movz instruction in the span of your\n// cs instance, movz will be aliased to\n// foo, the id will still remain the same as movz.\n// To reset the mnemonic, recall this with the same\n// id, but with mnemonic set to null(JavaScript null)\nconst mnObj = {\n  id: 191, // the id returned in the insn object, in this case, its movz, you can also find more in the Typescript file corresponding to your arch (arch/\u003carch\u003e.ts)\n  mnemonic: 'foo', // the new name of the mnemonic, or null\n};\ncs.option(CS.OPT_MNEMONIC, mnObj);\n\n// OPT_MODE\n\n// after using this, your cs mode\n// will be MODE_LITTLE_ENDIAN until the\n// instance is closed or changed again.\ncs.option(CS.OPT_MODE, CS.MODE_LITTLE_ENDIAN);\n\n// OPT_SYNTAX\n\ncs.option(CS.OPT_SYNTAX, CS.OPT_SYNTAX_INTEL); // Default assembly syntax of all platforms (CS.OPT_SYNTAX).\n\n// OPT_SKIPDATA\n\n// When disassembling binary code, there are\n// often sections that contain non-executable\n// data, such as ASCII strings, data structures,\n// or other non-instruction bytes. By using\n// CS.OPT_SKIPDATA, you can instruct Capstone\n// to skip over these non-instruction bytes\n// and only disassemble the actual instructions.\ncs.option(\n  CS.OPT_SKIPDATA,\n  true, // true/false/CS.OPT_ON/CS.OPT_OFF\n);\n\n// OPT_DETAIL\n\n// This option adds instructions/architecture\n// specific detail, like operands, opcodes,\n// reg_ids, groups, and in this case, a sub\n// arm64 object with detailed info specific\n// to the instruction and architecture.\ncs.option(CS.OPT_DETAIL, true);\n\n// OPT_BUFFER\n\n// When enabled, this option instructs Capstone\n// to include the raw instruction bytes and detail\n// bytes in the disassembled output. These buffers\n// contain the original bytes of the instruction\n// and any associated detail information,\n// respectively. Enabling this option can be\n// useful when needing access to the raw\n// binary data of disassembled instructions for\n// further analysis or processing.\ncs.option(CS.OPT_BUFFER, true);\n\n// To access data from the buffer in JavaScript,\n// use DataView. For types other than `int32`,\n// little-endianness is required due to the nature\n// of the underlying buffer being a Uint8Array.\n// Use DataView to read the buffer as follows:\n\n// For `int32`: Use `getInt32()` method of DataView\n// directly. For other types (e.g., `uint64`),\n// specify `littleEndian` as `true` in DataView\n// constructor to correctly interpret the bytes.\nlet buffer = /* Raw buffer received from the insn object */;\nlet view = new DataView(buffer.buffer);\nlet id = view.getUint32(0, true); // Read the 32-bit integer id from the buffer with little-endian.\nlet address = view.getBigUint64(8, true); // Read a 64-bit integer address with little-endian.\n\n// Also for things like strings(cstrings in this case),\n// you can simply use a TextDecoder, each character is\n// stored as a int8 anyways so all you have to do is\n// throw `utf-8` in the TextDecoder constructor\nconst mnemonic_bytes =\n  buffer.slice(\n    42, // offset for the mnemonic\n    74 // 74 - 42 = 32 = CS.MNEMONIC_SIZE\n  )\n\n// TextDecoder doesn't automatically stop at null\n// terminator, this isn't needed if your simply\n// inspecting it, but for comparisons there will\n// be trailing `\\u0000`\nconst mn_null_index = mn_bytes.indexOf(0);\nconst truncated_mn =\n    mn_null_index !== -1 ? mn_bytes.subarray(0, mn_null_index) : mn_bytes; // slice off every trailing null terminator\n\nconst mnemonic = new TextDecoder(\"utf-8\").decode(truncated_mn)\n\n// offsets are as follows:\n// id: 0\n// address: 8\n// size: 16\n// bytes: 18\n// mnemonic: 42\n// op_str: 74\n// detail: 0 in the insn.detail.buffer\n\n// NOT IMPLEMENTED\n\n// OPT_SKIPDATA_SETUP: will need to implement a way to create the callback this needs, while still keeping as little memory management as possible.\n// OPT_UNSIGNED: to little documentation.\n// OPT_MEM: unnecessary because you won't need to worry about any memory management.\n\n// support\n\n// this will return a boolean, true if valid\n// and false if not, To verify if this library\n// supports all the archs, use CS.ARCH_ALL(true),\n// To check if this library is in 'diet' mode,\n// set query to CS.SUPPORT_DIET(false).\ncs.support(CS.MODE_LITTLE_ENDIAN); // true\n\n// version\n\n// The version of capstone this library is using.\ncs.version(); // 5.0\n\n// group_name\n\n// This returns the name of the group\n// that an instruction can belong to\n// These groups can be found in the\n// arch/\u003carch\u003e.ts file or the detail obj\n// when CS_DETAIL is turned on.\ncs.group_name(2); // call\n\n// reg_name\n\n// These register IDs can be found either in\n// the arch/\u003carch\u003e.ts file or the detail object\n// when CS.DETAIL is on, like regs_read/regs_write.\ncs.reg_name(183); // w15\n\n// insn_name\n\n// This returns the name of the mnemonic\n// corresponding to the id. The id can be\n// found either from the (arch/\u003carch\u003e.ts)\n// file or from disassembly results.\ncs.insn_name(191); // s28\n\n// op_index\n\n// This retrieves the \"position\" of the given type.\n// This can be used to determine operands without\n// having to manually inspect the operands array.\n// This requires the detail object to be present in\n// the insn, so CS.OPT_DETAIL needs to be turned on\ncs.op_index(example_insn, ARM64.OP_REG, 1); // 1\n\n// op_count\n\n// This retrieves the operand count for the input\n// type provided an insn, which allows you to easily\n// tell how many of a certain type is present in the\n// object while not having to manually inspect the\n// detail object. This requires the detail object to\n// be present in the insn, so CS.OPT_DETAIL needs\n// to be turned on\ncs.op_count(example_insn, ARM64.OP_REG); // 1\n\n// regs_access\n\n// Retrieve all the registers accessed by an\n// instruction, either explicitly or implicitly.\ncs.regs_access(example_insn); // { regs_read: [], regs_read_count: 0, regs_write: [], regs_write_count: 0 }\n\n// reg_read\n\n// Check if a disassembled instruction IMPLICITLY\n// used a particular register. These registers can\n// be found in the constants file corresponding to\n// your chosen architecture (arch/\u003carch\u003e.ts)\ncs.reg_read(example_insn, ARM64.REG_NZCV); // false\n\n// reg_write\n\n// Check if a disassembled instruction IMPLICITLY\n// modified a particular register. These registers can\n// be found in the constants file corresponding to\n// your chosen architecture (arch/\u003carch\u003e.ts)\ncs.reg_write(example_insn, ARM64.REG_B0); // false\n\n// insn_group\n\n// Check if a disassembled instruction belong to a\n// particular group. You can find these groups\n// in the constants file corresponding to your\n// chosen architecture (arch/\u003carch\u003e.ts)\ncs.insn_group(example_insn, ARM64.GRP_PRIVILEGE); // true\n\n\n// fmt\n\n// This method is used to format the instruction\n// (or instructions) to be printable, this also\n// includes an option param that goes as follows:\nconst options = {\n  bytes: true, // Specifies if the formatted string should have the instructions bytes(default is true).\n  address: true, // Specifies if the formatted string should include the instructions address(default is true).\n  ASCII: true, // Specifies if the formatted string should include the bytes ASCII representation(default is false).\n}\nconst formatted_insn = cs.fmt(example_insn, options)\nconsole.log(formatted_insn)\n/*\noutput:\n0x1008 0c 05 13 d5 .... msr dbgdtrtx_el0, x12\n*/\n\n// close\n\n// this closes the Capstone instance, because we\n// are binding c to JS we now have to free unused\n// values, JS usually has garbage collection\n// but C does not, so we have to free the\n// capstone instance from memory manually\n// after it's no longer in use.\ncs.close();\n```\n\nyou can also take a look at the [tests](src/tests) for more specific examples.\n\n## Constants\n\nif you would like to see all the options and capstone\nconstants, you can find them in either the [capstone.ts](src/capstone.ts)\nfile or the [typescript file](src/arch) (arch/\\\u003carch\u003e.ts) for things like\nregister ids, options, error codes, groups, opcodes,\nmanifest constants, insns, ect\n\n## Compatibility\n\nAlthough all core functions have been implemented to\nthe best of my ability some helper functions and options\nhaven't and soon will if they are relivant, all of this includes\nthe following.\n\n| Case             | Compatibility |                                                       Notes |\n| :--------------- | :-----------: | ----------------------------------------------------------: |\n| Detail           |      ✅       |               Everything has also been checked and verified |\n| Architectures    |      ✅       |                                   Eveything relative to 5.0 |\n| Options          |      ❌       |                   OPT_MEM, OPT_SKIPDATA_SETUP, OPT_UNSIGNED |\n| Helper functions |      ✅       | Everything including helper functions have been implemented |\n| Web              |      ❔       |                                                    untested |\n\n## TODO\n\n- [ ] Implement all the options\n- [x] Add support for all small helper functions\n- [x] Make an npm package\n- [ ] Add better tests\n- [x] Implement cs_detail\n- [x] Make dedicated types\n- [x] Add support for all architectures\n- [x] Update capstone to 5.0\n- [x] JSDoc\n- [ ] Better error handling\n\n## Building\n\n### Prerequisites\n\n1. download the [capstone library](https://github.com/capstone-engine/capstone/releases/tag/5.0.1):\n2. Make sure you have bun and emsdk installed\n3. Install dependancies\n\n```shell\nnpm i -D\n```\n\n### Makefile\n\nThe makefile provides some commands for necessary builds, which includes...\n\n- `compile`: Compiles capstone into a static library via emcmake\n- `build`: Transpiles the static library file into js via emcc(requires make compile first)\n- `type`: Genorates declaration files\n- `bundle`: Bundles the source into one file via Bun.build\n- `format`: Formats everything\n- `compare`: A check to see if everything is the same as it is in the official capstone(manual)\n\n### Initializing\n\n```typescript\nimport Module from \"./capstone.js\"; // capstone.js should be in the src directory after building\nimport Memory from \"./memory.ts\"; // utilities for working with memory\n\nconst Capstone = new Module();\n// Use as necessary\n// ...\n```\n\n## Contributing\n\nContributions to the Capstone module are welcome. If you would like to contribute, please follow these guidelines:\n\n1. Fork the repository and clone it to your local machine.\n2. Create a new branch for your feature or bug fix: `git checkout -b my-feature`.\n3. Make your changes and test them thoroughly.\n4. Commit your changes with a clear and descriptive commit message: `git commit -am 'Add new feature'`.\n5. Push your branch to your fork: `git push origin my-feature`.\n6. Create a pull request against the main repository's `main` branch.\n\nBefore submitting a pull request, ensure that:\n\n- Your code follows the existing style and conventions ( in some cases this doesnt matter )\n- You have added appropriate documentation for your changes.\n- All existing tests pass, and you have added new tests for any new functionality.\n- The fix or added function acts as it does in the official capstone\n\n## Issues\n\nIf you encounter any bugs, have questions, or want to suggest new features for the Capstone wrapper, please open an issue on the GitHub repository.\n\nBefore opening a new issue, please ensure that:\n\n- You have searched existing issues to see if the problem or suggestion has already been reported.\n- You provide detailed information about the problem or suggestion, including steps to reproduce for bugs.\n- Make sure this isnt something to do with your JavaScript runtime, or your typescript transpiler\n\nWhen opening a new issue, please use a clear and descriptive title and provide as much context as possible to help understand the issue or suggestion.\n\n## License\n\nThis project is licensed under the `MIT` License. See the [LICENSE](LICENSE) file for more information.\n\n## Documentation\n\nFor detailed documentation on available constants and methods, refer to the source code comments or the Capstone website:\n\n- [Function Reference](https://code.dlang.org/packages/d-capstone) for constants and function documentation\n- [Capstone Website](https://www.capstone-engine.org/iteration.html) capstone website\n- [Source](https://github.com/capstone-engine/capstone) source code for capstone\n\n## Credits\n\n- [capstone](https://github.com/capstone-engine/capstone)\n- [emscripten](https://emscripten.org/docs/getting_started/downloads.html#sdk-download-and-install)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fn0thhhing%2Fts-capstone","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fn0thhhing%2Fts-capstone","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fn0thhhing%2Fts-capstone/lists"}