Merge "Adding USB exception for mschilder."
diff --git a/common.mk b/common.mk
index f375ce3..058e906 100644
--- a/common.mk
+++ b/common.mk
@@ -64,7 +64,11 @@
 # Possible command line variables:
 #   - COLOR=[0|1] to set ANSI color output (default: 1)
 #   - VERBOSE=[0|1] to hide/show commands (default: 0)
-#   - MODE=dbg to turn down optimizations (default: opt)
+#   - MODE=[opt|dbg|profiling] (default: opt)
+#          opt - Enable optimizations for release builds
+#          dbg - Turn down optimization for debugging
+#          profiling - Turn off optimization and turn on profiling/coverage
+#                      support.
 #   - ARCH=[x86|arm|supported qemu name] (default: from portage or uname -m)
 #   - SPLITDEBUG=[0|1] splits debug info in target.debug (default: 0)
 #        If NOSTRIP=1, SPLITDEBUG will never strip the final emitted objects.
@@ -97,8 +101,6 @@
 VERBOSE ?= 0
 MODE ?= opt
 ARCH ?= $(shell uname -m)
-# TODO: profiling support not completed.
-PROFILING ?= 0
 NEEDS_ROOT = 0
 NEEDS_MOUNTS = 0
 
@@ -161,8 +163,7 @@
 _all::
 %::
 	$(if $(filter 0,$(RUN_ONCE)), \
-	  $(QUIET)mkdir -p "$(OUT)" && \
-	  cd $(OUT) && \
+	  cd "$(OUT)" && \
 	  $(MAKE) -r -I "$(SRC)" -f "$(CURDIR)/Makefile" \
 	    SRC="$(CURDIR)" OUT="$(OUT)" $(foreach g,$(MAKECMDGOALS),"$(g)"),)
 	$(eval RUN_ONCE := 1)
@@ -182,10 +183,15 @@
 # Helper macros
 #
 
+# Create the directory if it doesn't yet exist.
+define auto_mkdir
+  $(if $(wildcard $(dir $1)),$2,$(QUIET)mkdir -p "$(dir $1)")
+endef
+
 # Creates the actual archive with an index.
 # The target $@ must end with .pic.a or .pie.a.
 define update_archive
-  $(QUIET)mkdir -p "$(dir $(TARGET_OR_MEMBER))"
+  $(call auto_mkdir,$(TARGET_OR_MEMBER))
   $(QUIET)# Create the archive in one step to avoid parallel use accessing it
   $(QUIET)# before all the symbols are present.
   @$(ECHO) "AR		$(subst \
@@ -235,24 +241,34 @@
 # Default variable values
 #
 
-OBJCOPY ?= objcopy
-STRIP ?= strip
+# Only override toolchain vars if they are from make.
+CROSS_COMPILE ?=
+define override_var
+ifneq ($(filter undefined default,$(origin $1)),)
+$1 = $(CROSS_COMPILE)$2
+endif
+endef
+$(eval $(call override_var,AR,ar))
+$(eval $(call override_var,CC,gcc))
+$(eval $(call override_var,CXX,g++))
+$(eval $(call override_var,OBJCOPY,objcopy))
+$(eval $(call override_var,PKG_CONFIG,pkg-config))
+$(eval $(call override_var,RANLIB,ranlib))
+$(eval $(call override_var,STRIP,strip))
+
 RMDIR ?= rmdir
-# Only override CC and CXX if they are from make.
-ifeq ($(origin CC), default)
-  CC = gcc
-endif
-ifeq ($(origin CXX), default)
-  CXX = g++
-endif
-ifeq ($(origin RANLIB), default)
-  RANLIB = ranlib
-endif
-RANLIB ?= ranlib
 ECHO = /bin/echo -e
 
-ifeq ($(PROFILING),1)
-  $(warning PROFILING=1 disables relocatable executables.)
+ifeq ($(lastword $(subst /, ,$(CC))),clang)
+CDRIVER = clang
+else
+CDRIVER = gcc
+endif
+
+ifeq ($(lastword $(subst /, ,$(CXX))),clang++)
+CXXDRIVER = clang
+else
+CXXDRIVER = gcc
 endif
 
 # To update these from an including Makefile:
