doc(syscall): improve README and add example (#5135) (#5619)

Co-authored-by: Maijin <maijin21@gmail.com>
This commit is contained in:
Maijin 2025-12-15 14:02:55 +08:00 committed by GitHub
parent 129903687e
commit d28ddde0e7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 171 additions and 40 deletions

View file

@ -0,0 +1,51 @@
// SPDX-FileCopyrightText: 2025 Maijin <maijin21@gmail.com>
// SPDX-License-Identifier: LGPL-3.0-only
#include <rz_syscall.h>
#include <rz_util.h>
#include <stdio.h>
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;
}

View file

@ -4,4 +4,10 @@ if get_option('enable_examples')
dependencies: [rz_hash_dep], dependencies: [rz_hash_dep],
install: false install: false
) )
executable('linux_x64', 'api/syscall/linux_x64.c',
include_directories: [platform_inc],
dependencies: [rz_syscall_dep, rz_util_dep],
install: false
)
endif endif

View file

@ -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 <rz_syscall.h>
#include <rz_util.h>
#include <stdio.h>
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 `<os>-<arch>-<bits>.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.

View file

@ -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
}
}'

View file

@ -1,2 +0,0 @@
#!/bin/sh
grep '{ "'|tr '{",}' ' ' |sed -e 's,NULL,,g' | awk '{ print $1"="$2","$3","$4","$5}'

View file

@ -1,6 +0,0 @@
#!/bin/sh
awk -F '(=|,)' '{
print $2"."$3"="$1
# exit=0x80,1,1,i
print $1"="$2","$3
}'

View file

@ -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