Use PIE format for user program

This commit is contained in:
Yann MAGNIN 2020-03-18 17:48:53 +01:00
parent da5ff236bb
commit 67201cd226
12 changed files with 4220 additions and 131 deletions

View File

@ -3,6 +3,7 @@
# Tools
COMPILER := sh3eb-elf-
CC := $(COMPILER)gcc
LD := $(COMPILER)ld
OBJCOPY := $(COMPILER)objcopy
OBJDUMP := $(COMPILER)objdump
WRAPPER := g1a-wrapper

View File

@ -11,5 +11,6 @@
extern int loader(struct process *process, const char *path);
extern int loader_get_header(FILE *file, Elf32_Ehdr *header);
extern int loader_load_image(struct process *process, FILE *file, Elf32_Ehdr *header);
extern int loader_reloc_sym(struct process *process, FILE *file, Elf32_Ehdr *header);
#endif /*__KERNEL_LOADER_H__*/

File diff suppressed because it is too large Load Diff

View File

@ -4,6 +4,20 @@
#include <stddef.h>
#include <stdint.h>
// CMDBLOCK()
// Generate a "command block" stored in ".cmd.cahce" section.
// We need to "hide" the block, so we generate anonyme name using
// __COUNTER__ macros.
#define gen_name(n) _##n
#define anonym_name(n) gen_name(n)
#define VHEX_BUILTIN(builtin) \
static int builtin(int argc, char **argv); \
__attribute__((section(".builtin.cache"))) \
static const struct builtin_s anonym_name(__COUNTER__) = { \
.name = #builtin, \
.entry = builtin \
}; \
static int builtin(int argc, char **argv)
// Define builtin struct.
struct builtin_s
@ -13,8 +27,8 @@ struct builtin_s
};
// Builtin list
extern int builtin_proc(void);
extern int builtin_ram(void);
//extern int builtin_proc(void);
//extern int builtin_ram(void);
#endif /*__USER_BUILTIN_H__*/

View File

@ -39,5 +39,13 @@ int loader(struct process *process, const char *path)
DBG_WAIT;
return (-3);
}
// Relocalise sections / symbols
if (loader_reloc_sym(process, &file, &header) != 0)
{
earlyterm_write("loader: ELF relo error !");
DBG_WAIT;
return (-4);
}
return (0);
}

View File

@ -9,28 +9,28 @@ int loader_get_header(FILE *file, Elf32_Ehdr *header)
return (-1);
// Check magic number
if (header->e_ident[EI_MAG0] != 0x7f ||
header->e_ident[EI_MAG1] != 'E' ||
header->e_ident[EI_MAG2] != 'L' ||
header->e_ident[EI_MAG3] != 'F')
if (header->e_ident[EI_MAG0] != ELFMAG0 ||
header->e_ident[EI_MAG1] != ELFMAG1 ||
header->e_ident[EI_MAG2] != ELFMAG2 ||
header->e_ident[EI_MAG3] != ELFMAG3)
return (-2);
// Check class
if (header->e_ident[EI_CLASS] != 1)
if (header->e_ident[EI_CLASS] != ELFCLASS32)
return (-3);
//TODO: Check OSABI (?)
// Check ELF type.
if (header->e_type != ET_EXEC)
if (header->e_type != ET_DYN)
return (-4);
// Check ELF specifique instruction
if (header->e_machine != 0x2A)
if (header->e_machine != EM_SH)
return (-5);
// Check ELF version
if (header->e_version != 0x01)
if (header->e_version != EV_CURRENT)
return (-6);
return (0);
}

View File