@@ -260,16 +276,14 @@
 #  CXXFLAGS := -mahflag $(CXXFLAGS) # Prepend to the list
 #  CXXFLAGS := $(filter-out badflag,$(CXXFLAGS)) # Filter out a value
 # The same goes for CFLAGS.
-COMMON_CFLAGS := -Wall -Werror -fstack-protector-strong -fno-strict-aliasing \
-  -ggdb3 -Wa,--noexecstack -O1 -fvisibility=internal -Wformat=2
-CXXFLAGS += $(COMMON_CFLAGS)
-CFLAGS += $(COMMON_CFLAGS)
+COMMON_CFLAGS-gcc := -fstack-protector-strong -fvisibility=internal -ggdb3 \
+  -Wa,--noexecstack
+COMMON_CFLAGS-clang := -fstack-protector-all -fvisibility=hidden -ggdb
+COMMON_CFLAGS := -Wall -Werror -fno-strict-aliasing -O1 -Wformat=2
+CXXFLAGS += $(COMMON_CFLAGS) $(COMMON_CFLAGS-$(CXXDRIVER))
+CFLAGS += $(COMMON_CFLAGS) $(COMMON_CFLAGS-$(CDRIVER))
 CPPFLAGS += -D_FORTIFY_SOURCE=2
 
-ifeq ($(PROFILING),1)
-  CFLAGS := -pg
-  CXXFLAGS := -pg
-endif
 
 ifeq ($(MODE),opt)
   # Up the optimizations.
@@ -283,6 +297,12 @@
   endif
 endif
 
+ifeq ($(MODE),profiling)
+  CFLAGS := $(CFLAGS) -O0 -g  --coverage
+  CXXFLAGS := $(CXXFLAGS) -O0 -g  --coverage
+  LDFLAGS := $(LDFLAGS) --coverage
+endif
+
 LDFLAGS := $(LDFLAGS) -Wl,-z,relro -Wl,-z,noexecstack -Wl,-z,now
 
 # Fancy helpers for color if a prompt is defined
@@ -322,7 +342,7 @@
 # all non-.o files.
 define COMPILE_BINARY_implementation
   @$(ECHO) "LD$(1)		$(subst $(PWD)/,,$(TARGET_OR_MEMBER))"
-  $(QUIET)mkdir -p "$(dir $(TARGET_OR_MEMBER))"
+  $(call auto_mkdir,$(TARGET_OR_MEMBER))
   $(QUIET)$($(1)) $(COMPILE_PIE_FLAGS) -o $(TARGET_OR_MEMBER) \
     $(2) $(LDFLAGS) \
     $(filter %.o %.a,$(^:.o=.pie.o)) \
@@ -346,7 +366,7 @@
 COMMA := ,
 define COMPILE_LIBRARY_implementation
   @$(ECHO) "SHARED$(1)	$(subst $(PWD)/,,$(TARGET_OR_MEMBER))"
-  $(QUIET)mkdir -p "$(dir $(TARGET_OR_MEMBER))"
+  $(call auto_mkdir,$(TARGET_OR_MEMBER))
   $(QUIET)$($(1)) -shared -Wl,-E -o $(TARGET_OR_MEMBER) \
     $(2) $(LDFLAGS) \
     $(if $(filter %.a,$^),-Wl$(COMMA)--whole-archive,) \
@@ -501,30 +521,30 @@
 # $(5) source dir: _only_ if $(SRC). Leave blank for obj tree.
 define add_object_rules
 $(patsubst %.o,%.pie.o,$(1)): %.pie.o: $(5)%.$(3) %.o.depends
-	$$(QUIET)mkdir -p "$$(dir $$@)"
+	$$(call auto_mkdir,$$@)
 	$$(call OBJECT_PATTERN_implementation,$(2),\
           $$(basename $$@),$$($(4)) $$(CPPFLAGS) $$(OBJ_PIE_FLAG))
 
 $(patsubst %.o,%.pic.o,$(1)): %.pic.o: $(5)%.$(3) %.o.depends
-	$$(QUIET)mkdir -p "$$(dir $$@)"
+	$$(call auto_mkdir,$$@)
 	$$(call OBJECT_PATTERN_implementation,$(2),\
           $$(basename $$@),$$($(4)) $$(CPPFLAGS) -fPIC)
 
 # Placeholder for depends
 $(patsubst %.o,%.o.depends,$(1)):
