指定内存地址,其中C中的单个指令将被汇编。

huangapple go评论64阅读模式
英文:

Specify the memory address where a single instruction in c will be assembled

问题

我用Verilog编写了一个SoC,并将C代码编译成了一个二进制文件,然后用它初始化了SoC的ROM。为了设计一个错误注入,我需要能够在汇编指令(例如printf("123"))组装后人为地指定ROM地址。是否有一种方法可以做到这一点,比如使用内联汇编?

英文:

I built a SoC written in Verilog, compiled the c code into a binary file and initialized the SoC ROM with it. In order to design an error injection, I needed to be able to artificially specify the ROM address after the assembly of an instruction such as printf ("123"). Is there a way to do this, for example, using inline assembly?

答案1

得分: 0

以下是翻译好的内容:

  1. 可能有一种非常笨拙且不可靠的方式,偶然在调试构建中起作用,依赖于关于编译器工作方式的假设。我不知道为什么你要这样做;你不能从函数外部跳转到那里。如果你只想设置断点,通常可以使用调试信息按行号来实现。

  2. 创建一个汇编标签/符号表条目
    printf("123") 不能编译为单个指令。会有一些设置指针参数的指令,以及一个或多个实际执行 call printf 或等效操作的指令。在调试构建中,它们将是连续的块,否则可能不是。

    在调试构建(禁用优化)中,如果你使用内联汇编在 C 函数中间发出一个标签,如 asm(".globl foo; foo:"),它可能会出现在下一个 C 语句对应的指令块之前。在优化构建中,一个 C 语句对应的指令不会在连续的块中,除非使用 C goto 标签和使用 GNU C 标签作为值来获取其地址。但我认为你无法通过链接器来控制它们的地址,因为你不会知道一个汇编符号的名称。

  3. 使用链接器脚本来移动段的起始位置,使你的符号位于所需的地址
    你可以使用链接器脚本将 .text 段的起始位置放置在某个地址上,类似于在发出映射你想要的段之前使用 . = 0x401000 这样的方式。

    如果你计算该地址,例如 . = 0x401000 - (symbol - start_of_text),使用符号与段起始位置的距离,那么符号应该最终位于你想要的地址上。

    你可以将单独的函数放入它们自己的段中,以便在链接器中进行布局调整(使用 gcc -ffunction-sections),以便可以按函数来执行这个操作。

  4. 我不建议这样做。如果你设计的东西依赖于这种方式来正常工作,请考虑不同的设计。这太糟糕了。

英文:

There might be a very hacky and unreliable way that happens to work in a debug build, relying on assumptions about how compilers work. IDK why you'd want to do it; you can't jump there from outside the function. If you just want to be able to set a breakpoint, normally you can do that by line number with debug info.


Creating an asm label / symbol-table entry

printf("123") can't compile to a single instruction. There will be some that set up a pointer arg, and one or more that actually do a call printf or equivalent. In a debug build those will be contiguous block, otherwise they might not be.

In a debug build (optimization disabled), if you use inline asm to emit a label in the middle of your C function, like asm(".globl foo; foo:" ::: "memory"), it will probably be right before the block of instructions corresponding to the next C statement. (In an optimized build, the instructions corresponding to one C statement won't be in a contiguous block, and there'd be no way to do anything like what you're asking, except maybe with C goto labels like foo: and using GNU C labels-as-values to take their address. But I don't think you could control their address with the linker since you wouldn't know an asm symbol name.)


Using a linker script to move the start of a section so your symbol lands at the desired address

You can use a linker script to place the start of the .text section at a certain address. Something like . = 0x401000 before emitting the segment that maps the sections you want.

If you compute that address like . = 0x401000 - (symbol - start_of_text), using the distance of the symbol from the start of the section, then the symbol should end up at the address you want.

You can put individual functions in their own section so you can play with layout in the linker (gcc -ffunction-sections) so you could do that on a per-function basis.


I wouldn't recommend doing this. If something you're designing relies on this to work correctly, design it differently. This is horrible.

huangapple
  • 本文由 发表于 2023年6月8日 01:19:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/76425693.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定