@ -0,0 +1,107 @@
#include <kernel/loader.h>
#include <kernel/devices/earlyterm.h>
#include <kernel/memory.h>
#include <kernel/fs/vfs.h>
static char *get_shstrtab(FILE *file, Elf32_Ehdr *header)
{
Elf32_Shdr shdr;
char *shstrtab;
// Get sections string header tables
vfs_lseek(file, header->e_shoff + (header->e_shstrndx * sizeof(shdr)), SEEK_SET);
if (vfs_read(file, &shdr, sizeof(shdr)) != sizeof(shdr))
{
earlyterm_write("loader_relo_sym: section header table error\n");
return (NULL);
}
// Allocate dump area
shstrtab = (char*)pm_alloc(shdr.sh_size);
if (shstrtab == NULL)
{
earlyterm_write("loader_relo_sym: memory error\n");
return (NULL);
}
// Get string tables
vfs_lseek(file, shdr.sh_offset, SEEK_SET);
if (vfs_read(file, shstrtab, shdr.sh_size) != (ssize_t)shdr.sh_size)
{
earlyterm_write("loader_relo_sym: shstrtab size error\n");
pm_free(shstrtab);
return (NULL);
}
return (shstrtab);
}
static int reloc_section(struct process *process, FILE *file, Elf32_Shdr *shdr)
{
Elf32_Rela rela;
uint32_t *prog;
// List symbols
prog = (void*)process->memory.program.start;
for (uint32_t i = 0 ; i < shdr->sh_size / shdr->sh_entsize ; ++i)
{
// Get relocatable entry
vfs_lseek(file, shdr->sh_offset + (i * sizeof(rela)), SEEK_SET);
if (vfs_read(file, &rela, sizeof(rela)) != sizeof(rela))
{
earlyterm_write("reloc_section: reloc section size error\n");
return (-1);
}
// Relocalise symbols
//earlyterm_write("* [%d] %p, %#x\n", i, rela.r_offset, rela.r_addend);
prog[rela.r_offset >> 2] = rela.r_addend + process->memory.program.start;
//DBG_WAIT;
}
return (0);
}
int loader_reloc_sym(struct process *process, FILE *file, Elf32_Ehdr *header)
{
Elf32_Shdr shdr;
char *shstrtab;
//TODO
(void)process;
// DEBUG
//earlyterm_write("e_shnum = %d\n", header->e_shnum);
//earlyterm_write("e_shstrndx = %d\n", header->e_shstrndx);
// Get the shstrtab
shstrtab = get_shstrtab(file, header);
if (shstrtab == NULL)
return (-1);
// List header tables
for (int i = 1 ; i < header->e_shnum ; ++i)
{
// Get next section header
vfs_lseek(file, header->e_shoff + (i * sizeof(shdr)), SEEK_SET);
if (vfs_read(file, &shdr, sizeof(shdr)) != sizeof(shdr))
{
earlyterm_write("loader_reloc_sym: section header\n");
return (-2);
}
// Check relocatable sections
if (shdr.sh_type != SHT_RELA)
continue;
// Diplay section name
earlyterm_write("[%d] %s - %d\n", i, &shstrtab[shdr.sh_name], shdr.sh_size / shdr.sh_entsize);
if (reloc_section(process, file, &shdr) != 0)
return (-3);
}
pm_free(shstrtab);
//earlyterm_write("start = %p\n", process->memory.program.start);
//DBG_WAIT;
//DBG_WAIT;
//DBG_WAIT;
return (0);
}

View File

@ -45,9 +45,7 @@ OBJ := $(patsubst ._%,$(BUILD)/%.o,$(subst /,_,$(subst src/,,$(basename $(SRC)))
all: $(EXEC)
$(EXEC): $(OBJ) | $(DEBUG)
$(CC) -fPIC -Wl,-M $(LDFLAG) $(CFLAGS) -o $(DEBUG)/$(NAME).elf.big $(OBJ) $(HEADER) $(LIBS) > $(MEMORY_MAP)
$(OBJCOPY) -S $(DEBUG)/$(NAME).elf.big $@
rm -f $(DEBUG)/$(NAME).elf.big
$(CC) -pie -Wl,-M $(LDFLAG) $(CFLAGS) -o $@ $(OBJ) $(HEADER) $(LIBS) > $(MEMORY_MAP)
$(BUILD) $(DEBUG):
@ printf "Create $(blue)$@$(nocolor) directory\n"
@ -77,7 +75,7 @@ sec:
define rule-src
$(patsubst ._%,$(BUILD)/%.o,$(subst /,_,$(subst src/,,$(basename $1)))): $1 | $(BUILD)
@ printf "compiling $(white)$$<$(nocolor)..."
@ $(CC) -fPIC $(CFLAGS) -o $$@ -c $$< $(HEADER) -lgcc
@ $(CC) -pie $(CFLAGS) -o $$@ -c $$< $(HEADER) -lgcc
@ printf "$(green)[ok]$(nocolor)\n"
endef

View File

@ -1,4 +1,4 @@
/*#include "builtin.h"
#include "builtin.h"
#include <lib/display.h>
VHEX_BUILTIN(fxdb)
@ -7,9 +7,9 @@ VHEX_BUILTIN(fxdb)
(void)argc;
(void)argv;
dclear();
dprint(0, 0, "FXDB - entry !!");
dupdate();
//dclear();
//dprint(0, 0, "FXDB - entry !!");
//dupdate();
for (int i = 0 ; i < 9000000 ; i = i + 1);
return (0);
@ -32,5 +32,5 @@ VHEX_BUILTIN(fxdb)
// Power OFF UBC module.
// ubc_close();
return (0);
}*/
// return (0);
}

View File

@ -2,10 +2,6 @@
#include <lib/unistd.h>
#include "util.h"
// @note
// For now all kernel invocation is
// made by the `unistd` library.
//TODO: documentation.
int main(void)
{
@ -40,7 +36,7 @@ int main(void)
__asm__ volatile ("sleep");
}
}
// Shell main loop.
write(fd, "Boot Complete !\n", 16);
while (1)
@ -54,11 +50,14 @@ int main(void)
input[cmd_size - 1] = '\0';
// Check buit-in.
//if (check_builtin(input) != 0)
//{
if (check_builtin(input) != 0)
{
write(fd, input, cmd_size - 1);
write(fd, ": command not found\n", 20);
//}
} else {
write(fd, input, cmd_size - 1);
write(fd, ": command found :D !\n", 21);
}
}
return (0);
}