-	$$(QUIET)mkdir -p "$$(dir $$@)"
+	$$(call auto_mkdir,$$@)
 	$$(QUIET)touch "$$@"
 
 $(1): %.o: %.pic.o %.pie.o
-	$$(QUIET)mkdir -p "$$(dir $$@)"
+	$$(call auto_mkdir,$$@)
 	$$(QUIET)touch "$$@"
 endef
 
 define OBJECT_PATTERN_implementation
   @$(ECHO) "$(1)		$(subst $(SRC)/,,$<) -> $(2).o"
-  $(QUIET)mkdir -p "$(dir $(2))"
+  $(call auto_mkdir,$@)
   $(QUIET)$($(1)) -c -MD -MF $(2).d $(3) -o $(2).o $<
-  $(QUIET)# Wrap all the deps in $(wildcard) so a missing header
+  $(QUIET)# Wrap all the deps in $$(wildcard) so a missing header
   $(QUIET)# won't cause weirdness.  First we remove newlines and \,
   $(QUIET)# then wrap it.
   $(QUIET)sed -i -e :j -e '$$!N;s|\\\s*\n| |;tj' \
@@ -612,7 +632,6 @@
   $(info - ARCH=$(ARCH))
   $(info - QEMU_ARCH=$(QEMU_ARCH))
   $(info - SYSROOT=$(SYSROOT))
-  $(info - ROOT=$(ROOT))
   $(info )
 endif
 
@@ -628,7 +647,27 @@
 
 # Builds and runs tests for the target arch
 # Run them in parallel
+# After the test have completed, if profiling, run coverage analysis
 tests:
+ifeq ($(MODE),profiling)
+	@$(ECHO) -n "COVERAGE		gcov "
+	@$(ECHO) "[$(COLOR_YELLOW)STARTED$(COLOR_RESET)]"
+	$(QUIET)(FILES="";						\
+		for GCNO in `find . -name "*.gcno"`;			\
+		do							\
+			GCDA="$${GCNO%.gcno}.gcda";			\
+			[ -e $${GCDA} ] && FILES="$${FILES} $${GCDA}";	\
+		done;							\
+		gcov -l $${FILES})
+	@$(ECHO) -n "COVERAGE		gcov "
+	@$(ECHO) "[$(COLOR_YELLOW)FINISHED$(COLOR_RESET)]"
+	@$(ECHO) -n "COVERAGE		lcov "
+	@$(ECHO) "[$(COLOR_YELLOW)STARTED$(COLOR_RESET)]"
+	$(QUIET)lcov --capture --directory . --output-file=lcov-coverage.info
+	$(QUIET)genhtml lcov-coverage.info --output-directory lcov-html
+	@$(ECHO) -n "COVERAGE		lcov "
+	@$(ECHO) "[$(COLOR_YELLOW)FINISHED$(COLOR_RESET)]"
+endif
 .PHONY: tests
 
 qemu_clean:
@@ -733,6 +772,8 @@
 clean: qemu_clean
 clean: CLEAN($(OUT)*.d) CLEAN($(OUT)*.o) CLEAN($(OUT)*.debug)
 clean: CLEAN($(OUT)*.test) CLEAN($(OUT)*.depends)
+clean: CLEAN($(OUT)*.gcno) CLEAN($(OUT)*.gcda) CLEAN($(OUT)*.gcov)
+clean: CLEAN($(OUT)lcov-coverage.info) CLEAN($(OUT)lcov-html)
 
 clean:
 	$(QUIET)# Always delete the containing directory last.
@@ -776,6 +817,9 @@
 clean: CLEAN($(OUT)$(MODULE)/*.d) CLEAN($(OUT)$(MODULE)/*.o)
 clean: CLEAN($(OUT)$(MODULE)/*.debug) CLEAN($(OUT)$(MODULE)/*.test)
 clean: CLEAN($(OUT)$(MODULE)/*.depends)
+clean: CLEAN($(OUT)$(MODULE)/*.gcno) CLEAN($(OUT)$(MODULE)/*.gcda)
+clean: CLEAN($(OUT)$(MODULE)/*.gcov) CLEAN($(OUT)lcov-coverage.info)
+clean: CLEAN($(OUT)lcov-html)
 
 $(info + submodule: $(MODULE_NAME))
 # We must eval otherwise they may be dropped.