4.5

list_strings

list_strings returns every string that Ghidra defined as Data, which includes loader metadata and symbol fragments, and excludes any text Ghidra did not define.

You expect five labels and three format strings. list_strings returns 39 items, among them /usr/lib/dyld, _label, _, and an empty string. Each one is a real run of bytes in the file. The list is complete for what Ghidra defined, and it is only that.

When you finish this section, you can place each of the 39 strings in its load command. You can also say what an empty result does and does not prove.

The call

list_strings and three of its itemsjsonFull log
"name": "list_strings",
"arguments": {}
…
{
  "address": "0x100000770",
  "value": "F",
  "string": {
    "encoding": "US-ASCII",
    "termination": "present_or_not_required",
    "byte_length": 2
  }
},
…
{
  "address": "0x1000007cf",
  "value": "",
  "string": {
    "encoding": "US-ASCII",
    "termination": "present_or_not_required",
    "byte_length": 1
  }
},
…
{
  "address": "0x1000080c7",
  "value": "_label",
  "string": {
    "encoding": "US-ASCII",
    "termination": "present_or_not_required",
    "byte_length": 7
  }
},
…
"limitations": [
  …
  "Only Ghidra-defined string Data is observed; packed or undefined string bytes may be absent. Completeness applies to that inventory, and an empty search does not establish that text is absent from the artifact. If an address is known, use read_bytes and xrefs to inspect bytes and references.",
  "Charset is reported, while a non-missing terminator cannot distinguish a present terminator from a fixed or Pascal layout.",
  …
],
The request arguments, three items cut from the 39, and the two string limitations of the seven.

The bridge walks every defined data item in the program and keeps the ones with a string value. For each it records the charset, whether a required terminator is missing, and the byte length. Each item is a Data object that Ghidra's loader or analyzers created. A run of printable bytes that no analyzer turned into Data is not in the list. The first limitation is fixed in rea, and the docs say the same:

termination has two values. missing means a string type that needs a null byte has none. present_or_not_required covers everything else, because Ghidra cannot tell a present terminator from a layout that needs none. byte_length counts the terminator: F is two bytes.

Thirty-nine strings in six places

Sort the 39 addresses and they fall into six runs. Each run is one load command from section 3.2.

WhereAddressesCountExamples
load command strings in the header0x100000404, 0x1000004902/usr/lib/dyld, /usr/lib/libSystem.B.dylib
__TEXT,__cstring, file 19040x100000770 to 0x1000007cf10F, D, C, B, A, usage: ledger <before> <after> [score...]\n, change %d%%\n, total %d\n, score %d grade %s\n, and one empty string
LC_DYLD_CHAINED_FIXUPS import names, file 327680x100008069 to 0x1000080a76___stack_chk_fail, _atoi, _printf
LC_DYLD_EXPORTS_TRIE edge labels, file 329440x1000080b2 to 0x1000081117_, _label, grade, main, percent_change, total
LC_SYMTAB string table, file 333040x10000821a to 0x1000082a513__mh_execute_header, _grade_label, _labels
LC_CODE_SIGNATURE identifier, file 334560x10000831c1ledger-arm64-O1

The ten in __cstring are the program's own text. The section is 95 bytes, and Ghidra's block for it in section 3.4 is 96. The block runs to the start of __const at 0x1000007d0. The extra byte at 0x1000007cf is the alignment pad, and Ghidra defined it as an empty string of length 1. That item is real and harmless, and you will see pads like it in every linked image.

The export trie is a prefix tree of the exported names. Its edges carry shared prefixes once. Ghidra's string data therefore holds seven fragments, _, _label, _mh_execute_header, grade, main, percent_change, and total, and not the six export names. The string table of LC_SYMTAB holds the thirteen full names, which match the nsyms of 13. The last string is the code signature's identifier, the output file name that the linker embedded. That is why the capture kit warns that a different output name gives different bytes.

Fig. 4.7the 39 strings of ledger-arm64-O1 by load commandstructure
The 39 strings of ledger-arm64-O1 by load command Six rows sorted by address. Two load command strings in the header, the dyld and libSystem paths. Ten strings in __TEXT,__cstring from 0x100000770, the labels, the format strings and one empty pad. Six import names in the chained fixups from 0x100008069. Seven edge labels of the exports trie from 0x1000080b2. Thirteen names in the LC_SYMTAB string table from 0x10000821a. One code signature identifier, ledger-arm64-O1, at 0x10000831c. The total is 39, the string_count of the overview. WHERE ADDRESSES COUNT EXAMPLE header load commands 0x100000404, 0x100000490 2 /usr/lib/dyld __TEXT,__cstring 0x100000770 to 0x1000007cf 10 score %d grade %s chained fixups imports 0x100008069 to 0x1000080a7 6 ___stack_chk_fail exports trie edges 0x1000080b2 to 0x100008111 7 _label LC_SYMTAB string table 0x10000821a to 0x1000082a5 13 _grade_label code signature 0x10000831c 1 ledger-arm64-O1 string_count 39 · encoding US-ASCII on every item · 10 program strings, 29 names and paths
Ten of the 39 strings are the program's text, and the other 29 are names and paths that the loader and the linker keep in the file. Read top to bottom by address. Each row names the load command, the address range, the count, and one example.

Strings a function refers to

The dossier of _grade_label has a referenced_strings facet with one item, F at 0x100000770, from the load at 0x1000005c8. The function does not load F. It loads a pointer from _labels at 0x100004030, the 40-byte __const in __DATA_CONST that holds five pointers to the five labels. Ghidra followed the first pointer and recorded the string behind it, and its referenced_names facet lists both _labels and s_F_100000770 from the same instruction. Read a referenced string as a string the function can reach, not as the only one.

In the x86-64 object the same five labels sit in .rodata.str1.1, the ten-byte block in section 3.4, and string_count is 20. Lesson 32 reads the ELF string tables that hold the other ten.

What the inventory cannot prove

The limit is in the first word of the rule: defined. Three kinds of text are not Data. A compiler can pack a string into a struct. The analyzer can skip a string without a terminator. A program can build a string at run time. The list has none of them.

The capture target has none of those, so the 39 items are the whole file. For a target you did not build, treat an absent string as unknown. When you know an address, read_bytes returns the bytes and xrefs returns who uses them, as the limitation says. Section 5.2 shows how rea records that kind of unknown.

rea (rea-agents) with the Ghidra provider rea-agents 6.7.0, Ghidra 12.1.4 · 27dc42d · 2026-10-18 · Edition 2026.10