Add support for asm-level filtering through LOCAL_FILTER_ASM
Change-Id: I937e9f8e53debf8a4eb3b64151ed8738d75158ac
diff --git a/build/core/definitions.mk b/build/core/definitions.mk
index b52c999..d749dd9 100644
--- a/build/core/definitions.mk
+++ b/build/core/definitions.mk
@@ -174,6 +174,7 @@
EXPORT_CPPFLAGS \
EXPORT_LDLIBS \
EXPORT_C_INCLUDES \
+ FILTER_ASM \
# The following are generated by the build scripts themselves
@@ -785,6 +786,102 @@
hide = @
endif
+# This assumes that many variables have been pre-defined:
+# _SRC: source file
+# _OBJ: destination file
+# _CC: 'compiler' command
+# _FLAGS: 'compiler' flags
+# _TEXT: Display text (e.g. "Compile++ thumb", must be EXACTLY 15 chars long)
+#
+define ev-build-file
+$$(_OBJ): PRIVATE_SRC := $$(_SRC)
+$$(_OBJ): PRIVATE_OBJ := $$(_OBJ)
+$$(_OBJ): PRIVATE_MODULE := $$(LOCAL_MODULE)
+$$(_OBJ): PRIVATE_TEXT := "$$(_TEXT)"
+$$(_OBJ): PRIVATE_CC := $$(_CC)
+$$(_OBJ): PRIVATE_CFLAGS := $$(_FLAGS)
+$$(_OBJ): $$(_SRC) $$(LOCAL_MAKEFILE) $$(NDK_APP_APPLICATION_MK)
+ @mkdir -p $$(dir $$(PRIVATE_OBJ))
+ @echo "$$(PRIVATE_TEXT) : $$(PRIVATE_MODULE) <= $$(notdir $$(PRIVATE_SRC))"
+ $(hide) $$(PRIVATE_CC) $$(PRIVATE_CFLAGS) $$(PRIVATE_SRC) -o $$(PRIVATE_OBJ)
+endef
+
+# This assumes the same things than ev-build-file, but will handle
+# the definition of LOCAL_FILTER_ASM as well.
+define ev-build-source-file
+LOCAL_DEPENDENCY_DIRS += $$(dir $$(_OBJ))
+ifndef LOCAL_FILTER_ASM
+ # Trivial case: Directly generate an object file
+ $$(eval $$(call ev-build-file))
+ LOCAL_OBJECTS += $$(_OBJ)
+else
+ # This is where things get hairy, we first transform
+ # the source into an assembler file, send it to the
+ # filter, then generate a final object file from it.
+ #
+
+ # First, remember the original settings and compute
+ # the location of our temporary files.
+ #
+ _ORG_SRC := $$(_SRC)
+ _ORG_OBJ := $$(_OBJ)
+ _ORG_FLAGS := $$(_FLAGS)
+ _ORG_TEXT := $$(_TEXT)
+
+ _OBJ_ASM_ORIGINAL := $$(patsubst %.o,%.s,$$(_ORG_OBJ))
+ _OBJ_ASM_FILTERED := $$(patsubst %.o,%.filtered.s,$$(_ORG_OBJ))
+
+ # If the source file is a plain assembler file, we're going to
+ # use it directly in our filter.
+ ifneq (,$$(filter %.s,$$(_SRC)))
+ _OBJ_ASM_ORIGINAL := $$(_SRC)
+ endif
+
+ $$(info SRC=$$(_SRC) OBJ=$$(_OBJ) OBJ_ORIGINAL=$$(_OBJ_ASM_ORIGINAL) OBJ_FILTERED=$$(_OBJ_ASM_FILTERED))
+
+ # We need to transform the source into an assembly file, instead of
+ # an object. The proper way to do that depends on the file extension.
+ #
+ # For C and C++ source files, simply replace the -c by an -S in the
+ # compilation command (this forces the compiler to generate an
+ # assembly file).
+ #
+ # For assembler templates (which end in .S), replace the -c with -E
+ # to send it to the preprocessor instead.
+ #
+ # Don't do anything for plain assembly files (which end in .s)
+ #
+ ifeq (,$$(filter %.s,$$(_SRC)))
+ _OBJ := $$(_OBJ_ASM_ORIGINAL)
+ ifneq (,$$(filter %.S,$$(_SRC)))
+ _FLAGS := $$(patsubst -c,-E,$$(_ORG_FLAGS))
+ else
+ _FLAGS := $$(patsubst -c,-S,$$(_ORG_FLAGS))
+ endif
+ $$(eval $$(call ev-build-file))
+ endif
+
+ # Next, process the assembly file with the filter
+ $$(_OBJ_ASM_FILTERED): PRIVATE_SRC := $$(_OBJ_ASM_ORIGINAL)
+ $$(_OBJ_ASM_FILTERED): PRIVATE_DST := $$(_OBJ_ASM_FILTERED)
+ $$(_OBJ_ASM_FILTERED): PRIVATE_FILTER := $$(LOCAL_FILTER_ASM)
+ $$(_OBJ_ASM_FILTERED): PRIVATE_MODULE := $$(LOCAL_MODULE)
+ $$(_OBJ_ASM_FILTERED): $$(_OBJ_ASM_ORIGINAL)
+ @echo "AsmFilter : $$(PRIVATE_MODULE) <= $$(notdir $$(PRIVATE_SRC))"
+ $(hide) $$(PRIVATE_FILTER) $$(PRIVATE_SRC) $$(PRIVATE_DST)
+
+ # Then, generate the final object, we need to keep assembler-specific
+ # flags which look like -Wa,<option>:
+ _SRC := $$(_OBJ_ASM_FILTERED)
+ _OBJ := $$(_ORG_OBJ)
+ _FLAGS := $$(filter -Wa%,$$(_ORG_FLAGS)) -c
+ _TEXT := "Assembly "
+ $$(eval $$(call ev-build-file))
+
+ LOCAL_OBJECTS += $$(_ORG_OBJ)
+endif
+endef
+
# -----------------------------------------------------------------------------
# Template : ev-compile-c-source
# Arguments : 1: single C source file name (relative to LOCAL_PATH)
@@ -798,30 +895,19 @@
_SRC:=$$(LOCAL_PATH)/$(1)
_OBJ:=$$(LOCAL_OBJS_DIR)/$(2)
-$$(_OBJ): PRIVATE_SRC := $$(_SRC)
-$$(_OBJ): PRIVATE_OBJ := $$(_OBJ)
-$$(_OBJ): PRIVATE_MODULE := $$(LOCAL_MODULE)
-$$(_OBJ): PRIVATE_ARM_MODE := $$(LOCAL_ARM_MODE)
-$$(_OBJ): PRIVATE_ARM_TEXT := $$(call get-src-file-text,$1)
-$$(_OBJ): PRIVATE_CC := $$($$(my)CC)
-$$(_OBJ): PRIVATE_CFLAGS := $$($$(my)CFLAGS) \
- $$(call get-src-file-target-cflags,$(1)) \
- $$(LOCAL_C_INCLUDES:%=-I%) \
- -I$$(LOCAL_PATH) \
- $$(LOCAL_CFLAGS) \
- $$(NDK_APP_CFLAGS) \
- $$($(my)C_INCLUDES:%=-I%) \
+_FLAGS := $$($$(my)CFLAGS) \
+ $$(call get-src-file-target-cflags,$(1)) \
+ $$(LOCAL_C_INCLUDES:%=-I%) \
+ -I$$(LOCAL_PATH) \
+ $$(LOCAL_CFLAGS) \
+ $$(NDK_APP_CFLAGS) \
+ $$($(my)C_INCLUDES:%=-I%) \
+ -MMD -MP -MF $$(_OBJ).d -c \
-$$(_OBJ): $$(_SRC) $$(LOCAL_MAKEFILE) $$(NDK_APP_APPLICATION_MK)
- @mkdir -p $$(dir $$(PRIVATE_OBJ))
- @echo "Compile $$(PRIVATE_ARM_TEXT) : $$(PRIVATE_MODULE) <= $$(PRIVATE_SRC)"
- $(hide) $$(PRIVATE_CC) $$(PRIVATE_CFLAGS) -c \
- -MMD -MP -MF $$(PRIVATE_OBJ).d \
- $$(PRIVATE_SRC) \
- -o $$(PRIVATE_OBJ)
+_TEXT := "Compile $$(call get-src-file-text,$1)"
+_CC := $$(TARGET_CC)
-LOCAL_OBJECTS += $$(_OBJ)
-LOCAL_DEPENDENCY_DIRS += $$(dir $$(_OBJ))
+$$(eval $$(call ev-build-source-file))
endef
# -----------------------------------------------------------------------------
@@ -840,7 +926,7 @@
# Usage : $(call compile-s-source,<srcfile>)
# Rationale : Setup everything required to build a single Assembly source file
# -----------------------------------------------------------------------------
-compile-s-source = $(eval $(call ev-compile-c-source,$1,$(1:%.S=%.o)))
+compile-s-source = $(eval $(call ev-compile-c-source,$1,$(patsubst %.s,%.o,$(patsubst %.S,%.o,$1))))
# -----------------------------------------------------------------------------
@@ -855,35 +941,23 @@
define ev-compile-cpp-source
_SRC:=$$(LOCAL_PATH)/$(1)
_OBJ:=$$(LOCAL_OBJS_DIR)/$(2)
+_FLAGS := $$($$(my)CXXFLAGS) \
+ $$(call get-src-file-target-cflags,$(1)) \
+ $$(LOCAL_C_INCLUDES:%=-I%) \
+ -I$$(LOCAL_PATH) \
+ $$(LOCAL_CFLAGS) \
+ $$(LOCAL_CPPFLAGS) \
+ $$(LOCAL_CXXFLAGS) \
+ $$(NDK_APP_CFLAGS) \
+ $$(NDK_APP_CPPFLAGS) \
+ $$(NDK_APP_CXXFLAGS) \
+ $$($(my)C_INCLUDES:%=-I%) \
+ -MMD -MP -MF $$(_OBJ).d -c \
-$$(_OBJ): PRIVATE_SRC := $$(_SRC)
-$$(_OBJ): PRIVATE_OBJ := $$(_OBJ)
-$$(_OBJ): PRIVATE_MODULE := $$(LOCAL_MODULE)
-$$(_OBJ): PRIVATE_ARM_MODE := $$(LOCAL_ARM_MODE)
-$$(_OBJ): PRIVATE_ARM_TEXT := $$(call get-src-file-text,$1)
-$$(_OBJ): PRIVATE_CXX := $$($$(my)CXX)
-$$(_OBJ): PRIVATE_CXXFLAGS := $$($$(my)CXXFLAGS) \
- $$(call get-src-file-target-cflags,$(1)) \
- $$(LOCAL_C_INCLUDES:%=-I%) \
- -I$$(LOCAL_PATH) \
- $$(LOCAL_CFLAGS) \
- $$(LOCAL_CPPFLAGS) \
- $$(LOCAL_CXXFLAGS) \
- $$(NDK_APP_CFLAGS) \
- $$(NDK_APP_CPPFLAGS) \
- $$(NDK_APP_CXXFLAGS) \
- $$($(my)C_INCLUDES:%=-I%) \
+_CC := $$($$(my)CXX)
+_TEXT := "Compile++ $$(call get-src-file-text,$1)"
-$$(_OBJ): $$(_SRC) $$(LOCAL_MAKEFILE) $$(NDK_APP_APPLICATION_MK)
- @mkdir -p $$(dir $$(PRIVATE_OBJ))
- @echo "Compile++ $$(PRIVATE_ARM_TEXT): $$(PRIVATE_MODULE) <= $$(PRIVATE_SRC)"
- $(hide) $$(PRIVATE_CXX) $$(PRIVATE_CXXFLAGS) -c \
- -MMD -MP -MF $$(PRIVATE_OBJ).d \
- $$(PRIVATE_SRC) \
- -o $$(PRIVATE_OBJ)
-
-LOCAL_OBJECTS += $$(_OBJ)
-LOCAL_DEPENDENCY_DIRS += $$(dir $$(_OBJ))
+$$(eval $$(call ev-build-source-file))
endef
# -----------------------------------------------------------------------------
diff --git a/docs/ANDROID-MK.TXT b/docs/ANDROID-MK.TXT
index fd162dc..d4a0b34 100644
--- a/docs/ANDROID-MK.TXT
+++ b/docs/ANDROID-MK.TXT
@@ -649,3 +649,34 @@
There, libbar.so will be built with a -llog at the end of the linker
command to indicate that it depends on the system logging library,
because it depends on 'foo'.
+
+LOCAL_FILTER_ASM
+ Define this variable to a shell command that will be used to filter
+ the assembly files from, or generated from, your LOCAL_SRC_FILES.
+
+ When it is defined, the following happens:
+
+ - Any C or C++ source file is generated into a temporary assembly
+ file (instead of being compiled into an object file).
+
+ - Any temporary assembly file, and any assembly file listed in
+ LOCAL_SRC_FILES is sent through the LOCAL_FILTER_ASM command
+ to generate _another_ temporary assembly file.
+
+ - These filtered assembly files are compiled into object file.
+
+ In other words, If you have:
+
+ LOCAL_SRC_FILES := foo.c bar.S
+ LOCAL_FILTER_ASM := myasmfilter
+
+ foo.c --1--> $OBJS_DIR/foo.S.original --2--> $OBJS_DIR/foo.S --3--> $OBJS_DIR/foo.o
+ bar.S --2--> $OBJS_DIR/bar.S --3--> $OBJS_DIR/bar.o
+
+ Were "1" corresponds to the compiler, "2" to the filter, and "3" to the
+ assembler. The filter must be a standalone shell command that takes the
+ name of the input file as its first argument, and the name of the output
+ file as the second one, as in:
+
+ myasmfilter $OBJS_DIR/foo.S.original $OBJS_DIR/foo.S
+ myasmfilter bar.S $OBJS_DIR/bar.S
diff --git a/docs/CHANGES.TXT b/docs/CHANGES.TXT
index 47c88c6..f392084 100644
--- a/docs/CHANGES.TXT
+++ b/docs/CHANGES.TXT
@@ -57,6 +57,10 @@
When doing a "ndk-build -j<number>", with <number> bigger than 1.
+- Add support for assembly-level source filtering. See the description of
+ LOCAL_FILTER_ASM in docs/ANDROID-MK.TXT for more details. This can be useful
+ for certain kinds of obfuscation tasks.
+
OTHER FIXES & CHANGES:
- The path to system headers is now included last in the compilation command