Firmware Fn mv check turn - krcenov/RNS510-Map-Viewer GitHub Wiki

mv_check_turn

Part of Firmware Reversing.

  • Naive symbol-table address: 0x587440 (VA 0xf6e15134)
  • Nearest preceding prologue found FIRST (undershot): 0x5872d0 (VA 0xf6e14fc4)
  • Real, confirmed true start: 0x586f3c (VA 0xf6e14c30) — 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, 2 int args)

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 a MDEDMDatabase (the same real EDB/SQL layer documented on Firmware Reversing) — then iterates over the query's results with a classic lwz/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 (rlwinm bit-extraction, compared against 0x20/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__C13MDEDMDatabaseP31CfcPredefinedStatementInterface
  • oslibVfs_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 exactly 0x32/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 where v3 is 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.