【发布时间】:2018-09-23 21:07:28
【问题描述】:
我正在用 Rust 为 Raspberry Pi 3 编写裸机代码,但是,我对放置在 @0x80000 的代码有疑问,因为它不是 _start 函数。
编译器设置为 AArch64 架构,我使用 LLD 作为链接器。
# .cargo/config
[build]
target = "aarch64-unknown-none"
[target.aarch64-unknown-none]
rustflags = [
# uncomment to use rustc LLD linker
"-C", "link-arg=-Tlayout.ld",
"-C", "linker=lld-link",
"-Z", "linker-flavor=ld.lld",
]
启动后要调用的第一个函数:(获取核心ID,只让primary继续,其他停止;为primary和init内存设置堆栈)
#[link_section = ".reset_vector"]
#[no_mangle]
pub extern "C" fn _start() -> !{
unsafe {
// Halt all cores but the primary
asm!(" mrs x1, mpidr_el1
and x1, x1, #3
cmp x1, #0
bne halt"::::"volatile");
// Setup stack pointer
asm!(" mov sp, #0x80000"::::"volatile");
}
init_runtime();
main();
loop{}
}
fn init_runtime() {
extern "C" {
static mut _sbss: u64;
static mut _ebss: u64;
static mut _sdata: u64;
static mut _edata: u64;
static _sidata: u64;
}
unsafe{
// Zero the BSS section in RAM
r0::zero_bss(&mut _sbss, &mut _ebss);
// Copy variables in DATA section in FLASH to RAM
r0::init_data(&mut _sdata, &mut _edata, &_sidata);
}
}
停止除主核心以外的核心的功能:
#[no_mangle]
pub fn halt() {
unsafe {asm!("wfe"::::"volatile");}
}
我正在使用r0 crate 来初始化内存:
fn init_runtime() {
extern "C" {
static mut _sbss: u64;
static mut _ebss: u64;
static mut _sdata: u64;
static mut _edata: u64;
static _sidata: u64;
}
unsafe{
// Zero the BSS section in RAM
r0::zero_bss(&mut _sbss, &mut _ebss);
// Copy variables in DATA section in FLASH to RAM
r0::init_data(&mut _sdata, &mut _edata, &_sidata);
}
}
最后是链接器脚本:
ENTRY(_start)
SECTIONS {
. = 0x80000;
.text : {
KEEP(*(.reset_vector));
__reset_vector = ABSOLUTE(.);
*(.text .text.* .gnu.linkonce.t*)
}
.rodata : {
*(.rodata .rodata.* .gnu.linkonce.r*)
}
.data : {
_sdata = .;
*(.data .data.* .gnu.linkonce.d*)
_edata = ALIGN(8);
}
.bss (NOLOAD) : {
. = ALIGN(32);
_bss = .;
*(.bss .bss.*)
*(COMMON)
_ebss = ALIGN(8);
}
__bss_length = (__bss_end - __bss_start);
/DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) }
}
这是反汇编:
(gdb) disassemble 0x0000000000080000, 0x000000000008035c
Dump of assembler code from 0x80000 to 0x8035c:
=> 0x0000000000080000 <core::mem::uninitialized+0>: sub sp, sp, #0x10
0x0000000000080004 <core::mem::uninitialized+4>: ldr x0, [sp, #8]
0x0000000000080008 <core::mem::uninitialized+8>: str x0, [sp]
0x000000000008000c <core::mem::uninitialized+12>: ldr x0, [sp]
0x0000000000080010 <core::mem::uninitialized+16>: add sp, sp, #0x10
0x0000000000080014 <core::mem::uninitialized+20>: ret
函数_start的指令需要放在@0x80000,但不是这样,因为有core::mem::uninitialized的指令。
如何修改链接描述文件,使mrs x1, mpidr_el1成为第一个被执行的指令?
【问题讨论】:
-
感谢您的指导,它帮助我完成了链接器脚本中的部分,因为问题部分存在于 Rust 代码中,因此该线程的标题有点误导。
标签: linker raspberry-pi rust