How can I use GCC to compile a binary file which can be used for my FPGA,where I have used verilog to synthesis - compilation

First I synthesized a CPU that supports RISCV32IM using verilog, but I can't test if the CPU is working properly. I hope a compiler(such as GCC) can generate instructions to help me test, but normal compilers can only generate EXE files that require the operating system. Obviously, my FPGA can't do this.
I only need a series of RISCV32IM instructions that can run on FPGA and can implement the corresponding functions. If I can, I want his first instruction to be the program entry, which will save me energy.

Of course you can it is somewhat trivial, you did or someone selected baremetal tab for you, it is a baremetal program I assume you want to run.
so.s
lui x2,0x22222
lui x3,0x33333
lui x4,0x44444
lui x5,0x55555
lui x6,0x66666
j .
riscv32-none-elf-as so.s -o so.o
riscv32-none-elf-objdump -d -Mnumeric so.o
so.o: file format elf32-littleriscv
Disassembly of section .text:
00000000 <.text>:
0: 22222137 lui x2,0x22222
4: 333331b7 lui x3,0x33333
8: 44444237 lui x4,0x44444
c: 555552b7 lui x5,0x55555
10: 66666337 lui x6,0x66666
14: 0000006f j 14 <.text+0x14>
now you can just
riscv32-none-elf-ld -Ttext=0 so.o -o so.elf
riscv32-none-elf-ld: warning: cannot find entry symbol _start; defaulting to 0000000000000000
riscv32-none-elf-objdump -d -Mnumeric so.elf
so.elf: file format elf32-littleriscv
Disassembly of section .text:
00000000 <__BSS_END__-0x1018>:
0: 22222137 lui x2,0x22222
4: 333331b7 lui x3,0x33333
8: 44444237 lui x4,0x44444
c: 555552b7 lui x5,0x55555
10: 66666337 lui x6,0x66666
14: 0000006f j 14 <__BSS_END__-0x1004>
but at least with arm and not sure about other binutils targets there are very very old, longstanding bugs in the tools when used like that (get gaps in the binary, etc). So
memmap
MEMORY
{
hello : ORIGIN = 0x00000000, LENGTH = 0x3000
}
SECTIONS
{
.text : { *(.text*) } > hello
.rodata : { *(.rodata*) } > hello
.bss : { *(.bss*) } > hello
.data : { *(.data*) } > hello
}
and
riscv32-none-elf-ld -T memmap so.o -o so.elf
riscv32-none-elf-objdump -d -Mnumeric so.elf
so.elf: file format elf32-littleriscv
Disassembly of section .text:
00000000 <.text>:
0: 22222137 lui x2,0x22222
4: 333331b7 lui x3,0x33333
8: 44444237 lui x4,0x44444
c: 555552b7 lui x5,0x55555
10: 66666337 lui x6,0x66666
14: 0000006f j 14 <.text+0x14>
so now you have an elf (or exe or whatever) you can
riscv32-none-elf-objcopy so.elf -O binary so.bin
hexdump -C so.bin
00000000 37 21 22 22 b7 31 33 33 37 42 44 44 b7 52 55 55 |7!"".1337BDD.RUU|
00000010 37 63 66 66 6f 00 00 00 |7cffo...|
00000018
or
riscv32-none-elf-objcopy --srec-forceS3 so.elf -O srec so.srec
cat so.srec
S00A0000736F2E7372656338
S3150000000037212222B731333337424444B75255554C
S30D00000010376366666F0000000D
S70500000000FA
or
riscv32-none-elf-objcopy so.elf -O ihex so.ihex
cat so.ihex
:1000000037212222B731333337424444B752555552
:08001000376366666F00000013
and so on.
Then you can also...
so.s
lui x2,0x00002
jal notmain
j .
.globl hello
hello:
ret
notmain.c
void hello ( unsigned int );
void notmain ( void )
{
unsigned int r;
for (r=0;r<32;r++)
{
hello(r);
}
}
build with commands like these
riscv32-none-elf-as -march=rv32im so.s -o so.o
riscv32-none-elf-gcc -O2 -c -fomit-frame-pointer -march=rv32im -mabi=ilp32 notmain.c -o notmain.o
riscv32-none-elf-ld -T memmap so.o notmain.o -o so.elf
riscv32-none-elf-objdump -D -Mnumeric so.elf
riscv32-none-elf-objcopy -O binary so.elf so.bin
giving
Disassembly of section .text:
00000000 <hello-0xc>:
0: 00002137 lui x2,0x2
4: 00c000ef jal x1,10 <notmain>
8: 0000006f j 8 <hello-0x4>
0000000c <hello>:
c: 00008067 ret
00000010 <notmain>:
10: ff010113 addi x2,x2,-16 # 1ff0 <notmain+0x1fe0>
14: 00812423 sw x8,8(x2)
18: 00912223 sw x9,4(x2)
1c: 00112623 sw x1,12(x2)
20: 00000413 li x8,0
24: 02000493 li x9,32
28: 00040513 mv x10,x8
2c: 00140413 addi x8,x8,1
30: fddff0ef jal x1,c <hello>
34: fe941ae3 bne x8,x9,28 <notmain+0x18>
38: 00c12083 lw x1,12(x2)
3c: 00812403 lw x8,8(x2)
40: 00412483 lw x9,4(x2)
44: 01010113 addi x2,x2,16
48: 00008067 ret
and you can use the .bin file or .srec or whatever you prefer.
basic bare metal stuff...gnu works great for this, very easy to use. llvm/clang is more complicated to figure out but technically will work as well.
I changed the line to
for (r=0;r<3200;r++)
because it was unrolling the loop. I gave up trying to keep track of the ever changing generic llvm tool command line options, so now I build specific for riscv32 and can then use the generic program names as cross tools...
clang -c -march=rv32im so.s -o so.o
clang -c -O2 -march=rv32im notmain.c -o notmain.o
ld.lld -T memmap so.o notmain.o -o so.elf
llvm-objcopy -O binary so.elf so.bin
llvm-objdump -D -Mnumeric so.elf
so.elf: file format elf32-littleriscv
Disassembly of section .text:
00000000 <.text>:
0: 37 21 00 00 lui x2, 2
4: ef 00 c0 00 jal 0x10 <notmain>
8: 6f 00 00 00 j 0x8 <.text+0x8>
0000000c <hello>:
c: 67 80 00 00 ret
00000010 <notmain>:
10: 13 01 01 ff addi x2, x2, -16
14: 23 26 11 00 sw x1, 12(x2)
18: 23 24 81 00 sw x8, 8(x2)
1c: 23 22 91 00 sw x9, 4(x2)
20: 13 04 00 00 li x8, 0
24: 37 15 00 00 lui x10, 1
28: 93 04 05 c8 addi x9, x10, -896
0000002c <.LBB0_1>:
2c: 13 05 04 00 mv x10, x8
30: ef f0 df fd jal 0xc <hello>
34: 13 04 14 00 addi x8, x8, 1
38: e3 1a 94 fe bne x8, x9, 0x2c <.LBB0_1>
3c: 83 20 c1 00 lw x1, 12(x2)
40: 03 24 81 00 lw x8, 8(x2)
44: 83 24 41 00 lw x9, 4(x2)
48: 13 01 01 01 addi x2, x2, 16
4c: 67 80 00 00 ret

