Provided by: radare2_6.0.7+ds-1_amd64 bug

NAME

       r_syscall — radare2 syscall information library

SYNOPSIS

       #include <r_syscall.h>

DESCRIPTION

       The  r_syscall  API  provides  a lightweight, architecture- and OS-aware syscall database used by radare2
       components such as the assembler, disassembler and  analyzer.  It  exposes  utilities  to  load  platform
       specific  syscall  tables,  query  syscall  names and numbers, parse syscall item descriptions and access
       related system registers and I/O port mappings.

       The primary object is RSyscall, which holds loaded SDB databases and small lookup  helpers.  The  API  is
       designed  for  fast in-process lookups and shallow ownership rules: callers allocate and free the context
       with the provided constructors and share references with r_syscall_ref(RSyscall *sc).

INITIALIZATION

       Create and destroy syscall contexts using the following helpers. The constructor  returns  a  new,  zero-
       initialized context with internal SDB containers ready to be loaded by r_syscall_setup(RSyscall *s, const
       char *arch, int bits, const char *cpu, const char *os).

       RSyscall * r_syscall_new(void)

       Allocates  and  returns  a  new  RSyscall  instance. New instances have internal SDB fields allocated and
       default platform values set (but no syscall data loaded until  r_syscall_setup(RSyscall  *s,  const  char
       *arch, int bits, const char *cpu, const char *os, is, called).)

       void r_syscall_free(RSyscall *ctx)

       Decrements  the  reference  counter  and  frees  the context when no more references remain. The API uses
       simple reference counting; use r_syscall_ref(RSyscall *sc, to, create, an, additional,  reference,  when,
       sharing,  the,  object,  between,  subsystems, (for, example, binding, the, analyzer, and, assembler, to,
       the, same, syscall, database).)

SETUP

       Loading  the  correct  syscall  and  sysregs  tables  for  the  target  platform  is   done   with   bool
       r_syscall_setup(RSyscall *s, const char *arch, int bits, const char *cpu, const char *os)

       Call this after creating the context (or when the target architecture / OS changes). The function chooses
       the  appropriate  SDB  file  (or embedded gperf table) using the pattern "syscall/<os>-<arch>-<bits>" and
       "sysregs/<arch>-<bits>-<cpu>".

       Typical  usage:  the  assembler/disassembler  initializes   its   local   syscall   context   and   calls
       r_syscall_setup(RSyscall  *s,  const  char  *arch,  int bits, const char *cpu, const char *os, with, the,
       same, parameters, used, to, configure, the, engine., Example, from, `libr/main/rasm2.c`:)

             as->a->syscall = r_syscall_new();
             r_syscall_setup (as->a->syscall, arch, bits, as->opt.cpu, as->opt.kernel);

       Note: the function normalizes common aliases (for example `android` -> `linux`) and may  switch  internal
       defaults for certain architectures (e.g. x86 syscall port tables).

LOOKUP BY NUMBER AND NAME

       The  main  operations  allow mapping from numbers to names (and more structured items), and from names to
       numbers. These helpers are the most used by analysis and assembly codepaths.

       RSyscallItem * r_syscall_get(RSyscall *ctx, int num, int swi)

       Given a syscall number and an optional software interrupt  selector  (swi),  returns  a  newly  allocated
       RSyscallItem  describing  the  syscall  (name, number, swi and argument information). The caller owns the
       returned item and must free it with r_syscall_item_free(RSyscallItem *si).

       Example (used in `libr/core/canal.c` to label discovered SWI instructions):

             int sig = r_syscall_get_num (core->anal->syscall, sysnumstr);
             RSyscallItem *si = r_syscall_get (core->anal->syscall, snv, -1);
             if (si) {
                 // annotate flags or print name
                 r_flag_set_next (core->flags, r_strf ("syscall.%s", si->name), cur, 1);
                 r_syscall_item_free (si);
             } else {
                 r_flag_set_next (core->flags, r_strf ("syscall.%d", snv), cur, 1);
             }

       int r_syscall_get_num(RSyscall *ctx, const char *str)

       Look up the numerical identifier for a syscall by name. This returns -1 on errors or when the database is
       not loaded. Commonly used when an assembler or scripting helper needs to convert  textual  syscall  names
       into numbers to emit proper immediates.

       Example: get the syscall number for `write`:

             int write_num = r_syscall_get_num (sc, "write");

       const char * r_syscall_get_i(RSyscall *ctx, int num, int swi)

       Returns  the  raw string key for a syscall entry (often the dotted key stored in the SDB). This helper is
       useful when you only need the textual mapping without allocating a full RSyscallItem.

