aboutsummaryrefslogtreecommitdiff
path: root/GNUmakefile.gcc_plugin
blob: 8f06792dc4d21cd593926498004028962381c84e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
#
# american fuzzy lop++ - GCC plugin instrumentation
# -----------------------------------------------
#
# Written by Austin Seipp <aseipp@pobox.com> and
#            Laszlo Szekeres <lszekeres@google.com> and
#            Michal Zalewski and
#            Heiko Eißfeldt  <heiko@hexco.de>
#
# GCC integration design is based on the LLVM design, which comes
# from Laszlo Szekeres.
#
# Copyright 2015 Google Inc. All rights reserved.
# Copyright 2019-2024 AFLplusplus Project. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
#   https://www.apache.org/licenses/LICENSE-2.0
#
#TEST_MMAP=1
PREFIX      ?= /usr/local
HELPER_PATH ?= $(PREFIX)/lib/afl
BIN_PATH    ?= $(PREFIX)/bin
DOC_PATH    ?= $(PREFIX)/share/doc/afl
MAN_PATH    ?= $(PREFIX)/share/man/man8

VERSION     = $(shell grep '^$(HASH)define VERSION ' ./config.h | cut -d '"' -f2)

CFLAGS          ?= -O3 -g -funroll-loops
# -D_FORTIFY_SOURCE=1
CFLAGS_SAFE     := -Wall -Iinclude -Wno-pointer-sign \
                   -DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \
                   -DGCC_VERSION=\"$(GCCVER)\" -DGCC_BINDIR=\"$(GCCBINDIR)\" \
                   -Wno-unused-function
override CFLAGS += $(CFLAGS_SAFE)

CXXFLAGS    ?= -O3 -g -funroll-loops
# -D_FORTIFY_SOURCE=1
CXXEFLAGS   := $(CXXFLAGS) $(CPPFLAGS) -Wall -std=c++11

CC          ?= gcc
CXX         ?= g++

SYS = $(shell uname -s)

ifeq "clang" "$(CC)"
        CC  = gcc
        CXX = g++
endif

ifeq "clang++" "$(CXX)"
        CC  = gcc
        CXX = g++
endif

ifeq "$(findstring Foundation,$(shell $(CC) --version))" ""
        CC  = gcc
        CXX = g++
endif

PLUGIN_BASE = "$(shell $(CC) -print-file-name=plugin)"
PLUGIN_FLAGS = -fPIC -fno-rtti -fno-exceptions -I$(PLUGIN_BASE)/include -I$(PLUGIN_BASE)
HASH=\#

GCCVER    = $(shell $(CC) --version 2>/dev/null | awk 'NR == 1 {print $$NF}')
GCCBINDIR = $(shell dirname `command -v $(CC)` 2>/dev/null )

ifeq "$(shell echo '$(HASH)include <sys/ipc.h>@$(HASH)include <sys/shm.h>@int main() { int _id = shmget(IPC_PRIVATE, 65536, IPC_CREAT | IPC_EXCL | 0600); shmctl(_id, IPC_RMID, 0); return 0;}' | tr @ '\n' | $(CC) -x c - -o .test2 2>/dev/null && echo 1 || echo 0 ; rm -f .test2 )" "1"
	SHMAT_OK=1
else
	SHMAT_OK=0
	override CFLAGS_SAFE += -DUSEMMAP=1
endif

ifeq "$(TEST_MMAP)" "1"
	SHMAT_OK=0
	override CFLAGS_SAFE += -DUSEMMAP=1
endif

ifneq "$(SYS)" "Haiku"
ifneq "$(SYS)" "OpenBSD"
  	LDFLAGS += -lrt
endif
else
	CFLAGS_SAFE += -DUSEMMAP=1
endif

ifeq "$(SYS)" "OpenBSD"
    CC  = egcc
    CXX = eg++
    PLUGIN_FLAGS += -I/usr/local/include
endif

ifeq "$(SYS)" "DragonFly"
  	PLUGIN_FLAGS += -I/usr/local/include
endif

ifeq "$(SYS)" "SunOS"
  	PLUGIN_FLAGS += -I/usr/include/gmp
endif


PASSES       = ./afl-gcc-pass.so ./afl-gcc-cmplog-pass.so ./afl-gcc-cmptrs-pass.so

PROGS        = $(PASSES) ./afl-compiler-rt.o ./afl-compiler-rt-32.o ./afl-compiler-rt-64.o

.PHONY: all
all: test_shm test_deps $(PROGS) test_build all_done

.PHONY: test_shm
ifeq "$(SHMAT_OK)" "1"
test_shm:
	@echo "[+] shmat seems to be working."
	@rm -f .test2
else
test_shm:
	@echo "[-] shmat seems not to be working, switching to mmap implementation"
endif

.PHONY: test_deps
test_deps:
	@echo "[*] Checking for working '$(CC)'..."
	@command -v $(CC) >/dev/null 2>&1 || ( echo "[-] Oops, can't find '$(CC)'. Make sure that it's in your \$$PATH (or set \$$CC and \$$CXX)."; exit 1 )
