Firmware Fn mv check turn - krcenov/RNS510-Map-Viewer GitHub Wiki
mv_check_turn
Part of Firmware Reversing.
- Naive symbol-table address:
0x587440(VA0xf6e15134) - Nearest preceding prologue found FIRST (undershot):
0x5872d0(VA0xf6e14fc4) - Real, confirmed true start:
0x586f3c(VA0xf6e14c30) — see "Boundary mystery resolved" below - Status: 🟡* Partially traced — the real boundary question is now
resolved (see below), but the function is large (at least
0x62c/ 1,580 bytes) and wasn't transcribed line-by-line in full - Full mangled name:
mv_check_turn__Fii(global function, 2intargs)
Part of the maneuver-generator (mv_*) internals — see
calculateManeuvers for the
subsystem's real entry point.
A real complication: the backward-prologue-scan technique undershot
Disassembling from 0x5872d0 reaches a genuine blr at 0x587568
(664 bytes later) — looks like a clean, complete function at first.
But the loop that drives it (0x587548: blt 0x587150) branches
backward to an address BEFORE 0x5872d0 — i.e. before what the
backward-prologue-scan found as this function's "start." Checked
directly: 0x587150 is not itself a prologue, and the nearest real
stwu/mflr prologue before it is at 0x586f3c — roughly 900 bytes
earlier still.
This means the simple "scan backward for the nearest prologue" method
(used successfully to find true starts for
getNodeVidArmMP0,
getIndexOfVid, and
filterToggleSeg) is not always
sufficient — it finds a nearby prologue, but not necessarily the
one whose control flow actually reaches the code being examined. What
was disassembled here (0x5872d0-0x587568) is very likely a MIDDLE
fragment of a larger enclosing function that actually starts at or
before 0x586f3c, not mv_check_turn's own complete, isolated body.
Recorded honestly as an open methodological gap rather than papered
over.
UPDATE, immediately following, same session: a validated call-
target cross-reference tool (see Firmware Reversing)
found one real, confirmed computed-call target at 0x587224 — inside
the uncertain range, between the loop's own backward-branch target
(0x587150) and the originally-assumed start (0x5872d0). Checked
directly: not itself a function prologue, but genuinely real,
independently call-reachable code (part of a clrlwi/cmpwi/beq
sequence). Doesn't fully resolve the boundary, but confirms this
uncertain range contains real, separately-invokable structure — most
consistent with a shared case/label inside the same larger enclosing
routine, reached via computed call from elsewhere, rather than
mv_check_turn being a simple standalone function.
Boundary mystery resolved: the real true start is 0x586f3c
Disassembling from the next-earlier real prologue (0x586f3c, the
"roughly 900 bytes earlier" candidate flagged above as unexplored)
finds real, coherent, on-topic code the whole way through to the
already-confirmed blr at 0x587568 — this IS the function's real,
complete body, confirming the earlier backward-prologue-scan undershot
by exactly one real function. Real, confirmed evidence this is the
correct boundary (not just "a" prologue):
- Calls
resetStatement__C13MDEDMDatabaseP31CfcPredefinedStatementInterface— a real precompiled-SQL-statement reset on aMDEDMDatabase(the same real EDB/SQL layer documented on Firmware Reversing) — then iterates over the query's results with a classiclwz/stw-pair copy loop. - Calls
oslibVfs_register__Fi— a real, direct VxWorks OS-library virtual-filesystem registration call. - Classifies each result row's extracted angle-ish field (
rlwinmbit-extraction, compared against0x20/0x40) into one of 3 real turn-type codes (0x32/0x3a/0x2a) — directly matching the function's own name ("check turn"), and feeding straight into the 6-case switch statement already captured below.
This is now a confirmed, resolved true start, not just a
plausible candidate — real size at least 0x587568 - 0x586f3c = 0x62c (1,580) bytes.
What was disassembled (real code, but see caveat above)
0x5872d0: stwu r1, -0x40(r1)
0x5872d4: mflr r0
0x5872d8: stw r28, 0x30(r1)
0x5872dc: stw r29, 0x34(r1)
0x5872e0: stw r30, 0x38(r1)
0x5872e4: stw r31, 0x3c(r1)
0x5872e8: stw r0, 0x44(r1)
0x5872ec: mr r30, r3
0x5872f0: lwz r0, 0x420(r30) ; a count field
0x5872f4: li r28, 0 ; loop index = 0
0x5872f8: cmpw r28, r0
0x5872fc: bge 0x5876fc
0x587300: lis r9, -0x86d
0x587304: lwz r11, -0x4268(r9)
0x587308: slwi r0, r28, 4 ; index * 0x10 (16-byte stride)
0x58730c: lis r9, -0x8f5
0x587310: add r29, r11, r0
0x587314: addi r10, r1, 0x20
0x587318: addi r9, r9, -0x2ce8
0x58731c: mtlr r9
0x587320: mr r5, r10
0x587324: addi r3, r30, 0xe4
0x587328: addi r4, r29, 4
0x58732c: li r6, 1
0x587330: li r0, 0
0x587334: stw r0, 0x20(r1)
0x587338: stw r0, 4(r10)
0x58733c: blrl ; virtual call
0x587340: lwz r9, 0xc(r29)
0x587344: srwi r9, r9, 0x1d
0x587348: addi r0, r9, -1
0x58734c: cmplwi r0, 5
0x587350: bgt 0x5876ec
0x587354: lis r11, -0x894
0x587358: addi r11, r11, 0x1e10 ; a real jump table base
0x58735c: slwi r0, r0, 2
0x587360: lwzx r10, r11, r0 ; load table[value]
0x587364: lis r9, -0x894
0x587368: addi r9, r9, 0x1e10
0x58736c: add r10, r10, r9 ; relative jump-table entry
0x587370: mtctr r10
0x587374: bctr ; REAL C++ switch statement
(the switch's 6 cases and the loop back to 0x587150 -- outside this
capture, per the caveat above -- are not reproduced here; the loop
eventually reaches 0x587568: blr.)
Analysis
A real for-loop (0x5872f4-0x5872fc, 0x587540-0x587548) over a
count field at this+0x420, with a genuine compiler-generated switch
statement (mtctr/bctr off a computed jump-table lookup,
0x587354-0x587374) inside it, dispatching to (at least) 6 real
cases. Now confirmed (see "Boundary mystery resolved" above) to be the
back half of the SAME function that starts at 0x586f3c with a real
SQL-query/angle-classification preamble — together, the whole function
queries a predefined turn-geometry statement from the real MDEDMDatabase,
classifies each result row into one of 3 turn-type codes, and the
switch/loop captured here dispatches on that classification across (at
least) 6 cases, consistent with the function's own name end to end.
Callees
resetStatement__C13MDEDMDatabaseP31CfcPredefinedStatementInterfaceoslibVfs_register__Fi
The switch statement's own 6 case targets and the loop body back to
0x587150 were not individually traced — a real, scoped-out next step.
UPDATE: real Hex-Rays decompilation independently confirms this
analysis and adds 3 new real details
With whole-file function recovery in place (see
Firmware Reversing), 0x586f3c/VA 0xf6e14c30
now decompiles directly — and it's the SAME function already documented
above (confirmed by matching content), giving a genuine independent
cross-check rather than new guesswork:
- The 3 turn-type codes match exactly: Hex-Rays shows the
bit-extraction classifying into decimal
50/58/42, which are exactly0x32/0x3a/0x2a— the same 3 codes already documented above from manual disassembly. Independent confirmation, via a completely different tool/method, that this trace is correct. - New: immediately after the classification, a real 2D bounding-box
/ geofence check —
x >= this[0x400] && y >= this[0x404] && x <= this[0x408] && y <= this[0x40c]— applied to coordinate pairs copied out of the query-result stream in the loop already documented above. Not previously captured at this level of detail. - New call target:
unk_F7178080(2883633, v6, v5 >> 2)— called once, early, with a large constant ID (2883633=0x2C0031) a pointer, and a shifted count. Not yet characterized; worth checking against other call sites of the same address in a future session. - Caveat: later in the decompiled output, a computed call through
(v3 - 11496)appears wherev3is never visibly assigned — this is almost certainly a decompilation artifact of the forced function boundary (see Firmware Reversing's "JUMPOUT" discussion) rather than a literal computed jump in the real program; not to be read as real behavior without further checking.