Skip to content

riscv64: add ELF relocation support#637

Open
Jvlegod wants to merge 4 commits intoangr:masterfrom
Jvlegod:riscv
Open

riscv64: add ELF relocation support#637
Jvlegod wants to merge 4 commits intoangr:masterfrom
Jvlegod:riscv

Conversation

@Jvlegod
Copy link

@Jvlegod Jvlegod commented Dec 30, 2025

Hello maintainers,

This change introduces an initial implementation of RISCV64 relocations.

In a follow-up PR, I plan to add a dedicated, minimal and reproducible test fixture following the existing AArch64 pattern:

  • A minimal RISCV64 relocation .o file under the binaries repository.

  • A pytest under cle/tests/ to assert the relocation results.(I've implemented the test script, and I'll try to merge it into the repository if you approve.)

I have verified the implementation using several real-world object files (e.g., snake/tetris projects) as stress tests in my local environment.(test script)

Regarding the upcoming test fixture, could you please share your requirements for adding new files to the binaries repository?

References

  1. https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#relocations
  2. https://docs.riscv.org/reference/isa/_attachments/riscv-unprivileged.pdf

@Jvlegod
Copy link
Author

Jvlegod commented Dec 30, 2025

I have verified the implementation using several real-world object files (e.g., snake/tetris projects) as stress tests in my local environment.(test script)

My script execution example(This is a Snake game project.).

$ python3 test_riscv64_relocations.py 
============================================================
Testing: Game.o
============================================================
# ......
Relocation Test Report:
    - lo12_i         : 48
    - call           : 540
    - branch         : 105
    - rvc_jump       : 152
    - rvc_branch     : 143

============================================================
Testing: Snake.o
============================================================
# ......
Relocation Test Report:
    - lo12_i         : 22
    - call           : 262
    - branch         : 45
    - rvc_jump       : 80
    - rvc_branch     : 86

============================================================
Testing: main.o
============================================================
# ......
Relocation Test Report:
    - lo12_i         : 41
    - lo12_s         : 1
    - call           : 237
    - 64_abs         : 1
    - branch         : 23
    - rvc_jump       : 58
    - rvc_branch     : 72

============================================================
Testing: snake_all.o
============================================================
# ......
Relocation Test Report:
    - lo12_i         : 150
    - lo12_s         : 1
    - call           : 775
    - 64_abs         : 1
    - branch         : 144
    - rvc_jump       : 216
    - rvc_branch     : 212

============================================================
Testing: test.o
============================================================
# ......
Relocation Test Report:
    - call           : 23
    - branch         : 5
    - rvc_jump       : 8
    - rvc_branch     : 16

------------------------------------------------------------
Summary: 5/5 files passed.
------------------------------------------------------------

@rhelmot
Copy link
Member

rhelmot commented Dec 30, 2025

I would prefer if you could add the testcase in this PR. feel free to submit any binary to the binaries repository as long as you have the rights to distribute it. If possible, please also add the source code in the tests_src folder.

@Jvlegod
Copy link
Author

Jvlegod commented Dec 31, 2025

I would prefer if you could add the testcase in this PR. feel free to submit any binary to the binaries repository as long as you have the rights to distribute it. If possible, please also add the source code in the tests_src folder.

Okay, I'm doing this as you expect.

@Jvlegod
Copy link
Author

Jvlegod commented Dec 31, 2025

feel free to submit any binary to the binaries repository as long as you have the rights to distribute it.

The PR is here: #150

The script will automatically run the files located in binaries/tests/riscv64. The test cases are from the LLVM project repository.

My local execution results are as follows.

$ python3 test_riscv64_relocations.py 
# ......
============================================================
Testing: riscv-branch.rv64.o
============================================================
INFO:cle.backends.elf.elf:no PT_LOAD segments identified
INFO:cle.loader:Linking /home/jvle/Desktop/works/sec/angr-dev/binaries/tests/riscv64/riscv-branch.rv64.o
INFO:cle.backends.externs:Created extern symbol for foo
INFO:cle.backends.externs:Created extern symbol for bar
INFO:cle.loader:Mapping /home/jvle/Desktop/works/sec/angr-dev/binaries/tests/riscv64/riscv-branch.rv64.o at 0x210000
INFO:cle.loader:Mapping cle##externs at 0x300000
WARNING:cle.loader:Symbol imported without a known size; emulation may fail if it is used non-opaqely: bar, foo. See https://docs.angr.io/extending-angr/environment#simdata
Relocation Test Report:
    - jal            : 2

