I've been looking at loading a elf file into the memory, but in the process, I've found out that there is huge chunk of unused space in the file.
This is the elf file i got https://cyao.page/kernel.elf (~2.1Mib) and this is my linker script:
ENTRY(start)
OUTPUT_FORMAT(elf64-x86-64)
SECTIONS {
. = 0xC00000;
phys = .;
.text ALIGN(0x1000): {
code = .;
*(.text)
. = ALIGN(0x1000);
}
.rodata ALIGN(0x1000): {
*(.rodata*)
. = ALIGN(0x1000);
}
.data ALIGN(0x1000): {
data = .;
*(.data)
. = ALIGN(0x1000);
}
.bss ALIGN(0x1000): {
bss = .;
*(.bss)
. = ALIGN(0x1000);
}
end = .; _end = .; __end = .;
/DISCARD/ : {
*(.comment)
*(.note.gnu.build-id)
}
}
When I you look at the p_offset in the program header (in adress 0x40), you will see that the offset is 0x200000, and in all the section tables, all their's offset are bigger then 0x200000
The same goes with x86_64-elf-objdump
cdcontents/!kernel.bin: file format elf64-x86-64
cdcontents/!kernel.bin
architecture: i386:x86-64, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x000000000c000000
Program Header:
LOAD off 0x0000000000200000 vaddr 0x000000000c000000 paddr 0x000000000c000000 align 2**12
filesz 0x0000000000009384 memsz 0x000000000000b000 flags rwx
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00006000 000000000c000000 000000000c000000 00200000 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .text.startup 00000094 000000000c006000 000000000c006000 00206000 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
2 .data 00001000 000000000c007000 000000000c007000 00207000 2**5
CONTENTS, ALLOC, LOAD, DATA
3 .rodata 00001000 000000000c008000 000000000c008000 00208000 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .eh_frame 00000384 000000000c009000 000000000c009000 00209000 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .bss 00001000 000000000c00a000 000000000c00a000 00209384 2**5
ALLOC
6 .debug_info 000035be 0000000000000000 0000000000000000 00209384 2**0
CONTENTS, READONLY, DEBUGGING, OCTETS
7 .debug_abbrev 00000db5 0000000000000000 0000000000000000 0020c942 2**0
CONTENTS, READONLY, DEBUGGING, OCTETS
8 .debug_loclists 00006865 0000000000000000 0000000000000000 0020d6f7 2**0
CONTENTS, READONLY, DEBUGGING, OCTETS
9 .debug_aranges 000001b0 0000000000000000 0000000000000000 00213f5c 2**0
CONTENTS, READONLY, DEBUGGING, OCTETS
10 .debug_rnglists 0000059a 0000000000000000 0000000000000000 0021410c 2**0
CONTENTS, READONLY, DEBUGGING, OCTETS
11 .debug_line 00002046 0000000000000000 0000000000000000 002146a6 2**0
CONTENTS, READONLY, DEBUGGING, OCTETS
12 .debug_str 000005f3 0000000000000000 0000000000000000 002166ec 2**0
CONTENTS, READONLY, DEBUGGING, OCTETS
13 .debug_line_str 0000015c 0000000000000000 0000000000000000 00216cdf 2**0
CONTENTS, READONLY, DEBUGGING, OCTETS
It shouldn't be the alignment since its aligned to 0x1000, not 0x200000.
Now the problem is: What is the space 0x78 (end of the headders) to 0x200000 used for? thats a whole 2 Mib wasted! (yea it's a lot compared to that i only reserved 512 Mib of memory for my kernel)
Here is a reduced version of my makefile:
C_SOURCES = $(wildcard lib/*.c) $(wildcard libc/*.c)
HEADERS = $(wildcard include/*.h) $(wildcard include/kernel/*.h)
OBJ = ${C_SOURCES:.c=.o} lib/idtr.o asmlib/memmove.o asmlib/memcpy.o asmlib/unalignedisfaster.o asmlib/instrset.o \
asmlib/cputype.o asmlib/cachesize64.o
CFLAGS = -O2 -std=gnu11 -g -static -Wall -Wextra -Werror -Wno-unused-function \
-Wno-unused-parameter -nostartfiles -Wno-unused-but-set-variable \
-Wstrict-prototypes -Wpointer-arith -Wcast-align -Wwrite-strings -Wshadow \
-fno-stack-protector -Wundef -nostdlib -fno-builtin -nodefaultlibs \
-fms-extensions -ffreestanding -mcmodel=large -fverbose-asm -nostartfiles \
-mno-red-zone -mno-mmx -mno-sse -mno-sse2 -Iinclude -Wfloat-equal
all: kernel.bin
kernel.bin: lib/kernel_start.o ${OBJ}
x86_64-elf-gcc -o $# $^ -T link.ld -ffreestanding -O2 -nostdlib -lgcc
%.o: %.c
x86_64-elf-gcc ${CFLAGS} -c $< -o $#
%.o: %.asm
nasm $< -f elf64 -o $#
for the full makefile you can look here https://github.com/cheyao/AchieveOS/blob/master/Makefile
Thanks to Michal Petch in their comment, the solution is to add -z max-page-size=0x1000 to the compiler flags
Related
I'm trying to make a simple kernel with multiboot. I got the multiboot header working in NASM, but now I'm trying to rewrite it in GNU AS syntax. I think problem is that clang (as on MacOS) is placing the multiboot header at a different address (beyond 8K), but I can't figure out how to get it to work the same as NASM. I'm using the same linker script.
Below is my NASM code, GAS code, linker script, and the output of nm kernel-nasm.bin kernel-gas.bin (sorry for the verbosity).
Here's the working NASM code:
MBALIGN equ 1 << 0
MEMINFO equ 1 << 1
FLAGS equ MBALIGN | MEMINFO
MAGIC equ 0x1BADB002
CHECKSUM equ -(MAGIC + FLAGS)
section .multiboot_header
header_start:
align 4
dd MAGIC
dd FLAGS
dd CHECKSUM
header_end:
section .text
global start
start:
mov dword [0xb8000], 0x2f4b2f4f
hlt
And here's the not working GNU AS code:
.set MBALIGN, 1 << 0
.set MEMINFO, 1 << 1
.set FLAGS, MBALIGN | MEMINFO
.set MAGIC, 0x1BADB002
.set CHECKSUM, -(MAGIC + FLAGS)
.section .multiboot_header
header_start:
.align 4
.long MAGIC
.long FLAGS
.long CHECKSUM
header_end:
.section .text
.global start
start:
movl $0x2f4b2f4f, (0xb8000)
hlt
Linker Script:
ENTRY(start)
SECTIONS {
. = 1M;
.boot : ALIGN(4K)
{
/* ensure that the multiboot header is at the beginning */
*(.multiboot_header)
}
.text : ALIGN (4K)
{
*(.text)
}
}
Output of nm kernel-nasm.bin kernel-gas.bin:
kernel-nasm.bin:
e4524ffb a CHECKSUM
00000003 a FLAGS
1badb002 a MAGIC
00000001 a MBALIGN
00000002 a MEMINFO
0010000c r header_end
00100000 r header_start
00101000 T start
kernel-gas.bin:
e4524ffb a CHECKSUM
00000003 a FLAGS
1badb002 a MAGIC
00000001 a MBALIGN
00000002 a MEMINFO
0000000c n header_end
00000000 n header_start
00100000 T start
Here's the commands I'm using to assemble the code. I'm using Homebrew's LLVM 14.0.6 on macOS:
# For kernel-nasm.bin
nasm -felf32 kernel-nasm.asm -o kernel-nasm.o
ld.lld -n -o kernel-nasm.bin -T linker.ld kernel-nasm.o
# For kernel-gas.bin
as --target=i386-pc-none-elf kernel-gas.S -o kernel-gas.o
ld.lld -n -o kernel-gas.bin -T linker.ld kernel-gas.o
As you can see from the --target= option, as on this machine is clang, not from GNU Binutils. Same for the ld.lld linker being LLVM, not Binutils.
The output of objdump -x kernel-nasm.bin is:
kernel-nasm.bin: file format elf32-i386
kernel-nasm.bin
architecture: i386, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x00101000
Program Header:
LOAD off 0x00001000 vaddr 0x00100000 paddr 0x00100000 align 2**12
filesz 0x0000000c memsz 0x0000000c flags r--
LOAD off 0x00002000 vaddr 0x00101000 paddr 0x00101000 align 2**12
filesz 0x0000000b memsz 0x0000000b flags r-x
STACK off 0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**0
filesz 0x00000000 memsz 0x00000000 flags rw-
Sections:
Idx Name Size VMA LMA File off Algn
0 .boot 0000000c 00100000 00100000 00001000 2**12
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .text 0000000b 00101000 00101000 00002000 2**12
CONTENTS, ALLOC, LOAD, READONLY, CODE
2 .comment 0000001c 00000000 00000000 0000200b 2**0
CONTENTS, READONLY
SYMBOL TABLE:
00000000 l df *ABS* 00000000 hdr.asm
00000001 l *ABS* 00000000 MBALIGN
00000002 l *ABS* 00000000 MEMINFO
00000003 l *ABS* 00000000 FLAGS
1badb002 l *ABS* 00000000 MAGIC
e4524ffb l *ABS* 00000000 CHECKSUM
00100000 l .boot 00000000 header_start
0010000c l .boot 00000000 header_end
00101000 g .text 00000000 start
The output of objdump -x kernel-gas.bin is:
kernel-gas.bin: file format elf32-i386
kernel-gas.bin
architecture: i386, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x00100000
Program Header:
LOAD off 0x00001000 vaddr 0x00100000 paddr 0x00100000 align 2**12
filesz 0x0000000b memsz 0x0000000b flags r-x
STACK off 0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**0
filesz 0x00000000 memsz 0x00000000 flags rw-
Sections:
Idx Name Size VMA LMA File off Algn
0 .boot 0000000c 00000000 00000000 00002000 2**12
CONTENTS, READONLY
1 .comment 0000001c 00000000 00000000 0000200c 2**0
CONTENTS, READONLY
2 .text 0000000b 00100000 00100000 00001000 2**12
CONTENTS, ALLOC, LOAD, READONLY, CODE
SYMBOL TABLE:
e4524ffb l *ABS* 00000000 CHECKSUM
00000003 l *ABS* 00000000 FLAGS
1badb002 l *ABS* 00000000 MAGIC
00000001 l *ABS* 00000000 MBALIGN
00000002 l *ABS* 00000000 MEMINFO
0000000c l .boot 00000000 header_end
00000000 l .boot 00000000 header_start
00100000 g .text 00000000 start
According to the GNU AS documentation, "If the section name is not recognized, the default will be for the section to have none of the above flags: it will not be allocated in memory, nor writable, nor executable. The section will contain data."
To make sure the .boot section is loaded into memory and can be read by the bootloader, the section must have the "a" flag added to it (more info in the documentation above). Like this:
// ... code ...
.section .multiboot_header, "a"
header_start:
.align 4
.long MAGIC
.long FLAGS
.long CHECKSUM
header_end:
// ... code ...
When we covert a .elf file generated from arm-gcc toolchain to .bin file, its size increases from 40kB to 1.1Gb.
For conversion we are using :
./arm-none-eabi-objcopy -O binary test.elf test.bin
It might be because of non-contiguous memory map and the gaps between the memory regions are just being filled with zeros.
What options can be used in objcopy? Or is there any other method to convert?
Following is the elf information:
Tag_CPU_name: "Cortex-M7" Tag_CPU_arch: v7E-M
Tag_CPU_arch_profile: Microcontroller Tag_THUMB_ISA_use: Thumb-2
Tag_FP_arch: FPv5/FP-D16 for ARMv8 Tag_ABI_PCS_wchar_t: 4
Tag_ABI_FP_denormal: Needed Tag_ABI_FP_exceptions: Needed
Tag_ABI_FP_number_model: IEEE 754 Tag_ABI_align_needed: 8-byte
Tag_ABI_enum_size: small Tag_ABI_VFP_args: VFP registers
Tag_ABI_optimization_goals: Aggressive Debug
Tag_CPU_unaligned_access: v6
The listing of sections contained in the ELF file is - there are 25 section headers, starting at offset 0x3e982c:
Section Headers:
[Nr] Name
Type Addr Off Size ES Lk Inf Al
Flags
[ 0]
NULL 00000000 000000 000000 00 0 0 0
[00000000]:
[ 1] .flash_config
PROGBITS 60000000 020000 000200 00 0 0 4
[00000002]: ALLOC
[ 2] .ivt
PROGBITS 60001000 021000 000030 00 0 0 4
[00000002]: ALLOC
[ 3] .interrupts
PROGBITS 60002000 022000 000400 00 0 0 4
[00000002]: ALLOC
[ 4] .text
PROGBITS 60002400 022400 312008 00 0 0 16
[00000006]: ALLOC, EXEC
[ 5] .ARM
ARM_EXIDX 60314408 334408 000008 00 4 0 4
[00000082]: ALLOC, LINK ORDER
[ 6] .init_array
INIT_ARRAY 60314410 334410 000004 04 0 0 4
[00000003]: WRITE, ALLOC
[ 7] .fini_array
FINI_ARRAY 60314414 334414 000004 04 0 0 4
[00000003]: WRITE, ALLOC
[ 8] .interrupts_ram
PROGBITS 20200000 380000 000000 00 0 0 1
[00000001]: WRITE
[ 9] .data
PROGBITS 20200000 340000 014bd0 00 0 0 8
[00000007]: WRITE, ALLOC, EXEC
[10] .ncache.init
PROGBITS 20214bd0 354bd0 011520 00 0 0 4
[00000003]: WRITE, ALLOC
[11] .ncache
NOBITS 20226100 366100 0021d8 00 0 0 64
[00000003]: WRITE, ALLOC
[12] .bss
NOBITS 20229000 369000 077ce8 00 0 0 4096
[00000003]: WRITE, ALLOC
[13] .NVM_TABLE
PROGBITS 20000000 010000 00000c 00 0 0 4
[00000003]: WRITE, ALLOC
[14] .heap
NOBITS 2000000c 01000c 000404 00 0 0 1
[00000003]: WRITE, ALLOC
[15] .stack
NOBITS 20000410 01000c 000400 00 0 0 1
[00000003]: WRITE, ALLOC
[16] .NVM
PROGBITS 60570000 370000 010000 00 0 0 1
[00000003]: WRITE, ALLOC
[17] .ARM.attributes
ARM_ATTRIBUTES 00000000 380000 00002e 00 0 0 1
[00000000]:
[18] .comment
PROGBITS 00000000 38002e 00004c 01 0 0 1
[00000030]: MERGE, STRINGS
[19] .debug_frame
PROGBITS 00000000 38007c 001174 00 0 0 4
[00000000]:
[20] .stab
PROGBITS 00000000 3811f0 0000cc 0c 21 0 4
[00000000]:
[21] .stabstr
STRTAB 00000000 3812bc 0001b9 00 0 0 1
[00000000]:
[22] .symtab
SYMTAB 00000000 381478 046620 10 23 13540 4
[00000000]:
[23] .strtab
STRTAB 00000000 3c7a98 021cb2 00 0 0 1
[00000000]:
[24] .shstrtab
STRTAB 00000000 3e974a 0000df 00 0 0 1
[00000000]:
so.s
.thumb
nop
.data
.word 0x11223344
so.ld
MEMORY
{
one : ORIGIN = 0x00000000, LENGTH = 0x1000
two : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > one
.data : { *(.data*) } > two
}
build
arm-none-eabi-as so.s -o so.o
arm-none-eabi-ld -T so.ld so.o -o so.elf
arm-none-eabi-objdump -D so.elf
arm-none-eabi-objcopy -O binary so.elf so.bin
536870916 Apr 28 15:23 so.bin
131556 Apr 28 15:23 so.elf
from readelf
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x010000 0x00000000 0x00000000 0x00002 0x00002 R E 0x10000
LOAD 0x020000 0x20000000 0x20000000 0x00004 0x00004 RW 0x10000
now so.ld
MEMORY
{
one : ORIGIN = 0x00000000, LENGTH = 0x1000
two : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > one
.bss : { *(.bss*) } > two AT > one
.data : { *(.data*) } > two AT > one
}
it is actually .bss that is doing the magic here, that is some other research project, I could have started with a .C file but tried asm...
6 Apr 28 15:30 so.bin
131556 Apr 28 15:29 so.elf
and now it is the possibly desired 6 bytes without padding, but of course you have to add labels in the linker script and use them in the bootstrap code to move .data to ram and zero .bss and such.
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x010000 0x00000000 0x00000000 0x00002 0x00002 R E 0x10000
LOAD 0x020000 0x20000000 0x00000002 0x00004 0x00004 RW 0x10000
Notice how now the physical is in the 0x00000000 range, it was tacked at the end of the space used by .text. but the virtual (where it wants to live, needs to live, do not think mmu here or anything like that just think the two address spaces (on flash and where it is used)).
In case this is not clear:
MEMORY
{
one : ORIGIN = 0xE0000000, LENGTH = 0x1000
two : ORIGIN = 0xE0000100, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > one
.data : { *(.data*) } > two
}
260 Apr 28 15:46 so.bin
66276 Apr 28 15:46 so.elf
objcopy starts the binary file at the lowest defined (loadable) address and not zero...The file size is the difference, inclusive, of the lowest addressed byte and the highest.
I have same problem with you, and I finally find it's not objcopy's problem, I just change my compile command and it work. At first, I just use gcc only, and I face the problem like you, then I try use gcc -c and ld(just separate this two steps), and the file is smaller in magically. so maybe the problem is in gcc, not objcopy. you can try like me, and my compile command now is:
gcc-4.8 -g -e boot_start -fno-builtin -Ttext 0x7C00 -nostdlib -m32 -c bootloader.S -o bootasm.o
gcc-4.8 -Os -fno-builtin -nostdlib -m32 -c bootloader.c -o bootc.o
ld -m elf_i386 -e boot_start -nostdlib -N bootasm.o bootc.o -o bootloader.o
objcopy -S -O binary bootloader.o bootloader.bin
hope it can help you...
I am using the nestedvm package, which includes a patched Gnu gcc compiler. For this package, callable user methods/functions have to annotated with __attribute__((section(".text"))), as shown in the C example below.
void echo(const char *string, int count) __attribute__((section(".text")));
void echo(const char *string, int count) {
int i;
for(i=0;i<count;i++)
printf("%d: %s\n",i,string);
}
I don't know about the inner workings of the patched compiler, but without this annotation, the user function is not visible to outside callers.
If using gfortran, how can I accomplish this annotation for Fortran subroutines and functions? Could this be done with a linker script file? I could write a C wrapper to the Fortran functions, but would like to avoid this if possible.
** UPDATE 1 **
Using nm to investigate the .o file sheds some light on the issue...a C method without the attribute looks like the suckram function (which is not callable in nestedvm), while the echo function has the attribute and is callable in nestedvm:
Name Value Class Type Size Line Section
suckram |00000000| T | FUNC|00000078| |.text.suckram
echo |00000200| T | FUNC|00000074| |.text
The test1 subroutine in my Fortran object looks like the suckram method without the attribute:
test1_ |00000000| T | FUNC|00000080| |.text.test1_
According to some nestedvm documentation I found, in order for a user function to be callable in nestedvm, it has to end up in the .text section.
** UPDATE 2 **
A link command line is below. It is too long to put in a comment. I removed some of the many .o files (…)
mips-unknown-elf-gfortran -O3 -mmemcpy -ffunction-sections -fdata-sections -falign-functions=512 -fno-rename-registers -fno-schedule-insns -fno-delayed-branch -march=mips1 -specs=/home/jhuber/Documents/source/nestedvm/upstream/install/mips-unknown-elf/lib/crt0-override.spec -I. -Wall -Wno-unused -o build/refprop/Refprop.mips build/refprop/NVM.o (...) build/refprop/TRNS_VIS.o build/refprop/MAIN.o -march=mips1 -specs=/home/jhuber/Documents/source/nestedvm/upstream/install/mips-unknown-elf/lib/crt0-override.spec --static -Wl,--gc-sections -Wl,-Map=output1.map -Wl,--cref -lc -Wl,-Map=output.map -Wl,--cref
Also, even though I am calling the code as a library, nestedvm requires the library to have a MAIN routine for initialization. If I make some dummy calls to the library functions in the MAIN routine, those functions that are called in MAIN are moved the .text section, and become callable.
** UPDATE 3 **
Verbose output from make. I removed some of the many .o files (…)
mips-unknown-elf-gfortran -O3 -mmemcpy -ffunction-sections -fdata-sections -falign-functions=512 -fno-rename-registers -fno-schedule-insns -fno-delayed-branch -march=mips1 -specs=/home/jhuber/Documents/source/nestedvm/upstream/install/mips-unknown-elf/lib/crt0-override.spec -I. -Wall -Wno-unused -o build/refprop/Refprop.mips build/refprop/NVM.o (…) build/refprop/TRNS_VIS.o build/refprop/MAIN.o -march=mips1 -specs=/home/jhuber/Documents/source/nestedvm/upstream/install/mips-unknown-elf/lib/crt0-override.spec --static -Wl,--gc-sections -Wl,-Map=output1.map -Wl,--cref -lc -Wl,-Map=output.map -Wl,--cref -v
Driving: mips-unknown-elf-gfortran -O3 -mmemcpy -ffunction-sections -fdata-sections -falign-functions=512 -fno-rename-registers -fno-schedule-insns -fno-delayed-branch -march=mips1 -specs=/home/jhuber/Documents/source/nestedvm/upstream/install/mips-unknown-elf/lib/crt0-override.spec -I. -Wall -Wno-unused -o build/refprop/Refprop.mips build/refprop/NVM.o (…) build/refprop/TRNS_VIS.o build/refprop/MAIN.o -march=mips1 -specs=/home/jhuber/Documents/source/nestedvm/upstream/install/mips-unknown-elf/lib/crt0-override.spec --static -Wl,--gc-sections -Wl,-Map=output1.map -Wl,--cref -lc -Wl,-Map=output.map -Wl,--cref -v -l gfortran -l m
Using built-in specs.
Reading specs from /home/jhuber/Documents/source/nestedvm/upstream/install/mips-unknown-elf/lib/crt0-override.spec
Reading specs from /home/jhuber/Documents/source/nestedvm/upstream/install/mips-unknown-elf/lib/crt0-override.spec
COLLECT_GCC=mips-unknown-elf-gfortran
COLLECT_LTO_WRAPPER=/home/jhuber/Documents/source/nestedvm/upstream/install/libexec/gcc/mips-unknown-elf/4.8.5/lto-wrapper
Target: mips-unknown-elf
Configured with: ../gcc-4.8.5/configure --prefix=/home/jhuber/Documents/source/nestedvm/upstream/install --target=mips-unknown-elf --disable-threads --disable-libssp --with-gnu-ld --with-gnu-as --with-newlib=yes --enable-sjlj-exceptions --enable-languages=c : (reconfigured) ../gcc-4.8.5/configure --prefix=/home/jhuber/Documents/source/nestedvm/upstream/install --target=mips-unknown-elf --disable-threads --disable-libssp --with-gnu-ld --with-gnu-as --with-newlib=yes --enable-sjlj-exceptions --enable-languages=c --enable-languages=c,c++,fortran
Thread model: single
gcc version 4.8.5 (GCC)
Reading specs from /home/jhuber/Documents/source/nestedvm/upstream/install/lib/gcc/mips-unknown-elf/4.8.5/../../../../mips-unknown-elf/lib/libgfortran.spec
rename spec lib to liborig
COLLECT_GCC_OPTIONS='-O3' '-mmemcpy' '-ffunction-sections' '-fdata-sections' '-falign-functions=512' '-fno-rename-registers' '-fno-schedule-insns' '-fno-delayed-branch' '-march=mips1' '-specs=/home/jhuber/Documents/source/nestedvm/upstream/install/mips-unknown-elf/lib/crt0-override.spec' '-I' '.' '-Wall' '-Wno-unused' '-o' 'build/refprop/Refprop.mips' '-march=mips1' '-specs=/home/jhuber/Documents/source/nestedvm/upstream/install/mips-unknown-elf/lib/crt0-override.spec' '-static' '-v'
COMPILER_PATH=/home/jhuber/Documents/source/nestedvm/upstream/install/libexec/gcc/mips-unknown-elf/4.8.5/:/home/jhuber/Documents/source/nestedvm/upstream/install/libexec/gcc/mips-unknown-elf/4.8.5/:/home/jhuber/Documents/source/nestedvm/upstream/install/libexec/gcc/mips-unknown-elf/:/home/jhuber/Documents/source/nestedvm/upstream/install/lib/gcc/mips-unknown-elf/4.8.5/:/home/jhuber/Documents/source/nestedvm/upstream/install/lib/gcc/mips-unknown-elf/:/home/jhuber/Documents/source/nestedvm/upstream/install/lib/gcc/mips-unknown-elf/4.8.5/../../../../mips-unknown-elf/bin/
LIBRARY_PATH=/home/jhuber/Documents/source/nestedvm/upstream/install/lib/gcc/mips-unknown-elf/4.8.5/:/home/jhuber/Documents/source/nestedvm/upstream/install/lib/gcc/mips-unknown-elf/4.8.5/../../../../mips-unknown-elf/lib/
COLLECT_GCC_OPTIONS='-O3' '-mmemcpy' '-ffunction-sections' '-fdata-sections' '-falign-functions=512' '-fno-rename-registers' '-fno-schedule-insns' '-fno-delayed-branch' '-march=mips1' '-specs=/home/jhuber/Documents/source/nestedvm/upstream/install/mips-unknown-elf/lib/crt0-override.spec' '-I' '.' '-Wall' '-Wno-unused' '-o' 'build/refprop/Refprop.mips' '-march=mips1' '-specs=/home/jhuber/Documents/source/nestedvm/upstream/install/mips-unknown-elf/lib/crt0-override.spec' '-static' '-v'
/home/jhuber/Documents/source/nestedvm/upstream/install/libexec/gcc/mips-unknown-elf/4.8.5/collect2 -EB -o build/refprop/Refprop.mips /home/jhuber/Documents/source/nestedvm/upstream/install/lib/gcc/mips-unknown-elf/4.8.5/crti.o /home/jhuber/Documents/source/nestedvm/upstream/install/lib/gcc/mips-unknown-elf/4.8.5/crtbegin.o /home/jhuber/Documents/source/nestedvm/upstream/install/lib/gcc/mips-unknown-elf/4.8.5/../../../../mips-unknown-elf/lib/crt0.o -L/home/jhuber/Documents/source/nestedvm/upstream/install/lib/gcc/mips-unknown-elf/4.8.5 -L/home/jhuber/Documents/source/nestedvm/upstream/install/lib/gcc/mips-unknown-elf/4.8.5/../../../../mips-unknown-elf/lib build/refprop/NVM.o (…) build/refprop/TRNS_VIS.o build/refprop/MAIN.o --gc-sections -Map=output1.map --cref -lc -Map=output.map --cref -lgfortran -lm -lgcc -lm -lgcc -lgcc /home/jhuber/Documents/source/nestedvm/upstream/install/lib/gcc/mips-unknown-elf/4.8.5/crtend.o /home/jhuber/Documents/source/nestedvm/upstream/install/lib/gcc/mips-unknown-elf/4.8.5/crtn.o
I did some local tests, and -ffunction-sections puts each fortran function its own section, as expected. Compare:
$ gfortran -c -O3 -o hello.o hello.f90
$ objdump -h hello.o
hello.o: file format elf64-x86-64
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 000000aa 0000000000000000 0000000000000000 00000040 2**4
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
1 .data 00000000 0000000000000000 0000000000000000 000000ea 2**0
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 0000000000000000 0000000000000000 000000ea 2**0
ALLOC
3 .rodata.str1.1 0000000a 0000000000000000 0000000000000000 000000ea 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .text.startup 00000026 0000000000000000 0000000000000000 00000100 2**4
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
5 .rodata 0000001c 0000000000000000 0000000000000000 00000130 2**4
CONTENTS, ALLOC, LOAD, READONLY, DATA
6 .comment 00000026 0000000000000000 0000000000000000 0000014c 2**0
CONTENTS, READONLY
7 .note.GNU-stack 00000000 0000000000000000 0000000000000000 00000172 2**0
CONTENTS, READONLY
8 .eh_frame 00000068 0000000000000000 0000000000000000 00000178 2**3
CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
to:
$ gfortran -ffunction-sections -c -O3 -o hello.o hello.f90
$ objdump -h hello.o
hello.o: file format elf64-x86-64
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000000 0000000000000000 0000000000000000 00000040 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00000000 0000000000000000 0000000000000000 00000040 2**0
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 0000000000000000 0000000000000000 00000040 2**0
ALLOC
3 .rodata.str1.1 0000000a 0000000000000000 0000000000000000 00000040 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .text.MAIN__ 00000097 0000000000000000 0000000000000000 00000050 2**4
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
5 .text.foo_ 0000000a 0000000000000000 0000000000000000 000000f0 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
6 .text.startup.main 00000026 0000000000000000 0000000000000000 00000100 2**4
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
7 .rodata 0000001c 0000000000000000 0000000000000000 00000130 2**4
CONTENTS, ALLOC, LOAD, READONLY, DATA
8 .comment 00000026 0000000000000000 0000000000000000 0000014c 2**0
CONTENTS, READONLY
9 .note.GNU-stack 00000000 0000000000000000 0000000000000000 00000172 2**0
CONTENTS, READONLY
10 .eh_frame 00000068 0000000000000000 0000000000000000 00000178 2**3
CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
The builtin linker script on my local machine rolls all of these into .text by default. It appears whatever you're linking with doesn't. You should be able to modify that script to do what you're trying. It's a bit more difficult than the attribute extensions, since you'll have to maintain the list in a separate file, but you should be able to locate things however you like. I can work up an example here if you give some more context about that in your question.
I was inspecting ELF binary for the code mentioned below.
I compiled it on gcc 7.4.0 on Ubuntu x86_64 system in Virtual Box as :
gcc -g scratch1.c -o scratch1.out
#include <stdio.h>
void do_stuff(int my_arg){
int my_local = my_arg + 2;
int i;
for (i = 0; i < my_local; ++i) printf("i = %d\n", i);
}
int main(){
do_stuff(2);
return 0;
}
However when I tried to refer to .debug_loc section, it was empty.
objdump --dwarf=loc scratch1.out
scratch1.out: file format elf64-x86-64
Although, I do see some other debug_ sections
[26] .debug_aranges PROGBITS 0000000000000000 0000103b
0000000000000030 0000000000000000 0 0 1
[27] .debug_info PROGBITS 0000000000000000 0000106b
000000000000035f 0000000000000000 0 0 1
[28] .debug_abbrev PROGBITS 0000000000000000 000013ca
0000000000000125 0000000000000000 0 0 1
[29] .debug_line PROGBITS 0000000000000000 000014ef
00000000000000e6 0000000000000000 0 0 1
[30] .debug_str PROGBITS 0000000000000000 000015d5
00000000000002b5 0000000000000001 MS 0 0 1
Need your help why this section is missing.
Need your help why this section is missing.
The .debug_loc section contains DW_AT_location lists, usually emitted only for optimized code.
Since you compiled without optimization, the compiler didn't emit this section. Try building with:
gcc -g -O3 scratch1.c -o scratch1.out
Here is what I see with gcc 8.3.0:
$ gcc -g scratch.c && readelf -WS a.out | grep debug_loc
# no output
$ gcc -g scratch.c -O3 && readelf -WS a.out | grep debug_loc
[32] .debug_loc PROGBITS 0000000000000000 0039db 000230 00 0 0 1
I have a function written in C that reads a character from the keyboard, and returns the pressed character.
kmain.c
#include <stdint.h>
char getch()
{
uint16_t inchar;
__asm__ __volatile__ ("int $0x16\n\t"
: "=a"(inchar)
: "0"(0x0));
return ((char)inchar);
}
void println(char *str)
{
while (*str)
{
// AH=0x0e, AL=char to print, BH=page, BL=fg color
__asm__ __volatile__ ("int $0x10"
:
: "a" ((0x0e<<8) | *str++),
"b" (0x0000));
}
}
void kernelmain()
{
println("Println called from C code");
char c;
c = getch();
println(c);
}
boot.asm
extern println
extern kernelmain
global start
bits 16
section .text
start:
xor ax, ax
mov ds, ax
mov es, ax
mov ss, ax
mov esp, 0x7C00
jmp 0x0000:setcs
setcs:
cld
push dword msg1
call dword println
; If you use call instead of jmp, it gonna throw a nice error :)
jmp kernelmain
cli
hlt ; halt the processor
section .data
msg1 db 'Println called from NASM code', 0x0A, 0x0D, 0
But when I want to print that obtained key, it throw this useless error:
qemu: fatal: Trying to execute code outside RAM or ROM at 0xd08ec08e
EAX=00002d78 EBX=00000000 ECX=00000000 EDX=00000000
ESI=00000000 EDI=00000000 EBP=d88ec031 ESP=00007c08
EIP=d08ec08e EFL=00000206 [-----P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0000 00000000 0000ffff 00009300
CS =0000 00000000 0000ffff 00009b00
SS =0000 00000000 0000ffff 00009300
DS =0000 00000000 0000ffff 00009300
FS =0000 00000000 0000ffff 00009300
GS =0000 00000000 0000ffff 00009300
LDT=0000 00000000 0000ffff 00008200
TR =0000 00000000 0000ffff 00008b00
GDT= 000f6c00 00000037
IDT= 00000000 000003ff
CR0=00000010 CR2=00000000 CR3=00000000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
DR6=ffff0ff0 DR7=00000400
CCS=00000004 CCD=0000fe9c CCO=EFLAGS
EFER=0000000000000000
FCW=037f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80
FPR0=0000000000000000 0000 FPR1=0000000000000000 0000
FPR2=0000000000000000 0000 FPR3=0000000000000000 0000
FPR4=0000000000000000 0000 FPR5=0000000000000000 0000
FPR6=0000000000000000 0000 FPR7=0000000000000000 0000
XMM00=00000000000000000000000000000000 XMM01=00000000000000000000000000000000
XMM02=00000000000000000000000000000000 XMM03=00000000000000000000000000000000
XMM04=00000000000000000000000000000000 XMM05=00000000000000000000000000000000
XMM06=00000000000000000000000000000000 XMM07=00000000000000000000000000000000
Aborted (core dumped)
to compile kernel.bin:
gcc -fno-PIC -ffreestanding -m16 -c kmain.c -o kmain.o
nasm -f elf32 boot.asm -o boot.o
ld -melf_i386 -T link.ld kmain.o boot.o -o kernel.elf
objcopy -O binary kernel.elf kernel.bin
qemu-system-i386 -fda kernel.bin
I found questions with this same error, but they didn't help me. Also, I know it would be better to compile this with OpenWatcom, but it's too complicated.