Firmware Fn ResolveUnsetNodeID - krcenov/RNS510-Map-Viewer GitHub Wiki

ResolveUnsetNodeID — AdasDBAccess::ResolveUnsetNodeID

Part of Firmware Reversing.

  • File offset: 0x828940 (true prologue start; naive symbol-table field-4 address is 0x828de8)
  • VA: 0xf70b6634 (= 0x828940 + 0xf688dcf4)
  • Status: 🟢 Fully traced (largest/most complex of the 4 fully-traced functions; one boundary noted below is not 100% pinned down)
  • Real name source: symbol/EH-descriptor table, loose match, true start found by scanning backward from the naive target the same way as getNodeVidArmMP0

Not to be confused with resolveUnsetVNodeId (LaneCalculation::resolveUnsetVNodeId) — a different class, different address, and (unlike this function) unreachable.

Disassembly

0x828940: stwu     r1, -0x30(r1)
0x828944: mflr     r0
0x828948: stmw     r29, 0x24(r1)
0x82894c: stw      r0, 0x34(r1)
0x828950: mr       r31, r3                  ; arg1 = this
0x828954: lwz      r0, 4(r31)               ; read this+4 -- the "node id" field?
0x828958: cmpwi    r0, 0
0x82895c: beq      0x82899c                 ; unset (==0) -> do real work below
0x828960: lis      r9, -0x91c
0x828964: addi     r0, r9, -0x52f4          ; computed call target (see below)
0x828968: addi     r29, r1, 0x10
0x82896c: mtlr     r0
0x828970: addi     r4, r31, 0x28
0x828974: mr       r3, r29
0x828978: blrl                              ; virtual call -- the actual resolve step
0x82897c: lwz      r11, 4(r31)
0x828980: mr       r4, r29
0x828984: lwz      r9, 4(r11)
0x828990: lwz      r0, 0x34(r1)
0x828994: mtlr     r0
0x828998: lmw      r29, 0x24(r1)
0x82899c: addi     r1, r1, 0x30             ; already-set path also lands here
0x8289a8: stmw     r28, 0x20(r1)            ; a DIFFERENT function's own prologue starts
0x8289ac: stw      r0, 0x34(r1)             ; immediately after -- see caveat below
0x8289b0: mr       r28, r3
0x8289b4: lwz      r8, 8(r28)
0x8289c0: mr       r31, r3
0x8289c4: mtlr     r0
0x8289c8: mr       r3, r28
0x8289d4: addi     r29, r1, 0x10
0x8289d8: addi     r28, r28, 0x28
0x8289e4: mr       r4, r3
0x8289e8: lwz      r9, 0(r4)
0x8289ec: mr       r5, r31
0x8289f0: mr       r3, r29
0x8289f4: lha      r0, 0x18(r9)
0x8289f8: lwz      r9, 0x1c(r9)
0x8289fc: add      r4, r4, r0
0x828a00: mtlr     r9
0x828a0c: mr       r4, r29
0x828a10: mr       r3, r28
0x828a1c: lwz      r0, 0x34(r1)
0x828a20: mtlr     r0
0x828a24: lmw      r28, 0x20(r1)
0x828a28: addi     r1, r1, 0x30
0x828a34: mr       r30, r3
0x828a38: lwz      r9, 0xc(r30)
0x828a3c: mr       r31, r4
0x828a40: lha      r3, 0x18(r9)
0x828a44: lwz      r0, 0x1c(r9)
0x828a50: cmplw    r31, r3
0x828a54: blt      0x828a74
0x828a58: lwz      r9, 0xc(r30)
0x828a64: addi     r31, r3, -1
0x828a68: lwz      r0, 4(r30)
0x828a6c: slwi     r3, r31, 2
0x828a70: add      r3, r0, r3
0x828a7c: or.      r30, r4, r4
0x828a80: mr       r29, r3
0x828a84: li       r3, 0
0x828a88: beq      0x828b2c
0x828a94: addi     r4, r4, -0x7a4c
0x828a98: li       r3, 0x18                 ; sizeof() -- allocating a new node
0x828a9c: li       r5, 0x19
0x828aa0: blrl                              ; virtual call -- allocator
0x828aa4: lwz      r4, 0(r30)
0x828aa8: mr       r31, r3
0x828aac: lwz      r11, 0x14(r30)
0x828ab0: cmpwi    r4, 0
0x828ab4: lwz      r0, 0x10(r30)
0x828ab8: lwz      r9, 0xc(r30)
0x828abc: stw      r11, 0x14(r3)
0x828ac0: stw      r0, 0x10(r3)
0x828ac4: stw      r9, 0xc(r31)
0x828ac8: beq      0x828aec
0x828acc: lis      r9, -0x8b8
0x828ad0: addi     r0, r9, 0x25fc
0x828ad4: mr       r3, r29
0x828ad8: mtlr     r0
0x828adc: blrl                              ; virtual call
0x828ae0: stw      r3, 0(r31)
0x828ae4: stw      r31, 8(r3)
0x828ae8: b        0x828af0
0x828aec: stw      r4, 0(r31)
0x828af0: lwz      r4, 4(r30)
0x828af4: cmpwi    r4, 0
0x828b00: stw      r3, 4(r31)
0x828b04: stw      r31, 8(r3)
0x828b08: b        0x828b10
0x828b0c: stw      r4, 4(r31)
0x828b10: mr       r3, r31
0x828b20: addi     r0, r9, -0x5f70
0x828b2c: blrl                              ; virtual call
0x828b30: lwz      r0, 4(r29)
0x828b34: lis      r9, -0x90f
0x828b38: stw      r0, 4(r31)
0x828b3c: lis      r4, -0x871
0x828b40: addi     r0, r9, 0x1714
0x828b44: addi     r4, r4, -0x7a4c
0x828b48: mtlr     r0
0x828b54: stw      r3, 8(r31)
0x828b58: li       r0, 0
0x828b5c: lwz      r9, 8(r29)
0x828b60: stw      r0, 0xc(r3)
0x828b64: lwz      r4, 8(r9)
0x828b68: cmpwi    r4, 0
0x828b6c: bne      0x828b80
0x828b70: stw      r4, 8(r3)
0x828b74: stw      r3, 0(r3)
0x828b78: stw      r3, 4(r3)
0x828b7c: b        0x828be0
0x828b80: lis      r9, -0x8b8
0x828b84: addi     r0, r9, 0x25fc
0x828b90: lwz      r9, 8(r31)
0x828b94: stw      r3, 8(r9)
0x828b98: stw      r9, 8(r3)
0x828b9c: lwz      r11, 8(r9)
0x828ba0: b        0x828ba8
0x828ba4: lwz      r11, 0(r11)             ; tree/list walk loop
0x828ba8: lwz      r0, 0(r11)
0x828bac: cmpwi    r0, 0
0x828bb0: bne      0x828ba4
0x828bb4: lwz      r9, 8(r31)
0x828bb8: lwz      r10, 8(r9)
0x828bbc: stw      r11, 0(r9)
0x828bc0: b        0x828bc8
0x828bc4: lwz      r10, 4(r10)
0x828bc8: lwz      r0, 4(r10)
0x828bd4: stw      r10, 4(r9)
0x828be0: addi     r0, r9, -0x5e84
0x828be4: mr       r29, r3
0x828be8: mtlr     r0
0x828bec: lwz      r3, 0(r29)
0x828bf8: li       r5, 0x147
0x828bfc: addi     r4, r4, -0x7370
0x828c08: lwz      r4, 0(r29)
0x828c0c: addi     r0, r9, 0x26d0
0x828c10: mtlr     r0
0x828c14: blrl                              ; virtual call
0x828c18: stw      r3, 0(r29)
0x828c24: lwz      r11, 0(r3)
0x828c28: lwz      r0, 4(r11)
0x828c2c: cmpwi    r0, 0
0x828c30: beq      0x828c5c
0x828c34: mr       r11, r0
0x828c38: lwz      r0, 0(r11)
0x828c3c: cmpwi    r0, 0
0x828c40: beq      0x828c88
0x828c4c: b        0x828c80
0x828c50: mr       r11, r9
0x828c54: lwz      r9, 8(r11)
0x828c58: lwz      r0, 4(r9)
0x828c5c: cmpw     r11, r0
0x828c60: beq      0x828c50               ; tree-rotation-shaped pointer fixup
0x828c64: lwz      r0, 4(r11)
0x828c68: xor      r0, r0, r9
0x828c6c: addic    r0, r0, -1
0x828c70: subfe    r0, r0, r0
0x828c74: andc     r9, r9, r0
0x828c78: and      r0, r11, r0
0x828c7c: or       r11, r0, r9
0x828c80: stw      r11, 0(r3)
0x828c84: li       r3, 0
0x828c88: blr