============================================================
Testing: riscv-call.rv64.o
============================================================
INFO:cle.backends.elf.elf:no PT_LOAD segments identified
INFO:cle.loader:Linking /home/jvle/Desktop/works/sec/angr-dev/binaries/tests/riscv64/riscv-call.rv64.o
INFO:cle.backends.externs:Created extern symbol for foo
INFO:cle.backends.externs:Created extern symbol for bar
INFO:cle.loader:Mapping /home/jvle/Desktop/works/sec/angr-dev/binaries/tests/riscv64/riscv-call.rv64.o at 0x210000
INFO:cle.loader:Mapping cle##externs at 0x300000
WARNING:cle.loader:Symbol imported without a known size; emulation may fail if it is used non-opaqely: bar, foo. See https://docs.angr.io/extending-angr/environment#simdata
Relocation Test Report:
    - call           : 2

============================================================
Testing: riscv-hi20-lo12.rv64.o
============================================================
INFO:cle.backends.elf.elf:no PT_LOAD segments identified
INFO:cle.loader:Linking /home/jvle/Desktop/works/sec/angr-dev/binaries/tests/riscv64/riscv-hi20-lo12.rv64.o
INFO:cle.backends.externs:Created extern symbol for foo
INFO:cle.backends.externs:Created extern symbol for bar
INFO:cle.loader:Mapping /home/jvle/Desktop/works/sec/angr-dev/binaries/tests/riscv64/riscv-hi20-lo12.rv64.o at 0x210000
INFO:cle.loader:Mapping cle##externs at 0x300000
WARNING:cle.loader:Symbol imported without a known size; emulation may fail if it is used non-opaqely: bar, foo. See https://docs.angr.io/extending-angr/environment#simdata
Relocation Test Report:
    - lo12_i         : 2
    - lo12_s         : 2

============================================================
Testing: riscv-jal.rv64.o
============================================================
INFO:cle.backends.elf.elf:no PT_LOAD segments identified
INFO:cle.loader:Linking /home/jvle/Desktop/works/sec/angr-dev/binaries/tests/riscv64/riscv-jal.rv64.o
INFO:cle.backends.externs:Created extern symbol for foo
INFO:cle.backends.externs:Created extern symbol for bar
INFO:cle.loader:Mapping /home/jvle/Desktop/works/sec/angr-dev/binaries/tests/riscv64/riscv-jal.rv64.o at 0x210000
INFO:cle.loader:Mapping cle##externs at 0x300000
WARNING:cle.loader:Symbol imported without a known size; emulation may fail if it is used non-opaqely: bar, foo. See https://docs.angr.io/extending-angr/environment#simdata
Relocation Test Report:
    - jal            : 2

============================================================
Testing: riscv-pcrel-hilo.rv64.o
============================================================
INFO:cle.backends.elf.elf:no PT_LOAD segments identified
INFO:cle.loader:Linking /home/jvle/Desktop/works/sec/angr-dev/binaries/tests/riscv64/riscv-pcrel-hilo.rv64.o
INFO:cle.backends.externs:Created extern symbol for foo
INFO:cle.backends.externs:Created extern symbol for bar
INFO:cle.loader:Mapping /home/jvle/Desktop/works/sec/angr-dev/binaries/tests/riscv64/riscv-pcrel-hilo.rv64.o at 0x210000
INFO:cle.loader:Mapping cle##externs at 0x300000
WARNING:cle.loader:Symbol imported without a known size; emulation may fail if it is used non-opaqely: bar, foo. See https://docs.angr.io/extending-angr/environment#simdata
Relocation Test Report:
    - pcrel_hi20     : 2
    - pcrel_lo12_i   : 2
    - pcrel_lo12_s   : 2

============================================================
Testing: riscv-plt.64.o
============================================================
INFO:cle.backends.elf.elf:no PT_LOAD segments identified
INFO:cle.loader:Linking /home/jvle/Desktop/works/sec/angr-dev/binaries/tests/riscv64/riscv-plt.64.o
INFO:cle.backends.externs:Created extern symbol for bar
INFO:cle.loader:Mapping /home/jvle/Desktop/works/sec/angr-dev/binaries/tests/riscv64/riscv-plt.64.o at 0x210000
INFO:cle.loader:Mapping cle##externs at 0x300000
WARNING:cle.loader:Symbol imported without a known size; emulation may fail if it is used non-opaqely: bar. See https://docs.angr.io/extending-angr/environment#simdata
Relocation Test Report:
    - call           : 4

