{"id":18646695,"url":"https://github.com/rinhizakura/mini-gdbstub","last_synced_at":"2025-04-09T23:15:39.690Z","repository":{"id":59226158,"uuid":"521632519","full_name":"RinHizakura/mini-gdbstub","owner":"RinHizakura","description":"An implementation of the GDB Remote Serial Protocol to help you adding debug mode on emulator","archived":false,"fork":false,"pushed_at":"2025-04-08T17:23:52.000Z","size":125,"stargazers_count":66,"open_issues_count":2,"forks_count":14,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-09T23:15:33.874Z","etag":null,"topics":["debugger","gdbrsp","gdbserver","gdbstub"],"latest_commit_sha":null,"homepage":"","language":"C","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/RinHizakura.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}},"created_at":"2022-08-05T12:36:50.000Z","updated_at":"2025-04-08T17:23:57.000Z","dependencies_parsed_at":"2025-03-02T13:10:50.878Z","dependency_job_id":"1fcc39dd-52ba-4fc1-a104-fd85878324cf","html_url":"https://github.com/RinHizakura/mini-gdbstub","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/RinHizakura%2Fmini-gdbstub","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RinHizakura%2Fmini-gdbstub/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RinHizakura%2Fmini-gdbstub/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RinHizakura%2Fmini-gdbstub/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RinHizakura","download_url":"https://codeload.github.com/RinHizakura/mini-gdbstub/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248125592,"owners_count":21051770,"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":["debugger","gdbrsp","gdbserver","gdbstub"],"created_at":"2024-11-07T06:22:11.904Z","updated_at":"2025-04-09T23:15:39.633Z","avatar_url":"https://github.com/RinHizakura.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# mini-gdbstub\n\n`mini-gdbstub` is an implementation of the\n[GDB Remote Serial Protocol](https://sourceware.org/gdb/onlinedocs/gdb/Remote-Protocol.html)\nthat gives your emulators debugging capabilities.\n\n## Usage\n\nThe very first thing you should do is to build the statically-linked library `libgdbstub.a`.\n```\nmake\n```\n\nTo use the library in your project, you should include the file `gdbstub.h` first.\nThen, you have to initialize the pre-allocated structure `gdbstub_t` with `gdbstub_init`.\n\n```c\nbool gdbstub_init(gdbstub_t *gdbstub, struct target_ops *ops, arch_info_t arch, char *s);\n```\n\nThe parameters `s` is the easiest one to understand. It is a string of the socket\nwhich your emulator would like to bind as gdb server.\n\nThe `struct target_ops` is made up of function pointers. Each member function represents an\nabstraction of your emulator's operation. The following lists the requirement\nthat should be provided for each method:\n\nMethod         | Description\n---------------|------------------\n`cont`         | Run the emulator until hitting breakpoint or exit.\n`stepi`        | Do one step on the emulator. You may define your own step for the emulator. For example, the common design is executing one instruction.\n`get_reg_bytes` | Get the register size in bytes for the register specified by `regno` as a return value.\n`read_reg`     | Read the value of the register specified by `regno` to `*value`. Return zero if the operation success, otherwise return an errno for the corresponding error.\n`write_reg`    | Write value `value` to the register specified by `regno`. Return zero if the operation success, otherwise return an errno for the corresponding error.\n`read_mem`     | Read the memory according to the address specified by `addr` with size `len` to the buffer `*val`. Return zero if the operation success, otherwise return an errno for the corresponding error.\n`write_mem`    | Write data in the buffer `val` with size `len` to the memory which address is specified by `addr`. Return zero if the operation success, otherwise return an errno for the corresponding error.\n`set_bp`       | Set type `type` breakpoint on the address specified by `addr`. Return true if we set the breakpoint successfully, otherwise return false.\n`del_bp`       | Delete type `type` breakpoint on the address specified by `addr`. Return true if we delete the breakpoint successfully, otherwise return false.\n`on_interrupt` | Do something when receiving interrupt from GDB client. This method will run concurrently with `cont`, so you should be careful if there're shared data between them. You will need a lock or something similar to avoid data race.\n`set_cpu`      | Set the debug target CPU to `cpuid`.\n`get_cpu`      | Get the current debug target CPU `cpuid` as return value.\n\n```c\nstruct target_ops {\n    gdb_action_t (*cont)(void *args);\n    gdb_action_t (*stepi)(void *args);\n    size_t (*get_reg_bytes)(int regno);\n    int (*read_reg)(void *args, int regno, void *value);\n    int (*write_reg)(void *args, int regno, void* value);\n    int (*read_mem)(void *args, size_t addr, size_t len, void *val);\n    int (*write_mem)(void *args, size_t addr, size_t len, void *val);\n    bool (*set_bp)(void *args, size_t addr, bp_type_t type);\n    bool (*del_bp)(void *args, size_t addr, bp_type_t type);\n    void (*on_interrupt)(void *args);\n\n    void (*set_cpu)(void *args, int cpuid);\n    int (*get_cpu)(void *args);\n};\n```\n\nFor `cont` and `stepi` which are used to process the execution of emulator, their return type\nshould be `gdb_action_t`. After performing the relevant operation, you should return `ACT_RESUME`\nto continue debugging; otherwise, return `ACT_SHUTDOWN` to finish debugging. The library\ntypically uses `ACT_NONE` to take no action.\n\n```c\ntypedef enum {\n    ACT_NONE,\n    ACT_RESUME,\n    ACT_SHUTDOWN,\n} gdb_action_t;\n```\n\nFor `set_bp` and `del_bp`, the type of breakpoint which should be set or deleted is described\nin the type `bp_type_t`. In fact, its value will always be `BP_SOFTWARE` currently.\n\n```c\ntypedef enum {\n    BP_SOFTWARE = 0,\n} bp_type_t;\n```\n\nAnother structure you have to declare is `arch_info_t`. You must explicitly specify about the\nfollowing field within `arch_info_t` while integrating into your emulator:\n* `smp`: Number of target's CPU\n* `reg_num`: Number of target's registers\n\nThe `target_desc` is an optional member which could be\n`TARGET_RV32`,  `TARGET_RV64` if the emulator is RISC-V 32-bit or 64-bit instruction\nset architecture or `TARGET_X86_64` if the emulator is x86_64 instruction set architecture. Alternatively, it can be a custom target description document\nstring used by gdb. If none of these apply, simply set it to NULL.\n\n* Although the value of `reg_num` may be determined by `target_desc`, those\nmembers are still required to be filled correctly.\n\n```c\ntypedef struct {\n    char *target_desc;\n    int smp;\n    int reg_num;\n} arch_info_t;\n```\n\nAfter startup, we can use `gdbstub_run` to run the emulator as gdbstub. The `args`\ncan be used to pass the argument to any function in `struct target_ops`.\n\n```c\nbool gdbstub_run(gdbstub_t *gdbstub, void *args);\n```\n\nWhen exiting from `gdbstub_run`, `gdbstub_close` should be called to recycle the resource on\nthe initialization.\n\n```c\nvoid gdbstub_close(gdbstub_t *gdbstub);\n```\n\nFinally, you can build you project with the statically-linked library `libgdbstub.a` now!\nAdditionally, it is advised that you check the reference emulator in the directory `emu,` which\ndemonstrates how to integrate `mini-gdbstub` into your project.\n\n## Reference\n### Project\n* [bet4it/gdbserver](https://github.com/bet4it/gdbserver)\n* [devbored/minigdbstub](https://github.com/devbored/minigdbstub)\n### Article\n* [Howto: GDB Remote Serial Protocol](https://www.embecosm.com/appnotes/ean4/embecosm-howto-rsp-server-ean4-issue-2.html)\n* [TLMBoy: Implementing the GDB Remote Serial Protocol](https://www.chciken.com/tlmboy/2022/04/03/gdb-z80.html)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frinhizakura%2Fmini-gdbstub","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frinhizakura%2Fmini-gdbstub","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frinhizakura%2Fmini-gdbstub/lists"}