(interstitial non-instruction words — EH-descriptor table entries, same pattern as elsewhere in this file — omitted from the listing above for readability; every one was checked and confirmed to decode as invalid, not silently skipped.)

Analysis

Reads offset+4 of its own argument and checks it against zero — consistent with a "resolved node id" field, matching the function's own name. If already set, execution falls through to 0x82899c and pops the stack frame — but does not reach a local blr there; it lands directly on what looks like a SEPARATE function's own prologue (stmw r28,0x20(r1) at 0x8289a8) with no call instruction in between, consistent with a real GCC tail-call optimization (reusing the frame pop, falling straight into the next routine using the original caller's own link register) rather than a simple return. This means the exact boundary between ResolveUnsetNodeID and whatever starts at 0x8289a8 is NOT fully pinned down — flagged honestly rather than assumed.

If unset, makes a virtual call (0x828978) passing this+0x28, then — after re-reading the result — performs substantial pointer/tree manipulation: an li r3,0x18/li r5,0x19 pair immediately before a virtual call (0x828aa0) looks like a real sizeof+alignment pair feeding an allocator (allocating a 0x18-byte node), followed by linked pointer field stores (0(r31)/4(r31)/8(r31)) and a loop (0x828ba4-0x828bb0) walking a chain via lwz r11,0(r11) until a NUL terminator, then more pointer rewiring using a branchless XOR-based conditional-swap idiom (0x828c64-0x828c7c) — the same general shape a red-black-tree or similar self-balancing structure's insert/rotate step would take. Consistent with "if this node's id hasn't been resolved yet, compute it and insert the result into a cache/index structure."

Callees

None of its own virtual-call targets have been checked yet — a concrete next step, though a deep one given how many calls this function alone makes.