Related

I believe GCC is producing incorrect machine code

I am trying to compile this dead simple program:
int print(int x, int y)
{
return x * y;
}
int main()
{
return print(8, 7);
}
with this command: gcc -c -nostdinc -m32 -masm=intel main.c -O0
The file produced (main.o) has the following object dump:
$ objdump -d main.o
main.o: file format elf32-i386
Disassembly of section .text:
00000000 <print>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: e8 fc ff ff ff call 4 <print+0x4>
8: 05 01 00 00 00 add $0x1,%eax
d: 8b 45 08 mov 0x8(%ebp),%eax
10: 0f af 45 0c imul 0xc(%ebp),%eax
14: 5d pop %ebp
15: c3 ret
00000016 <main>:
16: 55 push %ebp
17: 89 e5 mov %esp,%ebp
19: e8 fc ff ff ff call 1a <main+0x4>
1e: 05 01 00 00 00 add $0x1,%eax
23: 6a 07 push $0x7
25: 6a 08 push $0x8
27: e8 fc ff ff ff call 28 <main+0x12>
2c: 83 c4 08 add $0x8,%esp
2f: c9 leave
30: c3 ret
Disassembly of section .text.__x86.get_pc_thunk.ax:
00000000 <__x86.get_pc_thunk.ax>:
0: 8b 04 24 mov (%esp),%eax
3: c3 ret
If I understand correctly, this line
27: e8 fc ff ff ff call 28 <main+0x12> represents the call to print. However, the offset given is -4, which results in jumping to address 28. But there isn't even an instruction at that offset. The code does run however. But I have the feeling this machine code isn't quite right. (Also, why is there a call instruction in the print function, if the print function doesn't even call anything?)
You compiled with -c, thus the output is an object file. It still contains placeholders for symbols and such that will be resolved / patched by the linker. As mentioned, use objdump with flag -r added which will show symbol name for the reloc(s). Before linking, the bits in the opcode are 0, thus the call target points to the address as shown by objdump.

Why does gcc generates strange code without flag -fno-pie?

I am trying to compile dummy function in gcc with flag -fno-pie and without.
void dummy_test_entrypoint() { }
When i compile without the flag.
gcc -m32 -ffreestanding -c test.c -o test.o
I get the following disassembled code.
00000000 <dummy_test_entrypoint>:
0: 55 push ebp
1: 89 e5 mov ebp,esp
3: e8 fc ff ff ff call 4 <dummy_test_entrypoint+0x4>
8: 05 01 00 00 00 add eax,0x1
d: 90 nop
e: 5d pop ebp
f: c3 ret
When i compile with the flag.
00000000 <dummy_test_entrypoint>:
0: 55 push ebp
1: 89 e5 mov ebp,esp
3: 90 nop
4: 5d pop ebp
5: c3 ret
My question.
What is it???
3: e8 fc ff ff ff call 4 <dummy_test_entrypoint+0x4>
8: 05 01 00 00 00 add eax,0x1
You disassembled the object file without the --reloc flag, so the output is misleading. With the --reloc flag, you'll see this:
3: e8 fc ff ff ff call 4 <dummy_test_entrypoint+0x4>
4: R_386_PC32 __x86.get_pc_thunk.ax
8: 05 01 00 00 00 add $0x1,%eax
9: R_386_GOTPC _GLOBAL_OFFSET_TABLE_
And the subroutine looks like this:
00000000 <__x86.get_pc_thunk.ax>:
0: 8b 04 24 mov (%esp),%eax
3: c3 ret
This construct loads the GOT pointer into %eax, in case the function needs to reference global data. The function does not contain such a reference, but because you compiled the code without optimization, GCC did not remove the dead code.

Why do ELF object files contain dummy addresses for string literals and stdlib functions?

I wrote this Hello World in C :
#include<stdio.h>
int main() {
printf("Hello world !\n");
return 0;
}
Compiling with gcc to assembly code
I get this :
.file "file.c"
.section .rodata.str1.1,"aMS",#progbits,1
.LC0:
.string "Hello world !"
.section .text.unlikely,"ax",#progbits
.LCOLDB1:
.section .text.startup,"ax",#progbits
.LHOTB1:
.p2align 4,,15
.globl main
.type main, #function
main:
.LFB11:
.cfi_startproc
subq $8, %rsp
.cfi_def_cfa_offset 16
movl $.LC0, %edi
call puts
xorl %eax, %eax
addq $8, %rsp
.cfi_def_cfa_offset 8
ret
.cfi_endproc
.LFE11:
.size main, .-main
.section .text.unlikely
.LCOLDE1:
.section .text.startup
.LHOTE1:
.ident "GCC: (GNU) 4.9.2 20150304 (prerelease)"
.section .note.GNU-stack,"",#progbits
No problem here. But now, I want to compare the assembly code with a code disassembled by objdump :
For the main function I get this :
0000000000000000 <main>:
0: 48 83 ec 08 sub $0x8,%rsp
4: bf 00 00 00 00 mov $0x0,%edi
5: R_X86_64_32 .rodata.str1.1
9: e8 00 00 00 00 callq e <main+0xe>
a: R_X86_64_PC32 puts-0x4
e: 31 c0 xor %eax,%eax
10: 48 83 c4 08 add $0x8,%rsp
14: c3 retq
I don't understand two things :
Why move the number 0 on edi means to load the string "Hello world" ?
Moreover, the instruction callq call the address e. But the instruction at the addresse e is not the function puts but a xor. So what is the real address ?
The answer is that there are various fixups applied by the linker. When I do an objdump -d hello.o I get this:
Disassembly of section .text:
0000000000000000 <main>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: bf 00 00 00 00 mov $0x0,%edi
9: e8 00 00 00 00 callq e <main+0xe>
e: b8 00 00 00 00 mov $0x0,%eax
13: 5d pop %rbp
14: c3 retq
However, an extract from objdump -d hello yields this:
400536: 55 push %rbp
400537: 48 89 e5 mov %rsp,%rbp
40053a: bf e0 05 40 00 mov $0x4005e0,%edi
40053f: e8 cc fe ff ff callq 400410 <puts#plt>
400544: b8 00 00 00 00 mov $0x0,%eax
400549: 5d pop %rbp
40054a: c3 retq
The difference is that the zeroes for the string offset and the address of puts are now actually filled in by the linker. You can find those relocation entries with objdump -r hello.o
hello.o: file format elf64-x86-64
RELOCATION RECORDS FOR [.text]:
OFFSET TYPE VALUE
0000000000000005 R_X86_64_32 .rodata
000000000000000a R_X86_64_PC32 puts-0x0000000000000004
What that says is that the linker finds the actual address of .rodata (which is the address of the string) and puts it at offset 0x5 and the address of the library puts code and places it at offset 0xa.
This article on relocation describes the process in more detail and correctly points out that while some relocation happens at link-time, the loader can also supply relocation data.

Is there a way to output the assembly of a single function in isolation?

I am learning how a C file is compiled to machine code. I know I can generate assembly from gcc with the -S flag, however it also produces a lot of code to do with main() and printf() that I am not interested in at the moment.
Is there a way to get gcc or clang to "compile" a function in isolation and output the assembly?
I.e. get the assembly for the following c in isolation:
int add( int a, int b ) {
return a + b;
}
There are two ways to do this for a specific object file:
The -ffunction-sections option to gcc instructs it to create a separate ELF section for each function in the sourcefile being compiled.
The symbol table contains section name, start address and size of a given function; that can be fed into objdump via the --start-address/--stop-address arguments.
The first example:
$ readelf -S t.o | grep ' .text.'
[ 1] .text PROGBITS 0000000000000000 00000040
[ 4] .text.foo PROGBITS 0000000000000000 00000040
[ 6] .text.bar PROGBITS 0000000000000000 00000060
[ 9] .text.foo2 PROGBITS 0000000000000000 000000c0
[11] .text.munch PROGBITS 0000000000000000 00000110
[14] .text.startup.mai PROGBITS 0000000000000000 00000180
This has been compiled with -ffunction-sections and there are four functions, foo(), bar(), foo2() and munch() in my object file. I can disassemble them separately like so:
$ objdump -w -d --section=.text.foo t.o
t.o: file format elf64-x86-64
Disassembly of section .text.foo:
0000000000000000 <foo>:
0: 48 83 ec 08 sub $0x8,%rsp
4: 8b 3d 00 00 00 00 mov 0(%rip),%edi # a <foo+0xa>
a: 31 f6 xor %esi,%esi
c: 31 c0 xor %eax,%eax
e: e8 00 00 00 00 callq 13 <foo+0x13>
13: 85 c0 test %eax,%eax
15: 75 01 jne 18 <foo+0x18>
17: 90 nop
18: 48 83 c4 08 add $0x8,%rsp
1c: c3 retq
The other option can be used like this (nm dumps symbol table entries):
$ nm -f sysv t.o | grep bar
bar |0000000000000020| T | FUNC|0000000000000026| |.text
$ objdump -w -d --start-address=0x20 --stop-address=0x46 t.o --section=.text
t.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000020 <bar>:
20: 48 83 ec 08 sub $0x8,%rsp
24: 8b 3d 00 00 00 00 mov 0(%rip),%edi # 2a <bar+0xa>
2a: 31 f6 xor %esi,%esi
2c: 31 c0 xor %eax,%eax
2e: e8 00 00 00 00 callq 33 <bar+0x13>
33: 85 c0 test %eax,%eax
35: 75 01 jne 38 <bar+0x18>
37: 90 nop
38: bf 3f 00 00 00 mov $0x3f,%edi
3d: 48 83 c4 08 add $0x8,%rsp
41: e9 00 00 00 00 jmpq 46 <bar+0x26>
In this case, the -ffunction-sections option hasn't been used, hence the start offset of the function isn't zero and it's not in its separate section (but in .text).
Beware though when disassembling object files ...
This isn't exactly what you want, because, for object files, the call targets (as well as addresses of global variables) aren't resolved - you can't see here that foo calls printf, because the resolution of that on binary level happens only at link time. The assembly source would have the call printf in there though. The information that this callq is actually to printf is in the object file, but separate from the code (it's in the so-called relocation section that lists locations in the object file to be 'patched' by the linker); the disassembler can't resolve this.
The best way to go would be to copy your function in a single temp.c C file and to compile it with the -c flag like this: gcc -c -S temp.c -o temp.s
It should produce a more tighten assembly code with no other distraction (except for the header and footer).

