towards multi-arch

This commit is contained in:
Christian Dietrich
2021-08-16 10:59:38 +02:00
parent 39c0e0681e
commit a3fa6ea4ab
19 changed files with 488 additions and 38 deletions

View File

@ -1,42 +1,70 @@
FAIL_DIR ?= ~/fail FAIL_DOWNLOAD_BASE="https://collaborating.tuhh.de/e-exk4/projects/fail/-/jobs/artifacts/feature/sail/download"
FAIL_BIN ?= ${FAIL_DIR}/build/bin
BOCHS_RUNNER ?= python ${FAIL_DIR}/tools/bochs-experiment-runner/bochs-experiment-runner.py ARCH ?= bochs
all: help
BUILD_DIR := build-${ARCH}
FAIL_BIN ?= ${BUILD_DIR}/bin
BOCHS_RUNNER ?= ${FAIL_BIN}/bochs-experiment-runner
FAIL_SERVER ?= ${FAIL_BIN}/generic-experiment-server FAIL_SERVER ?= ${FAIL_BIN}/generic-experiment-server
FAIL_TRACE ?= ${FAIL_BIN}/fail-generic-tracing FAIL_TRACE ?= ${FAIL_BIN}/fail-generic-tracing
FAIL_INJECT ?= ${FAIL_BIN}/fail-generic-experiment FAIL_INJECT ?= ${FAIL_BIN}/fail-generic-experiment
FAIL_IMPORT ?= ${FAIL_BIN}/import-trace --enable-sanitychecks FAIL_IMPORT ?= ${FAIL_BIN}/import-trace --enable-sanitychecks
FAIL_PRUNE ?= ${FAIL_BIN}/prune-trace FAIL_PRUNE ?= ${FAIL_BIN}/prune-trace
EXPERIMENTS := $(patsubst %.c,%,$(shell echo *.c))
all: main/system.iso CFLAGS := -I. -include arch/${ARCH}/lib.c -O2 -std=c11
include arch/${ARCH}.mk
$(foreach element,$(EXPERIMENTS),$(eval $(call arch-make-targets,$(element))))
help:
@echo "Small Playground for FAIL* Injections"
@echo "-------------------------------------"
@echo "Architecture Unspecific Targets:"
@echo " \e[3mdocker\e[0m Start a Docker container with all dependencies"
@echo " \e[3mdownload\e[0m Download Precompiled FAIL* client"
@echo ""
@echo "Current Configuartion"
@echo " ARCH=${ARCH}"
docker:
@echo Starting Docker with ARCH=$(ARCH)
docker run \
-v ${PWD}:/home/fail/fail \
-e ARCH=${ARCH} \
-w /home/fail/fail \
-it danceos/fail-ci-build
################################################################
# Download
download: ${BUILD_DIR}/bin/fail-client
${BUILD_DIR}/bin/fail-client:
mkdir -p ${BUILD_DIR}/bin
wget ${FAIL_DOWNLOAD_URL} -O ${BUILD_DIR}/bin/fail.zip
cd ${BUILD_DIR}/bin/ && unzip fail.zip && mv build/bin/* . && rm -rf build
%/system.elf: %/system.o startup.o clean:
${CC} -Wl,-T linker.ld $^ -m32 -static -nostdlib -Wl,--build-id=none -o $@ @rm -rf build
%/system.o: %.c clean-%:
mkdir -p $(shell dirname $@) @rm -rf ${BUILD_DIR}/$(patsubst build-%,%,$@)
${CC} $< -o $@ -O2 -std=c11 -m32 -c -ffunction-sections
startup.o: startup.s build-%:
${CC} startup.s -m32 -c -o startup.o -ffunction-sections
%/system.iso: %/system.elf
rm -rf $(shell dirname $<)/grub
mkdir -p $(shell dirname $<)/grub/boot/grub
cp grub.cfg $(shell dirname $<)/grub/boot/grub
cp $< $(shell dirname $<)/grub/boot/system.elf
grub-mkrescue -o $@ $(shell dirname $<)/grub
@echo "****************************************************************\n\ @echo "****************************************************************\n\
* The next step is to trace a golden run. The golden run executes the\n\ * The next step is to trace a golden run. The golden run executes the\n\
* system-under-test (SUT) within the Bochs emulator. A trace file is \n\ * system-under-test (SUT) within the emulator. A trace file is \n\
* produced and saved as main/trace.pb\n\ * produced and saved as: ${BUILD_DIR}/main/trace.pb\n\
*\n\ *\n\
* $ make trace-$(shell dirname $<)\n\ * $ make trace-$(patsubst build-%,%,$@)\n\
****************************************************************" ****************************************************************"
trace-%: %/system.elf %/system.iso trace-%: %/system.elf %/system.iso
${BOCHS_RUNNER} -e $< -i $(shell dirname $<)/system.iso -1 \ ${BOCHS_RUNNER} -e $< -i $(shell dirname $<)/system.iso -1 \
-V vgabios.bin -b BIOS-bochs-latest \ -V vgabios.bin -b BIOS-bochs-latest \

30
arch/bochs.mk Normal file
View File

@ -0,0 +1,30 @@
FAIL_DOWNLOAD_URL = ${FAIL_DOWNLOAD_BASE}?job=build-bochs-generic-tools
CFLAGS += -m32
LDFLAGS += -Wl,-T linker.ld $^ -m32 -static -nostdlib -Wl,--build-id=none
################################################################
# Build Targets
${BUILD_DIR}/%/system.o: %.c
mkdir -p $(shell dirname $@)
${CC} $< -o $@ ${CFLAGS} -c -ffunction-sections
${BUILD_DIR}/startup.o: arch/bochs/startup.s
${CC} $< ${CFLAGS} -c -o $@ -ffunction-sections
${BUILD_DIR}/%/system.elf: ${BUILD_DIR}/%/system.o ${BUILD_DIR}/startup.o
${CC} ${LDFLAGS} -o $@
${BUILD_DIR}/%/system.iso: ${BUILD_DIR}/%/system.elf
rm -rf $(shell dirname $<)/grub
mkdir -p $(shell dirname $<)/grub/boot/grub
cp grub.cfg $(shell dirname $<)/grub/boot/grub
cp $< $(shell dirname $<)/grub/boot/system.elf
grub-mkrescue -o $@ $(shell dirname $<)/grub
define arch-make-targets
build-$1: ${BUILD_DIR}/$1/system.iso
endef

4
arch/bochs/lib.c Normal file
View File

@ -0,0 +1,4 @@
#pragma once
#define ARCH_ASM_CLOBBER_ALL "eax", "ebx", "ecx", "edx", "esi", "edi", "ebp"

33
arch/riscv-common.mk Normal file
View File

@ -0,0 +1,33 @@
CC := clang-11
CFLAGS += -nostdlib -fno-inline-functions -fno-unroll-loops -mcmodel=medium -gdwarf-5
LDFLAGS += -nostdlib -nostartfiles -static -fuse-ld=lld -Wl,-nostdlib -Wl,--script=arch/riscv/linker.ld
${BUILD_DIR}/startup.o: arch/riscv/bootcode/${ARCH}.c
@mkdir -p $(dir $@)
${CC} ${CFLAGS} -o $@ -c $^
${BUILD_DIR}/%/system.o: %.c
@mkdir -p $(dir $@)
${CC} ${CFLAGS} -o $@ -c $^
${BUILD_DIR}/%/system.elf: ${BUILD_DIR}/startup.o ${BUILD_DIR}/%/system.o
${CC} ${CFLAGS} ${LDFLAGS} -o $@ $^
define arch-make-targets
build-$1: ${BUILD_DIR}/$1/system.elf
trace-$1: ${BUILD_DIR}/$1/system.elf
${FAIL_TRACE} \
-Wf,--elf-file -Wf,$$< \
-Wf,--start-symbol -Wf,start_trace \
-Wf,--end-symbol -Wf,stop_trace \
-Wf,--check-bounds \
-Wf,--state-file=$$(dir $$<)/state \
-Wf,--trace-file=$$(dir $$<)/trace.pb \
$$<
endef

View File

@ -0,0 +1,30 @@
#pragma once
#if defined(__riscv) && !defined(__CHERI__)
#define RISCV 1
#define ARCH_ASM_CLOBBER_ALL NO_CAP_REGS
#elif defined(__riscv) && defined(__CHERI__)
#define RISCVCHERI 1
#define ARCH_ASM_CLOBBER_ALL NO_CAPS_REGS, CAP_REGS
#else
#warning compiling for unknown architecture, using stdlib malloc.
#endif
#define NO_CAP_REGS "ra","sp","gp","tp","t0","t1","t2","t3","t4","t5","t6","s0","s1","s2","s3","s4","s5","s6","s7","s8","s9","s10","s11","a0","a1","a2","a3","a4","a5","a6","a7"
#define CAP_REGS "cra","csp","cgp","ctp","ct0","ct1","ct2","ct3","ct4","ct5","ct6","cs0","cs1","cs2","cs3","cs4","cs5","cs6","cs7","cs8","cs9","cs10","cs11","ca0","ca1","ca2","ca3","ca4","ca5","ca6","ca7"
#ifndef __ASSEMBLER__
#if __riscv_xlen == 32
typedef unsigned int size_t;
#elif __riscv_xlen == 64
typedef unsigned long size_t;
#elif DEBUG
#else
#warning Unknown __riscv_xlen value
typedef unsigned long size_t;
#endif
#endif

View File

@ -0,0 +1,30 @@
#include <cheri_init_globals.h>
#include "boot.h"
asm (
".text" "\n"
".option push" "\n"
".option nocapmode" "\n"
".global _start" "\n"
"_start:" "\n"
" lla sp, __sp" "\n"
" lla t0, __stack_size" "\n"
" cfromptr csp, ddc, sp" "\n"
" csetbounds csp, csp, t0" "\n"
" cincoffset csp, csp, t0" "\n"
" lla t0, _start_purecap" "\n"
" cfromptr ct0, ddc, t0" "\n"
" li t1, 1" "\n"
" csetflags ct0, ct0, t1" "\n"
" cjr ct0" "\n"
".option pop" "\n"
);
extern void os_main();
void _start_purecap(void) {
cheri_init_globals_3(__builtin_cheri_global_data_get(),
__builtin_cheri_program_counter_get(),
__builtin_cheri_global_data_get());
os_main();
}

View File

@ -0,0 +1 @@
cheri32.c

View File

@ -0,0 +1,12 @@
#include "boot.h"
asm (
".text" "\n"
".global _start" "\n"
"_start:" "\n"
" la sp, __sp" "\n"
" la t0, __stack_size" "\n"
" add sp, sp, t0" "\n"
" la t0, os_main" "\n"
" jr t0" "\n"
);

View File

@ -0,0 +1 @@
riscv32.c

3
arch/riscv/lib.c Normal file
View File

@ -0,0 +1,3 @@
#include "arch/riscv/bootcode/boot.h"

254
arch/riscv/linker.ld Normal file
View File

@ -0,0 +1,254 @@
/*======================================================================*/
/* Default maven linker script */
/*======================================================================*/
/* This is the default linker script for maven. It is based off of the
mips idt32.ld linker script. I have added many more comments and
tried to clean things up a bit. For more information about standard
MIPS sections see Section 9.5 of "See MIPS Run Linux" by Dominic
Sweetman. For more generic information about the init, fini, ctors,
and dtors sections see the paper titled "ELF From the Programmers
Perspective" by Hongiu Lu. */
/*----------------------------------------------------------------------*/
/* Setup */
/*----------------------------------------------------------------------*/
/* The OUTPUT_ARCH command specifies the machine architecture where the
argument is one of the names used in the BFD library. More
specifically one of the entires in bfd/cpu-mips.c */
OUTPUT_ARCH( "riscv" )
/* The ENTRY command specifies the entry point (ie. first instruction to
execute). The symbol _start is defined in crt0.S */
ENTRY( _start )
/*----------------------------------------------------------------------*/
/* Sections */
/*----------------------------------------------------------------------*/
/* This is where we specify how the input sections map to output
sections. The .= commands set the location counter, and the
sections are inserted in increasing address order according to the
location counter. The following statement will take all of the .bar
input sections and reloate them into the .foo output section which
starts at address 0x1000.
. = 0.x1000;
.foo : { *(.bar) }
If we wrap an input specification with a KEEP command then it
prevents it from being eliminted during "link-time garbage
collection". I'm not sure what this is, so I just followed what was
done in idt32.ld.
We can also set a global external symbol to a specific address in the
output binary with this syntax:
_etext = .;
PROVIDE( etext = . );
This will set the global symbol _ftext to the current location. If we
wrap this in a PROVIDE commad, the symbol will only be set if it is
not defined. We do this with symbols which don't begin with an
underscore since technically in ansi C someone might have a function
with the same name (eg. etext).
If we need to label the beginning of a section we need to make sure
that the linker doesn't insert an orphan section inbetween where we
set the symbol and the actual begining of the section. We can do that
by assigning the location dot to itself.
. = .
_ftext = .;
.text :
{ }
*/
SECTIONS
{
/* Defines for stack and heap size. These are used by the startup code. */
__stack_size = 0x800;
__heap_size = 0x800;
/* Define data/bss padding size, defaults to zero but can be override by passing -Wl,--defsym=__padding_size=0x123 */
__padding_size = DEFINED(__padding_size) ? __padding_size: 0x0;
/*--------------------------------------------------------------------*/
/* Code and read-only segment */
/*--------------------------------------------------------------------*/
/* Begining of code and text segment */
. = 0x80000000;
_ftext = .;
/* text: Program code section */
.text :
{
*(.text)
*(.text.*)
*(.gnu.linkonce.t.*)
}
/* init: Code to execute before main (called by crt0.S) */
.init :
{
KEEP( *(.init) )
}
/* fini: Code to execute after main (called by crt0.S) */
.fini :
{
KEEP( *(.fini) )
}
/* rodata: Read-only data */
.rodata :
{
*(.rdata)
*(.rodata)
*(.rodata.*)
*(.gnu.linkonce.r.*)
}
/* End of code and read-only segment */
PROVIDE( etext = . );
_etext = .;
/*--------------------------------------------------------------------*/
/* Global constructor/destructor segement */
/*--------------------------------------------------------------------*/
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
}
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array ))
PROVIDE_HIDDEN (__init_array_end = .);
}
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array ))
PROVIDE_HIDDEN (__fini_array_end = .);
}
/*--------------------------------------------------------------------*/
/* Other misc gcc segments (this was in idt32.ld) */
/*--------------------------------------------------------------------*/
/* I am not quite sure about these sections but it seems they are for
C++ exception handling. I think .jcr is for "Java Class
Registration" but it seems to end up in C++ binaries as well. */
.eh_frame_hdr : { *(.eh_frame_hdr) }
.eh_frame : { KEEP( *(.eh_frame) ) }
.gcc_except_table : { *(.gcc_except_table) }
.jcr : { KEEP (*(.jcr)) }
/*--------------------------------------------------------------------*/
/* Initialized data segment */
/*--------------------------------------------------------------------*/
.padding_before : {
. += __padding_size;
}
/* Start of initialized data segment */
. = ALIGN(16);
_fdata = .;
/* data: Writable data */
.data :
{
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
}
/* End of initialized data segment */
PROVIDE( edata = . );
_edata = .;
/* Have _gp point to middle of sdata/sbss to maximize displacement range */
. = ALIGN(16);
_gp = . + 0x800;
/* Writable small data segment */
.sdata :
{
*(.sdata)
*(.sdata.*)
*(.srodata.*)
*(.gnu.linkonce.s.*)
}
/*--------------------------------------------------------------------*/
/* Uninitialized data segment */
/*--------------------------------------------------------------------*/
/* Start of uninitialized data segment */
. = ALIGN(16);
_fbss = .;
/* Writable uninitialized small data segment */
.sbss :
{
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
}
/* bss: Uninitialized writeable data section */
. = .;
_bss_start = .;
.bss :
{
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
}
.padding_after : {
. += __padding_size;
}
/*--------------------------------------------------------------------*/
/* Stack and Heap storage */
/*--------------------------------------------------------------------*/
.heap : ALIGN(16) {
*(.heap)
*(.heap.*)
}
.stack : ALIGN(16) {
PROVIDE(__sp = .);
. += __stack_size;
}
/*--------------------------------------------------------------------*/
/* HTIF, isolated on a seperate page. */
/*--------------------------------------------------------------------*/
.htif (NOLOAD) : ALIGN(0x1000) {
tohost = .;
PROVIDE(tohost = tohost);
. += 8;
fromhost = .;
PROVIDE(fromhost = fromhost);
. += 8;
}
. = ALIGN(0x1000);
}

