* librz/core,cmd: add pf-aware autocompletion arg types
The `pf` family of commands (`pf`, `pf-`, `pfa`, `pfc`, `pfd`, `pf.`,
`pfn`, `pfo`, `pfs`, `pfv`, `pfw`) takes either a registered named
format, a `<format>.<field>[<idx>]...` path, or a Format Definition
File. None of these were autocompletable: the arg type was always
`RZ_CMD_ARG_TYPE_STRING`, so tab on `pf. <TAB>` did nothing and the
user had to remember every format and field name by hand.
Add three new arg types and wire them to the cmd_descs:
* `RZ_CMD_ARG_TYPE_PF_FORMAT_NAME` enumerates the named formats
from `rz_type_db_format_all()` and filters by the partial prefix.
Used by `pf-`, `pfa`, `pfc`, `pfd`, `pfn`, `pfs`, `pfv`.
* `RZ_CMD_ARG_TYPE_PF_FORMAT_PATH` is the path-aware completer for
`pf.` and `pfw`. Both accept arbitrarily deep paths of the form
`name[.field[<idx>]?]*`, walking through nested struct fields
(e.g. `pf. troll.str[1].two` follows the same path syntax that
`pf_path_navigate` accepts at runtime). The completer:
- Finds the last `.` in the partial input; everything before
it (inclusive) is the committed path, what follows is the
segment being completed.
- Walks each committed `name[N]?` segment in turn, looking up
STRUCT fields' `type_name` in the typedb and re-parsing the
referenced format. Descent past a scalar or an inline struct
(no `type_name`) returns no options.
- Offers the resolved format's field names for the tail.
- Returns nothing when the tail contains `[` or `]` -- the
user is mid-index or mid-descent, where identifier
completion would produce a syntax error if accepted.
- Suppresses the trailing space after each successful
completion so `.` can be typed next without an inserted
space getting in the way of descent.
- Rewrites `res->start` past the last `.` so completion only
replaces the tail; the committed path stays put.
* `RZ_CMD_ARG_TYPE_PF_FDF_FILE` lists the basenames of FDFs found
in the user's home formats dir and the system formats dir,
mirroring the search order used by `pfo` itself; files present
in both locations are reported once via the same `HtSU` de-dup
used in `cmd_print_format_file_handler`. Used by `pfo`.
All three new types are added to `CD_ARG_LAST_TYPES` in
cmd_descs_util.py. The generator sets `RZ_CMD_ARG_FLAG_LAST` on the
final arg of a command whenever that arg's type is in this set;
that flag tells the runtime arg-preprocessor to merge any trailing
whitespace-separated tokens into a single argv slot. This is the
same implicit-FLAG_LAST treatment `RZ_CMD_ARG_TYPE_STRING` already
gets, and it is what keeps invocations like `pfc zd4x8 foo bar cow`
(five tokens, one logical format-with-names argument) working --
without it the cmd parser would reject the extra tokens with "Wrong
number of arguments". The implicit merge does not interfere with
autocompletion: the completer still receives the partial input up
to the cursor and prefix-matches against it, and the format-path
completer's dot/bracket scan is unaffected by whitespace.
The path completer uses a small helper, `pf_path_seg_consume`, that
parses one `name[N]?` segment with safe handling of unterminated `[`,
empty `[]`, non-numeric indices, and end-of-input. `pf_resolve_path_format`
walks all committed segments and returns the RzPfFormat the caller
should complete against; the resolver is the same shape as the
`pf_path_navigate` walker in librz/type/pf/pf_parser.c, except it
operates on RzPfFormat trees (typedb names) rather than RzPfValue
trees (decoded data), so it can run before any read has happened.
The completers live in `cautocmpl.c` next to the existing type-name
completers (`autocmplt_cmd_arg_struct_type` and friends) and follow
the same loop+strncmp pattern. The dispatcher entry for
`RZ_CMD_ARG_TYPE_FOLDER` was missing an explicit `break;` and would
fall through to `default`; harmless, but fixed in passing so the
three new cases sit cleanly above `default:`.
Note on dot-search direction: `rz_sub_str_rchr` is `start..end`
range search returning the FIRST hit, not a right-to-left "find
last" -- the `r` is for "range", not "right". The path completer
needs the last dot, so it walks the buffer backwards itself.
* test/integration: cover pf autocompletion
Thirteen new tests in test_autocmplt.c exercise the three new pf arg
types, including the multi-segment path resolver:
Format name completion:
* `pf_format_name` -- `pfn ut_<TAB>` after registering two formats
confirms both are offered.
Single-segment path completion:
* `pf_format_path` -- three-phase walk through `pf. ut_path<TAB>`,
`pf. ut_path.<TAB>`, `pf. ut_path.cou<TAB>`, covering name-only,
dot-only, and dot-with-prefix. Verifies that `res->end_string`
is empty in the name phase (so `.` can be typed next without an
inserted space) and that `res->start` advances past the dot in
the field phase (so the completion only replaces the field
portion).
* `pfw_format_path` -- the same `<format>.<field>` syntax must
work on the write side too; confirms the PATH completer fires
for `pfw` and is not pf.-specific.
* `pf_format_path_empty` -- bare `pf. <TAB>` lists every
registered format. Snapshots the baseline count first so the
assertion stays robust against any default formats the type DB
might seed.
* `pf_format_path_unknown_name` -- `pf. nonexistent.<TAB>`
returns an empty option list rather than crashing or leaking
diagnostics.
* `pf_format_path_anon_field` -- formats whose fields don't all
have names (e.g. a `.` skip slot) must be iterated safely; the
named fields are offered and the anonymous slot is silently
dropped.
Multi-segment / nested-struct path completion:
* `pf_format_path_nested` -- two-level descent through a STRUCT
field whose `type_name` references another registered format,
parsing the child format and offering its fields.
* `pf_format_path_three_levels` -- three-level descent narrows
correctly: A -> B -> C, then filter C's fields by a prefix.
* `pf_format_path_array_index` -- `pf. troll.str[1].<TAB>` mirrors
the existing cmd_pf2 runtime test; the array index in the
middle segment is parsed and skipped (it doesn't change the
target type).
* `pf_format_path_inside_brackets` -- cursor inside an
unclosed `[` returns no options (mid-index).
* `pf_format_path_after_close_bracket` -- cursor right after `]`
without a trailing `.` also returns no options (mid-descent).
* `pf_format_path_through_scalar` -- descent past a scalar field
is meaningless and returns no options.
The tests use plain `rz_core_new()` (the real cmd_descs already
registers all `pf*` commands), matching the pattern used by
`test_autocmplt_eco_themes`. Format strings use the parser's
"specifier-then-names" form (no internal whitespace in the spec
region) so `rz_pf_parse` produces the expected field count.
* doc,librz/core: align pf docs and `pf?` help with the parser
The standalone reference doc/pf.md and the in-tree `pf?` help (driven
by the details: block in librz/core/cmd_descs/cmd_print.yaml) had
drifted from each other and from what the parser actually accepts.
Both are now consistent with librz/type/pf/pf_parser.c.
Specific corrections:
* `n` family. doc/pf.md claimed `N1`/`N2`/`N4`/`N8` existed as BE
counterparts to `n1`-`n8`, and that bare `n`/`N` defaulted to
`ctx.bits/8`. The parser handles only `n{1,2,4,8}`; all four
forms are context-endian (follow `ctx->big_endian`), and bare
`n` produces "unknown specifier". Rewrite the section to match,
and explain why context-endian is the right choice for header
readers like ELF.
* Deprecation list. The `pf?` "deprecation" note listed `c, s, z`
among the deprecated bare-letter codes -- they are not deprecated
(`c` is the current 1-byte-as-char specifier, `s` is the current
pointer-to-zstring, `z` is the current inline zstring). It was
missing `C, i, Z, X, F, T` which the parser does warn on.
doc/pf.md had `c` in its table marked "unchanged" (so it was
visibly inconsistent with itself) and was missing the `x` row.
Both lists now mirror the parser's PF_DIAG(DEPRECATED) call
sites: b, C, d, f, F, i, o, q, t, T, w, x, X, Z.
* TLV `h=`. `pf?` said "h=v/a (header inclusion)" (two options);
the parser accepts `v` (value only, default), `l` (length covers
len+value), and `a` (length covers tag+len+value). doc/pf.md
already listed all three; help now matches.
* `v(N)` bitvector. doc/pf.md documented this in detail (the
1..4096-bit-wide field type used for things like ELF
`DT_FLAGS_1`, PE characteristics, page-allocation maps), but the
`pf?` help didn't mention it at all. Added to the DSL extensions
section.
* Pointer widths. doc/pf.md documented `p2`/`p4`/`p8` explicitly;
`pf?` only mentioned bare `p` with a "size from ctx.bits"
parenthetical. Help now lists the four forms in one entry.
* GUID layouts. Both docs claimed `G(le)` was "all little-endian",
but the renderer treats `G(le)` and `G(ms)` identically -- D4
(the trailing 8 bytes) is always in buffer order regardless of
layout. Document the actual behaviour rather than the implied
one; this is a description fix, not a code change. Anyone who
wants the byte-reversed-D4 reading can still file it as a
follow-up bug against the renderer in pf_render.c.
cmd_descs.[ch] is regenerated automatically by the custom_target rule
when cmd_print.yaml changes; the .c diff in this commit is the result
of that regeneration (5 lines of comment text inside the existing
detail entries).
|
||
|---|---|---|
| .. | ||
| arch | ||
| bin | ||
| config | ||
| cons | ||
| core | ||
| crypto | ||
| debug | ||
| demangler | ||
| diff | ||
| egg | ||
| flag | ||
| hash | ||
| il | ||
| include | ||
| io | ||
| lang | ||
| magic | ||
| main | ||
| mark | ||
| reg | ||
| search | ||
| sign | ||
| socket | ||
| syscall | ||
| type | ||
| util | ||
| meson.build | ||
| plugins.h.in | ||
| README.md | ||
| RizinConfig.cmake.in | ||
| RzModulesConfig.cmake.in | ||
Rizin Libs (librz)
The Rizin framework is composed of several pieces that work together to provide a reverse-engineering framework useful for a variety of use-cases and tasks. All tools present in binrz are based on the libraries present in this directory, so getting a general idea of what these libraries are and do is key to navigate the codebase.