LISTING

       RList * r_syscall_list(RSyscall *ctx)

       Enumerate the syscalls currently available for the loaded configuration. The  function  returns  a  newly
       allocated  RList  of  RSyscallItem objects; the caller is responsible for the list and item deallocation.
       Use this when building UIs or dump utilities that need a complete picture of the available syscall set.

             RList *list = r_syscall_list (sc);
             // iterate and free using r_list_foreach or r_list_pop

SYSREGS AND I/O PORTS

       Some platforms provide named system registers (sysregs) and well-known  I/O  port  names.  These  helpers
       query the loaded sysregs DB or fall back to small built-in tables.

       const char * r_syscall_sysreg(RSyscall *s, const char *type, ut64 num)

       Return  a  string  describing  a  system  register or resource of a given type (for example `io`, `sr` or
       vendor-specific namespaces) indexed by num. The string points into the SDB internal storage and must  not
       be freed by the caller.

       const char * r_syscall_get_io(RSyscall *s, int ioport)

       Convenience  wrapper  to  get an I/O port name by number. Internally it tries `r_syscall_sysreg (s, "io",
       ioport)` first and then consults a small in-memory table for common ports (for example on x86).

SYSITEM CREATION AND LIFETIME

       RSyscallItem * r_syscall_item_new_from_string(const char *name, const char *s)

       Parse a compact SDB-style syscall description string and return an allocated RSyscallItem. The format  is
       typically  a  comma separated string describing the swi, number, argument count and argument descriptors.
       This helper is used internally by the lookup functions and is exposed for tools that  need  to  construct
       items from raw SDB values.

       void r_syscall_item_free(RSyscallItem *si)

       Free an item previously returned by the API.

SOFTWARE INTERRUPTS (SWI)

       Some architectures multiplex syscall tables through different SWI numbers or selectors. The API exposes a
       small helper to retrieve the current default SWI for the loaded database.

       int r_syscall_get_swi(RSyscall *s)

       Returns the default software interrupt number used by the currently loaded syscall table, or -1 on error.

       Typical  callers  pass  `-1`  for  the `swi` parameter of r_syscall_get(RSyscall *ctx, int num, int swi),
       which causes the implementation to substitute the configured default value  (see  the  internal  `getswi`
       helper used by the library).

EXAMPLES

       This  section  contains  practical  code  snippets  extracted  from  radare2 sources showing common usage
       patterns.

       1) Binding and sharing a syscall context between analyzer and assembler:

             // when initializing core subsystems
             core->rasm->syscall = r_syscall_ref (core->anal->syscall); // share reference

             // when creating an independent assembler context (rasm2 example)
             as->a->syscall = r_syscall_new();
             r_syscall_setup (as->a->syscall, arch, bits, as->opt.cpu, as->opt.kernel);

       2) Annotating discovered SWI instructions in the analysis pipeline (from `libr/core/canal.c`):

             int snv = (arch == R2_ARCH_THUMB)? op.val: (int)r_reg_getv (core->anal->reg, sn);
             if (snv > 0 && snv < 0xFFFF) {
                 RSyscallItem *si = r_syscall_get (core->anal->syscall, snv, -1);
                 if (si) {
                     r_flag_set_next (core->flags, r_strf ("syscall.%s", si->name), cur, 1);
                     r_syscall_item_free (si);
                 } else {
                     r_flag_set_next (core->flags, r_strf ("syscall.%d", snv), cur, 1);
                 }
             }

       3) Looking up a numeric value from a textual name for assembly and scripting helpers:

             int num = r_syscall_get_num (sc, "write");
             if (num >= 0) {
                 // emit syscall immediate or use it in analysis
             }

       4) Enumerating and printing all loaded syscalls:

             RList *list = r_syscall_list (sc);
             RListIter *it;
             RSyscallItem *si;
             r_list_foreach (list, it, si) {
                 printf ("%s: swi=%d num=%d args=%d0, si->name, si->swi, si->num, si->args);
             }
             r_list_free (list);

SEE ALSO

       r_anal(3), r_esil(3)

Debian                                         September 20, 2025                                   R_SYSCALL(3)