ARM objcopy results in empty binary file

How can I get arm-none-eabi-objcopy to copy/translate my .axf file into a .bin suitable for flashing to the device with lm4tools?
I have a ~20KB .axf file compiled and linked with arm-none-eabi-*. For anyone interested, this is with the Stellaris Launchpad.
I'm trying to modify the example provided with the stellaris-launchpad-template-gcc project to compile with C++ code. I've managed to get it to produce a .axf file in elf32-littlearm format (according to the .lst file), however when I try to do
arm-none-eabi-objcopy -v -O binary main.axf foo.bin
to translate it into a programmable file, the .bin file output has a size of 0 bytes. This question describes a similar problem. I'm confident the .axf file is complete, so why isn't my .bin file being populated with anything? If I remove -O binary, the file is copied fine. The directory is writeable and all permissions are fine. I've tried searching both on SO and the rest of the internet with various terms, all of which turned up nothing of use. It seems nobody's had this problem before.
Running arm-none-eabi-objdump -D main.axf yields a dump of the file in what appears to be assembler:
main.axf: file format elf32-littlearm
Disassembly of section .debug_info:
00000000 <_end_text>:
0: 00000082 andeq r0, r0, r2, lsl #1
4: 00000002 andeq r0, r0, r2
8: 01040000 mrseq r0, (UNDEF: 4)
c: 00000057 andeq r0, r0, r7, asr r0
10: 00000c04 andeq r0, r0, r4, lsl #24
14: 00002300 andeq r2, r0, r0, lsl #6
...
28: 08010200 stmdaeq r1, {r9}
2c: 00000015 andeq r0, r0, r5, lsl r0
30: 00410103 subeq r0, r1, r3, lsl #2
34: 32010000 andcc r0, r1, #0
38: 00000048 andeq r0, r0, r8, asr #32
...
48: 69050404 stmdbvs r5, {r2, sl}
4c: 0500746e streq r7, [r0, #-1134] ; 0x46e
50: 00000001 andeq r0, r0, r1
54: 46430100 strbmi r0, [r3], -r0, lsl #2
...
Is this correct, or am I not even compiling properly, seeing as this appears to be some kind of assembler?
Some info about the .axf file:
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: ARM
Version: 0x1
Entry point address: 0x0
Start of program headers: 52 (bytes into file)
Start of section headers: 20372 (bytes into file)
Flags: 0x5000000, Version5 EABI
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 0
Size of section headers: 40 (bytes)
Number of section headers: 14
Section header string table index: 11
After running arm-none-eabi-readelf -lS main.axf, no program headers are returned:
There are 14 section headers, starting at offset 0x4f94:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .debug_info PROGBITS 00000000 000034 0019a6 00 0 0 1
[ 2] .debug_abbrev PROGBITS 00000000 0019da 0005ad 00 0 0 1
[ 3] .debug_loc PROGBITS 00000000 001f87 001796 00 0 0 1
[ 4] .debug_aranges PROGBITS 00000000 003720 000088 00 0 0 8
[ 5] .debug_ranges PROGBITS 00000000 0037a8 000130 00 0 0 1
[ 6] .debug_line PROGBITS 00000000 0038d8 00077d 00 0 0 1
[ 7] .debug_str PROGBITS 00000000 004055 000aa8 01 MS 0 0 1
[ 8] .comment PROGBITS 00000000 004afd 00003a 01 MS 0 0 1
[ 9] .ARM.attributes ARM_ATTRIBUTES 00000000 004b37 000039 00 0 0 1
[10] .debug_frame PROGBITS 00000000 004b70 000388 00 0 0 4
[11] .shstrtab STRTAB 00000000 004ef8 00009a 00 0 0 1
[12] .symtab SYMTAB 00000000 0051c4 000200 10 13 18 4
[13] .strtab STRTAB 00000000 0053c4 0000e0 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
There are no program headers in this file.

Resources