============================================================
Testing: riscv-reloc-64-pic.o
============================================================
INFO:cle.backends.elf.elf:no PT_LOAD segments identified
INFO:cle.loader:Linking /home/jvle/Desktop/works/sec/angr-dev/binaries/tests/riscv64/riscv-reloc-64-pic.o
INFO:cle.backends.externs:Created extern symbol for a
INFO:cle.loader:Mapping /home/jvle/Desktop/works/sec/angr-dev/binaries/tests/riscv64/riscv-reloc-64-pic.o at 0x210000
INFO:cle.loader:Mapping cle##externs at 0x300000
WARNING:cle.loader:Symbol imported without a known size; emulation may fail if it is used non-opaqely: a. See https://docs.angr.io/extending-angr/environment#simdata
Relocation Test Report:
    - 32_abs         : 1

============================================================
Testing: riscv-reloc-copy.o
============================================================
INFO:cle.backends.elf.elf:no PT_LOAD segments identified
INFO:cle.loader:Linking /home/jvle/Desktop/works/sec/angr-dev/binaries/tests/riscv64/riscv-reloc-copy.o
INFO:cle.backends.externs:Created extern symbol for x
INFO:cle.loader:Mapping /home/jvle/Desktop/works/sec/angr-dev/binaries/tests/riscv64/riscv-reloc-copy.o at 0x210000
INFO:cle.loader:Mapping cle##externs at 0x300000
WARNING:cle.loader:Symbol imported without a known size; emulation may fail if it is used non-opaqely: x. See https://docs.angr.io/extending-angr/environment#simdata
Relocation Test Report:
    - pcrel_hi20     : 1
    - pcrel_lo12_i   : 1

============================================================
Testing: riscv-reloc-copy_1.o
============================================================
INFO:cle.backends.elf.elf:no PT_LOAD segments identified
INFO:cle.loader:Linking /home/jvle/Desktop/works/sec/angr-dev/binaries/tests/riscv64/riscv-reloc-copy_1.o
INFO:cle.backends.externs:Created extern symbol for x
INFO:cle.loader:Mapping /home/jvle/Desktop/works/sec/angr-dev/binaries/tests/riscv64/riscv-reloc-copy_1.o at 0x210000
INFO:cle.loader:Mapping cle##externs at 0x300000
WARNING:cle.loader:Symbol imported without a known size; emulation may fail if it is used non-opaqely: x. See https://docs.angr.io/extending-angr/environment#simdata
Relocation Test Report:
    - pcrel_hi20     : 1
    - pcrel_lo12_i   : 1

============================================================
Testing: riscv-reloc-got.o
============================================================
INFO:cle.backends.elf.elf:no PT_LOAD segments identified
INFO:cle.loader:Linking /home/jvle/Desktop/works/sec/angr-dev/binaries/tests/riscv64/riscv-reloc-got.o
INFO:cle.backends.externs:Created extern symbol for b
INFO:cle.loader:Mapping /home/jvle/Desktop/works/sec/angr-dev/binaries/tests/riscv64/riscv-reloc-got.o at 0x210000
INFO:cle.loader:Mapping cle##externs at 0x300000
WARNING:cle.loader:Symbol imported without a known size; emulation may fail if it is used non-opaqely: b. See https://docs.angr.io/extending-angr/environment#simdata
Relocation Test Report:
    - pcrel_lo12_i   : 2

============================================================
Testing: riscv64-reloc-64-pic.o
============================================================
INFO:cle.backends.elf.elf:no PT_LOAD segments identified
INFO:cle.loader:Linking /home/jvle/Desktop/works/sec/angr-dev/binaries/tests/riscv64/riscv64-reloc-64-pic.o
INFO:cle.backends.externs:Created extern symbol for a
INFO:cle.loader:Mapping /home/jvle/Desktop/works/sec/angr-dev/binaries/tests/riscv64/riscv64-reloc-64-pic.o at 0x210000
INFO:cle.loader:Mapping cle##externs at 0x300000
WARNING:cle.loader:Symbol imported without a known size; emulation may fail if it is used non-opaqely: a. See https://docs.angr.io/extending-angr/environment#simdata
Relocation Test Report:
    - 64_abs         : 2

