From e50094fa0fa9ff0f68fec1cfdbf0f454b483ca17 Mon Sep 17 00:00:00 2001 From: Bet4 <0xbet4@gmail.com> Date: Thu, 21 Apr 2022 19:15:05 +0800 Subject: [PATCH] Release udbserver 0.1.0 version --- .gitignore | 3 ++ Cargo.toml | 19 ++++++-- LICENSE | 21 ++++++++ Makefile | 16 ------- README.md | 77 ++++++++++++++++++++++++++++++ {include => assets}/udbserver.h | 0 bindings/c/README.md | 8 ++++ bindings/c/example.c | 2 +- bindings/go/README.md | 7 +++ bindings/go/example/main.go | 2 +- bindings/go/go.mod | 6 +-- bindings/go/go.sum | 4 +- bindings/go/udbserver/udbserver.go | 7 ++- bindings/java/README.md | 10 ++++ bindings/python/README.md | 10 ++++ bindings/python/setup.py | 17 +++++-- bindings/python/udbserver.c | 4 +- src/capi.rs | 3 +- src/emu.rs | 16 ++++--- src/lib.rs | 4 +- 20 files changed, 189 insertions(+), 47 deletions(-) create mode 100644 LICENSE delete mode 100644 Makefile create mode 100644 README.md rename {include => assets}/udbserver.h (100%) create mode 100644 bindings/c/README.md create mode 100644 bindings/go/README.md create mode 100644 bindings/java/README.md create mode 100644 bindings/python/README.md diff --git a/.gitignore b/.gitignore index 24a0145..ac1aa2b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,7 @@ /target +/build +dist +udbserver.egg-info Cargo.lock *.so diff --git a/Cargo.toml b/Cargo.toml index b87d081..8fc277e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,11 +2,24 @@ name = "udbserver" version = "0.1.0" authors = ["Bet4 <0xbet4@gmail.com>"] -edition = "2018" +description = "Provide Unicorn emulator with a debug server" +license = "MIT" +edition = "2021" +readme = "README.md" +repository = "http://github.com/bet4it/udbserver" +categories = ["emulators"] +keywords = ["gdb", "debugging", "emulator"] [lib] -crate-type = ["lib", "cdylib"] +crate-type = ["lib"] + +[features] +capi = [] [dependencies] gdbstub = "0.6" -unicorn-engine = { git = "https://github.com/unicorn-engine/unicorn", branch = "dev", features = ["use_system_unicorn"] } +unicorn-engine = { version = "2.0.0-rc7", features = ["use_system_unicorn"] } + +[package.metadata.capi.header] +subdirectory = false +generation = false diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..4ad3fd9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Bet4 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Makefile b/Makefile deleted file mode 100644 index a815c56..0000000 --- a/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -.PHONY: rust c java python go - -rust: - cargo build --release - -c: - cd bindings/c && gcc -I../../include -L../../target/release example.c -lunicorn -ludbserver -o example && LD_LIBRARY_PATH=../../target/release ./example - -java: - cd bindings/java && make all && LD_LIBRARY_PATH=.:../../target/release make example - -python: - cd bindings/python && python3 setup.py build_ext --inplace && LD_LIBRARY_PATH=../../target/release python3 example.py - -go: - cd bindings/go && LD_LIBRARY_PATH=../../target/release go run ./example diff --git a/README.md b/README.md new file mode 100644 index 0000000..ff64731 --- /dev/null +++ b/README.md @@ -0,0 +1,77 @@ +# udbserver - Unicorn Emulator Debug Server + +When you do emulation with [Unicorn Engine](https://www.unicorn-engine.org/), do you want to inspect the inner state during every step? + +`udbserver` is a plugin for Unicorn, provides a debug server which implements [GDB Remote Serial Protocol](https://sourceware.org/gdb/onlinedocs/gdb/Remote-Protocol.html). You can connect it by a `GDB` client and do debugging as what you do on real program. + +`udbserver` can be used as a crate by Rust program, but it also provides a C library and bindings for other languages. You can use it inside most Unicorn based projects! + +## Features + +* [x] Registers +* [x] Memory +* [x] Single Step +* [x] Breakpoint +* [x] Watchpoint +* [ ] Ctrl-C interrupt + +## Architectures support + +* i386 +* x86\_64 +* ARM +* AArch64 +* MIPS +* PowerPC + +# Usage + +## API + +`udbserver` only provides one API: + +```c +void udbserver(void* handle, uint16_t port, uint64_t start_addr); +``` + +The `handle` should be the raw handle of a Unicorn instance, `port` is the port to be listened, `start_addr` is the address which when Unicorn runs at the debug server will start and wait to be connected. if `start_addr` is provided with `0`, the debug server will start instantly. + +You can call this API inside a Unicorn hook, so you can integrate `udbserver` inside other Unicorn based project easily. + +## Used in Rust + +You can use `udbserver` as a crate in `Rust`. + +You can check the [example](examples/server.rs) on how to use it. + +And you can try it by: + +```sh +$ cargo run --example server +``` + +Then you can connect it with a `GDB` client. + +## Installation + +`udbserver` provides a C-compatible set of library, header and pkg-config files, which help you to use it with other languages. + +To build and install it you need to use [cargo-c](https://crates.io/crates/cargo-c): + +```sh +$ cargo install cargo-c +$ mkdir build +$ cargo cinstall --release --prefix=/usr --destdir build +$ sudo cp -a build/* / +``` + +## Language bindings + +After install the `udbserver` library, you can use `udbserver` in other languages. + +You could check the examples on how to use `udbserver` by different languages: + +* [C](bindings/c) +* [Go](bindings/go) +* [Java](bindings/java) +* [Python](bindings/python) diff --git a/include/udbserver.h b/assets/udbserver.h similarity index 100% rename from include/udbserver.h rename to assets/udbserver.h diff --git a/bindings/c/README.md b/bindings/c/README.md new file mode 100644 index 0000000..949bd3c --- /dev/null +++ b/bindings/c/README.md @@ -0,0 +1,8 @@ +# Use udbserver in C + +Check the [example](example.c) on how to use it. + +```sh +$ gcc example.c -lunicorn -ludbserver -o example +$ ./example +``` diff --git a/bindings/c/example.c b/bindings/c/example.c index eb76bcf..20b967b 100644 --- a/bindings/c/example.c +++ b/bindings/c/example.c @@ -1,5 +1,5 @@ #include -#include "udbserver.h" +#include int ADDRESS = 0x1000; const unsigned char ARM_CODE[64] = {0x0f, 0x00, 0xa0, 0xe1, 0x14, 0x00, 0x80, 0xe2, 0x00, 0x10, 0x90, 0xe5, 0x14, 0x10, 0x81, 0xe2, 0x00, 0x10, 0x80, 0xe5, 0xfb, 0xff, 0xff, 0xea}; diff --git a/bindings/go/README.md b/bindings/go/README.md new file mode 100644 index 0000000..1d4b01c --- /dev/null +++ b/bindings/go/README.md @@ -0,0 +1,7 @@ +# Use udbserver in Go + +Check the [example](example/main.go) on how to use it. + +```sh +$ go run ./example +``` diff --git a/bindings/go/example/main.go b/bindings/go/example/main.go index 4f8b470..3a23384 100644 --- a/bindings/go/example/main.go +++ b/bindings/go/example/main.go @@ -4,7 +4,7 @@ import ( "fmt" uc "github.com/unicorn-engine/unicorn/bindings/go/unicorn" - udbserver "sample.com/udbserver/go/udbserver" + udbserver "github.com/bet4it/udbserver/bindings/go/udbserver" ) func run() error { diff --git a/bindings/go/go.mod b/bindings/go/go.mod index 74547ac..34d4302 100644 --- a/bindings/go/go.mod +++ b/bindings/go/go.mod @@ -1,5 +1,5 @@ -module sample.com/udbserver/go +module github.com/bet4it/udbserver/bindings/go -go 1.16 +go 1.18 -require github.com/unicorn-engine/unicorn v0.0.0-20210516133931-668c43c94d5b // indirect +require github.com/unicorn-engine/unicorn v0.0.0-20220417144812-185a6fec9eaa diff --git a/bindings/go/go.sum b/bindings/go/go.sum index 2e8b6b5..38c2cef 100644 --- a/bindings/go/go.sum +++ b/bindings/go/go.sum @@ -1,2 +1,2 @@ -github.com/unicorn-engine/unicorn v0.0.0-20210516133931-668c43c94d5b h1:2EG7u1+P+rTXwIO37ciA9Te7WcpdJRzmb7jLo/c1vt8= -github.com/unicorn-engine/unicorn v0.0.0-20210516133931-668c43c94d5b/go.mod h1:vm0xtY46O4X0t1J6Ob+syPhvL38XAAidXGXmTSlcMZM= +github.com/unicorn-engine/unicorn v0.0.0-20220417144812-185a6fec9eaa h1:xm6nL6HwVdIwdXyOZBSAmBBhwJuiqd2ca2dwSyTMLoU= +github.com/unicorn-engine/unicorn v0.0.0-20220417144812-185a6fec9eaa/go.mod h1:mcHBrigWSHlMZYol9QOFnK7sbltIt/OaKP5CQBZsC+4= diff --git a/bindings/go/udbserver/udbserver.go b/bindings/go/udbserver/udbserver.go index 72fed0c..3796308 100644 --- a/bindings/go/udbserver/udbserver.go +++ b/bindings/go/udbserver/udbserver.go @@ -7,10 +7,9 @@ import ( ) /* -#cgo CFLAGS: -O3 -Wall -Werror -I../../../include -#cgo LDFLAGS: -L../../../target/release -ludbserver -#cgo linux LDFLAGS: -L../../../target/release -ludbserver -lrt -#include "udbserver.h" +#cgo CFLAGS: -O3 -Wall -Werror +#cgo LDFLAGS: -ludbserver +#include */ import "C" diff --git a/bindings/java/README.md b/bindings/java/README.md new file mode 100644 index 0000000..45ce599 --- /dev/null +++ b/bindings/java/README.md @@ -0,0 +1,10 @@ +# Use udbserver in Java + +Remember to [install Unicorn java bindings](https://github.com/unicorn-engine/unicorn/tree/master/bindings/java) before use it. + +Check the [example](Example.java) on how to use it. + +```sh +$ sudo make install +$ make example +``` diff --git a/bindings/python/README.md b/bindings/python/README.md new file mode 100644 index 0000000..1ebce5e --- /dev/null +++ b/bindings/python/README.md @@ -0,0 +1,10 @@ +# Use udbserver in Python + +Check the [example](example.py) on how to use it. + +```sh +$ sudo python3 setup.py install +$ python3 example.py +``` + +If you encounter any errors when use it, try to compile and install the latest Unicorn library and Unicorn python bindings by yourself. diff --git a/bindings/python/setup.py b/bindings/python/setup.py index a2af608..04f8bd9 100644 --- a/bindings/python/setup.py +++ b/bindings/python/setup.py @@ -1,20 +1,27 @@ #!/usr/bin/env python3 # encoding: utf-8 -from distutils.core import setup, Extension +from setuptools import setup, Extension rust_module = Extension('udbserver', sources=['udbserver.c'], libraries=['udbserver'], - include_dirs=['../../include'], - library_dirs=['../../target/release'], ) setup (name = 'udbserver', version = '0.1', - author = "Bet4", - description = """Udbserver""", + author = 'Bet4', + author_email = '0xbet4@gmail.com', + description = 'Python bindings of udbserver', + url = 'https://github.com/bet4it/udbserver', + license='MIT License', + classifiers=[ + 'Intended Audience :: Developers', + 'License :: OSI Approved :: MIT License', + 'Programming Language :: Python :: 3', + 'Topic :: Software Development :: Debuggers', + ], ext_modules = [rust_module], py_modules = [], ) diff --git a/bindings/python/udbserver.c b/bindings/python/udbserver.c index cb19d0c..f3dca71 100644 --- a/bindings/python/udbserver.c +++ b/bindings/python/udbserver.c @@ -1,7 +1,7 @@ #include #include -#include "udbserver.h" +#include static PyObject* _udbserver(PyObject *self, PyObject *args) { PyObject *uc; @@ -28,7 +28,7 @@ static PyMethodDef udbserver_methods[] = { static struct PyModuleDef udbserver_definition = { PyModuleDef_HEAD_INIT, "udbserver", - "Unicorn debugger server.", + "Unicorn emulator debug server.", -1, udbserver_methods }; diff --git a/src/capi.rs b/src/capi.rs index 2eb0873..e4f09fd 100644 --- a/src/capi.rs +++ b/src/capi.rs @@ -5,8 +5,7 @@ use std::ffi::c_void; use std::ptr::null_mut; use unicorn_engine::Unicorn; -pub type uc_handle = *mut c_void; -pub type uc_hook = *mut c_void; +type uc_handle = *mut c_void; static mut HANDLE: uc_handle = null_mut(); static mut UNICORN: Option<&mut Unicorn<()>> = None; diff --git a/src/emu.rs b/src/emu.rs index 6e8dd84..7cbeaaa 100644 --- a/src/emu.rs +++ b/src/emu.rs @@ -1,5 +1,4 @@ use crate::arch; -use crate::capi::uc_hook; use crate::reg::Register; use crate::DynResult; @@ -9,12 +8,15 @@ use gdbstub::target::ext::breakpoints::WatchKind; use gdbstub::target::{TargetError, TargetResult}; use std::collections::HashMap; use std::convert::TryFrom; +use std::ffi::c_void; use unicorn_engine::unicorn_const::{uc_error, HookType, MemType, Mode, Query}; use unicorn_engine::Unicorn; +type Hook = *mut c_void; + struct EmuState { step_state: bool, - step_hook: Option, + step_hook: Option, watch_addr: Option, } @@ -75,11 +77,11 @@ fn mem_hook(uc: &mut Unicorn<()>, _mem_type: MemType, addr: u64, _size: usize, _ pub struct Emu<'a> { uc: &'a mut Unicorn<'static, ()>, reg: Register, - bp_sw_hooks: HashMap, - bp_hw_hooks: HashMap, - wp_r_hooks: HashMap>, - wp_w_hooks: HashMap>, - wp_rw_hooks: HashMap>, + bp_sw_hooks: HashMap, + bp_hw_hooks: HashMap, + wp_r_hooks: HashMap>, + wp_w_hooks: HashMap>, + wp_rw_hooks: HashMap>, } impl<'a> Emu<'a> { diff --git a/src/lib.rs b/src/lib.rs index b85ee9a..ec45e3f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,7 @@ -mod arch; +#[cfg(feature = "capi")] mod capi; + +mod arch; mod emu; mod reg;