Skip to content

Resolve branches between functions without relocations #324

@MonsterDruide1

Description

@MonsterDruide1

When compiling C++ with clang (at least on 3.9.1), the compiler might not output a relocation for branch targets within the same translation unit/object file.

Example:

00000000000001a4 <_ZN6Player7exeWaitEv>:
 1a4:    f81e0ff3     str    x19, [sp, #-32]!
 1a8:    a9017bfd     stp    x29, x30, [sp, #16]

[...]

00000000000008b8 <_ZNK12_GLOBAL__N_113PlayerNrvWait7executeEPN2al11NerveKeeperE>:
 8b8:    f9400020     ldr    x0, [x1]
 8bc:    17fffe3a     b    1a4 <_ZN6Player7exeWaitEv>

The final branch at 8bc outputs no relocation here:

[...]
0000000000000878 R_AARCH64_ADR_PREL_PG_HI21  .data+0x0000000000000020
000000000000087c R_AARCH64_ADD_ABS_LO12_NC  .data+0x0000000000000020
0000000000000884 R_AARCH64_CALL26  _ZN2al8setNerveEPNS_9IUseNerveEPKNS_5NerveE


RELOCATION RECORDS FOR [.text._ZN4sead14SafeStringBaseIcED0Ev]:
[...]

An example file can be found here:
Player.zip

Source: https://github.com/MonsterDruide1/OdysseyDecomp/blob/master/src/Player/Player.cpp

Just put it into a diff on both sides, and check one of the (anonymous namespace):: entries, for example (anonymous namespace)::PlayerNrvWait::execute(al::NerveKeeper*) const. objdiff correctly finds it matching (100%), but displays b $<invalid> for the branch.

A relevant point to start investigation is here:
https://github.com/encounter/objdiff/blob/main/objdiff-core/src/diff/display.rs#L274

In this case, dest = 0x1a4, resolved.symbol.address = 0x8bc, so the u64.checked_sub fails.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions