Working with Make and Linker Script: Unterschied zwischen den Versionen

Aus C und Assembler mit Raspberry
 
(4 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 12: Zeile 12:
LOADADDR = 0x80000
LOADADDR = 0x80000


GCCFLAGS = -mcpu=cortex-a76 -mlittle-endian -Wall -O0 -ffreestanding
GCCFLAGS = -mcpu=cortex-a76 -mlittle-endian -Wall -O0 -ffreestanding \
-nostartfiles -nostdlib -nostdinc -g -I ./include
          -nostartfiles -nostdlib -nostdinc -g -I ./include


AFLAGS = -mcpu=cortex-a76 -mlittle-endian -I ./include -O0 -g
AFLAGS = -mcpu=cortex-a76 -mlittle-endian -I ./include -O0 -g


CFLAGS = -mcpu=cortex-a76 -mlittle-endian -Wall -fsigned-char -ffreestanding -g
CFLAGS = -mcpu=cortex-a76 -mlittle-endian -Wall -fsigned-char -ffreestanding -g \
-I ./include -O0 -fno-exceptions
        -I ./include -O0 -fno-exceptions  


CPPFLAGS = -fno-exceptions -fno-rtti -nostdinc++ -mcpu=cortex-a76 -mlittle-endian -Wall -fsigned-char
CPPFLAGS = -fno-exceptions -fno-rtti -nostdinc++ -mcpu=cortex-a76 -mlittle-endian -Wall -fsigned-char \
-ffreestanding -g -I ./include -O0 -mstrict-align -std=c++14 -Wno-aligned-new
  -ffreestanding -g -I ./include -O0 -mstrict-align -std=c++14 -Wno-aligned-new


all: clean new kernel_2712.img
all: clean new kernel_2712.img


%.o: %.S
%.o: %.S
@echo "as $@"
@echo "as $@"
@aarch64-none-elf-gcc $(AFLAGS) -c $< -o $@
@aarch64-none-elf-gcc $(AFLAGS) -c $< -o $@


%.o: %.c
%.o: %.c
@echo "gcc $@"
@echo "gcc $@"
@aarch64-none-elf-gcc $(CFLAGS) -c $< -o $@
@aarch64-none-elf-gcc $(CFLAGS) -c $< -o $@


%.o: %.cpp
%.o: %.cpp
@echo "g++ $@"
@echo "g++ $@"
@aarch64-none-elf-g++ $(CPPFLAGS) -c $< -o $@
@aarch64-none-elf-g++ $(CPPFLAGS) -c $< -o $@


kernel_2712.img: $(AllOBJS)
kernel_2712.img: $(AllOBJS)
@echo "============================================================================="
@echo "============================================================================="
@echo "Linking..."
@echo "Linking..."
@aarch64-none-elf-ld -o kernel_2712.elf -Map kernel_2712.map -nostdlib
@aarch64-none-elf-ld -o kernel_2712.elf -Map kernel_2712.map -nostdlib \
--section-start=.init=$(LOADADDR) --no-warn-rwx-segments
--section-start=.init=$(LOADADDR) --no-warn-rwx-segments \
-g -T linker.ld $(AllOBJS)
-g -T linker.ld $(AllOBJS)
aarch64-none-elf-objcopy -O binary kernel_2712.elf kernel_2712.img
aarch64-none-elf-objcopy -O binary kernel_2712.elf kernel_2712.img


clean:
clean:
/bin/rm -f kernel_2712.elf *.o *.img > /dev/null 2> /dev/null || true
/bin/rm -f kernel_2712.elf *.o *.img > /dev/null 2> /dev/null || true


new:
new:
/bin/clear
/bin/clear
</syntaxhighlight>
</syntaxhighlight>


Zeile 76: Zeile 76:
SECTIONS
SECTIONS
{
{
.init : {
.init : {
(.init)
*(.init)
}
}
.text : {
.text : {
(.text)
*(.text*)
_etext = .;
_etext = .;
}
}
.rodata : {
.rodata : {
(.rodata)
*(.rodata*)
}
}
.init_array : {
.init_array : {
__init_start = .;
__init_start = .;
KEEP((.init_array*))
KEEP(*(.init_array*))
__init_end = .;
__init_end = .;
}
}
.ARM.exidx : {
.ARM.exidx : {
__exidx_start = .;
__exidx_start = .;
(.ARM.exidx)
*(.ARM.exidx*)
__exidx_end = .;
__exidx_end = .;
}
}
.eh_frame : {
.eh_frame : {
(.eh_frame)
*(.eh_frame*)
}
}
.data : {
.data : {
(.data)
*(.data*)
}
}
.bss : {
.bss : {
__bss_start = .;
__bss_start = .;
(.bss)
*(.bss*)
*(COMMON)
*(COMMON)
__bss_end = .;
__bss_end = .;
}
}
}
}
__bss_size = (__bss_end - __bss_start) >> 3;
__bss_size = (__bss_end - __bss_start) >> 3;
</syntaxhighlight>
</syntaxhighlight>
Name this file "linker.ld".
Name this file "linker.ld".
=== Explanation of the Linker Script ===
=== Explanation of the Linker Script ===
'''ENTRY(_start)''': Defines the entry point of the program.
'''ENTRY(_start)''': Defines the entry point of the program.


'''SECTIONS''': Defines the various sections of the program and their memory locations.
'''SECTIONS''': Defines the various sections of the program and their memory locations.
-----
{| style="width: 100%;
| style="width: 33%;" | [[Running the Program on the Raspberry Pi 5|< Back (Running the Program on the Raspberry Pi 5)]]
| style="width: 33%; text-align:center;" | [[English|< Home >]]
| style="width: 33%; text-align:right;" | [[Our First Program (PI5)|Next (Our First Program in Assembly (PI5)) >]] <br /> [[Our First Program in C (PI5)|Next (Our First Program in C (PI5)) >]]
|}

Aktuelle Version vom 23. August 2024, 11:12 Uhr

In this section, we will learn how to develop an operating system on the Raspberry Pi 5 by creating multiple source files and linking them with a linker. We will also use a Makefile to automate the build process. Additionally, we will cover C and C++.

Creating a Makefile

A Makefile helps us automate the build process and keep track of our files. Here is an example Makefile:

CSRCS := $(wildcard *.c)
CPPSRCS := $(wildcard *.cpp)
ASRCS := $(wildcard *.S)
COBJS := $(CSRCS:.c=.o)
CPPOBJS := $(CPPSRCS:.cpp=.o)
AOBJS := $(ASRCS:.S=.o)
AllOBJS := $(COBJS) $(CPPOBJS) $(AOBJS)
LOADADDR = 0x80000

GCCFLAGS = -mcpu=cortex-a76 -mlittle-endian -Wall -O0 -ffreestanding \
           -nostartfiles -nostdlib -nostdinc -g -I ./include

AFLAGS = -mcpu=cortex-a76 -mlittle-endian  -I ./include -O0 -g

CFLAGS = -mcpu=cortex-a76 -mlittle-endian -Wall -fsigned-char -ffreestanding -g \
         -I ./include -O0 -fno-exceptions 

CPPFLAGS = -fno-exceptions -fno-rtti -nostdinc++ -mcpu=cortex-a76 -mlittle-endian -Wall -fsigned-char \
			  -ffreestanding -g -I ./include -O0 -mstrict-align -std=c++14 -Wno-aligned-new

all: clean new kernel_2712.img

%.o: %.S
	@echo "as $@"
	@aarch64-none-elf-gcc $(AFLAGS) -c $< -o $@

%.o: %.c
	@echo "gcc $@"
	@aarch64-none-elf-gcc $(CFLAGS) -c $< -o $@

%.o: %.cpp
	@echo "g++ $@"
	@aarch64-none-elf-g++ $(CPPFLAGS) -c $< -o $@

kernel_2712.img: $(AllOBJS)
	@echo "============================================================================="
	@echo "Linking..."
	@aarch64-none-elf-ld -o kernel_2712.elf -Map kernel_2712.map -nostdlib \
		--section-start=.init=$(LOADADDR) --no-warn-rwx-segments \
		-g -T linker.ld $(AllOBJS)
	aarch64-none-elf-objcopy -O binary kernel_2712.elf kernel_2712.img

clean:
	/bin/rm -f kernel_2712.elf *.o *.img > /dev/null 2> /dev/null || true

new:
	/bin/clear

Explanation of the Makefile

Defining Variables: The first lines of the Makefile define variables containing the source files (C, C++, and Assembly) and their object files.

Compiler Flags: The flags "GCCFLAGS", "AFLAGS", "CFLAGS", and "CPPFLAGS" contain the compiler options for the various file types.

Build Targets:

all: This target deletes old files (clean), clears the screen (new), and builds the kernel (kernel_2712.img).

%.o: %.S, %.o: %.c, %.o: %.cpp: These rules define how to compile Assembly, C, and C++ source code into object files.

kernel_2712.img: This target links all object files and creates the final binary file kernel_2712.img.

clean: Deletes all generated files.

new: Clears the screen.

The Linker Script

A linker script determines how the linker arranges the various sections of the program in memory. Here is an example of a linker script:

ENTRY(_start)

SECTIONS
{
	.init : {
		*(.init)
	}
	.text : {
		*(.text*)
		_etext = .;
	}
	.rodata : {
		*(.rodata*)
	}
	.init_array : {
		__init_start = .;
		KEEP(*(.init_array*))
		__init_end = .;
	}
	.ARM.exidx : {
		__exidx_start = .;
		*(.ARM.exidx*)
		__exidx_end = .;
	}
	.eh_frame : {
		*(.eh_frame*)
	}
	.data : {
		*(.data*)
	}
	.bss : {
		__bss_start = .;
		*(.bss*)
		*(COMMON)
		__bss_end = .;
	}
}
__bss_size = (__bss_end - __bss_start) >> 3;

Name this file "linker.ld".

Explanation of the Linker Script

ENTRY(_start): Defines the entry point of the program.

SECTIONS: Defines the various sections of the program and their memory locations.


< Back (Running the Program on the Raspberry Pi 5) < Home > Next (Our First Program in Assembly (PI5)) >
Next (Our First Program in C (PI5)) >