Twili
Twili is a debug monitor/bridge for homebrew applications running on the Nintendo Switch.
The debug monitor aspect of it aims to provide a sane solution for stdio and logging, and to ease development by generating crash reports and allowing debugging of running applications. The debug bridge aspect aims to provide similar utilities to ADB, allowing fast and convenient sideloading.
Table of Contents
Supported Firmware Versions
Version | Support |
---|---|
1.0.0 | Tested working (limited functionality) |
2.0.0 | Expected working |
2.1.0 - 2.3.0 | Expected working |
3.0.0 | Tested working |
3.0.1 - 4.0.0 | Expected working |
4.0.1 | Tested working |
4.1.0 | Expected working |
5.0.0 | Tested working |
5.0.1 - 5.1.0 | Expected working |
6.0.0 | Expected working |
6.0.1 | Tested working |
6.1.0 | Tested working |
6.2.0 | Tested working |
7.0.0 | Expected working |
7.0.1 | Tested working |
8.0.0 | Tested working |
Limitations
These are temporary and are planned to be addressed.
- Applets cannot be launched without an active control applet (hbmenu open).
- Applets are library applets, not applications (this means they're limited to using memory in the APPLET pool).
Application Development
If you're developing with libtransistor, Twili integration is automatic. Standard I/O will automatically be attached to the twib console.
If you're developing an application with libnx, try libtwili for twib stdio.
Most libnx applications are applets. If you're developing an applet (interacts with the user), make sure you use -a
with twib run
to run it as an applet.
If you're developing a sysmodule, you can use twib run
without -a
to run it as a sysmodule.
Application Debugging
As of v1.2.0, twib includes a GDB stub.
Features
- Works with homebrew apps and sysmodules as well as official Nintendo software
- Breakpoints
- Continuing from breakpoints and single-stepping (with twili-gdb)
- Memory viewing (
p
command) - Function calling (
p
command with twili-gdb) - Multiprocess extensions
Limitations
- twili-gdb is required for single-stepping. This is because the Horizon kernel does not implement hardware single-stepping, so I had to implement software single stepping in GDB.
- twili-gdb is required for function calling. This is because Horizon executables are marked as shared libraries but have entry point 0x0, which GDB interprets as no entry point.
- GDB File I/O and
run
commands are unsupported. Not yet implemented. - Hardware breakpoints and watchpoints are unsupported. Not yet implemented.
- Windows is unsupported. Not yet implemented.
Installing twili-gdb
If you are running Arch Linux, there is an AUR package for twili-gdb. Otherwise, you will need to build it from source. It's a standard autotools build. Make sure to specify --target=twili
, or, if you prefer longer prefixes, aarch64-twili-elf
should work too.
$ git clone https://github.com/misson20000/twili-gdb.git
$ cd twili-gdb
$ mkdir build
$ cd build
$ ../configure --target=twili --enable-targets=twili --prefix=/usr --disable-sim
$ make
$ sudo make install
Using the GDB Stub
Use the gdb stub with target extended-remote | twib gdb
.
$ twili-gdb
GNU gdb (GDB) 8.3.50.20190328-git
Copyright (C) 2019 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "--host=x86_64-pc-linux-gnu --target=twili".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".
(gdb) target extended-remote | twib gdb
Remote debugging using | twib gdb
(gdb)
You can attach to an existing process with attach 0x<pid>
. Use twib ps
from another terminal to list process IDs. I recommend loading symbol files (via command-line or via file
command) before attaching processes, since the stub does not provide symbols.
Use info threads
to list threads, break
to set breakpoints, c
to continue, etc.
Suspended Start
Many times, you don't want to attach to an existing process, but you want to debug a process from the start. There are two ways to do this.
Monitored Process Suspended Start
For monitored processes (twib run
), you can pass the -d
(or --debug-suspend
) option. Twili will block HBABIShim/AppletHost on an IPC call until a debugger is attached. This is usually good enough, but if you need suspended start on an unmonitored process (official processes) or need to debug before AppletHost, there is another way.
PM Suspended Start
The GDB stub implements two monitor commands: wait application
and wait title 0x<title id>
. These commands will wait for either any application to be launched, or the specified title ID respectively. When the application or title is launched, it will be suspended before any code at all even executes and the PID will be printed in the GDB console. Use the attach
command to attach to the suspended process.
(gdb) monitor wait application
PID: 0x8a
(gdb) attach 0x8a
Details
Base Address Detection
For "monitored processes" (launched from twib), Twili reports the base address to gdb as wherever the user-supplied executable was placed in memory. This is usually what you want, but not that this skips over HBABIShim or AppletHost, which you may see in your backtrace. For non-monitored processes, the base address reported to gdb is wherever the first static code module is. This is usually rtld
or main
.
Breakpoints
Although Horizon supports hardware breakpoints, I don't use them. Breakpoints are implemented as software breakpoints, which overwrite instructions in the process with trap instructions that trigger exceptions that gdb intercepts. Continuing from one of these requires restoring the original instruction, single stepping the thread one instruction, then restoring the trap instruction.
Single Stepping
Horizon does not support single stepping. Single stepping is implemented by predicting the next instruction and placing a breakpoint on it.
Debugging PID 0
On lower firmware versions, process IDs begin at 0. This causes assertion failures in GDB if you try to attach to process 0, so the stub will automatically translate PID 512 into process 0.
Installation
Download the latest release of twili.zip
and extract it to the root of your microSD card, letting the atmosphere
directory merge with any existing directory tree. The only CFW that I officially support is Atmosphère (v0.8.3+). Running Twili on piracy firmware will make me cry, so don't do it. 😢
You will also need to install the workstation-side tools, twib
and twibd
.
Linux
Arch Linux
If you're running Arch Linux, you can install twib-git from the AUR. This package installs twibd as a systemd service, so you're ready to launch Twili and start using twib
.
Other Linux Distrubutions
It is recommended to build twib/twibd from source. If you need a binary release though, you can download twib_linux64
and twibd_linux64
from the latest release. Twibd will likely need to be run as root to grant permissions for USB devices and /var/run, but with udev rules, you can run it as a normal user. You will need to leave twibd running in the background.
OSX
OSX users can download twib_osx64
and twibd_osx64
from the latest release. Alternatively, you may build from source.
Windows
Windows support is experimental and is being improved. Windows users may download twib_win64.exe
and twibd_win64.exe
from the latest release. Boot your switch with Twili installed, then install the libusbK-based driver package. Run twibd_win64.exe
, and leave it running in the background. twib_win64.exe
should be run from the command prompt.
Configuration
The Twili sysmodule has a number of different configuration options which can be changed by modifying sdmc:/twili.ini
. If the file does not exist, it will be generated from the current defaults.
The default configuration is as follows.
; Twili Configuration File
[twili]
service_name = twili
; paths are relative to root of sd card
hbmenu_path = /hbmenu.nro
temp_directory = /.twili_temp
[pipes]
pipe_buffer_size_limit = 0x80000
[logging]
verbosity = 0
enable_usb = true
[usb_bridge]
enabled = true
[tcp_bridge]
enabled = true
port = 15152
[twili]
service_name
Default: twili
Controls the name that is used to register the twili service with sm
.
Changing this will break a lot of things if you're not careful, but may be useful for development.
hbmenu_path
Default: /hbmenu.nro
Contains a path relative to the root of the SD card that should be used to access the homebrew menu NRO.
temp_directory
Default: /.twili_temp
Contains a path relative to the root of the SD card that should be used as a temporary directory. This directory will be created if it does not exist, and all files inside it will be deleted on every boot. It is used for storing files sent over twib run
.
[pipes]
pipe_buffer_size_limit
Default: 0x80000
Twib pipes (used for standard i/o in twib run
) will buffer up to a maximum of this amount of data. If more data is written, the write will block until the other end reads out data instead of completing instantly.
This buffering behavior greatly speeds up small writes, since otherwise each write would involve round trip USB transactions. However, it loses the assurance that a write will not return until the data has been delivered to the other end. If this is important, the pipe_buffer_size_limit
can be set to zero (0
) to disable buffering and block writes until the data is delivered to the other end and another write is ready.
[logging]
verbosity
Default: 0
Controls verbosity threshold for various log messages for debugging. Higher is more verbose.
- 0: Default
- 1:
USBBridge::RequestReader
shows message headers
enable_usb
Default: true
Controls whether the USB serial port endpoints are exposed or not.
[usb_bridge]
enabled
Default: true
Controls whether the USB bridge is enabled or not. This can be turned off if it's conflicting with something else that needs USB, or if Nintendo changes the usb:ds
interface again.
[tcp_bridge]
enabled
Default: true
Controls whether the TCP bridge is enabled or not. This can be turned off if you don't want Twili to constantly try to bring up a network connection, or if you're concerned about security.
port
Default: 15152
Controls which port the TCP bridge listens on.
Building From Source
Twili
First, you will need to install libtransistor. Download the latest release from my fork, extract it somewhere, and set LIBTRANSISTOR_HOME
to that path. After that, building Twili should be as simple as running make
. To use Atmosphère-boot2 to launch Twili, you can copy the files from build/atmosphere/
to the /atmosphere/
directory on your microSD card. You will also need to install switch-tools. The preferred way to do this is through dkp-pacman.
Twib
Linux / OSX
You will need libusb development headers installed. On Debian-based distros, these are usually in the libusb-1.0.0-dev
package.
Clone this repo and clone its submodules.
$ git clone --recurse-submodules git@github.com:misson20000/twili.git
Change into the twib/
subdirectory, and make a build/
directory.
$ cd twib
$ mkdir build
$ cd build
Choose your configuration parameters for CMake, run CMake, and build twib/twibd.
$ cmake -G "Unix Makefiles" .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr -DWITH_SYSTEMD=ON
$ make -j4
Finally, you can install twib/twibd.
$ sudo make install
If you are using systemd and built with systemd support, you will want to enable the twibd socket.
$ sudo systemctl enable --now twibd.socket
If you are using macOS/OSX and built with launchd support, you will want to enable the twibd service.
$ sudo launchctl enable system/com.misson20000.twibd
$ sudo launchctl bootstrap system /Library/LaunchDaemons/com.misson20000.twibd.plist
Twib Usage
twib
is the command line tool for interacting with Twili. The twibd
daemon needs to be running in order to use twib
. On Linux systems, it is recommended to use the systemd units provided. The twibd
daemon acts as a driver for Twili, so that you can run multiple copies of twib
at the same time that all interact with the same device.
Twili debug monitor client
Usage: twib [OPTIONS] SUBCOMMAND
Options:
-h,--help Print this help message and exit
-d,--device DeviceId (Env:TWIB_DEVICE)
Use a specific device
-v,--verbose Enable debug logging
-f,--frontend TEXT in {tcp,unix} (Env:TWIB_FRONTEND)
-P,--unix-path TEXT (Env:TWIB_UNIX_FRONTEND_PATH)
Path to the twibd UNIX socket
-p,--tcp-port UINT (Env:TWIB_TCP_FRONTEND_PORT)
Port for the twibd TCP socket
-n,--pipe-name TEXT (ENV:TWIB_NAAMED_PIPE_FRONTEND_NAME)
Name for the twibd pipe
Subcommands:
list-devices List devices
connect-tcp Connect to a device over TCP
run Run an executable
reboot Reboot the device
coredump Make a coredump of a crashed process
terminate Terminate a process on the device
ps List processes on the device
identify Identify the device
list-named-pipes List named pipes on the device
open-named-pipe Open a named pipe on the device
get-memory-info Gets memory usage information from the device
debug Prints debug info
launch Launches an installed title
pull Pulls files from device's SD card
push Pushes files to device's SD card
All twib
commands require a device to be specified, except for list-devices
and connect-tcp
. If no device is explicitly specified and there is exactly one device currently connected to the daemon, that device will be used. Otherwise, a device must be specified by device ID (obtained from list-devices
) via the -d
option or the TWIB_DEVICE
environment variable.
Detailed help on all subcommands can be obtained by running twib <subcommand> --help
.
twib list-devices
Lists all devices currently known to Twib.
$ twib list-devices
Device ID | Nickname | Firmware Version | Bridge Type
1e462a6e | m20k's Switch | 4.0.1 | tcp
f41efe28 | m20k's Switch | 3.0.0 | usb
twib connect-tcp
Attempts to connect to a device over TCP by address and optional port number.
$ twib connect-tcp 10.0.0.218
twib run
Runs an NRO executable on the target console.
If the -a
flag is used, the executable will be run in applet mode. These are called AppletProcess internally and are managed by AppletTracker. If the homebrew menu is open already, it will be closed and the applet started. Otherwise, you will have to open the homebrew menu first and the applet will be automatically launched. Only one such applet can be run at a time, so they will be queued instead.
If the -a
flag is not used, the executable will be run as a background process managed via pm:shell
. These are called ShellProcess internally and are managed by ShellTracker.
In the future, both shell and applet processes will be able to be launched from ExeFS NSP, NSO, NRO, or ELF.
Twib will stay alive until the process exits. If the application implements Twili stdio, any output from the process will come out of twib and any input given to Twib will be sent to the target process. You can use the -q
flag to silence the PID output if you are using twib in a shell script or pipeline.
$ twib run test_helloworld.nro
PID: 0x85
Hello, World!
twib reboot
Reboots the target console. This performs a hard, dirty reboot.
$ twib reboot
twib coredump
Creates an ELF core dump from the given running process ID. This core dump will be suitable for loading in radare2, aarch64-linux-gnu-gdb
(note: not aarch64-none-elf-gdb
), IDA, or faron. This may take a few minutes depending on how much memory the process is using, up to tens of minutes for games such as Breath of the Wild. The process is not terminated afterwards.
$ twib coredump am.elf 0x57
twib terminate
Terminates a process on the target console by PID.
$ twib terminate 0x57
twib ps
Lists all processes running on the target console, whether pm knows about them or not. One process will come up with error 0x16ef
in the result column. This process is Twili itself, and the error represents Twili's refusal to attempt to debug itself.
$ twib ps
Process ID | Result | Title ID | Process Name | MMU Flags
0x1 | 0x0 | 0x100000000000000 | FS | 0x27
0x2 | 0x0 | 0x100000000000001 | Loader | 0x27
0x3 | 0x0 | 0x100000000000002 | NCM | 0x27
0x4 | 0x0 | 0x100000000000003 | ProcessMana | 0x27
0x5 | 0x0 | 0x100000000000004 | sm | 0x27
0x6 | 0x0 | 0x100000000000028 | spl | 0x27
0x51 | 0x0 | 0x100000000000021 | psc | 0x137
0x52 | 0x0 | 0x10000000000001d | pcie.withou | 0x137
...
twib identify
Shows identifying information for the target console.
$ twib identify
bluetooth_bd_address : [ ... ]
device_nickname : m20k's Switch
firmware_version : [ ... ]
mii_author_id : [ ... ]
protocol : 2
serial_number : XAW...
service : twili
wireless_lan_mac_address : [ ... ]
twib list-named-pipes
Lists any named pipes that exist on the target console. Typically, none will exist to be listed here. Named pipes are a way for sysmodules to output debug messages over Twili without being monitored by Twili.
$ twib list-named-pipes
twib open-named-pipe
Opens a named pipe. Twib will stay alive until the pipe is closed, and will continuously output messages sent over the pipe.
$ twib open-named-pipe testpipe
twib get-memory-info
Shows memory usage information on the target console.
$ twib get-memory-info
Twili Memory: 16 MiB / 38 MiB (42%)
System Category Limit: 280 MiB / 303 MiB (92%)
Application Category Limit: 0 MiB / 3285 MiB (0%)
Applet Category Limit: 82 MiB / 501 MiB (16%)
twib debug
Requests for Twili to print debug information to its standard output. Twib shouldn't output anything. See twibd's logs for output.
twib launch
Launches a title on the console using pm:shell. Note that this is not sufficient to launch games.
$ twib launch 01006A800016E000 gc
0x81
Understood Locations:
- none
- host
- gamecard, gc
- nand-system, system
- nand-user, user
- sdcard, sd
twib pull
Pulls files from the device's SD card. Multiple files can be pulled if the destination is a directory.
If the destination is -
, file contents will be written to standard output.
$ twib pull /path/to/file/on/device1 /another/file/on/device2 /destination/directory/on/host/
/path/to/file/on/device1 -> /destination/directory/on/host/device1
/another/file/on/device2 -> /destination/directory/on/host/device2
NOTE: If you're running twib
from a mingw environment, you will need to put two forward slashes in front of device paths to prevent them from being converted to Windows paths.
$ twib pull //path/to/file/on/device1 //another/file/on/device2 /destination/directory/on/host/
/path/to/file/on/device1 -> /destination/directory/on/host/device1
/another/file/on/device2 -> /destination/directory/on/host/device2
twib push
Pushes files to device's SD card. Multiple files can be pushed if the destination is a directory.
$ twib push /path/to/file/on/host1 /path/to/another/host/file /destination/directory/on/device/
/path/to/file/on/host1 -> /destination/directory/on/device/host1
/path/to/another/host/file -> /destination/directory/on/device/file
NOTE: If you're running twib
from a mingw environment, you will need to put two forward slashes in front of device paths to prevent them from being converted to Windows paths.
$ twib push /path/to/file/on/host1 /path/to/another/host/file //destination/directory/on/device/
/path/to/file/on/host1 -> /destination/directory/on/device/host1
/path/to/another/host/file -> /destination/directory/on/device/file
Developer Details
Project Organization
- common: Code common between Twili and Twib.
- docs: Documentation
- hbabi_shim: Homebrew ABI shim
- twib: PC-side bridge client
- cmake: CMake modules
- common: Code common between tool and daemon
- daemon:
twibd
driver daemon - externals: Dependency submodues
- platform: Platform specific code
- tool:
twib
command-line tool
- twili: Main
twili
sysmodule- twili/bridge: Bridge code
- twili/bridge/interfaces: Twib endpoints
- twili/bridge/tcp: TCPBridge implementation
- twili/bridge/usb: USBBridge implementation
- twili/ipcbind: IPC client code for various services
- twili/msgpack11: msgpack11 submodule
- twili/process: Process management code.
- twili/process/fs: Virtual filesystem code
- twili/service: IPC service code
- twili/bridge: Bridge code
- twili_applet_shim: Applet shim code
- twili_common: Code common between twili components that run on console
Title Table
Title ID | Description |
---|---|
0100000000006480 | Twili Sysmodule |
0100000000006481 | Twili Managed Process (twib run) |
0100000000006482 | Twili Applet Shim |
Process Management
- Process: Base class. Exposes
GetPid
,AddNotes
, andTerminate
.- MonitoredProcess: Process started by Twili.
- ManagedProcess: Processes that hide from
pm
and are managed by Twili. - AppletProcess: Library applet managed by am/pm.
- ManagedProcess: Processes that hide from
- UnmonitoredProcess: Shim for quick operations on arbitrary processes.
- MonitoredProcess: Process started by Twili.
Homebrew ABI Shim
This is a small chunk of code that is loaded before each application that obtains Homebrew ABI keys and handles from Twili, passes them on to the application, and passes the application's return code back to Twili when it exits.
Applet Shim
Twili uses Atmosphere-loader's SetExternalContentSource extension to override the album applet with twili_applet_shim
, which has two jobs. One of them is to connect to Twili and wait for messages. Only one instance of twili_applet_shim
should be running in this mode at a time, and it is called the "control applet". When Twili needs to launch an applet, it uses the SetExternalContentSource extension again to add the target executable to the next instance of twili_applet_shim
to be launched. It then sends a message to the control applet telling it to ask am to launch another album applet. This new instance of twili_applet_shim
will come up and connect to Twili, and fulfill the other job, becoming a "host applet". Twili will attach this applet to the respective AppletProcess
instance, and then pass over all relevant HBABI keys and the host applet shim will jump to the target process image.
Twib
Twib is the workstation-side tool, consisting of two parts: twibd
, and twib
. twibd
is the server side, which communicates with Twili over USB or sockets, and multiplexes access between multiple instances of the twib
client-side. The twibd
server-side has a number of backends, which handle talking to Twili. It also has a number of frontends, which accept connections from the twib
client. On UNIX systems, this is a UNIX socket. On Windows systems, this is a named pipe.
The frontend and backend each run in their own threads to simplify synchronization.
Protocol Overview
Twili will provide a USB interface with class 0xFF, subclass 0x01, and protocol 0x00. This interface shall have four bulk endpoints, two IN, and two OUT. Communication happens as requests and responses over these endpoints.
A request contains an id for the remote bridge object that should handle the request, a command id to determine which function the remote object is to perform, a tag to associate the request with its response, and an arbitrarily sized payload containing any additional data needed for the operation.
The request header is sent over the first OUT endpoint as a single transfer. Next, if the request header indicates that a payload is present, the data is sent over the second OUT endpoint. Finally, if the request header indicates that there are objects being sent, the IDs of each object are sent over the same (second) OUT endpoint in a single transfer.
Once the request is processed, a response header is sent over the first IN endpoint. If the response header indicates that a payload is present, it is sent over the second IN endpoint. If the response header indicates that there are objects being sent, the IDs of each object are sent over the same (second) IN endpoint in a single transfer.
Upon receiving a request, the specified function is invoked on the specified object.
When the operation completes, as either a success or a failure, a response is sent.
The response's tag
field must match the tag of the request that started the operation.
Any operation may be executed asynchronously, meaning that responses may be sent in a
different order from the requests that caused them.
If a response includes any references to bridge objects, their IDs are encoded in the payload as indexes into the array of object IDs sent with the response.
Requests and responses share a similar format.
struct message {
// header
union {
u32 device_id; // for transport between twib and twibd
u32 client_id; // for transport between twibd and twili
};
u32 object_id;
union {
u32 command_id; // request
u32 result_code; // response
};
u32 tag;
u64 payload_size;
u32 object_count;
// payload
u8 payload[payload_size];
// object IDs
u32 object_ids[object_count];
};
Initially, only the object with id 0 exists on the device. It represents ITwibDeviceInterface
.
Every object responds to command 0xffffffff
, which destroys the object, except for
ITwibDeviceInterface
which handles this command by destroying every object except itself.
This is invoked when a device is first detected by twibd, to indicate to the device that
any objects that may have previously existed have had their references lost and should be
cleaned up.
Twibd also implements device id 0, whose object id 0 represents ITwibMetaInterface
.
ITwibMetaInferface
LIST_DEVICES
Command ID 10: Takes an empty request payload, returns a MessagePack-encoded array of information about currently connected devices.
Response
MessagePack array of objects containing these keys:
device_id
- Device ID for message headers.bridge_type
- String, eitherusb
ortcp
to indicate how the device is connected.identification
- Identification message fromITwibDeviceInterface#IDENTIFY
.
CONNECT_TCP
Command ID 11: Requests that the Twibd server attempt to connect to the device at the specified address over TCP. Empty response.
Request
u64 hostname_length;
u64 port_length;
char hostname[hostname_length];
char port[port_length];
ITwibDeviceInterface
CREATE_MONITORED_PROCESS
Command ID 10: Takes a raw string indicating the type of monitored process to create (either managed
or applet
) and returns an ITwibProcessMonitor.
Request
char process_type[];
Response
u32 monitor_object_index; // ITwibProcessMonitor
REBOOT
Command ID 11: This request has no payload, and does not send any response on success, because it brings the USB interface down with it.
COREDUMP
Command ID 12: Takes a PID, sends an ELF core dump file as a response.
Request
u64 pid;
Response
u8 elf_file[];
TERMINATE
Command ID 13: The request payload for this command is a single u64 process_id
. It does not have a response payload.
Request
u64 process_id;
LIST_PROCESSES
Command ID 14: This command has no request payload. The response payload is an array of ProcessReport
s.
Response
struct ProcessReport {
u64 process_id;
u32 result_code;
u64 title_id;
u8 process_name[12];
u32 mmu_flags;
} reports[];
UPGRADE_TWILI
Command ID 15: Stubbed.
IDENTIFY
Command ID 16: This command has no request payload. The response payload is a MessagePack object containing details about the device.
Response
MessagePack object containing these keys:
service
=twili
protocol_version
=1
firmware_version
(binary data fetched fromset:sys
#3)serial_number
(binary data fetched fromset:cal
#9)bluetooth_bd_address
(binary data fetched fromset:cal
#0)wireless_lan_mac_address
(binary data fetched fromset:cal
#6)device_nickname
(string fetched fromset:sys
#77)mii_author_id
(binary data fetched fromset:sys
#90)
LIST_NAMED_PIPES
Command ID 17: Takes empty request payload, reponds with a list of pipe names.
Response
u32 pipe_count;
struct pipe_name {
u32 length;
char name[length];
} pipe_names[pipe_count];
OPEN_NAMED_PIPE
Command ID 18: Takes the name of a pipe, returns an ITwibPipeReader.
Request
char pipe_name[];
Response
u32 reader_object_index; // ITwibPipeReader
OPEN_ACTIVE_DEBUGGER
Command ID 19: Opens a debugger for the given process.
Request
u64 process_id;
Response
u32 debugger_object_index; // ITwibDebugger
GET_MEMORY_INFO
Command ID 20: Takes empty request paylolad, responds with MessagePack-encoded information about current memory limits.
Response
MessagePack object containing these keys:
total_memory_available
- Total memory available to the Twili service process.total_memory_usage
- Total memory usage by the Twili service process.limits
- Array of details on global resource limits.category
- Resource limit category (0:System
, 1:Application
, 2:Applet
)current_value
- Current memory usage within this category.limit_value
- Maximum allowed memory usage within this category.
ITwibPipeReader
READ
Command ID 10: Reads data from the pipe, or blocks until some is available. Responds with the data that was read, or TWILI_ERR_EOF
if the pipe is closed.
ITwibPipeWriter
WRITE
Command ID 11: Writes data from the request payload to the pipe, blocking until it is read. Reponds with empty response, or TWILI_ERR_EOF
if the pipe is closed.
CLOSE
Command ID 12: Closes the pipe. Empty request, empty response.
ITwibDebugger
QUERY_MEMORY
Command ID 10: READ_MEMORY
Command ID 11: WRITE_MEMORY
Command ID 12: LIST_THREADS
Command ID 13: GET_DEBUG_EVENT
Command ID 14: GET_THREAD_CONTEXT
Command ID 15: BREAK_PROCESS
Command ID 16: CONTINUE_DEBUG_EVENT
Command ID 17: SET_THREAD_CONTEXT
Command ID 18: GET_NSO_INFOS
Command ID 19: WAIT_EVENT
Command ID 20: ITwibProcessMonitor
LAUNCH
Command ID 10: RUN
Command ID 11: Reserved for future separation between process creation and process starting, to aid debugging.
TERMINATE
Command ID 12: APPEND_CODE
Command ID 13: OPEN_STDIN
Command ID 14: OPEN_STDOUT
Command ID 15: OPEN_STDERR
Command ID 16: WAIT_STATE_CHANGE
Command ID 17: Other Tools
- CircuitBreaker, an interactive hacking toolkit has two backends designed to work with Twili. The
faron
backend allows low-level inspection of core dumps generated by Twili. Thelanayru
backend allows you to attach CircuitBreaker to an active process running on the console.