View File

@ -1,5 +1,5 @@
OUTPUT_FORMAT("elf32-sh", "elf32-sh", "elf32-sh")
OUTPUT_ARCH(sh3)
OUTPUT_FORMAT(elf32-sh)
ENTRY(_main)
/*
@ -11,26 +11,57 @@ MEMORY
userram (WX) : o = 0x00000000, l = 256k
}
PHDRS
{
text PT_LOAD ;
data PT_LOAD ;
}
SECTIONS
{
/* Read-only sections */
.text : {
/* Code */
*(.text);
*(.text.*);
} : text
.rodata : {
/* Read-Only data */
*(.rodata);
*(.rodata.*);
}
/* Dynamic symbols */
*(.hash)
*(.dynsym)
*(.dynstr)
*(.dynbss)
*(.dynamic)
/* Procedure Linkage Table */
*(.plt)
/* GLobal Offset Table */
*(.got.plt)
*(.got.*)
*(.got)
/* ???? */
*(.rofixup)
/* Internal builtin cache */
PROVIDE (_builtin_list = ALIGN(4));
*(.builtin)
*(.builtin.*)
PROVIDE (_builtin_list_end = . );
} > userram
/* Relocatable sections */
.rela.dyn : {
*(.rela.plt)
*(.rela.got)
*(.rela.got.*)
*(.rela.*)
*(.rela.text)
*(.real.data)
} > userram
/* readable / writable data */
.data ALIGN(4) : {
*(.plt);
/* Data sections */
*(.data);
*(.data.*);
@ -38,18 +69,11 @@ SECTIONS
*(.bss);
*(.bss.*);
*(COMMON);
} : data
.relocgot : {
BRELOC_GOT = . ;
*(.got.plt)
*(.got)
ERELOC_GOT = . ;
}
} > userram
/* unwanted section */
/DISCARD/ : {
*(.gnu.*)
*(.debug_info)
*(.debug_abbrev)
*(.debug_loc)
@ -61,5 +85,6 @@ SECTIONS
*(.eh_frame_hdr)
*(.eh_frame)
*(.comment)
*(.interp)
}
}

View File

@ -7,20 +7,46 @@
// Internal builtin list
// FIXME: due to PIE binary format, we can not
// FIXME: use address of builtin_proc !!
/*struct builtin_s list[1] = {
struct builtin_s builtin[2] = {
{
.name = "proc",
.entry = (void*)&builtin_proc
.entry = NULL
},
//{
// .name = "ram",
// .entry = (void *)&builtin_ram
//}
};*/
{
.name = "ram",
.entry = NULL
}
};
//TODO: use agc, argv.
int check_builtin(char *cmd)
{
/* extern struct builtin_s *builtin_list;
extern struct builtin_s *builtin_list_end;
int i;
// Try to find builtin
i = -1;
while (&builtin_list[++i] < builtin_list_end)
{
// Check builtin name
if (strcmp(builtin_list[i].name, cmd) != 0)
continue;
// Execute builtin
builtin_list[i].entry(0, NULL);
return (0);
}*/
for (int i = 0 ; i < 2 ; ++i) {
if (strcmp(builtin[i].name, cmd) != 0)
continue;
if (builtin[i].entry != NULL)
(*builtin[i].entry)(0, NULL);
return (0);
}
return (-1);
// Process test
/* dclear();
@ -56,11 +82,11 @@ int check_builtin(char *cmd)
// Try to find builtin
/* for (int i = 0 ; i < 1 ; i++)
{
if (strcmp(list[i].name, cmd) != 0)
if (strcmp(builtin[i].name, cmd) != 0)
continue;
// Execute builtin
list[i].entry(0, NULL);
builtin[i].entry(0, NULL);
return (0);
}*/
return (-1);