Firmware Fn mv generate mnvr name - krcenov/RNS510-Map-Viewer GitHub Wiki
mv_generate_mnvr_name
Part of Firmware Reversing.
- Naive symbol-table address:
0x5b54f8(VA0xf6e431ec) - True, confirmed start:
0x5b5314(VA0xf6e43008) — the original "boundary ambiguity" concern below is now resolved: this genuinely IS the function's own complete, standalone start. - Status: 🟡* Partially traced — real logic confirmed throughout
(including the real explanation for the
r31puzzle below); not transcribed past the first ~200 bytes for length. - Full mangled name:
mv_generate_mnvr_name__FibP14Mv_Info_Struct(global function,int,bool,Mv_Info_Struct*)
Part of the maneuver-generator (mv_*) internals — see
calculateManeuvers for the
subsystem's real entry point.
The r31 puzzle — resolved, not a boundary problem
At 0x5b5344/0x5b5348, the code does stw r31,0(r31) /
stw r31,4(r31) — using r31 as BOTH the value stored and the target
address, with no visible assignment to r31 beforehand (only a save
of its INCOMING value to the stack at 0x5b5324, standard callee-save
preamble). The same is true of r30, used as a live pointer from
0x5b5350 on with no assignment either. Originally flagged as a
possible repeat of the real boundary-undershoot bug confirmed on
mv_check_turn.
Checked directly and ruled out. Disassembling the immediately
preceding real function (prologue at 0x5b526c, unnamed in the
catalog) shows it ending completely independently: builds a real
doubly-linked-list node (calling
getOffroadDistanceFromRouteToDestination__25CfcTypeRoadClassStatistic
and getCertainty_total__23CfcTypePossibleLocation — both already
seen elsewhere on this wiki — then linking the new node into a list
via r25/r26/r27/r29), pops its own stack frame, and ends in the
same "no locally-visible blr" shape documented centrally on
Firmware Reversing — immediately followed by
mv_generate_mnvr_name's own clean, fresh stwu/mflr prologue at
0x5b5314. This is a real, independent function boundary, not a
continuation — so 0x5b5314 genuinely is this function's own
complete start.
The real explanation: r30 and r31 are real, additional
arguments passed in via callee-saved registers rather than the
standard r3-r10 parameter registers — a legitimate, if
non-obvious, GCC calling-convention choice available for a static/
internal-linkage helper like this one, where no external ABI contract
constrains register assignment. The function still faithfully SAVES
the caller's original r30/r31 to the stack and restores them before
returning (so the caller's own values are preserved across the call,
exactly as the callee-saved contract requires) — it just also reads
their INCOMING values as real inputs before doing so, which is what
looked like "uninitialized use" at first glance. Net effect: this
function's REAL effective signature carries (at least) 2 more
pointer-shaped inputs than its mangled name declares — not unusual for
a compiler-internal helper that's always called from known,
compiler-visible call sites.
What was disassembled
0x5b5314: stwu r1, -0xa0(r1)
0x5b5318: mflr r0
0x5b531c: stw r29, 0x94(r1)
0x5b5320: stw r30, 0x98(r1)
0x5b5324: stw r31, 0x9c(r1)
0x5b5328: stw r0, 0xa4(r1)
0x5b5334: mr r29, r4 ; arg2
0x5b5340: li r10, 0
0x5b5344: stw r31, 0(r31) ; r31 = real incoming arg, see above
0x5b5348: stw r31, 4(r31)
0x5b534c: lwz r9, 4(r29)
0x5b5350: lwz r11, 4(r30)
0x5b5354: lwz r0, 0(r9)
0x5b5358: stw r10, 8(r30)
0x5b535c: cmpw r0, r9
0x5b5360: stw r11, 0x30(r1)
0x5b5364: stw r0, 0x10(r1)
0x5b5368: stw r9, 0x20(r1)
0x5b536c: beq 0x5b53bc
0x5b5370: lis r9, -0x8f2
0x5b5374: addi r31, r9, 0x74
0x5b5378: lwz r9, 0x10(r1) ; <- loop-back target
0x5b537c: addi r3, r1, 0x40
0x5b5380: lwz r0, 0x30(r1)
0x5b5384: mr r4, r30
0x5b5388: addi r6, r9, 8
0x5b538c: mtlr r31
0x5b5390: addi r5, r1, 0x50
0x5b5394: stw r9, 0x78(r1)
0x5b5398: stw r0, 0x50(r1)
0x5b539c: lwz r0, 0(r9)
0x5b53a0: stw r0, 0x10(r1)
0x5b53a4: stw r9, 0x60(r1)
0x5b53a8: blrl ; virtual call, inside a real loop
0x5b53ac: lwz r9, 0x10(r1)
0x5b53b0: lwz r0, 0x20(r1)
0x5b53b4: cmpw r9, r0
0x5b53b8: bne 0x5b5378 ; loop -- this one stays within bounds
0x5b53bc: mr r3, r30
0x5b53c0: lwz r0, 0xa4(r1)
0x5b53c4: mtlr r0
0x5b53c8: lwz r29, 0x94(r1)
0x5b53cc: lwz r30, 0x98(r1)
0x5b53d0: lwz r31, 0x9c(r1)
0x5b53d4: addi r1, r1, 0xa0
(reaches a real blr further on, at 0x5b5578, after more virtual
calls not reproduced here for length — none of them loop backward past
the confirmed start.)
Analysis
A real linked-list-style loop (0x5b5378-0x5b53b8: walk while
lwz r9,4(r29) chain doesn't return to its own head, calling a virtual
method each iteration) over the Mv_Info_Struct*-shaped data passed in
via r30. Consistent with the function's own name — generating a
maneuver name/description likely involves walking a list of info
records (street names, distances, etc.) to compose the final string.
Callees
Not traced beyond the virtual-call sites shown above (none resolved to
named symbols — all genuine virtual/indirect calls through computed
vtable-style pointers, not direct lis/addi references to named
functions).