0

Quoting the Solana documentation [1];

The virtual address memory map used by Solana BPF programs is fixed and laid out as follows

  • Program code starts at 0x100000000
  • Stack data starts at 0x200000000
  • Heap data starts at 0x300000000
  • Program input parameters start at 0x400000000

Using a modified version of the Solana helloworld example [2], our custom log function displays the address of the string before calling the original sol_log macro. In the program helloworld.so, the initial static string addresses stored in the .rodata section are as follow:

llvm-objdump -s -j .rodata dist/program/helloworld.so

Contents of section .rodata:
 ...
 0820 6d206964 00486172 64636f64 65645265  m id.HardcodedRe
                                                ^ (0x0820+0x5)
 0830 61644f6e 6c794461 74610048 656c6c6f  adOnlyData.Hello
                                                      ^ (0x0830+0xb)
 0840 21004865 6c6c6f77 6f726c64 20432070  !.Helloworld C p
                                             ^ (0x0840+0x2)
 0850 726f6772 616d2065 6e747279 706f696e  rogram entrypoin
 0860 74004772 65657465 64206163 636f756e  t.Greeted accoun
 ...

From the llvm-objdump command above;

  • "HardcodedReadOnlyData" static string address is 0x0825
  • "Hello!" static string address is 0x0842
  • "Helloworld C program entrypoint" static string address is 0x0842

However, when the program is ran, the corresponding static data addresses are different;

  • "HardcodedReadOnlyData" static string address is 0x100000825
  • "Hello!" static string address is 0x100000842
  • "Helloworld C program entrypoint" static string is 0x100000842

We can see that each static data have been relocated to another address, with an offset of 0x100_000_000 added to each static data.

Our goal is to

  • Identify and understand the mechanism responsible of the relocation of the static data of the .rodata section, because we have another program where this relocation does not occur, leading to the static data keeping their original address at run time (i.e "Hello!" address is 0x0842 instead of 0x100000842 during the execution). That issue leads to Access violation when manipulating the static string during program execution.
  • Make sure that this mechanism is activated when executing the erroneous program Thanks

[1]

https://docs.solana.com/developing/on-chain-programs/overview

[2]

  void custom_log(const char * arg1) {
    sol_log_64(42, 42, 42, 42, (uint64_t)arg1);  
    sol_log(arg1);
  }

1 Answer 1

0

The above relocation process is performed by the solana rbpf [1] component in src/elf.rs line 893 loop.

// non relevant parts of the code have been skipped
for relocation in elf.dynamic_relocations() {
    match BpfRelocationType::from_x86_relocation_type(relocation.r_type()) {
        Some(BpfRelocationType::R_Bpf_64_Relative) => {
            if refd_addr < ebpf::MM_PROGRAM_START {
                // The linker hasn't already placed rodata within
                // MM_PROGRAM_START, so we do so now
                refd_addr = ebpf::MM_PROGRAM_START.saturating_add(refd_addr);
            }
        }
    }
}

The purpose of this code is to iterate through the relocations present in the program .rel.dyn section, and add ebpf::MM_PROGRAM_START (0x100000000) to the corresponding address (crafted from the offset)

$ llvm-readelf --all dist/program/helloworld.so
    Relocation section '.rel.dyn' at offset 0x26a0 contains 46 entries:
        Offset             Info             Type               Symbol's Value  Symbol's Name
    0000000000000308  0000000000000008 R_SBF_64_RELATIVE                 
    0000000000000320  0000000000000008 R_SBF_64_RELATIVE

As showed in the Info column above, they are related to the .symtab section, which in fine refers to the static strings contained in the .rodata section (snippet of .rodata available in the post above).

Section Headers:
  [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
  [ 8] .symtab           SYMTAB          0000000000000000 000968 000270 18     10  24  8

The issue with the erroneous program is that the linker --pack-dyn-relocs=relr option removes the R_SBF_64_RELATIVE data from the .rel.dyn section, and add replace them by some R_SBF_NONE data in the .relr.dyn section. Thus, the addresses of the static strings present in the program are not relocated in the 0x100000000 address space.

As a work-around, removing the linker --pack-dyn-relocs=relr option fixed the issue for that program.

[1]

https://github.com/solana-labs/rbpf

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.