How to disassemble .elf file to .asm file in riscv - c

I have generated a .elf file by using
riscv64-unknown-elf-gcc -march=rv64imac -mabi=lp64 -Tlinker.ld *.o add.o -o add.elf -static -nostartfiles -lm -lgcc
And now I want to see the stack to check the values assigned to variables used in my add.c. I believe the same can be obtained from a .dasm/.asm file. How can I generate a .asm/.dasm file from an .elf file?

Just as an extension to dratenik's answer.
I am using riscv32-unknown-elf-objdump --disassemble-all NAME.elf > NAME.disasm
This way you don't even have to go over the -S option. And can just disassemble your .elf file.
Again as dratenik noted you need to adjust the prefix of objdump to you toolchain aka. your compiler prefix

You can stop gcc at the assembly stage by adding the -S switch, the file output by -o will then be an asm source file. Or you can let gcc finish and then take the resulting binary apart with objdump -d. Of course you need to run the objdump binary from the same toolchain, not your system one.

Related

CMake compile NASM and C and link everything together

I'm trying to compile assembly files with NASM and C files with GCC and link all object files together. Moreover, I'd like the C preprocessor to process the assembly files as well. This is normally no problem from the command line or a simple makefile, but I've had some trouble in replicating this functionality in CMake.
The exact process, assuming three files (boot.S, kernel.c, link.ld) would look something like this:
gcc -E -P boot.S -D <...> -o boot.s
nasm -f elf32 boot.s -o boot.o
gcc -c kernel.c -o kernel.o -ffreestanding -O2 -Wall -Wextra
Now its time to link. I want to do this like this (maybe with a few extra flags):
gcc -T link.ld -o out.bin -ffreestanding -O2 -nostdlib boot.o kernel.o -lgcc
The problems with CMake are the following:
Cmake support for NASM is weird at best. When adding .S files as sources to targets they don't get recognized as assembly files and I get hit with 'cannot determine linker language for target'. I have tried adding 's S' to CMAKE_ASM_NASM_SOURCE_FILE_EXTENSIONS but it still doesn't work unless I manually set the languages with set_source_files_properties(). Moreover, as is pointed out here, CMAKE_ASM_NASM_LINK_EXECUTABLE is broken.
As far as I understand, after compiling source files to objects, CMake attempts to link them automatically. Which linker will it use to link all .o files? Will it use the linker for C? Will it use the linker for NASM? The answer is relevant, because I need to configure it with the flags I mentioned above.
What would an example CMakeLists.txt would look like that replicates the previously mentioned process? Also do I need a create_custom_command() in order to invoke just the preprocessor? Thank you.

How do I produce plain binary from object files?

How should I produce raw binary file from two object (.o) files?
I want the plain binary format produced by nasm -f bin when compiling a .asm file, but for .o files.
By a plain binary, I mean a file which contains only the instructions, not some extra information, as many executable files contain a lot of extra helpful information.
See http://www.nasm.us/doc/nasmdoc7.html for information on that.
PS: I want to make a "plain binary" to start in QEMU.
This brings back memories. I'm sure there is a better way to do this with linker scripts, but this is how I did it when I was young and stupid:
# compile some files
gcc -c -nostdlib -nostartfiles -nodefaultlibs -fno-builtin kernel.c -o kernel.o
gcc -c -nostdlib -nostartfiles -nodefaultlibs -fno-builtin io.c -o io.o
# link files and place code at known address so we can jump there from asm
ld -Ttext 0x100000 kernel.o io.o -o kernel.out
# get a flat binary
objcopy -S -O binary kernel.out kernel.bin
The file kernel.c started with
__asm__("call _kmain");
__asm__("ret");
void kmain(void) { ... }
The fun part is writing the loader in assembler.
ld --oformat binary is a more direct option:
ld --oformat binary -o main.img -Ttext 0x7C00 main.o
The downside of this method is that I don't think it is possible to reuse the symbols to debug, as we'd want something like:
qemu-system-i386 -hda main.img -S -s &
gdb main.elf -ex 'target remote localhost:1234'
So in that case you should stick to objcopy. See also: https://stackoverflow.com/a/32960272/895245
Also make sure that you use your own clean linker script: https://stackoverflow.com/a/32594933/895245
Repository with working examples for some common cases:
boot sectors
multiboot interfacing with C
Similar question: How to generate plain binaries like nasm -f bin with the GNU GAS assembler?

How to generate an c function directly to excutable machine code?

My file is bootpack.c and it has a function void f() { while(1); } in it.
I want to generate it directly to excutable machine code. So I compile it like this:
gcc -c -nostdinc -fno-builtin bootpack.c
ld -nostdlib file.o -o bootpack.bin
But I find that bootpack.bin is 3.84KB. It is should only be a few bytes, I thought, because it is just a loop. What is wrong? And how to generate this file correctly?
You can use binary as output format for the GNU (BFD-based) linker:
ld -nostdlib file.o --oformat=binary -o bootpack.bin
You can then disassemble that with:
objdump -b binary -m i386 -D bootpack.bin
(substitute your target architecture in place of i386).
Because it contain symbol table information ,to reduce the size of executable you can use strip command .
Use it as "strip --strip-all executable-file-name" so it will remove extra information such as symbol table etc. Even in gcc option -s can be used , there are more option in gcc which can be used .

Generating a.out file format with GCC

How do I generate the a.out file format with GCC on x86 architectures?
With NASM I can do this easily with the -f flag, for example:
nasm -f aout start.asm
objdump -a start.o
start.o: file format a.out-i386-linux
start.o
On Linux, compiling .c files produces an ELF object file. How can I produce a.out files with GCC?
To generate the a.out format with gcc, your linker needs to be told to do so. You can do it by passing it flags from gcc thanks to the -Wl flag.
Here is what you would do for the a.out format:
gcc -Wl,--oformat=a.out-i386-linux file.c -o file.out
You can also display all formats supported by typing:
objdump -i
According to the post Re: How can I control the gcc's output format?, you need to build gcc for a different target (i386-aout).
It sounds plausible as a.out has been deprecated for years (10+).
There are two answers to this question. One is that you'll need to compile a fresh GCC with aout as its target; it's not as simple as flipping a command-line switch. The other answer is a question: why do you actually need this? I can't immediately think of a valid reason.

Linux Novice Question: GCC Compiler output

I am a complete novice with Linux. I have Mint on a laptop and have recently been playing around with it.
I wrote a simple C program and saved the file.
Then in the command line I typed
gcc -c myfile
and out popped a file called a.out. I naively (after years of Windows usage) expected a nice .exe file to appear. I have no idea what to do with this a.out file.
Name it with -o and skip the -c:
gcc -Wall -o somefile myfile
You should name your sourcefiles with a .c extension though.
The typical way of compiling e.g. two source files into an executable:
#Compile (the -c) a file, this produces an object file (file1.o and file2.o)
gcc -Wall -c file1.c
gcc -Wall -c file2.c
#Link the object files, and specify the output name as `myapp` instead of the default `a.out`
gcc -o myapp file1.o file2.o
You can make this into a single step:
gcc -Wall -o myapp file1.c file2.c
Or, for your case with a single source file:
gcc -Wall -o myapp file.c
The -Wall part means "enable (almost) all warnings" - this is a habit you should pick up from the start, it'll save you a lot of headaches debugging weird problems later.
The a.out name is a leftover from older unixes where it was an executable format. Linkers still name files a.out by default, event though they tend to produce ELF and not a.out format executables now.
a.out is the executable file.
run it:
./a.out

Resources