#	@echo "[*] Checking for gcc for plugin support..."
#	@$(CC) -v 2>&1 | grep -q -- --enable-plugin || ( echo "[-] Oops, this gcc has not been configured with plugin support."; exit 1 )
	@echo "[*] Checking for gcc plugin development header files..."
	@test -d `$(CC) -print-file-name=plugin`/include || ( echo "[-] Oops, can't find gcc header files. Be sure to install 'gcc-X-plugin-dev'."; exit 1 )
	@echo "[*] Checking for './afl-showmap'..."
	@test -f ./afl-showmap || ( echo "[-] Oops, can't find './afl-showmap'. Be sure to compile AFL first."; exit 1 )
	@echo "[+] All set and ready to build."

afl-common.o: ./src/afl-common.c
	$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ $(LDFLAGS)

./afl-compiler-rt.o: instrumentation/afl-compiler-rt.o.c
	$(CC) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -fPIC -c $< -o $@

./afl-compiler-rt-32.o: instrumentation/afl-compiler-rt.o.c
	@printf "[*] Building 32-bit variant of the runtime (-m32)... "
	@$(CC) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m32 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi

./afl-compiler-rt-64.o: instrumentation/afl-compiler-rt.o.c
	@printf "[*] Building 64-bit variant of the runtime (-m64)... "
	@$(CC) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m64 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi

$(PASSES): instrumentation/afl-gcc-common.h

./afl-gcc-pass.so: instrumentation/afl-gcc-pass.so.cc | test_deps
	$(CXX) $(CXXEFLAGS) $(PLUGIN_FLAGS) -shared $< -o $@
	ln -sf afl-cc afl-gcc-fast
	ln -sf afl-cc afl-g++-fast
	ln -sf afl-cc.8 afl-gcc-fast.8
	ln -sf afl-cc.8 afl-g++-fast.8

./afl-gcc-cmplog-pass.so: instrumentation/afl-gcc-cmplog-pass.so.cc | test_deps
	$(CXX) $(CXXEFLAGS) $(PLUGIN_FLAGS) -shared $< -o $@

./afl-gcc-cmptrs-pass.so: instrumentation/afl-gcc-cmptrs-pass.so.cc | test_deps
	$(CXX) $(CXXEFLAGS) $(PLUGIN_FLAGS) -shared $< -o $@

.PHONY: test_build
test_build: $(PROGS)
	@echo "[*] Testing the CC wrapper and instrumentation output..."
	unset AFL_USE_ASAN AFL_USE_MSAN; ASAN_OPTIONS=detect_leaks=0 AFL_QUIET=1 AFL_INST_RATIO=100 AFL_PATH=. AFL_CC=$(CC) ./afl-gcc-fast $(CFLAGS) $(CPPFLAGS) ./test-instr.c -o test-instr $(LDFLAGS)
	ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr0 ./test-instr </dev/null
	echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
	@rm -f test-instr
	@cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation does not seem to be behaving correctly!"; echo; echo "Please post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue."; echo; exit 1; fi
	@echo "[+] All right, the instrumentation seems to be working!"

.PHONY: all_done
all_done: test_build
	@echo "[+] All done! You can now use './afl-gcc-fast' to compile programs."

.NOTPARALLEL: clean

%.8: %
	@echo .TH $* 8 `date "+%Y-%m-%d"` "AFL++" > ./$@
	@echo .SH NAME >> ./$@
	@echo .B $* >> ./$@
	@echo >> ./$@
	@echo .SH SYNOPSIS >> ./$@
	@./$* -h 2>&1 | head -n 3 | tail -n 1 | sed 's/^\.\///' >> ./$@
	@echo >> ./$@
	@echo .SH OPTIONS >> ./$@
	@echo .nf >> ./$@
	@./$* -h 2>&1 | tail -n +4 >> ./$@
	@echo >> ./$@
	@echo .SH AUTHOR >> ./$@
	@echo "AFL++ was written by Michal \"lcamtuf\" Zalewski and is maintained by Marc \"van Hauser\" Heuse <mh@mh-sec.de>, Dominik Maier <domenukk@gmail.com>, Andrea Fioraldi <andreafioraldi@gmail.com> and Heiko \"hexcoder-\" Eissfeldt <heiko.eissfeldt@hexco.de>" >> ./$@
	@echo  The homepage of AFL++ is: https://github.com/AFLplusplus/AFLplusplus >> ./$@
	@echo >> ./$@
	@echo .SH LICENSE >> ./$@
	@echo Apache License Version 2.0, January 2004 >> ./$@
	ln -sf afl-cc.8 ./afl-g++-fast.8

.PHONY: install
install: all
	ln -sf afl-cc $${DESTDIR}$(BIN_PATH)/afl-gcc-fast
	ln -sf afl-c++ $${DESTDIR}$(BIN_PATH)/afl-g++-fast
	ln -sf afl-compiler-rt.o $${DESTDIR}$(HELPER_PATH)/afl-gcc-rt.o
	install -m 755 ./afl-gcc-pass.so $${DESTDIR}$(HELPER_PATH)
	install -m 755 ./afl-gcc-cmplog-pass.so $${DESTDIR}$(HELPER_PATH)
	install -m 755 ./afl-gcc-cmptrs-pass.so $${DESTDIR}$(HELPER_PATH)
	install -m 644 -T instrumentation/README.gcc_plugin.md $${DESTDIR}$(DOC_PATH)/README.gcc_plugin.md

.PHONY: clean
clean:
	rm -f *.o *.so *~ a.out core core.[1-9][0-9]* test-instr .test-instr0 .test-instr1 .test2
	rm -f $(PROGS) afl-common.o ./afl-g++-fast ./afl-g*-fast.8 instrumentation/*.o