diff --git a/examples/api/syscall/linux_x64.c b/examples/api/syscall/linux_x64.c new file mode 100644 index 0000000000..cb9f33d754 --- /dev/null +++ b/examples/api/syscall/linux_x64.c @@ -0,0 +1,51 @@ +// SPDX-FileCopyrightText: 2025 Maijin +// SPDX-License-Identifier: LGPL-3.0-only + +#include +#include +#include + +int main(void) { + RzPath *path = rz_path_new(); + if (!path) { + fprintf(stderr, "Failed to create RzPath\n"); + return 1; + } + + RzSyscall *sc = rz_syscall_new(); + if (!sc) { + fprintf(stderr, "Failed to create RzSyscall\n"); + rz_path_free(path); + return 1; + } + + // Setup for Linux x86_64 + if (!rz_syscall_setup(sc, path, "x86", 64, NULL, "linux")) { + fprintf(stderr, "Failed to setup RzSyscall for linux-x86-64\n"); + rz_syscall_free(sc); + rz_path_free(path); + return 1; + } + + // Resolve syscall number 1 (write) + int syscall_num = 1; + RzSyscallItem *item = rz_syscall_get(sc, syscall_num, -1); + if (item) { + printf("Syscall %d on Linux x86_64 is '%s'\n", syscall_num, item->name); + rz_syscall_item_free(item); + } else { + printf("Syscall %d not found\n", syscall_num); + } + + // Resolve syscall name 'open' + int num; + if (rz_syscall_get_num(sc, "open", &num)) { + printf("Syscall 'open' on Linux x86_64 is %d\n", num); + } else { + printf("Syscall 'open' not found\n"); + } + + rz_syscall_free(sc); + rz_path_free(path); + return 0; +} diff --git a/examples/meson.build b/examples/meson.build index c1251319c0..8982746e6b 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -4,4 +4,10 @@ if get_option('enable_examples') dependencies: [rz_hash_dep], install: false ) + + executable('linux_x64', 'api/syscall/linux_x64.c', + include_directories: [platform_inc], + dependencies: [rz_syscall_dep, rz_util_dep], + install: false + ) endif diff --git a/librz/syscall/README.md b/librz/syscall/README.md index e69de29bb2..4240a84765 100644 --- a/librz/syscall/README.md +++ b/librz/syscall/README.md @@ -0,0 +1,114 @@ +# RzSyscall + +`RzSyscall` provides functionality to manage system calls and system registers for different architectures and operating systems. It allows mapping between syscall numbers and names, as well as resolving system register values. + +## Architecture + +The core structure is `RzSyscall`, which holds the database of system calls loaded from SDB files. + +### Key Structures + +- `RzSyscall`: Main handle, contains the SDB database and context information (OS, Arch, CPU, Bits). +- `RzSyscallItem`: Represents a single system call with its name, number, arguments, etc. +- `RzPath`: Helper structure used during initialization to locate SDB files. + +### Workflow + +```mermaid +graph TD + A[RzPath New] --> B[RzSyscall New] + B --> C{rz_syscall_setup} + C -->|Locates SDBs| D[Load Syscall DB] + D --> E[Ready for Query] + E --> F[rz_syscall_get] + E --> G[rz_syscall_get_num] +``` + +## Usage + +Using `RzSyscall` involves the following steps: + +1. **Initialize `RzPath`**: Create an `RzPath` instance to help locate system files. +2. **Create `RzSyscall`**: Allocate a new `RzSyscall` instance. +3. **Setup**: Configure the instance with the desired OS, Architecture, and bitness using `rz_syscall_setup()`. +4. **Query**: Use functions like `rz_syscall_get()` or `rz_syscall_get_num()` to resolve syscalls. + +## Example: Resolving a Syscall on Linux x86_64 + +```c +#include +#include +#include + +int main(void) { + // 1. Create RzPath to locate SDB files + RzPath *path = rz_path_new(); + if (!path) { + fprintf(stderr, "Failed to create RzPath\n"); + return 1; + } + + // 2. Create RzSyscall instance + RzSyscall *sc = rz_syscall_new(); + if (!sc) { + fprintf(stderr, "Failed to create RzSyscall\n"); + rz_path_free(path); + return 1; + } + + // 3. Setup for Linux x86_64 + // rz_syscall_setup(sc, path, arch, bits, cpu, os) + if (!rz_syscall_setup(sc, path, "x86", 64, NULL, "linux")) { + fprintf(stderr, "Failed to setup RzSyscall for linux-x86-64\n"); + rz_syscall_free(sc); + rz_path_free(path); + return 1; + } + + // 4. Query a syscall (e.g., write = 1 on Linux x86_64) + int syscall_num = 1; + RzSyscallItem *item = rz_syscall_get(sc, syscall_num, -1); + if (item) { + printf("Syscall %d on Linux x86_64 is '%s'\n", syscall_num, item->name); + rz_syscall_item_free(item); + } else { + printf("Syscall %d not found\n", syscall_num); + } + + // Cleanup + rz_syscall_free(sc); + rz_path_free(path); + return 0; +} +``` + +## Syscall Database (SDB) + +The syscall database is stored in `librz/syscall/d` as plain text files with the `.sdb.txt` extension. These files are compiled into binary SDB files during the build process. + +### File Format + +Each line represents a syscall definition in the following format: + +``` +name=swi,num,args,types +``` + +- **name**: Name of the syscall (e.g., `write`, `open`). +- **swi**: Software interrupt number (usually `0x80` for Linux x86). +- **num**: Syscall number. +- **args**: Number of arguments. +- **types**: String representing the types of arguments (optional). + +**Key-Value Pairs for Lookup:** + +The SDB file assumes specific keys for lookup: +- `_`: Stores the default SWI number (e.g., `_=0x80`). +- `name`: Lookup by name (e.g., `write` -> `0x80,1,3,izi`). +- `swi.num`: Lookup by SWI and number (e.g., `0x80.1` -> `write`). + +### Adding a New Database + +1. Create a new file in `librz/syscall/d/` named `--.sdb.txt`. +2. Populate it with syscall definitions. +3. Add the new file to `librz/syscall/d/meson.build` to ensure it gets compiled and installed. diff --git a/librz/syscall/d/gen.sh b/librz/syscall/d/gen.sh deleted file mode 100755 index 8a35e07922..0000000000 --- a/librz/syscall/d/gen.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh -#echo "_=0x80" -awk -F '(=|,)' '{ - # 0x80.1=exit - if ($1 == "_") { - print $1"="$2 - } else { - print $2"."$3"="$1 - # exit=0x80,1,1,i - print $1"="$2","$3","$4","$5 - } -}' diff --git a/librz/syscall/d/par.sh b/librz/syscall/d/par.sh deleted file mode 100755 index 886d0364a8..0000000000 --- a/librz/syscall/d/par.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -grep '{ "'|tr '{",}' ' ' |sed -e 's,NULL,,g' | awk '{ print $1"="$2","$3","$4","$5}' diff --git a/librz/syscall/d2/gen.sh b/librz/syscall/d2/gen.sh deleted file mode 100755 index 8af3b5694d..0000000000 --- a/librz/syscall/d2/gen.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -awk -F '(=|,)' '{ - print $2"."$3"="$1 - # exit=0x80,1,1,i - print $1"="$2","$3 -}' diff --git a/librz/syscall/d2/x86-16.txt b/librz/syscall/d2/x86-16.txt deleted file mode 100644 index 7d95124d86..0000000000 --- a/librz/syscall/d2/x86-16.txt +++ /dev/null @@ -1,20 +0,0 @@ -from bochs: http://bochs.sourceforge.net/techspec/PORTS.LST - -0x0000-0x001F The first legacy DMA controller, often used for transfers to floppies. -0x0020-0x0021 The first Programmable Interrupt Controller -0x0022-0x0023 Access to the Model-Specific Registers of Cyrix processors. -0x0040-0x0047 The PIT (Programmable Interval Timer) -0x0060-0x0064 The "8042" PS/2 Controller or its predecessors, dealing with keyboards and mice. -0x0070-0x0071 The CMOS and RTC registers -0x0080-0x008F The DMA (Page registers) -0x0092 The location of the fast A20 gate register -0x00A0-0x00A1 The second PIC -0x00C0-0x00DF The second DMA controller, often used for soundblasters -0x00E9 Home of the Port E9 Hack. Used on some emulators to directly send text to the hosts' console. -0x0170-0x0177 The secondary ATA harddisk controller. -0x01F0-0x01F7 The primary ATA harddisk controller. -0x0278-0x027A Parallel port -0x02F8-0x02FF Second serial port -0x03B0-0x03DF The range used for the IBM VGA, its direct predecessors, as well as any modern video card in legacy mode. -0x03F0-0x03F7 Floppy disk controller -0x03F8-0x03FF First serial port