Firmware map¶
Where the application image's code goes, and how much of it has been looked at. The Architecture page describes how the pieces talk. This page accounts for the whole image, one function at a time, and tracks which parts have been read closely.
All figures on this page come from tools/survey.py, run on the owner's own stock NAV
SMEG5.43.A.R2 image and the symbol map SPYSTORE copies off the unit. Figures for the
AUDIO_BT build will differ.
Scale¶
| NAV 5.43.A.R2 | |
|---|---|
code symbols (T/W in abs_symbols_base) inside the image |
89 351 |
| instructions spanned by those symbols | ≈ 7.99 million (31.9 MB) |
| families (class prefix, or library for free functions) | 1 030 |
functions with at least one bl caller, materialised reference or data pointer found |
79 462 |
| functions with none found | 9 889 (≈ 625 000 instructions) |
Reading every instruction by hand is not feasible, so the working unit is the function. Every function gets a row in the survey. Each subsystem that matters to a patch then gets a close reading, recorded in the coverage ledger below.
What the instruction counts over-state
A symbol map carries no sizes. A function's extent runs to the next symbol, so any
unlabelled constant data after a function is counted as its code. That is why a few
single functions show hundreds of kilobytes (fnmatch, mxmlSetElement). Treat
per-function sizes as upper bounds, and family totals as close but inflated.
Where the code goes¶
About 35% of the instructions belong to families whose names identify a third-party
library. That labelling is inferred from names (sqlite3_*, png_*, FT_*, Q*); no
library version has been checked against its upstream source.
| layer | functions | instructions | share | what it is |
|---|---|---|---|---|
| Qt | 20 736 | 1 437 421 | 18.0% | Qt middleware (widgets, QWS, graphics) |
C_HMI_* |
9 957 | 1 292 224 | 16.2% | HMI applications: one family per app (tuner, BT, media, nav, drive, config, upgrade, climate…) |
| free functions (unlabelled) | 8 159 | 1 064 426 | 13.3% | C code with no class; includes vendor C modules and unrecognised libraries |
C_BCM_* |
12 202 | 894 919 | 11.2% | Business components, the logic behind each HMI app, and their DBUS server/client pairs |
| C++ standard library | 9 638 | 579 088 | 7.3% | template instantiations |
C_GUI_* |
2 979 | 362 951 | 4.5% | the vendor widget toolkit over Qt (lists, coverflow, bezier, …) |
V3D |
2 684 | 285 849 | 3.6% | the 3D map renderer |
C_I2C_SMART_RADIO |
299 | 139 247 | 1.7% | the radio/audio front-end over I2C |
| TagLib | 1 994 | 137 794 | 1.7% | media tag parsing |
| SQLite | 184 | 127 099 | 1.6% | the database engine |
com_MM_* |
2 583 | 119 826 | 1.5% | generated DBUS proxies (com/MM/... interfaces) |
C_MODULE_* |
672 | 97 969 | 1.2% | hardware owners: C_MODULE_TUNER, C_MODULE_AUDIO, the multi-tuner variants |
C_NAV_*, TCartogr, Map, M_MAP_MNG |
2 006 | 184 435 | 2.3% | navigation server, cartography and map management |
C_SRV_* |
1 210 | 65 136 | 0.8% | services (C_SRV_AUDIO_SERVER, media, tuner) |
C_MGR_* |
112 | 10 170 | 0.1% | C_MGR_SRC (the source scheduler) and C_MGR_BT |
| everything else | ≈ 1.2 M | ≈ 15% | FreeType, libpng, libjpeg, HarfBuzz, expat, a Bluetooth stack, codecs, and ~900 small vendor families |
The layer that decides behaviour is small. C_MGR_SRC is 71 functions and ≈ 7 600
instructions out of eight million. Every AUX patch edits C_MGR_SRC,
C_HMI_AUDIO_APP_BASE or C_HMI_MEDIA_APP_BASE.
Producing the inventory¶
tools/survey.py makes one pass over the image. For every code symbol it records:
- its family and size;
- its direct
blcallers; - its materialised references:
lis+addi/oripairs that build its address. This is how most of this firmware's calls are made (throughmtctr/bctrl), and it is exactly whattools/callers.pycannot see.C_MGR_SRC::ExecuteAllocationFirstRoundhas 0blcallers and 1 materialised reference, fromExecuteAllocation; - pointers to it held in data (vtables, callback tables).
C_HMI_MEDIA_APP_BASE::InitAppandC_MGR_SRC::StartUpare reached this way only; - the strings whose address it builds, usually its trace text;
- the vtable slots it occupies. A vtable is the
_ZTVsymbol: two zero words (offset to top, and typeinfo, since there is no RTTI), then one function pointer per slot.
Besides the per-function table it writes three more:
vtables.tsv: every slot of every vtable (class, slot offset, function). NAV 5.43.A.R2: 36 758 slots in 3 103 vtables.virtual_calls.tsv: call sites of the formlwz vptr,0(obj)→lwz rZ,off(vptr)→mtctr rZ→bctrl, with the slot offset each calls: 10 495 on NAV. The object's class is not inferred, so a site is not attributed to one function.StartUpandInitAppstill show no direct callers for that reason.globals.tsv: each data symbol, including BSS past the end of the image, with the functions that read and write it throughlis rX,hi+ a load or store atlo(rX): 3 199 on NAV.C_MGR_SRC::m_Instancehas 3 readers and 3 writers.
uv run tools/survey.py ~/Downloads/SMEG_PLUS_UPG/NAV/AppBin/f_BigQuick.bin \
abs_symbols_base.txt.gz --out ~/smeg-survey
It takes f_BigQuick.bin or an inflated image, and abs_symbols_base.txt.gz from a
SPYSTORE dump, gzipped or not. The run takes a few seconds. The output is derived from the
vendor's symbol map, so it stays on your machine. Do not commit it; see AGENTS.md.
Reference counts are lower bounds
An address taken from a register computed at run time, reached through a branch table,
or built further than 30 instructions from its lis is not counted. Nor is a virtual
call whose vtable pointer passes through a stack slot or another register first. A
function in unreached.tsv has no reference this scan recognises; that does not prove
it is dead. 4 100 of the 9 889 are Qt, where unused library code is expected.
Coverage ledger¶
How closely each part has been examined, using the evidence tiers from Verification. Read means disassembled or decompiled and followed. Executed means run under the emulator or observed on the car.
| area | depth | where |
|---|---|---|
| the whole image: every function, vtable slot, virtual call site and global | inventoried by tools/survey.py (executed); not read |
this page |
C_MGR_SRC, the source scheduler: all 71 functions |
every function read; AddRequest and ChangeToNextSchedulerPosition executed under emulation; the boot restore executed on the car (FM without the AUX patches, AUX with them) |
The source scheduler, The AUX chain |
C_MODULE_AUDIO, the audio module: 273 functions |
25 read (the AUX path, lifecycle, event dispatch, mute); 248 inferred from names, strings and a decompile digest | The audio module |
C_HMI_AUDIO_APP_BASE::IsAUXSRCAvailable |
read; the patched version executed under emulation and on the car | The AUX chain, Patches |
C_HMI_SrcMgntBase and every ActivateSource(bool) call site (17) |
read; the InitApp and handler PrOnly edits executed on the car (boot to AUX) |
How HMI apps request sources |
C_HMI_MEDIA_APP_BASE::HandleAudioAuxInputStatusChnged and its HandleDBUSMessage dispatch |
read; both executed under emulation, stock and with aux-signal-switch |
The AUX chain, The AUX signal path |
the AUX signal path: detection in the radio driver, Elab_AUDIO_AUX_SIGNAL_STATUS_CHANGED, DBUS forwarding, every app's 0xcc handling |
read. Whether the detector measures AUX while another source plays is not known | The AUX signal path |
ring tone names: C_SRV_RING_TOUCH::SetRingFilePath and the name literals |
read; the in-place name patch executed on a real build (not yet on the car) | Ring tones |
the System Information version screen: C_BCM_VERSION and the C_HMI_CONFIG pages |
read | Version strings |
the update flow: C_BCM_UPGRADE (353), C_HMI_UPGRADE (293), C_HMI_UPG (195) |
about 30 functions read: plugin loading, the contract check, mount/probe, skin rewrite, result mapping; HandlePrivateMessage skimmed per case; the rest inferred from names. Everything after upgplugin_LaunchUpgrade is outside the image |
The update flow |
the package: container, manifests, contract.dat |
read; the contract decrypted and re-sealed (executed); packages flash on the car | Boot & update chain, Media protection |
the *_ctrl.bin manifests, including the CheckType-3 CRC-16 |
layout and all three value types reproduced from the stock files (executed); upgrade.out's CheckEntryFile and the kernel's ComputeCrc read |
Boot & update chain |
cheat codes and the spy collectors: C_BCM_SPY (109), C_BCM_Cheat_Code, the 25 libcheatcode_* libraries |
every code's Activate read from its relocations; the collect path read; real -USER captures read with tools/spy_read.py (executed) |
Cheatcodes & spy |
| HMI framework: messages, event handler, menus | named from symbols, partly read | Architecture |
| everything else | inventoried by the survey only | this page |
When a subsystem is read closely, add a row here with its depth and the page it is written on. Keep the tier honest: a function that is named, or that has a caller, has not been read.