I'm compiling a c file in xv6 and I used their Makefile to compile. I used readelf and found out the ELF it outputs has just one program header.
ryan#ubuntu:~/Documents/xv6-OS-for-arm-v8-fixed/xv6-armv8/usr$ readelf -l _init --wide
Elf file type is EXEC (Executable file)
Entry point 0x0
There is 1 program header, starting at offset 64
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000078 0x0000000000000000 0x0000000000000000 0x0011a8 0x0011c0 RWE 0x8
Section to Segment mapping:
Segment Sections...
00 .text .rodata .data .bss
This program header has just 4 sections: .text .rodata .data .bss
I checked its CFLAGS and it's showed below:
CROSSCOMPILE := aarch64-none-elf-
# try linux eabi
# CROSSCOMPILE := arm-linux-gnueabi-
CC = $(CROSSCOMPILE)gcc
AS = $(CROSSCOMPILE)as
LD = $(CROSSCOMPILE)ld
OBJCOPY = $(CROSSCOMPILE)objcopy
OBJDUMP = $(CROSSCOMPILE)objdump
CFLAGS = -march=armv8-a -mtune=cortex-a57 -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -I. -g
LDFLAGS = -L.
ASFLAGS = -march=armv8-a
But I don't know which of these flags make it this way.
I'm build a ARM-based OS. How can I compile one of this ELF in ARM by myself?
I'm writing my own OS. But in the tutorial (https://github.com/AlgorithMan-de/wyoos/commit/7eb9f8a1d5089cf7587e553e601c42db34dc94a2) he is writing it for i386 arch with x86_32. But now I want to change it to x86_64.
Now I have to replace a few things in the Makefile and in the Linker (like the OUTPUT_ARCH()) but I don't now what I should write there instead.
linker.ld
ENTRY(loader)
OUTPUT_FORMAT(elf32-i386)
OUTPUT_ARCH(i386:i386)
SECTIONS
{
. = 0x0100000;
.text :
{
*(.multiboot)
*(.text*)
*(.rodata)
}
.data :
{
start_ctors = .;
KEEP(*( .init_array ));
KEEP(*(SORT_BY_INIT_PRIORITY( .init_array.* )));
end_ctors = .;
*(.data)
}
.bss :
{
*(.bss)
}
/DISCARD/ : { *(.fini_array*) *(.comment) }
}
Makefile
GCCPARAMS = -m32 -fno-use-cxa-atexit -nostdlib -fno-builtin -fno-rtti -fno-exceptions -fno-leading-underscore
ASPARAMS = --32
LDPARAMS = -melf_i386
objects = loader.o kernel.o
%.o: %.cpp
gcc $(GCCPARAMS) -c -o $# $<
%.o: %.s
as $(ASPARAMS) -o $# $<
mykernel.bin: linker.ld $(objects)
ld $(LDPARAMS) -T $< -o $# $(objects)
install: mykernel.bin
sudo cp $< /boot/mykernel.bin
EDIT
I have now edited the Makefile and the linker.ld
Makefile
GCCPARAMS = -m64 -fno-use-cxa-atexit -nostdlib -fno-builtin -fno-rtti -fno-exceptions -fno-leading-underscore
ASPARAMS = --64
LDPARAMS = -melf_x86_64
objects = loader.o kernel.o
%.o: %.cpp
gcc $(GCCPARAMS) -c -o $# $<
%.o: %.s
as $(ASPARAMS) -o $# $<
mykernel.bin: linker.ld $(objects)
ld $(LDPARAMS) -T $< -o $# $(objects)
install: mykernel.bin
sudo cp $< /boot/mykernel.bin
linker.ld
ENTRY(loader)
OUTPUT_FORMAT(elf64-x86-64)
OUTPUT_ARCH(i386:x86-64)
SECTIONS
{
. = 0x0100000;
.text :
{
*(.multiboot)
*(.text*)
*(.rodata)
}
.data :
{
start_ctors = .;
KEEP(*( .init_array ));
KEEP(*(SORT_BY_INIT_PRIORITY( .init_array.* )));
end_ctors = .;
*(.data)
}
.bss :
{
*(.bss)
}
/DISCARD/ : { *(.fini_array*) *(.comment) }
}
But when I try to compile it (ld -melf_x86_64 -T linker.ld -o mykernel.bin loader.o kernel.o), I get an error:
ld: loader.o: in function 'loader':
(.text+0x6): undefined reference to 'eax'
ld: (.text+0xb): undefined reference to 'ebx'
ld: (.text+0x20): undefined reference to 'kernelMain'
I think I have to install a binutil but I don't know which one.
Can someone help me finding the right one?
I've got some Errors while running the Makefile. I am currently using MacOS Mojave, and got some weird errors and I am not able to understand them. The Makefile hadn't work at all, there was an error in ASPARAMS = -m32 (before that it was ASPARAMS= --32 {didn't work}. Now the Makefile has no errors but a other file does. Here is the code of the Makefile:
GPPPARAMS = -m32 -fno-use-cxa-atexit -nostdlib -fno-builtin -fno-rtti -fno-exceptions -fno-leading-underscore
ASPARAMS = -m32
LDPARAMS = -melf_i386
objects = loader.o kernel.o
%.o: %.cpp
g++ $(GPPPARAMS) -o $# -c $<
%.o: %.s
as $(ASPARAMS) -o $# $<
mykernel.bin: linker.ld $(objects)
ld $(LDPARAMS) -T $< -o $# $(objects)
install: mykernel.bin
sudo cp $< /boot/mykernel.bin
mykernel.iso: mykernel.bin
mkdir iso
mkdir iso/boot
mkdir iso/boot/grub
cp $< iso/boot/
echo 'set timeout-0' >> iso/boot/grub/grub.cfg
echo 'set default-0' >> iso/boot/grub/grub.cfg
echo 'menuentry "My Operating System"{' >> iso/boot/grub/grub.cfg
echo ' multiboot /boot/mykernel.bin' >> iso/boot/grub/grub.cfg
echo ' boot' >> iso/boot/grub/grub.cfg
echo '}' >> iso/boot/grub/grub.cfg
grub-mkrescue --output=$# iso
rm -rf iso
run: mykernel.iso
(killall VirtualBox && sleep 1) || true
VirtualBox --startvm "My Operating System" &
Here are the errors:
loader.s:5:20: error: unexpected token in '.section' directive
.section .multiboot
^
loader.s:12:15: error: unexpected token in '.section' directive
.section .text
^
loader.s:29:15: error: unexpected token in '.section' directive
.section .bss
^
make: *** [loader.o] Error 1
And here is the file were the errors appear:
.set MAGIC, 0x1badb002
.set FLAGS, (1<<0 | 1<<1)
.set CHECKSUM, -(MAGIC + FLAGS)
.section .multiboot
.long MAGIC
.long FLAGS
.long CHECKSUM
.section .text
.extern kernelMain
.extern callConstructors
.global loader
loader:
mov $kernel_stack, %esp
call callConstructors
push %eax
push %ebx
call kernelMain
_stop:
cli
hlt
jmp _stop
.section .bss
.space 2*1024*1024;
kernel_stack:
I have following makefile executed by python script:
SOURCES_DIRECTORY = sources
# These directories should be created by build.py script
BUILD_DIRECTORY = builds
OBJECTS_DIRECTORY = objs
CORE = cortex-m4
LINKER_SCRIPT = linker_rom.ld
# C definitions
ifeq ($(RAM_FLASH), 1)
C_DEFS = -DRAM_FLASH
else
C_DEFS =
endif
INC_DIRS = sources
SRCS_DIRS = sources
# extension of C files
C_EXT = c
# wildcard for C source files (all files with C_EXT extension found in current
# folder and SRCS_DIRS folders will be compiled and linked)
C_SRCS = $(wildcard $(patsubst %, %/*.$(C_EXT), . $(SRCS_DIRS)))
# extension of ASM files
AS_EXT = s
# wildcard for ASM source files (all files with AS_EXT extension found in
# current folder and SRCS_DIRS folders will be compiled and linked)
AS_SRCS = $(wildcard $(patsubst %, %/*.$(AS_EXT), . $(SRCS_DIRS)))
# optimization flags ("-O0" - no optimization, "-O1" - optimize, "-O2" -
# optimize even more, "-Os" - optimize for size or "-O3" - optimize yet more)
OPTIMIZATION = -Og
# set to 1 to optimize size by removing unused code and data during link phase
REMOVE_UNUSED = 1
C_WARNINGS = -Wall -Wextra -Werror
# C language standard ("c89" / "iso9899:1990", "iso9899:199409",
# "c99" / "iso9899:1999", "gnu89" - default, "gnu99")
C_STD = c99
VPATH = $(SRCS_DIRS)
#============================================#
# Toolchain Configuration #
#============================================#
TOOLCHAIN = arm-none-eabi-
CXX = $(TOOLCHAIN)g++
CC = $(TOOLCHAIN)gcc
AS = $(TOOLCHAIN)gcc -x assembler-with-cpp
OBJCOPY = $(TOOLCHAIN)objcopy
OBJDUMP = $(TOOLCHAIN)objdump
SIZE = $(TOOLCHAIN)size
RM = rm -f
.PHONY: all clean
#=============================================================================#
# various compilation flags
#=============================================================================#
# core flags
CORE_FLAGS = -mcpu=$(CORE) -mthumb -specs=nano.specs -specs=nosys.specs -mfpu=fpv4-sp-d16 -mfloat-abi=hard
# flags for C compiler
C_FLAGS = -std=$(C_STD) -g -ggdb3 -fverbose-asm -Wa,-ahlms=$(OBJECTS_DIRECTORY)/$(notdir $(<:.$(C_EXT)=.lst)) -DSTM32F429xx $(FLAGS)
# flags for assembler
AS_FLAGS = -g -ggdb3 -Wa,-amhls=$(OBJECTS_DIRECTORY)/$(notdir $(<:.$(AS_EXT)=.lst)) $(FLAGS)
# flags for linker
LD_FLAGS = -T$(LINKER_SCRIPT) -g -Wl,-Map=$(OBJECTS_DIRECTORY)/test.map,--cref,--no-warn-mismatch
# process option for removing unused code
ifeq ($(REMOVE_UNUSED), 1)
LD_FLAGS += -Wl,--gc-sections
OPTIMIZATION += -ffunction-sections -fdata-sections
endif
LIBS = libmylib.a
LIB_DIRS = ./sources
#=============================================================================#
# do some formatting
#=============================================================================#
C_OBJS = $(addprefix $(OBJECTS_DIRECTORY)/, $(notdir $(C_SRCS:.$(C_EXT)=.o)))
AS_OBJS = $(addprefix $(OBJECTS_DIRECTORY)/, $(notdir $(AS_SRCS:.$(AS_EXT)=.o)))
OBJS = $(AS_OBJS) $(C_OBJS) $(CXX_OBJS) $(USER_OBJS)
DEPS = $(OBJS:.o=.d)
INC_DIRS_F = -I. $(patsubst %, -I%, $(INC_DIRS))
LIB_DIRS_F = $(patsubst %, -L%, $(LIB_DIRS))
ELF = $(BUILD_DIRECTORY)/$(NAME).elf
HEX = $(BUILD_DIRECTORY)/$(NAME).hex
BIN = $(BUILD_DIRECTORY)/$(NAME).bin
LSS = $(BUILD_DIRECTORY)/$(NAME).lss
DMP = $(BUILD_DIRECTORY)/$(NAME).dmp
# format final flags for tools, request dependancies for C++, C and asm
C_FLAGS_F = $(CORE_FLAGS) $(OPTIMIZATION) $(C_WARNINGS) $(C_FLAGS) $(C_DEFS) -MD -MP -MF $(OBJECTS_DIRECTORY)/$(#F:.o=.d) $(INC_DIRS_F)
AS_FLAGS_F = $(CORE_FLAGS) $(AS_FLAGS) $(AS_DEFS) -MD -MP -MF $(OBJECTS_DIRECTORY)/$(#F:.o=.d) $(INC_DIRS_F)
LD_FLAGS_F = $(CORE_FLAGS) $(LD_FLAGS) $(LIB_DIRS_F)
#contents of output directory
GENERATED = $(wildcard $(patsubst %, $(BUILD_DIRECTORY)/*.%, bin d dmp elf hex lss lst map o))
#=============================================================================#
# make all
#=============================================================================#
all : $(ELF) $(LSS) $(DMP) $(HEX) $(BIN)
# make object files dependent on Makefile
$(OBJS) : $(MAKEFILE_NAME)
# make .elf file dependent on linker script
$(ELF) : $(LINKER_SCRIPT)
#-----------------------------------------------------------------------------#
# linking - objects -> elf
#-----------------------------------------------------------------------------#
$(ELF) : $(OBJS)
$(CC) $(LD_FLAGS_F) $(OBJS) $(LIBS) -o $#
#-----------------------------------------------------------------------------#
# compiling - C source -> objects
#-----------------------------------------------------------------------------#
objs/%.o : %.$(C_EXT)
$(CC) -c $(C_FLAGS_F) $< -o $#
#-----------------------------------------------------------------------------#
# assembling - ASM source -> objects
#-----------------------------------------------------------------------------#
objs/%.o : %.$(AS_EXT)
$(AS) -c $(AS_FLAGS_F) $< -o $#
#-----------------------------------------------------------------------------#
# memory images - elf -> hex, elf -> bin
#-----------------------------------------------------------------------------#
$(HEX) : $(ELF)
$(OBJCOPY) -O ihex $< $#
$(BIN) : $(ELF)
$(OBJCOPY) -O binary $< $#
#-----------------------------------------------------------------------------#
# memory dump - elf -> dmp
#-----------------------------------------------------------------------------#
$(DMP) : $(ELF)
$(OBJDUMP) -x --syms $< > $#
#-----------------------------------------------------------------------------#
# extended listing - elf -> lss
#-----------------------------------------------------------------------------#
$(LSS) : $(ELF)
$(OBJDUMP) -S $< > $#
# include dependancy files
-include $(DEPS)
This is the project tree
-> /sources/
-> /sources/libmylib.a
-> /makefile
I thought adding
LIBS = libmylib.a
LIB_DIRS = ./sources
will solve the problem. My lib is libmylib.a file. However console still outputs the errors with undefined references to functions. What should I change?
Path to the directories with sources, objects, headers and flags are passed dynamically by the python script as arguments.
It should be:
LIBS = -lmylib
The compiler will prepend lib and append .a to the libraries you specify, making it look for a library file named libmylib.a which is what you want.
This is my makefile:
OBJECTS = main.o
CFLAGS = -g -wall
NAME = make
CC = gcc
build: $(OBJECTS)
$(CC) $(CFLAGS) $(OBJECTS) -o $(NAME)
I'm getting below error when I tried to make(Applied tab before gcc command) :
makefile:6: *** missing separator. Stop.
How can I fix this?
First of all, it looks like you have spaces instead of tab.
As for the Makefile itself, I'd make it little bit simpler. For a source file main.c:
int main() {
return 0;
}
I would go with Makefile:
CFLAGS = -g -wall
CC = gcc
main: main.c
$(CC) $(CFLAGS) $< -o $#