Follow up RIODescInfo consolidation: target info, size and IO capabilities
Follow-up to #26121, which consolidates device/debugger flags and listener detection in RIODescInfo.
The goal is to remove duplicate callbacks and query wrappers, simplify consumers, and keep descriptor information cheap to obtain. This is a candidate inventory for discussion, not a proposal to add every field.
listener is the clearest additional consolidation: it already had a separate plugin callback and r_io_is_listener() wrapper. It is being handled in #26121; the remaining options are tracked here.
The strongest candidates for consolidating existing queries:
| Candidate | What it provides | Main consideration |
|---|---|---|
listener |
Whether this descriptor is accepting connections | Handled in #26121 by removing the separate callback and wrapper. |
pid, tid |
Process and thread associated with the descriptor | Define whether these mean attached or currently selected; existing plugins differ. |
baddr |
Main executable's load base | Distinguish it from the start of an IO mapping. |
size |
Length of the exposed data, including device capacity in bytes | Must distinguish unknown size from an empty descriptor and an address-space limit. |
size_kind or size validity |
Exact, unknown, or unbounded size | Could replace ambiguous size sentinels. |
seek_caps |
Supported positioning: absolute, relative, end, holes | More useful for IO decisions than using chrdev as a proxy for seek behavior. |
caps |
Read, write, resize, extend, accept capabilities | Describe this descriptor's capabilities. A callback existing does not guarantee the operation works. |
| Resource classification | File, block device, character device, stream, memory | Keep independent properties such as isdbg separate; a remote debugger can also expose memory. |
Device geometry and transfer constraints are also eligible, provided something consumes them:
| Candidate | What it enables | Main consideration |
|---|---|---|
logical_block_size |
Correct sector addressing and minimum device access units | Separate from total device capacity. |
physical_block_size |
Better alignment of device writes | Different from logical sector size. |
| Read/write offset alignment | Alignment of the requested address | Read and write requirements can differ. |
| Read/write length alignment | Valid transfer lengths | Separate from address alignment. |
| Buffer alignment | Requirements on the caller's memory buffer | Only expose restrictions the plugin passes through to callers. |
min_io, preferred_io |
Minimum and efficient transfer sizes | Required constraints and performance hints need distinct meanings. |
max_read, max_write |
Generic chunking for remote or device IO | Report usable payload sizes, not raw protocol packet sizes. |
page_size |
Target memory page granularity | Target page size can differ from the host's. |
allocation_granularity |
Alignment for allocation or mapping | Not necessarily the page size. |
erase_block_size, write granularity |
Flash programming constraints | Useful for device backends; probably a separate feature. |
| Address bounds | Lowest/highest address the descriptor can represent | Bounds do not establish that every address inside is readable. |
addrbytes / address unit |
Conversion between addresses and byte counts | Would require reconciling the existing RIO.addrbytes setting. |
| Address-space kind | File offsets, process virtual memory, physical memory, registers | Useful only if generic code makes a concrete decision from it. |
| Sparse/hole behavior | Whether gaps exist and how reads of gaps behave | Actual extents need a separate query or iterator. |
Other plausible options, with weaker justification for the initial consolidation:
| Candidate | Potential use | Why to be selective |
|---|---|---|
volatile / externally mutable |
Cache invalidation decisions for live memory or changing resources | Ordinary files can change externally too; define a precise guarantee. |
| Read/write side-effect flags | Avoid repeated reads of device registers or MMIO | Often belongs to individual ranges rather than the whole descriptor. |
| Growing / fixed-length / snapshot properties | Decide whether cached size remains useful | Distinct from whether callers may resize it. |
| Native FD or handle | Polling, OS integration, zero-copy operations | Needs a tagged, borrowed handle; it is different from r2's descriptor ID. |
isatty |
Terminal-specific behavior | Character device alone does not imply terminal. |
| Nonblocking / append mode | Explain effective IO semantics | Describe the exposed descriptor, including any buffering performed by the plugin. |
| Transport / remote status | Diagnostics and connection presentation | Prefer actual capabilities over decisions based solely on "remote". |
| Connection state, EOF, readiness, available bytes | Stream handling | These become stale immediately; explicit status/poll queries usually fit better. |
| Current offset | Replace queries that use seek-to-current | Existing global and plugin-local offsets need consistent semantics first. |
| Backing descriptor and offset | Describe slices and layered resources | Compression and transformations cannot always be represented as a simple offset. |
| File identity, timestamps, allocated size | Detect replacement/modification; describe sparse storage | This starts becoming a separate stat API. |
| Target executable path | Avoid textual debugger commands for executable discovery | String ownership and remote-query cost complicate a small value struct. |
| Architecture, bits, endian, OS hints | Initialize target configuration from a backend | Keep ownership with the appropriate architecture/debug layer; avoid conflicting copies. |
| Generation counter | Tell consumers when cached information changed | Only useful with a defined update/invalidation contract. |
Avoid duplicating fd, permissions, name, URI, plugin identity, or configuration already accessible through RIODesc. Registers, stop reasons, thread/module lists, and memory maps belong in their existing debug/map APIs.
The limiting factor is query cost. r_io_desc_info() is called during ordinary reads and writes in libr/io/io_plugin.c. Querying sysgdb's PID sends a debugger command; querying descriptor size can perform three seeks. Those operations cannot become an automatic consequence of checking a flag.
The suggested priority after listener consolidation is PID/TID/base consolidation. Seek capabilities are the strongest additional behavioral improvement. Size and geometry deserve an explicit query-cost contract first. Optional values also need validity indicators: zero is a valid size or base address, and "unknown" must remain distinguishable.
Source: radareorg/radare2