From 0f9ced8eb13c3087397996ea08ee39f5e2ef016f Mon Sep 17 00:00:00 2001 From: omicron Date: Thu, 3 Apr 2025 23:14:56 +0200 Subject: [PATCH 1/2] Rework the build system to be more modular Split most of the work off into make/base.mk and allow for easy wrappers to be created around that that can build with different instrumentation in their own build directory. Create wrappers for the following: - release build - debug build - afl++ fuzzing build - static analysis with clang - clang memory sanitizer - clang address/undefined sanitizer --- Makefile | 70 ++++++++++++++++++++----------------------------- make/afl.mk | 14 ++++++++++ make/analyze.mk | 9 +++++++ make/asan.mk | 5 ++++ make/base.mk | 27 +++++++++++++++++++ make/debug.mk | 1 + make/msan.mk | 5 ++++ make/release.mk | 5 ++++ validate.sh | 16 +++++------ 9 files changed, 102 insertions(+), 50 deletions(-) create mode 100644 make/afl.mk create mode 100644 make/analyze.mk create mode 100644 make/asan.mk create mode 100644 make/base.mk create mode 100644 make/debug.mk create mode 100644 make/msan.mk create mode 100644 make/release.mk diff --git a/Makefile b/Makefile index d685209..4b73e61 100644 --- a/Makefile +++ b/Makefile @@ -1,54 +1,42 @@ -.PHONY: all clean clean-objects clean-reports run sanitize validate fuzz +.PHONY: all clean distclean release debug afl asan msan validate analyze fuzz -CC=clang -LD=clang -CFLAGS=-Wall -Wextra -Wpedantic -O0 -g3 -std=c23 -fno-omit-frame-pointer -fno-optimize-sibling-calls -D_POSIX_C_SOURCE=200809L -LDFLAGS?= +debug: + make -rRf make/debug.mk all -SOURCES = $(shell find src/ -type f -name '*.c') -OBJECTS = $(SOURCES:.c=.o) -DEPENDENCIES = $(SOURCES:.c=.d) -TARGET?=oas -OUTPUTS=oas oas-asan oas-msan oas-afl -RUNARGUMENTS?=ast tests/input/valid.asm - -all: $(TARGET) +all: debug release afl asan msan -run: $(TARGET) - ./$(TARGET) $(RUNARGUMENTS) +release: + make -rRf make/release.mk all + +afl: + make -rRf make/afl.mk all fuzz: - make CC="afl-clang-fast" LD="afl-clang-fast" TARGET="oas-afl" clean-objects all - make clean-objects - mkdir -p reports/afl - afl-fuzz -i tests/input -o reports/afl -m none -- ./oas-afl -tokens @@ + make -rRf make/afl.mk fuzz -sanitize: - make CFLAGS="$(CFLAGS) -fsanitize=address,undefined" \ - LDFLAGS="-fsanitize=address,undefined" \ - TARGET="oas-asan" clean-objects all - make CFLAGS="$(CFLAGS) -fsanitize=memory -fsanitize-memory-track-origins=2" \ - LDFLAGS="-fsanitize=memory -fsanitize-memory-track-origins=2" \ - TARGET="oas-msan" clean-objects all - make clean-objects +asan: + make -rRf make/asan.mk all -validate: +msan: + make -rRf make/msan.mk all + +validate: asan msan debug ./validate.sh -$(TARGET): $(OBJECTS) - $(LD) $(LDFLAGS) -o $@ $^ +analyze: + make -rRf make/analyze.mk clean all -%.o: %.c - $(CC) $(CFLAGS) -MMD -MP -c $< -o $@ +clean: + make -rRf make/release.mk clean + make -rRf make/debug.mk clean + make -rRf make/afl.mk clean + make -rRf make/msan.mk clean + make -rRf make/asan.mk clean + make -rRf make/analyze.mk clean + rm -rf build/ --include $(DEPENDENCIES) - -clean-objects: - rm -f $(OBJECTS) $(DEPENDENCIES) - -clean-reports: +distclean: clean + make -rRf make/afl.mk distclean + make -rRf make/analyze.mk distclean rm -rf reports/ - -clean: clean-objects - rm -f $(TARGET) $(OUTPUTS) diff --git a/make/afl.mk b/make/afl.mk new file mode 100644 index 0000000..958b14a --- /dev/null +++ b/make/afl.mk @@ -0,0 +1,14 @@ +.PHONY: fuzz distclean + +CC=afl-clang-fast +LD=afl-clang-fast +BUILD_DIR=build/afl/ + +-include make/base.mk + +fuzz: $(BUILD_DIR)$(TARGET) + mkdir -p reports/afl + afl-fuzz -i tests/input -o reports/afl -m none -- ./$< -tokens @@ + +distclean: clean + rm -rf reports/afl diff --git a/make/analyze.mk b/make/analyze.mk new file mode 100644 index 0000000..03be3f6 --- /dev/null +++ b/make/analyze.mk @@ -0,0 +1,9 @@ +BUILD_DIR=build/analyze/ +-include make/base.mk + +analyze: + mkdir -p reports/static-analysis + scan-build -o reports/static-analysis/ -plist-html --status-bugs make -rRf make/analyze.mk all + +distclean: clean + rm -rf reports/static-analysis diff --git a/make/asan.mk b/make/asan.mk new file mode 100644 index 0000000..2004eba --- /dev/null +++ b/make/asan.mk @@ -0,0 +1,5 @@ +CFLAGS=-Wall -Wextra -Wpedantic -O0 -g3 -std=c23 -fno-omit-frame-pointer -fno-optimize-sibling-calls -D_POSIX_C_SOURCE=200809L -fsanitize=address,undefined +LDFLAGS=-fsanitize=address,undefined +BUILD_DIR=build/asan/ + +-include make/base.mk diff --git a/make/base.mk b/make/base.mk new file mode 100644 index 0000000..ce47405 --- /dev/null +++ b/make/base.mk @@ -0,0 +1,27 @@ +.PHONY: all clean + +CC?=clang +LD?=clang +CFLAGS?=-Wall -Wextra -Wpedantic -O0 -g3 -std=c23 -fno-omit-frame-pointer -fno-optimize-sibling-calls -D_POSIX_C_SOURCE=200809L +LDFLAGS?= +BUILD_DIR?=build/debug/ + +SOURCES?=$(shell find src/ -type f -name '*.c') +OBJECTS=$(patsubst %.c,$(BUILD_DIR)%.o,$(SOURCES)) +DEPENDENCIES=$(OBJECTS:.o=.d) +TARGET?=oas + +all: $(BUILD_DIR)$(TARGET) + + +$(BUILD_DIR)$(TARGET): $(OBJECTS) + $(LD) $(LDFLAGS) -o $@ $^ + +$(BUILD_DIR)%.o: %.c + mkdir -p $(dir $@) + $(CC) $(CFLAGS) -MMD -MP -c $< -o $@ + +-include $(DEPENDENCIES) + +clean: + rm -rf $(BUILD_DIR) diff --git a/make/debug.mk b/make/debug.mk new file mode 100644 index 0000000..4da7592 --- /dev/null +++ b/make/debug.mk @@ -0,0 +1 @@ +-include make/base.mk diff --git a/make/msan.mk b/make/msan.mk new file mode 100644 index 0000000..b28000e --- /dev/null +++ b/make/msan.mk @@ -0,0 +1,5 @@ +CFLAGS=-Wall -Wextra -Wpedantic -O0 -g3 -std=c23 -fno-omit-frame-pointer -fno-optimize-sibling-calls -D_POSIX_C_SOURCE=200809L -fsanitize=memory +LDFLAGS=-fsanitize=memory +BUILD_DIR=build/msan/ + +-include make/base.mk diff --git a/make/release.mk b/make/release.mk new file mode 100644 index 0000000..606940c --- /dev/null +++ b/make/release.mk @@ -0,0 +1,5 @@ +CFLAGS?=-Wall -Wextra -Wpedantic -O2 -std=c23 -flto -fomit-frame-pointer -DNDEBUG -D_POSIX_C_SOURCE=200809L +LDFLAGS?=-flto -s -Wl,--gc-sections +BUILD_DIR?=build/release/ + +-include make/base.mk diff --git a/validate.sh b/validate.sh index 33313da..01a22a7 100755 --- a/validate.sh +++ b/validate.sh @@ -2,19 +2,17 @@ set -euo pipefail -# Start with static analysis -make clean all -mkdir -p reports/static-analysis -scan-build -o reports/static-analysis/ -plist-html --status-bugs make all +make analyze debug asan msan -# Run the sanitizer builds and valgrind -make clean sanitize all +ASAN=build/asan/oas +MSAN=build/msan/oas +DEBUG=build/debug/oas ARGUMENTS=("tokens" "text" "ast") while IFS= read -r INPUT_FILE; do for ARGS in ${ARGUMENTS[@]}; do - ./oas-asan $ARGS $INPUT_FILE > /dev/null - ./oas-msan $ARGS $INPUT_FILE > /dev/null - valgrind --leak-check=full --error-exitcode=1 ./oas $ARGS $INPUT_FILE >/dev/null + $ASAN $ARGS $INPUT_FILE > /dev/null + $MSAN $ARGS $INPUT_FILE > /dev/null + valgrind --leak-check=full --error-exitcode=1 $DEBUG $ARGS $INPUT_FILE >/dev/null done done < <(find tests/input/ -type f -name '*.asm') -- 2.47.2 From 1571c520128c88439e23d3b0028b47ef7e91a2a3 Mon Sep 17 00:00:00 2001 From: omicron Date: Fri, 4 Apr 2025 02:17:23 +0200 Subject: [PATCH 2/2] Add some building documentation that clarifies the make targets --- doc/BUILDING.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 doc/BUILDING.md diff --git a/doc/BUILDING.md b/doc/BUILDING.md new file mode 100644 index 0000000..8c663b3 --- /dev/null +++ b/doc/BUILDING.md @@ -0,0 +1,29 @@ +# Building + +To build oas in the default configuration you just need (gnu) make and a +sufficiently modern clang. + +``` +make +``` + +## Make targets + +There are a number of make targets available to build various instrumented +builds that are used in validation, analysis and sanitizing. Some of these may +require extra dependencies. + + + - `debug`: Creates the debug build in `build/debug`. This is the default target. + - `all`: Builds all binary executable targets. These are + `debug`, `release`, `msan`, `asan` and `afl`. All executables can be found + in `build/` in a subdirectory matching their target names. + - `release`: Creates the release build in `build/release` + - `afl`: Creates a build with AFL++ instrumentation for fuzzing + - `fuzz`: Starts the fuzzer with the instrumented afl executable + - `asan`: builds with the address and undefined clang sanitizers + - `msan`: builds with the memory clang sanitizer + - `validate`: Builds `debug`, `msan`, and `asan` targets, then runs the + validation script. This script executes the sanitizer targets and runs + Valgrind on the debug target across multiple modes and test input files. + -- 2.47.2