How do I produce plain binary from object files? - c

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?

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.

makefile used compile program in Mac and cross compiler flags it uses in it.what they means & alternative 4 the flags if I am not using cross-compiler

I have a simple OS and Bootloader code downloaded from https://github.com/FRosner/FrOS/tree/minimal-c-kernel
tutorial is at https://dev.to/frosnerd/writing-my-own-boot-loader-3mld
I have some questions about the make file
in below makefile what is x86_64-elf-ld, ld I belive is to link the object files and libraries into output .a and bin files which are libraries. So I believe to output a library called kernel.bin the author used ld's -o flag since its linker then the output is .bin file. I like to know can I output .o file from ld program (by using only ld program can I output .o binary executable, if no, then I assumed its a linker not compiler and compiler can output only executable/or self executable with main() and linker can output only library which needed by some other executable code to call its functions )
the first line is noticed is
kernel.bin: kernel_entry.o kernel.o
x86_64-elf-ld -m elf_i386 -o $# -Ttext 0x1000 $^ --oformat binary
since the author built the program in Mac computer and wanted to output binary from code that runs on x86-64 architecture so he needed x86-64 linker which is x86_64-elf-ld and can be easily installed on Mac. But I do not have Mac, I have x86-64 computer then can I use only ld instead of cross platform ld which is x86_64-elf-ld on authors computer also what is -m flag? does -m is an option and elf_i386 is a value of the option -m, can any one please clarify this. or are they (-m and elf_i386 are two separate things if yes then what they mean?) and is with flag -Ttext can I specify the address of output file? so what exactly above two lines means along with there flags
this is next is
kernel_entry.o: kernel_entry.asm
nasm $< -f elf -o $#
what is -f flag and what is elf in above two lines? in above its output-ing .o $# target file which is executable. with NASM assembly compiler
so in rest of the makefile what are -m32,-b,-f,-ffreestanding,-fda flags and what is xxd program?
These are many questions or someone just direct me to some page where I will not like to be lost in dozens of flags. May concise page where these flags can be covered. Or if some one take time to explain them then very thanks
# $# = target file
# $< = first dependency
# $^ = all dependencies
# First rule is the one executed when no parameters are fed to the Makefile
all: run
# Notice how dependencies are built as needed
kernel.bin: kernel_entry.o kernel.o
x86_64-elf-ld -m elf_i386 -o $# -Ttext 0x1000 $^ --oformat binary
kernel_entry.o: kernel_entry.asm
nasm $< -f elf -o $#
kernel.o: kernel.c
x86_64-elf-gcc -m32 -ffreestanding -c $< -o $#
# Disassemble
kernel.dis: kernel.bin
ndisasm -b 32 $< > $#
mbr.bin: mbr.asm
nasm $< -f bin -o $#
os-image.bin: mbr.bin kernel.bin
cat $^ > $#
run: os-image.bin
qemu-system-i386 -fda $<
echo: os-image.bin
xxd $<
clean:
$(RM) *.bin *.o *.dis
now the only question I have is why I have to resort to using
x86_64-elf-ld linker and x86_64-elf-gcc compiler since the author used
them because he was not developinh makefile and program on x86-64. But
why I have to use them. So question actually is now: can I use only
gcc instead of x86_64-elf-gcc cross compiler and can I use ld as
linker instead of x86_64-elf-ld cross platform linker.
in short, it is recommended to use a cross compiler when developing an os because it:
allows you to leave the current operating system behind, meaning that
no headers or libraries of your host operating system will be used.
You need a cross-compiler for operating system development, otherwise
a lot of unexpected things can happen because the compiler assumes
that your code is running on your host operating system.
for more information see:
Why do I need a Cross Compiler?
GCC Cross-Compiler
hence, even if you are on x86-64 it is still recommended to use a cross compiler, because it will save you a lot of trouble.
as for the linker, on osdev.org they recommend to:
Linking with your compiler rather than ld
You shouldn't be invoking ld directly. Your cross-compiler is able to
work as a linker and using it as the linker allows it control at the
linking stage. This control includes expanding the -lgcc to the full
path of libgcc that only the compiler knows about. If you get weird
errors during compilation, use your cross-compiler for linking and it
may go away. If you do need ld, be sure to use the cross-linker
(i686-elf-ld) rather than the system linker.
see also: https://wiki.osdev.org/Category:FAQ

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

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.

GCC: How to stop gcc from creating random temporary file name for the .o files

I am attempting to compile two .c files using the following gcc command:
gcc -O0 program1.c program2.c -o output.elf
and all is fine until I pass in a linker script and view the map file.
gcc -O0 program1.c program2.c -o output.elf -Xlinker -T memory.ld -Xlinker custom.ld
of which my custom.ld has the following:
1 SECTIONS
2 {
3 .mysection : {
4 program2.o
5 }>mymemory
6 }
and when I view the map file I get the following:
.data 0x00000720 0x4
.data 0x00000720 0x4 /tmp/ccW6dzJy.o
0x00000720 GLOBAL_SHARED_INT
where the filename is /tmp/ccW6dzJy.o which means that the wildcard match cannot happen since the linker does not get that information.
So the problem is that the program2.o is not put into the mymemory address because I think the culprit is the filename.
How can I make the gcc preserve the filename so that ld is able to pick up on this?
When you run the command:
gcc -O0 program1.c program2.c -o output.elf
You are telling the compiler "I don't need the object files, I just want the final linked target."
So if you need the object files, don't do that. Compile the .c files separately, using the -c flag to the compiler. This will produce the individual .o files with the names you expect. Then do the link step.

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 .

Resources