============================================================
Testing: riscv64-reloc-64-pic.so
============================================================
INFO:cle.loader:Linking /home/jvle/Desktop/works/sec/angr-dev/binaries/tests/riscv64/riscv64-reloc-64-pic.so
INFO:cle.backends.externs:Created extern symbol for a
INFO:cle.loader:Mapping /home/jvle/Desktop/works/sec/angr-dev/binaries/tests/riscv64/riscv64-reloc-64-pic.so at 0x210000
INFO:cle.loader:Mapping cle##externs at 0x300000
WARNING:cle.loader:Symbol imported without a known size; emulation may fail if it is used non-opaqely: a. See https://docs.angr.io/extending-angr/environment#simdata
Relocation Test Report:
    - 64_abs         : 1

------------------------------------------------------------
Summary: 12/12 files passed.
------------------------------------------------------------

@ltfish
Copy link
Member

ltfish commented Dec 31, 2025

@rhelmot @twizmwazin I don't think our CI runs any cle test cases...

@rhelmot
Copy link
Member

rhelmot commented Dec 31, 2025

https://github.com/angr/cle/actions/runs/20616728686/job/59211186139?pr=637#step:5:540 we are definitely running the CLE tests in the full ecosystem tests. The problem is that the test case is not written correctly - it should raise an exception or fail an assertion when something is wrong. Furthermore, it should probably raise a unittest.SkipTest if the binaries are missing instead of just returning.

@rhelmot
Copy link
Member

rhelmot commented Dec 31, 2025

Also, please fix the lint and typecheck CI passes, with one caveat:

  • feel free to # pylint: ignore=missing-class-docstring for the relocation class file

@Jvlegod Jvlegod force-pushed the riscv branch 2 times, most recently from b579fd8 to 3c040a1 Compare January 1, 2026 05:10
@Jvlegod
Copy link
Author

Jvlegod commented Jan 1, 2026

I have applied several fixes to address the previous CI failures:

  1. riscv64.py: Added docstrings for all relocation classes.

  2. test_riscv64_relocations.py: Removed unnecessary parentheses in assert statements (fixing superfluous-parens) and resolve type errors.

I am not entirely sure if this covers all CI requirements, so please let me know if further adjustments are needed.

@Jvlegod Jvlegod force-pushed the riscv branch 2 times, most recently from 2592498 to a5f1fef Compare January 1, 2026 14:41
@Jvlegod
Copy link
Author

Jvlegod commented Jan 1, 2026

The test script goes beyond opcode checks: it decodes the patched instruction/immediate fields and compares them against the expected relocated values. This is already sufficient to catch common implementation mistakes, so it should serve well as a test baseline.

One limitation to note: the script currently only asserts relocations with resolved == True. Depending on the input .o/.so and whether external symbols or dependencies are available, CLE may leave some relocations unresolved (resolved == False), and those entries are skipped.

As RISCV64 support grows (e.g., more relocation types), the script can be extended accordingly, and we can revisit whether more complete fixtures are needed to improve coverage.

@rhelmot
Copy link
Member

rhelmot commented Jan 2, 2026

I appreciate this pull request, but please in the future use chatgpt for just translation instead of having it describe your changes entirely. That description scans as almost entirely useless due to the way chatgpt describes things both vaguely and as exceptional. See https://en.wikipedia.org/wiki/Wikipedia:Signs_of_AI_writing

Please continue to fix the lint/typecheck passes. In order to fix the weird error about the value property, you can add type annotations to cle/backends/elf/relocation/elfreloc.py.

Signed-off-by: Jvle <keke.oerv@isrc.iscas.ac.cn>
Signed-off-by: Jvle <keke.oerv@isrc.iscas.ac.cn>
Signed-off-by: Jvle <keke.oerv@isrc.iscas.ac.cn>
@Jvlegod
Copy link
Author

Jvlegod commented Jan 3, 2026

please in the future use chatgpt for just translation instead of having it describe your changes entirely.

Thank you for your suggestion. In future work, I will not directly use GPT to explain the PR to ensure they accurately reflect the changes.

Please continue to fix the lint/typecheck passes. In order to fix the weird error about the value property

I added a new commit(3b0341b) to fix this issue.

Error: e/cle/build/src/cle/cle/backends/elf/relocation/riscv64.py:220:6: [error] Base classes for class "R_RISCV_GOT_HI20" define method "resolve" in incompatible way

https://github.com/angr/cle/actions/runs/20640448973/job/59336322698?pr=637

The error was caused by inconsistent function parameters during multiple inheritance, which I have fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants