1#   honggfuzz - Makefile
2#   -----------------------------------------
3#
4#   Author: Robert Swiecki <swiecki@google.com>
5#
6#   Copyright 2010-2015 by Google Inc. All Rights Reserved.
7#
8#   Licensed under the Apache License, Version 2.0 (the "License");
9#   you may not use this file except in compliance with the License.
10#   You may obtain a copy of the License at
11#
12#     http://www.apache.org/licenses/LICENSE-2.0
13#
14#   Unless required by applicable law or agreed to in writing, software
15#   distributed under the License is distributed on an "AS IS" BASIS,
16#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17#   See the License for the specific language governing permissions and
18#   limitations under the License.
19#
20#   NOTE: xcrun is within xcode...xcode is required on OSX.
21#
22
23# Common for all architectures
24CC ?= gcc
25LD = $(CC)
26BIN := honggfuzz
27HFUZZ_CC_BINS := hfuzz_cc/hfuzz-clang hfuzz_cc/hfuzz-clang++ hfuzz_cc/hfuzz-gcc hfuzz_cc/hfuzz-g++
28HFUZZ_CC_SRCS := hfuzz_cc/hfuzz-cc.c
29COMMON_CFLAGS := -D_GNU_SOURCE -Wall -Werror -Wframe-larger-than=131072 -Wno-format-truncation -I.
30COMMON_LDFLAGS := -lm libcommon/libcommon.a
31COMMON_SRCS := $(sort $(wildcard *.c))
32CFLAGS ?= -O3
33LDFLAGS ?=
34LIBS_CFLAGS ?= -fPIC -fno-stack-protector -fno-builtin -D__NO_STRING_INLINES -D__NO_INLINE__
35HFUZZ_USE_RET_ADDR ?= false
36ifneq ($(HFUZZ_USE_RET_ADDR),false)
37    LIBS_CFLAGS += -D_HF_USE_RET_ADDR=$(HFUZZ_USE_RET_ADDR) -Wno-error=frame-address
38endif
39
40OS ?= $(shell uname -s)
41MARCH ?= $(shell uname -m)
42
43ifeq ($(OS),Linux)
44    ARCH := LINUX
45
46    ARCH_CFLAGS := -std=c11 -I/usr/local/include \
47                   -Wextra -Wno-override-init \
48                   -funroll-loops \
49                   -D_FILE_OFFSET_BITS=64
50    ARCH_LDFLAGS := -L/usr/local/include \
51                    -lpthread -lunwind-ptrace -lunwind-generic -lbfd -lopcodes -lrt -ldl
52    ARCH_SRCS := $(sort $(wildcard linux/*.c))
53    LIBS_CFLAGS += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0
54
55    ifeq ("$(wildcard /usr/include/bfd.h)","")
56        WARN_LIBRARY += binutils-devel
57    endif
58    ifeq ("$(wildcard /usr/include/libunwind-ptrace.h)","")
59        WARN_LIBRARY += libunwind-devel/libunwind8-devel
60    endif
61    ifeq ("$(wildcard /usr/local/include/intel-pt.h)","/usr/local/include/intel-pt.h")
62        ARCH_CFLAGS += -D_HF_LINUX_INTEL_PT_LIB
63        ARCH_CFLAGS += -I/usr/local/include
64        ARCH_LDFLAGS += -L/usr/local/lib -lipt -Wl,--rpath=/usr/local/lib
65    endif
66    ifeq ("$(wildcard /usr/include/intel-pt.h)","/usr/include/intel-pt.h")
67        ARCH_CFLAGS += -D_HF_LINUX_INTEL_PT_LIB
68        ARCH_LDFLAGS += -lipt
69    endif
70    ifdef WARN_LIBRARY
71        $(info ***************************************************************)
72        $(info Development libraries which are most likely missing on your OS:)
73        $(info $(WARN_LIBRARY))
74        $(info ***************************************************************)
75    endif
76    # OS Linux
77else ifeq ($(OS),Darwin)
78    ARCH := DARWIN
79
80    # Figure out which crash reporter to use.
81    CRASHWRANGLER := third_party/mac
82    OS_VERSION := $(shell sw_vers -productVersion)
83    ifneq (,$(findstring 10.13,$(OS_VERSION)))
84        CRASH_REPORT := $(CRASHWRANGLER)/CrashReport_Sierra.o
85    else ifneq (,$(findstring 10.12,$(OS_VERSION)))
86        CRASH_REPORT := $(CRASHWRANGLER)/CrashReport_Yosemite.o
87    else ifneq (,$(findstring 10.11,$(OS_VERSION)))
88        # El Capitan didn't break compatibility
89        CRASH_REPORT := $(CRASHWRANGLER)/CrashReport_Yosemite.o
90    else ifneq (,$(findstring 10.10,$(OS_VERSION)))
91        CRASH_REPORT := $(CRASHWRANGLER)/CrashReport_Yosemite.o
92    else ifneq (,$(findstring 10.9,$(OS_VERSION)))
93        CRASH_REPORT := $(CRASHWRANGLER)/CrashReport_Mavericks.o
94    else ifneq (,$(findstring 10.8,$(OS_VERSION)))
95        CRASH_REPORT := $(CRASHWRANGLER)/CrashReport_Mountain_Lion.o
96    else
97        $(error Unsupported MAC OS X version)
98    endif
99
100    # Figure out which XCode SDK to use.
101    OSX_SDK_VERSION := $(shell xcrun --show-sdk-version)
102    SDK_NAME :=macosx$(OSX_SDK_VERSION)
103    SDK := $(shell xcrun --sdk $(SDK_NAME) --show-sdk-path 2>/dev/null)
104    ifeq (,$(findstring MacOSX.platform,$(SDK)))
105        XC_PATH := $(shell xcode-select -p)
106        $(error $(SDK_NAME) not found in $(XC_PATH))
107    endif
108
109    CC := $(shell xcrun --sdk $(SDK_NAME) --find cc)
110    LD := $(shell xcrun --sdk $(SDK_NAME) --find cc)
111    ARCH_CFLAGS := -arch x86_64 -std=c99 -isysroot $(SDK) \
112                   -x objective-c -pedantic -fblocks \
113                   -Wimplicit -Wunused -Wcomment -Wchar-subscripts -Wuninitialized \
114                   -Wreturn-type -Wpointer-arith -Wno-gnu-case-range -Wno-gnu-designator \
115                   -Wno-deprecated-declarations -Wno-unknown-pragmas -Wno-attributes
116    ARCH_LDFLAGS := -F/System/Library/PrivateFrameworks -framework CoreSymbolication -framework IOKit \
117                    -F$(SDK)/System/Library/Frameworks -F$(SDK)/System/Library/PrivateFrameworks \
118                    -framework Foundation -framework ApplicationServices -framework Symbolication \
119                    -framework CoreServices -framework CrashReporterSupport -framework CoreFoundation \
120                    -framework CommerceKit $(CRASH_REPORT)
121
122    XCODE_VER := $(shell xcodebuild -version | grep "^Xcode" | cut -d " " -f2)
123    ifeq "8.3" "$(word 1, $(sort 8.3 $(XCODE_VER)))"
124      ARCH_LDFLAGS += -F/Applications/Xcode.app/Contents/SharedFrameworks \
125                      -framework CoreSymbolicationDT \
126                      -Wl,-rpath,/Applications/Xcode.app/Contents/SharedFrameworks
127    endif
128
129    MIG_RET := $(shell mig -header mac/mach_exc.h -user mac/mach_excUser.c -sheader mac/mach_excServer.h \
130                 -server mac/mach_excServer.c $(SDK)/usr/include/mach/mach_exc.defs &>/dev/null; echo $$?)
131    ifeq ($(MIG_RET),1)
132        $(error mig failed to generate RPC code)
133    endif
134    ARCH_SRCS := $(sort $(wildcard mac/*.c))
135    # OS Darwin
136else
137    ARCH := POSIX
138    ARCH_SRCS := $(sort $(wildcard posix/*.c))
139    ARCH_CFLAGS := -std=c11 -I/usr/local/include \
140                   -Wextra -Wno-initializer-overrides -Wno-override-init \
141                   -Wno-unknown-warning-option -Wno-unknown-pragmas \
142                   -funroll-loops
143    ARCH_LDFLAGS := -lpthread -L/usr/local/include -lrt
144    # OS Posix
145endif
146
147COMPILER = $(shell $(CC) -v 2>&1 | \
148  grep -oE '((gcc|clang) version|LLVM version.*clang)' | \
149  grep -oE '(clang|gcc)' | head -n1)
150ifeq ($(COMPILER),clang)
151  ARCH_CFLAGS += -Wno-initializer-overrides -Wno-unknown-warning-option
152  ARCH_CFLAGS += -fblocks
153  CFLAGS_NOBLOCKS = -fno-blocks
154
155  ifneq ($(OS),Darwin)
156    ARCH_LDFLAGS += -lBlocksRuntime
157  endif
158endif
159
160SRCS := $(COMMON_SRCS) $(ARCH_SRCS)
161OBJS := $(SRCS:.c=.o)
162
163LHFUZZ_SRCS := $(wildcard libhfuzz/*.c)
164LHFUZZ_OBJS := $(LHFUZZ_SRCS:.c=.o)
165LHFUZZ_ARCH := libhfuzz/libhfuzz.a
166HFUZZ_INC ?= $(shell pwd)
167
168LCOMMON_SRCS := $(wildcard libcommon/*.c)
169LCOMMON_OBJS := $(LCOMMON_SRCS:.c=.o)
170LCOMMON_ARCH := libcommon/libcommon.a
171
172# Respect external user defines
173CFLAGS += $(COMMON_CFLAGS) $(ARCH_CFLAGS) -D_HF_ARCH_${ARCH}
174LDFLAGS += $(COMMON_LDFLAGS) $(ARCH_LDFLAGS)
175
176ifeq ($(DEBUG),true)
177    CFLAGS += -g -ggdb
178    LDFLAGS += -g -ggdb
179endif
180
181# Control Android builds
182ANDROID_API           ?= android-26
183ANDROID_DEBUG_ENABLED ?= false
184ANDROID_CLANG         ?= true
185ANDROID_APP_ABI       ?= armeabi-v7a
186ANDROID_SKIP_CLEAN    ?= false
187NDK_BUILD_ARGS :=
188
189ifeq ($(ANDROID_DEBUG_ENABLED),true)
190  NDK_BUILD_ARGS += V=1 NDK_DEBUG=1 APP_OPTIM=debug
191endif
192
193# By default ndk-build cleans all project files to ensure that no semi-completed
194# builds reach the app package. The following flag disables this check. It's mainly
195# purposed to be used with android-all rule where we want recursive invocations
196# to keep previous targets' binaries.
197ifeq ($(ANDROID_SKIP_CLEAN),true)
198  NDK_BUILD_ARGS += NDK_APP.local.cleaned_binaries=true
199endif
200
201ifeq ($(ANDROID_CLANG),true)
202  ANDROID_NDK_TOOLCHAIN_VER := clang
203  # clang works only against APIs >= 23
204  ifeq ($(ANDROID_APP_ABI),$(filter $(ANDROID_APP_ABI),armeabi armeabi-v7a))
205    ANDROID_NDK_TOOLCHAIN ?= arm-linux-androideabi-clang
206    ANDROID_ARCH_CPU := arm
207  else ifeq ($(ANDROID_APP_ABI),$(filter $(ANDROID_APP_ABI),x86))
208    ANDROID_NDK_TOOLCHAIN ?= x86-clang
209    ANDROID_ARCH_CPU := x86
210  else ifeq ($(ANDROID_APP_ABI),$(filter $(ANDROID_APP_ABI),arm64-v8a))
211    ANDROID_NDK_TOOLCHAIN ?= aarch64-linux-android-clang
212    ANDROID_ARCH_CPU := arm64
213  else ifeq ($(ANDROID_APP_ABI),$(filter $(ANDROID_APP_ABI),x86_64))
214    ANDROID_NDK_TOOLCHAIN ?= x86_64-clang
215    ANDROID_ARCH_CPU := x86_64
216  else
217    $(error Unsuported / Unknown APP_API '$(ANDROID_APP_ABI)')
218  endif
219else
220  ANDROID_NDK_TOOLCHAIN_VER := 4.9
221  ifeq ($(ANDROID_APP_ABI),$(filter $(ANDROID_APP_ABI),armeabi armeabi-v7a))
222    ANDROID_NDK_TOOLCHAIN ?= arm-linux-androideabi-4.9
223    ANDROID_ARCH_CPU := arm
224  else ifeq ($(ANDROID_APP_ABI),$(filter $(ANDROID_APP_ABI),x86))
225    ANDROID_NDK_TOOLCHAIN ?= x86-4.9
226    ANDROID_ARCH_CPU := x86
227  else ifeq ($(ANDROID_APP_ABI),$(filter $(ANDROID_APP_ABI),arm64-v8a))
228    ANDROID_NDK_TOOLCHAIN ?= aarch64-linux-android-4.9
229    ANDROID_ARCH_CPU := arm64
230  else ifeq ($(ANDROID_APP_ABI),$(filter $(ANDROID_APP_ABI),x86_64))
231    ANDROID_NDK_TOOLCHAIN ?= x86_64-4.9
232    ANDROID_ARCH_CPU := x86_64
233  else
234    $(error Unsuported / Unknown APP_API '$(ANDROID_APP_ABI)')
235  endif
236endif
237
238SUBDIR_ROOTS := linux mac posix libhfuzz libcommon
239DIRS := . $(shell find $(SUBDIR_ROOTS) -type d)
240CLEAN_PATTERNS := *.o *~ core *.a *.dSYM *.la *.so *.dylib
241SUBDIR_GARBAGE := $(foreach DIR,$(DIRS),$(addprefix $(DIR)/,$(CLEAN_PATTERNS)))
242MAC_GARGBAGE := $(wildcard mac/mach_exc*)
243ANDROID_GARBAGE := obj libs
244
245CLEAN_TARGETS := core Makefile.bak \
246  $(OBJS) $(BIN) $(HFUZZ_CC_BINS) \
247  $(LHFUZZ_ARCH) $(LHFUZZ_OBJS) $(LCOMMON_ARCH) $(LCOMMON_OBJS) \
248  $(MAC_GARGBAGE) $(ANDROID_GARBAGE) $(SUBDIR_GARBAGE)
249
250all: $(BIN) $(HFUZZ_CC_BINS) $(LHFUZZ_ARCH) $(LCOMMON_ARCH)
251
252%.o: %.c
253	$(CC) -c $(CFLAGS) -o $@ $<
254
255%.so: %.c
256	$(CC) -fPIC -shared $(CFLAGS) -o $@ $<
257
258%.dylib: %.c
259	$(CC) -fPIC -shared $(CFLAGS) -o $@ $<
260
261$(BIN): $(OBJS) $(LCOMMON_ARCH)
262	$(LD) -o $(BIN) $(OBJS) $(LDFLAGS)
263
264$(HFUZZ_CC_BINS): $(LHFUZZ_ARCH) $(LCOMMON_ARCH) $(HFUZZ_CC_SRCS)
265	$(LD) -o $@ $(HFUZZ_CC_SRCS) $(LDFLAGS) $(CFLAGS) -D_HFUZZ_INC_PATH=$(HFUZZ_INC)
266
267$(LHFUZZ_OBJS): $(LHFUZZ_SRCS)
268	$(CC) -c $(CFLAGS) $(LIBS_CFLAGS) $(CFLAGS_NOBLOCKS) -o $@ $(@:.o=.c)
269
270$(LHFUZZ_ARCH): $(LHFUZZ_OBJS) $(LCOMMON_ARCH)
271	$(AR) rcs $(LHFUZZ_ARCH) $(LHFUZZ_OBJS) $(LCOMMON_OBJS)
272
273$(LCOMMON_OBJS): $(LCOMMON_SRCS)
274	$(CC) -c $(CFLAGS) $(LIBS_CFLAGS) $(CFLAGS_NOBLOCKS) -o $@ $(@:.o=.c)
275
276$(LCOMMON_ARCH): $(LCOMMON_OBJS)
277	$(AR) rcs $(LCOMMON_ARCH) $(LCOMMON_OBJS)
278
279.PHONY: clean
280clean:
281	$(RM) -r $(CLEAN_TARGETS)
282
283.PHONY: indent
284indent:
285	clang-format -style="{BasedOnStyle: Google, IndentWidth: 4, ColumnLimit: 100, AlignAfterOpenBracket: false}" -i -sort-includes  *.c *.h */*.c */*.h
286
287.PHONY: depend
288depend:
289	makedepend -Y. -Y* -- *.c */*.c
290
291.PHONY: android
292android:
293	$(info ***************************************************************)
294	$(info *                 Use Android NDK 15 or newer                 *)
295	$(info ***************************************************************)
296	@ANDROID_API=$(ANDROID_API) third_party/android/scripts/compile-libunwind.sh \
297	third_party/android/libunwind $(ANDROID_ARCH_CPU)
298
299	@ANDROID_API=$(ANDROID_API) third_party/android/scripts/compile-capstone.sh \
300	third_party/android/capstone $(ANDROID_ARCH_CPU)
301
302  ifeq ($(ANDROID_CLANG),true)
303		@ANDROID_API=$(ANDROID_API) third_party/android/scripts/compile-libBlocksRuntime.sh \
304		third_party/android/libBlocksRuntime $(ANDROID_ARCH_CPU)
305  endif
306
307	ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./android/Android.mk \
308    APP_PLATFORM=$(ANDROID_API) APP_ABI=$(ANDROID_APP_ABI) \
309    NDK_TOOLCHAIN=$(ANDROID_NDK_TOOLCHAIN) NDK_TOOLCHAIN_VERSION=$(ANDROID_NDK_TOOLCHAIN_VER) \
310    $(NDK_BUILD_ARGS) APP_MODULES='honggfuzz hfuzz'
311
312# Loop all ABIs and pass-through flags since visibility is lost due to sub-process
313.PHONY: android-all
314android-all:
315	@echo "Cleaning workspace:"
316	$(MAKE) clean
317	@echo ""
318
319	@for abi in armeabi armeabi-v7a arm64-v8a x86 x86_64; do \
320	  ANDROID_APP_ABI=$$abi ANDROID_SKIP_CLEAN=true ANDROID_CLANG=$(ANDROID_CLANG) \
321	  ANDROID_API=$(ANDROID_API) ANDROID_DEBUG_ENABLED=$(ANDROID_DEBUG_ENABLED) \
322	  $(MAKE) android || { \
323	    echo "Recursive make failed"; exit 1; }; \
324	  echo ""; \
325	done
326
327.PHONY: android-clean-deps
328android-clean-deps:
329	@for cpu in arm arm64 x86 x86_64; do \
330	  make -C "third_party/android/capstone" clean; \
331	  rm -rf "third_party/android/capstone/$$cpu"; \
332	  make -C "third_party/android/libunwind" clean; \
333	  rm -rf "third_party/android/libunwind/$$cpu"; \
334	  ndk-build -C "third_party/android/libBlocksRuntime" \
335	    NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=Android.mk clean; \
336	  rm -rf "third_party/android/libBlocksRuntime/$$cpu"; \
337	done
338
339# DO NOT DELETE
340
341cmdline.o: cmdline.h honggfuzz.h libcommon/util.h libcommon/common.h
342cmdline.o: libcommon/files.h libcommon/common.h libcommon/log.h
343display.o: display.h honggfuzz.h libcommon/util.h libcommon/common.h
344display.o: libcommon/log.h libcommon/common.h
345fuzz.o: fuzz.h honggfuzz.h libcommon/util.h arch.h input.h libcommon/common.h
346fuzz.o: libcommon/files.h libcommon/common.h libcommon/log.h mangle.h
347fuzz.o: report.h sancov.h sanitizers.h subproc.h
348honggfuzz.o: cmdline.h honggfuzz.h libcommon/util.h libcommon/common.h
349honggfuzz.o: display.h fuzz.h input.h libcommon/files.h libcommon/common.h
350honggfuzz.o: libcommon/log.h
351input.o: input.h honggfuzz.h libcommon/util.h libcommon/common.h
352input.o: libcommon/files.h libcommon/common.h libcommon/log.h
353mangle.o: mangle.h honggfuzz.h libcommon/util.h libcommon/common.h
354mangle.o: libcommon/log.h libcommon/common.h
355report.o: report.h honggfuzz.h libcommon/util.h libcommon/common.h
356report.o: libcommon/log.h libcommon/common.h
357sancov.o: sancov.h honggfuzz.h libcommon/util.h libcommon/common.h
358sancov.o: libcommon/files.h libcommon/common.h libcommon/log.h sanitizers.h
359sanitizers.o: sanitizers.h honggfuzz.h libcommon/util.h libcommon/common.h
360sanitizers.o: libcommon/files.h libcommon/common.h libcommon/log.h
361subproc.o: subproc.h honggfuzz.h libcommon/util.h arch.h fuzz.h
362subproc.o: libcommon/common.h libcommon/files.h libcommon/common.h
363subproc.o: libcommon/log.h sanitizers.h
364hfuzz_cc/hfuzz-cc.o: honggfuzz.h libcommon/util.h libcommon/common.h
365hfuzz_cc/hfuzz-cc.o: libcommon/files.h libcommon/common.h libcommon/log.h
366libcommon/files.o: libcommon/files.h libcommon/common.h libcommon/log.h
367libcommon/files.o: libcommon/util.h
368libcommon/log.o: libcommon/log.h libcommon/common.h libcommon/util.h
369libcommon/ns.o: libcommon/ns.h libcommon/common.h libcommon/files.h
370libcommon/ns.o: libcommon/log.h
371libcommon/util.o: libcommon/util.h libcommon/common.h libcommon/files.h
372libcommon/util.o: libcommon/log.h
373libhfuzz/instrument.o: libhfuzz/instrument.h honggfuzz.h libcommon/util.h
374libhfuzz/instrument.o: libcommon/common.h libcommon/log.h libcommon/common.h
375libhfuzz/linux.o: libcommon/common.h libhfuzz/libhfuzz.h libcommon/files.h
376libhfuzz/linux.o: libcommon/common.h libcommon/log.h libcommon/ns.h
377libhfuzz/memorycmp.o: libhfuzz/instrument.h
378libhfuzz/persistent.o: libhfuzz/libhfuzz.h honggfuzz.h libcommon/util.h
379libhfuzz/persistent.o: libcommon/common.h libcommon/files.h
380libhfuzz/persistent.o: libcommon/common.h libcommon/log.h
381linux/arch.o: arch.h honggfuzz.h libcommon/util.h fuzz.h libcommon/common.h
382linux/arch.o: libcommon/files.h libcommon/common.h libcommon/log.h
383linux/arch.o: libcommon/ns.h linux/perf.h linux/trace.h sancov.h sanitizers.h
384linux/arch.o: subproc.h
385linux/bfd.o: linux/bfd.h linux/unwind.h honggfuzz.h libcommon/util.h
386linux/bfd.o: libcommon/common.h libcommon/files.h libcommon/common.h
387linux/bfd.o: libcommon/log.h
388linux/perf.o: linux/perf.h honggfuzz.h libcommon/util.h libcommon/common.h
389linux/perf.o: libcommon/files.h libcommon/common.h libcommon/log.h linux/pt.h
390linux/pt.o: libcommon/common.h libcommon/log.h libcommon/common.h
391linux/pt.o: libcommon/util.h linux/pt.h honggfuzz.h
392linux/trace.o: linux/trace.h honggfuzz.h libcommon/util.h libcommon/common.h
393linux/trace.o: libcommon/files.h libcommon/common.h libcommon/log.h
394linux/trace.o: linux/bfd.h linux/unwind.h sancov.h sanitizers.h subproc.h
395linux/unwind.o: linux/unwind.h honggfuzz.h libcommon/util.h
396linux/unwind.o: libcommon/common.h libcommon/log.h libcommon/common.h
397mac/arch.o: arch.h honggfuzz.h libcommon/util.h libcommon/common.h
398mac/arch.o: libcommon/files.h libcommon/common.h libcommon/log.h sancov.h
399mac/arch.o: subproc.h
400posix/arch.o: arch.h honggfuzz.h libcommon/util.h fuzz.h libcommon/common.h
401posix/arch.o: libcommon/files.h libcommon/common.h libcommon/log.h sancov.h
402posix/arch.o: subproc.h
403