1
arch/riscv32 Symbolic link
View File

@ -0,0 +1 @@
riscv

5
arch/riscv32.mk Normal file
View File

@ -0,0 +1,5 @@
FAIL_DOWNLOAD_URL = ${FAIL_DOWNLOAD_BASE}?job=build-riscv-generic-tools%3A+%5Briscv64%5D
include arch/riscv-common.mk
CFLAGS += -march=rv32im -target riscv32-unknown-freebsd

1
arch/riscv64 Symbolic link
View File

@ -0,0 +1 @@
riscv

24
lib.c Normal file
View File

@ -0,0 +1,24 @@
#pragma once
#define INLINE __attribute__((always_inline)) inline
#define NOINLINE __attribute__((noinline))
#define __QUOTE(x) #x
#define QUOTE(x) __QUOTE(x)
#define MARKER(str) __asm__ volatile(QUOTE(str) ":" \
: /* no inputs */ \
: /* no outputs */ \
: "memory", ARCH_ASM_CLOBBER_ALL \
)
#ifndef DEBUG
#define MAIN() void os_main(void)
#define PRINT_DEBUG(...)
#else
#include <stdio.h>
#define MARKER(str) printf(QUOTE(str) "\n")
#define DEBUG 1
#define PRINT_DEBUG(...) printf(__VA_ARGS__)
#define MAIN() void main(int argc, char** argv)
#endif

25
main.c
View File

@ -1,28 +1,21 @@
volatile int __dummy; #include "lib.c"
void __attribute__ ((noinline)) fail_marker();
void __attribute__ ((noinline)) fail_marker()
{
__dummy = 100;
}
void __attribute__ ((noinline)) stop_trace();
void __attribute__ ((noinline)) stop_trace()
{
__dummy = 100;
}
int array[] = {1, 1, 2, 3, 5, 8, 13, 21}; int array[] = {1, 1, 2, 3, 5, 8, 13, 21};
int sum; int sum;
void os_main() {
MAIN() {
MARKER(start_trace);
sum = 20; sum = 20;
for (int i = 0; i < sizeof(array)/sizeof(*array); i++) { for (int i = 0; i < sizeof(array)/sizeof(*array); i++) {
sum += (array[i] * 23) + 1; sum += (array[i] * 23) + 1;
} }
MARKER(stop_trace);
if (sum != 1270) if (sum != 1270)
fail_marker(); MARKER(fail_maker);
stop_trace(); else
MARKER(ok_marker);
} }