How to make objdump show assembly of sections only appeared in source code? - c

I would like to produce assemblies like the one in the answer of this question Using GCC to produce readable assembly?
for simple test code: test.c
void main(){
int i;
for(i=0;i<10;i++){
printf("%d\n",i);
}
}
gcc command : gcc -g test.c -o test.o
objdump command: objdump -d -M intel -S test.o
But what i got is assemblies starts with .init section
080482bc<_init>: and end with .fini section 080484cc<_fini>
which i do not want them to be shown.
why is this happening ? and how can i avoid showing sections that are not in the source file?

Right now you're creating an executable file and not an object file. The executable file of course contains lot of extra sections.
If you want to create an object file, use the -c flag to GCC.

You can specify sections using -j option.
So objdump -d executable -j .text -j .plt will only show disassembly from .text and .plt sections.

Related

gcc/objdump output containing lines from C source code among the lines of disassembled ASM code

I believe this question is significantly different from other, similar questions.
My flow is roughly this:
### Compile
%> gcc -ggdb3 file0.c ... -fno-builtin -c -o file0.o
%> gcc -ggdb3 file1.c ... -fno-builtin -c -o file1.o
...
%> gcc -ggdb3 fileN.c ... -fno-builtin -c -o fileN.o
### Link
%> gcc -ggdb3 -nostdlib -nodefaultlibs -Tscript.lds -Ttext=0x4000000 \
-Wl,--build-id=none -o main.elf file0.o file1.o ... fileN.o
### Disassemble
%> objdump -Stsxd main.elf > main.dis
I do not see the C code between lines of the disassembly file produced by objdump. See the image below for an example.
I don't blame objdump, because objdump --dwarf=decodedline main.elf shows nothing. I don't think the information is in the elf file.
I've fiddled with adding -g, -ggdb, and -gdwarf of various versions.
I've put full pathnames to files instead of relative paths.
I've tried -O0 to -O3.
The only flags not shown in my flow above are -W, -D, and -I flags.
If it matters, I'm using the Linaro port of gcc 6.4.1 targeting Cortex-A72 clusters. (My build machine is CentOS 7.9 on x86_64.) The commands to gcc and objdump above are prefixed to use that gcc version, and I see its banner from the debug section of the ELF in the disassembly file.
Is there some flag I am missing, or perhaps something I am adding (like -fno-builtin, or -Wl,--build-id=none) that could cause this?
Could my linker script file be stripping required information out, even though I provide a "debug" section (for .debug_info, .debug_line, and many other sections)?
Both objdump and readelf show a significant number of bytes in the debug section. What do I look for, more specifically?
edit:
I expect to see the kind of thing that is on the left of this image, but I see what is on the right:

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.

How can I use UEFI Runtime Services?

I want to learn more about firmware developement. I already know how to write assembly programs for the old BIOS and now I wanted to start with UEFI. I managed to compile and emulate a Hello World program, and now I was trying to write a program which displays on the screen the current time using the Runtime Service GetTime(). However when I use this function the program hangs, as if it wasn't installed during PI.
Here is the code:
#include <efi.h>
#include <efilib.h>
#include <efiapi.h>
//gBS: SystemTable->BootServices;
//gRS: SystemTable->RuntimeServices;
EFI_STATUS
efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE* systab)
{
EFI_TIME* time;
InitializeLib(image, systab);
RT->GetTime(time, NULL);
Print(L"Time %u\n", time->Hour);
return EFI_SUCCESS;
}
Do you have any clue about what I've done wrong?
Here is the code I use to compile and emulate in case you need:
gcc -I/usr/include/efi -I/usr/include/efi/x86_64/ -fpic -ffreestanding -fno-stack-protector -fno-stack-check -fshort-wchar -mno-red-zone -maccumulate-outgoing-args -c main.c -o main.o
ld -shared -Bsymbolic -L/usr/lib -T/usr/lib/elf_x86_64_efi.lds /usr/lib/crt0-efi-x86_64.o main.o -o main.so -lgnuefi -lefi
objcopy -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel -j .rela -j .rel.* -j .rela.* -j .reloc --target efi-app-x86_64 --subsystem=10 main.so main.efi
uefi-run -b /usr/share/edk2-ovmf/x64/OVMF.fd -q /usr/bin/qemu-system-x86_64 main.efi
If you are using gnu-efi, use uefi_call_wrapper() to call UEFI functions.
RT->GetTime(time, NULL); // Program hangs
uefi_call_wrapper(RT->GetTime, 2, time, NULL); // Okay
The reason is the different calling convention between UEFI (which uses Microsoft x64 calling convention) and Linux (which uses System V amd64 ABI). By default, gcc will generate the code in Linux format, so we need to explicitly tell it to generate it in UEFI format.
You can see the difference by peforming an objdump.
I think you missed to initialize RT.
RT = SystemTable->RuntimeServices;
Your code is very similar to one of the examples (the one at section 4.7.1) of the Unified Extensible Firmware Interface Specification 2.6. I doubth you haven't read it, but just in case.
https://www.uefi.org/sites/default/files/resources/UEFI%20Spec%202_6.pdf

Output relocatable section data from linker script

Using commands like BYTE or LONG, it is possible to include explicit bytes of data in an output section from a linker script. The linked page also describes that those commands can be used to output the value of symbols.
I would have expected that if you perform partial linking (i.e., using the -r option of ld), relocation records would be emitted for the symbols that are outputted in this way. However, it seems that the linker just outputs the currently known value1 of the symbol.
Here is a MWE to clarify what I mean.
test.c:
int foo = 1, bar = 2;
test.ld:
SECTIONS {
.data : {
*(.data)
LONG(foo)
LONG(bar)
}
}
Then run the following:
$ gcc -c test.c
$ ld -T test.ld -r -o test.elf test.o
$ readelf -r test.elf
There are no relocations in this file.
$ readelf -x .data test.elf
Hex dump of section '.data':
0x00000000 01000000 02000000 00000000 04000000 ................
As you can see, no relocations are created and the values that are outputted are the currently known values of foo and bar.
Could this be a bug? If not, is there any way to force the linker to output relocation records for symbols added to an output section?
1 I'm not sure of this is the correct term. What I mean is the value that you see when you run readelf -s on the input object file.

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?

Resources