Skip to content

Support for large function call parsing from asm instructions in RISCV broken #151

Description

@paulwuertz

While trying to apply puncover to the wifi shell sample from zephyr RTOS[1] on a ESP32C3 (the RISCV one) I ran into a bug:

File ".../puncover/puncover/collector.py", line 438, in add_function_call
if caller not in callee[CALLERS]:

Debugging the issue I found it came from one of the function call instructions.
This is caused, by the more complicated call scheme around this instruction.

There is jal and jalr, the later can be relative to a register, which is the issue.

So the call address cannot be parsed from one single instruction. Cite:

At one level, this post is about two instructions: jal (jump and link) and jalr (jump and link register). But these two instructions are exciting because they enable functions (also known as subroutines or procedure calls).

jal rd, imm # rd = pc+4; pc += imm
jalr rd, rs1, imm # rd = pc+4; pc = rs1+imm

Before updating the PC, a jump instruction writes the address of the following instruction into a register. By saving this return address, we can return to it and continue execution where we left off.

jal uses a 20-bit signed immediate for the jump destination, while jalr uses a register plus 12-bit signed offset in a similar way to the load and store instructions.

jal range is ±1MiB in units of two bytes for greater range with compressed instruction support.

jalr range is ±2KiB, but you can combine jalr with lui or auipc to reach any 32-bit address.

So the culprit assembly line is 4038a354:\t004080e7 jalr 4(ra) # 40000354 <memset>.

Applying the enhance_call_tree_pattern usually takes group 3 of the regex as the call address.

But in this case group 3 is 4, but which means register ra offset by 4.

So correct call path deduction from assembly is much harder on RISCV to implement and remains with...

Exporting the json report and grepping through it cat wifishell.json | grep -e 'jal\\' | wc -l (7181 instances) and cat wifishell.json | grep -e 'jalr' | wc -l (4429 instances) shows both instruction are used - depending how far the function are apart.

GCC output of some includes the callee name, sometimes only the register.

More examples cat wifishell.json | grep jalr:

                "4206d1aa:\t778080e7          \tjalr\t1912(ra) # 4038091e <phy_printf>",
                "4206d1c8:\t9782                \tjalr\ta5",
                "4206d2a2:\t9782                \tjalr\ta5",
                "4206d2ba:\t9782                \tjalr\ta5",
                "4206d2c8:\t9c02                \tjalr\ts8",
                "4206d2d4:\t9782                \tjalr\ta5",
                "4206d2e6:\t9782                \tjalr\ta5",
                "4206d374:\t9782                \tjalr\ta5",
                "4206d3d4:\t9782                \tjalr\ta5",
                "4206d3e8:\t9782                \tjalr\ta5",
                "4206d3fe:\t9782                \tjalr\ta5",
                "4206d412:\t9782                \tjalr\ta5",
                "4206d458:\t9782                \tjalr\ta5",
                "4206d65c:\t9802                \tjalr\ta6",
                "4206d67c:\t2a6080e7          \tjalr\t678(ra) # 4038091e <phy_printf>",
                "4206d6ca:\t258080e7          \tjalr\t600(ra) # 4038091e <phy_printf>",
                "4206d6f0:\t9802                \tjalr\ta6",
                "4206d7b2:\t9802                \tjalr\ta6",

[1] build by west build --sysbuild -p -b xiao_esp32c3/esp32c3 samples/net/wifi/shell/ -- -DCONFIG_STACK_USAGE=y
then puncover --generate-report --report-tag 123 --report-type json --build_dir ~/zephyrproject/zephyr/build/ --elf_file ~/zephyr/build/shell/zephyr/zephyr.elf --report-filename wifishell --gcc-tools-base ~/zephyr-sdk-1.0.1/gnu/riscv64-zephyr-elf/bin/riscv64-zephyr-elf- --report-max-static-stack-usage log_process_thread_func ~/zephyr/build/shell/zephyr/zephyr.elf

Activity

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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions