- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在出于自己的教育目的构建 Risk-V CPU 模拟器。我有小型 POC 工作,想要构建示例程序并在模拟器上测试它们。
我正在尝试用 Rust 构建示例程序,似乎取得了一些不错的进展,但是当我必须将编译后的程序加载到模拟器的内存中并将 CPU 执行转移到该程序时,我陷入了困境。
测试程序:
#![no_std]
#![no_main]
use core::panic::PanicInfo;
#[no_mangle]
pub extern "C" fn _start() -> ! {
loop {
for i in 0..1000 {
unsafe {
let r = i as *mut u32;
// This can panic because (500 - i) can be 0
*r = 20000 % (500 - i);
}
}
}
}
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
loop {}
}
构建:
$ cargo build --target riscv32i-unknown-none-elf --release
从 elf 目标生成二进制图像:
riscv32-unknown-linux-gnu-objcopy -g -O binary \
target/riscv32i-unknown-none-elf/release/sample1 \
target/riscv32i-unknown-none-elf/release/sample1.bin
到目前为止,这工作正常,并生成大小为 5156 字节的二进制文件。
我检查了 .bin 文件,它对我来说看起来是“合法的二进制文件”。我在文件的开头发现了一些可读的字符串(例如尝试计算除数为零的余数
) - 看起来它们与处理 panic 的代码有关,如果我这样做,可能会发生这种情况%0
。在文件末尾,我发现了一些看起来像riskv32i指令的东西(很容易注意到它们,因为最低有效位是11
)。文件的其余部分用零填充。
我陷入困境的地方是我无法弄清楚:
_start
)。如何找出哪个地址是入口点,以便在启动 CPU 周期之前将该地址放入 pc
寄存器中?它显然不在图像的开头(那里有人类可读的字符串)。当我使用objcopy
时,我可能走错了路。如果是这样,请告诉我将 ELF 文件加载到自制 CPU 模拟器中的正确方法是什么。
更新:链接器参数(由RUSTFLAGS =“-Z print-link-args”cargo build --target riscv32i-unknown-none-elf --release --verbose
提供):
rust-lld \
-flavor \
gnu \
-L \
/home/kris/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/riscv32i-unknown-none-elf/lib \
/mnt/c/src/ws/cpu/sample1/target/riscv32i-unknown-none-elf/release/deps/sample1-4813691a581d1819.sample1.251h7tq6-cgu.0.rcgu.o \
/mnt/c/src/ws/cpu/sample1/target/riscv32i-unknown-none-elf/release/deps/sample1-4813691a581d1819.sample1.251h7tq6-cgu.1.rcgu.o -o \
/mnt/c/src/ws/cpu/sample1/target/riscv32i-unknown-none-elf/release/deps/sample1-4813691a581d1819 \
--gc-sections \
-L \
/mnt/c/src/ws/cpu/sample1/target/riscv32i-unknown-none-elf/release/deps \
-L \
/mnt/c/src/ws/cpu/sample1/target/release/deps \
-L \
/home/kris/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/riscv32i-unknown-none-elf/lib \
-Bstatic \
/home/kris/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/riscv32i-unknown-none-elf/lib/librustc_std_workspace_core-6d1cf467df9db3bb.rlib \
/home/kris/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/riscv32i-unknown-none-elf/lib/libcore-a1a0b4993598bfe4.rlib \
/home/kris/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/riscv32i-unknown-none-elf/lib/libcompiler_builtins-a229bbbccd019775.rlib \
-Bdynamic
我知道程序中缺少一些重要的东西,例如初始化堆栈指针寄存器。我打算在弄清楚加载逻辑后处理这个问题
最佳答案
免责声明:我对 Rust 不熟悉,但你的问题更与 ELF 文件格式和可以理解它的工具有关 - 我的两分钱。
例如,这个documentation描述了一个文件 memory.x ,定义了链接器使用的内存映射:
MEMORY
{
RAM : ORIGIN = 0x80000000, LENGTH = 16K
FLASH : ORIGIN = 0x20000000, LENGTH = 16M
}
REGION_ALIAS("REGION_TEXT", FLASH);
REGION_ALIAS("REGION_RODATA", FLASH);
REGION_ALIAS("REGION_DATA", RAM);
REGION_ALIAS("REGION_BSS", RAM);
REGION_ALIAS("REGION_HEAP", RAM);
REGION_ALIAS("REGION_STACK", RAM);
在此示例中,生成的二进制文件可能应在偏移量 0x20000000
处加载。
应该有与您正在使用的工具链等效的工具。
_start
。例如,为 Aarch64 编译的一个可执行文件上的 aarch64-none-elf-nm
将显示:
aarch64-none-elf-nm h5-example.elf
0000000042000078 t $d
0000000042000000 t $x
0000000042000080 t $x
00000000420001dc t $x
00000000420001f4 t $x
0000000042000230 B __bss_end__
0000000042000230 B __bss_start__
0000000042000080 T c_entry
000000004200022c D __copy_table_end__
0000000042000220 D __copy_table_start__
0000000042000230 D __data_end__
0000000042000230 D __data_start__
0000000042000230 ? __end__
0000000042000230 B __etext
0000000042000218 T __exidx_end
0000000042000218 T __exidx_start
0000000042000230 d __fini_array_end
0000000042000230 d __fini_array_start
0000000046000230 ? __HeapLimit
0000000004000000 A __HEAP_SIZE
0000000042000230 d __init_array_end
0000000042000230 d __init_array_start
00000000420001f4 T main
0000000042000000 A __RAM_BASE
000000000e000000 A __RAM_SIZE
0000000042000000 T Reset_Handler
0000000000000000 A __ROM_BASE
0000000000000000 A __ROM_SIZE
000000004c000000 ? __StackLimit
0000000004000000 A __STACK_SIZE
0000000050000000 ? __StackTop
00000000420001dc t system_read_CurrentEL
0000000042000230 B __zero_table_end__
0000000042000230 B __zero_table_start__
就我而言,执行的第一条指令将位于Reset_Handler
。我可以使用以下命令检索引用它的行:
aarch64-none-elf-nm h5-example-02.elf | grep ' Reset_Handler$'
0000000042000000 T Reset_Handler
及其十六进制的确切地址,使用:
aarch64-none-elf-nm h5-example-02.elf | grep ' Reset_Handler$' | cut -d ' ' -f1
0000000042000000
RESET_HANDLER=$(aarch64-none-elf-nm h5-example-02.elf | grep ' Reset_Handler$' | cut -d ' ' -f1)
echo ${RESET_HANDLER}
当然会显示:
0000000042000000
现在起始地址已知,在您的 DIY 模拟器中使用它有多种选择。我想到的两个是:
a) 将地址作为参数传递给您的模拟器,即:
my-emulator 0000000042000000
或my-emulator -s 0000000042000000
b) 由于您掌握了模拟器将加载的图像的格式,因此您可以系统地将起始地址添加到 objcopy 生成的二进制文件中:这样,您将读取二进制文件的前 4 或 8 个字节首先文件,获取起始地址,然后读取剩余字节。
一个简单的方法是使用 xxd
和 cat
:
echo 0000000042000000 | xxd -r -p > final-image.bin
cat sample1.bin >> final-image.bin
使用包含“ABCD”的示例文件,我们将得到:
printf "ABCD" > sample1.bin
hexdump -C sample1.bin
00000000 41 42 43 44 |ABCD|
00000004
echo 0000000042000000 | xxd -r -p > final-image.bin
hexdump -C final-image.bin
00000000 00 00 00 00 42 00 00 00 |....B...|
00000008
cat sample1.bin >> final-image.bin
hexdump -C final-image.bin
00000000 00 00 00 00 42 00 00 00 41 42 43 44 |....B...ABCD|
0000000c
您当然可以定义一个更复杂的 header ,可能包含一些其他重要符号,或者向您的模拟器添加更多命令行选项 - 基本原理保持不变。
_start()
函数放入特定的链接器部分,如 here 中所述。 ,使用 link_section
指令/编译指示:程序:
#[no_mangle]
pub unsafe extern "C" fn Reset() -> ! {
let _x = 42;
// can't return so we go into an infinite loop here
loop {}
}
// The reset vector, a pointer into the reset handler
#[link_section = ".vector_table.reset_vector"]
#[no_mangle]
pub static RESET_VECTOR: unsafe extern "C" fn() -> ! = Reset;
链接脚本:
/* Memory layout of the LM3S6965 microcontroller */
/* 1K = 1 KiBi = 1024 bytes */
MEMORY
{
FLASH : ORIGIN = 0x00000000, LENGTH = 256K
RAM : ORIGIN = 0x20000000, LENGTH = 64K
}
/* The entry point is the reset handler */
ENTRY(Reset);
EXTERN(RESET_VECTOR);
SECTIONS
{
.vector_table ORIGIN(FLASH) :
{
/* First entry: initial Stack Pointer value */
LONG(ORIGIN(RAM) + LENGTH(RAM));
/* Second entry: reset vector */
KEEP(*(.vector_table.reset_vector));
} > FLASH
.text :
{
*(.text .text.*);
} > FLASH
/DISCARD/ :
{
*(.ARM.exidx .ARM.exidx.*);
}
}
这样,_start()
函数的代码将始终放在 .vector_table
部分的开头,该部分被定义为第一个FLASH区域。
因此,_start()
的地址始终为 0x00000000
,或者您决定重置地址位于 CPU 中的任何地址:您只需修改FLASH区域的起始地址。
该示例与 Arm Cortex-M MCU 相关,您可以将 .vector_table
部分替换为您自己的 .startup
部分。
我希望我没有偏离正轨......
关于rust - 如何获取 objcopy 生成的二进制镜像文件中的入口点地址?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63485595/
我正在尝试使用以下 keytool 命令为我的应用程序生成 keystore : keytool -genkey -alias tomcat -keystore tomcat.keystore -ke
编辑:在西里尔正确解决问题后,我注意到只需将生成轴的函数放在用于生成标签的函数下面就可以解决问题。 我几乎读完了 O'Reilly 书中关于 D3.js 的教程,并在倒数第二页上制作了散点图,但是当添
虽然使用 GraphiQL 效果很好,但我的老板要求我实现一个用户界面,用户可以在其中通过 UI 元素(例如复选框、映射关系)检查呈现给他们的元素并获取数据,这样做将为该人生成 graphql 输入,
我尝试在 Netbean 6.8 中使用 ws-import 生成 Java 类。我想重新生成 jax-ws,因为在 ebay.api.paypalapi 包中发现了一个错误(我认为该错误是由于 Pa
我有一个 perl 脚本,它获取系统日期并将该日期写入文件名。 系统日期被分配给 TRH1 变量,然后它被设置为一个文件名。 $TRH1 =`date + %Y%m%d%H%M`; print "TR
我是 Haskell 的新手,需要帮助。我正在尝试构建一种必须具有某种唯一性的新数据类型,因此我决定使用 UUID 作为唯一标识符: data MyType = MyType { uuid ::
我制作了一个脚本,它可以根据 Mysql 数据库中的一些表生成 XML。 该脚本在 PHP 中运行。 public function getRawMaterials($apiKey, $format
所以这是我的项目中的一个问题。 In this task, we will use OpenSSL to generate digital signatures. Please prepare a f
我在 SAS LIFEREG 中有一个加速故障时间模型,我想绘制它。因为 SAS 在绘图方面非常糟糕,我想实际重新生成 R 中曲线的数据并将它们绘制在那里。 SAS 提出了一个尺度(在指数分布固定为
我正在为 Django 后端制作一个样板,并且我需要能够使它到达下一个下载它的人显然无法访问我的 secret key 的地方,或者拥有不同的 key 。我一直在研究一些选项,并在这个过程中进行了实验
我正在创建一个生成采购订单的应用程序。我可以根据用户输入的详细信息创建文本文件。我想生成一个看起来比普通文本文件好得多的 Excel。有没有可以在我的应用程序中使用的开源库? 最佳答案 目前还没有任何
我正在尝试使用 ScalaCheck 为 BST 创建一个 Gen,但是当我调用 .sample 方法时,它给了我 java.lang.NullPointerException。我哪里错了? seal
已关闭。此问题需要 debugging details 。目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and the
我尝试编写一些代码,例如(在verilog中): parameter N = 128; if (encoder_in[0] == 1) begin 23 binary_out = 1;
我正忙于在 Grails 项目中进行从 MySQL 到 Postgres 的相当复杂的数据迁移。 我正在使用 GORM 在 PostGres 中生成模式,然后执行 MySQL -> mysqldump
如何使用纯 XSLT 生成 UUID?基本上是寻找一种使用 XSLT 创建独特序列的方法。该序列可以是任意长度。 我正在使用 XSLT 2.0。 最佳答案 这是一个good example 。基本上,
我尝试安装.app文件,但是当我安装并单击“同步”(在iTunes中)时,我开始在设备上开始安装,然后停止,这是一个问题,我不知道在哪里,但我看到了我无法解决的奇怪的事情: 最佳答案 似乎您没有在Xc
自从我生成 JavaDocs 以来已经有一段时间了,我确信这些选项在过去 10 年左右的时间里已经得到了改进。 我能否得到一些有关生成器的建议,该生成器将输出类似于 .Net 文档结构的 JavaDo
我想学习如何生成 PDF,我不想使用任何第三方工具,我想自己用代码创建它。到目前为止,我所看到的唯一示例是我通过在第 3 方 dll 上打开反射器查看的代码,以查看发生了什么。不幸的是,到目前为止我看
我正在从 Epplus 库生成 excel 条形图。 这是我成功生成的。 我的 table 是这样的 Mumbai Delhi Financial D
我是一名优秀的程序员,十分优秀!