Add a new imgdiag tool to diff boot.art/core.art against a process

Analyze the dirty memory pages of a running process per-object,
this allows is to to fine-tune the dirty object binning algorithm in
image writer.

Also:
* Factor out oatdump command line parsing code into cmdline.h
* Factor out common build rules for building variations of binaries
* Add a gtest for imgdiag

Bug: 17611661
Change-Id: I3ac852a0d223af66f6d59ae5dbc3df101475e3d0
diff --git a/build/Android.executable.mk b/build/Android.executable.mk
index be97e82..ef9e7cd 100644
--- a/build/Android.executable.mk
+++ b/build/Android.executable.mk
@@ -47,12 +47,13 @@
   art_target_or_host := $(5)
   art_ndebug_or_debug := $(6)
   art_multilib := $(7)
+  art_out_binary_name :=
 
   include $(CLEAR_VARS)
   LOCAL_CPP_EXTENSION := $(ART_CPP_EXTENSION)
   LOCAL_MODULE_TAGS := optional
   LOCAL_SRC_FILES := $$(art_source)
-  LOCAL_C_INCLUDES += $(ART_C_INCLUDES) art/runtime $$(art_c_includes)
+  LOCAL_C_INCLUDES += $(ART_C_INCLUDES) art/runtime art/cmdline $$(art_c_includes)
   LOCAL_SHARED_LIBRARIES += $$(art_shared_libraries)
   LOCAL_WHOLE_STATIC_LIBRARIES += libsigchain
 
@@ -91,32 +92,114 @@
   endif
 
   LOCAL_ADDITIONAL_DEPENDENCIES := art/build/Android.common_build.mk
+  LOCAL_ADDITIONAL_DEPENDENCIES += art/build/Android.common_utils.mk
   LOCAL_ADDITIONAL_DEPENDENCIES += art/build/Android.executable.mk
 
   ifeq ($$(art_target_or_host),target)
     LOCAL_MODULE_TARGET_ARCH := $(ART_SUPPORTED_ARCH)
   endif
 
-  # If multilib, need to provide stem.
   LOCAL_MULTILIB := $$(art_multilib)
+  art_out_binary_name := $$(LOCAL_MODULE)
+
+  # If multilib=both (potentially building both 32-bit and 64-bit), need to provide stem.
   ifeq ($$(art_multilib),both)
-    ifeq ($$(art_ndebug_or_debug),ndebug)
-      LOCAL_MODULE_STEM_32 := $$(art_executable)32
-      LOCAL_MODULE_STEM_64 := $$(art_executable)
-    else #debug
-      LOCAL_MODULE_STEM_32 := $$(art_executable)d32
-      LOCAL_MODULE_STEM_64 := $$(art_executable)d
+    # Set up a 32-bit/64-bit stem if we are building both binaries.
+    # In this case, the 32-bit binary has an additional 32-bit suffix.
+    LOCAL_MODULE_STEM_32 := $$(LOCAL_MODULE)32
+    LOCAL_MODULE_STEM_64 := $$(LOCAL_MODULE)
+
+    # Remember the binary names so we can add them to the global art executables list later.
+    art_out_binary_name := $$(LOCAL_MODULE_STEM_32) $$(LOCAL_MODULE_STEM_64)
+
+    # For single-architecture targets, remove any binary name suffixes.
+    ifeq ($$(art_target_or_host),target)
+      ifeq (,$(TARGET_2ND_ARCH))
+        LOCAL_MODULE_STEM_32 := $$(LOCAL_MODULE)
+        art_out_binary_name := $$(LOCAL_MODULE)
+      endif
+    endif
+
+    # For single-architecture hosts, remove any binary name suffixes.
+    ifeq ($$(art_target_or_host),host)
+      ifeq (,$(HOST_2ND_ARCH))
+        LOCAL_MODULE_STEM_32 := $$(LOCAL_MODULE)
+        art_out_binary_name := $$(LOCAL_MODULE)
+      endif
     endif
   endif
 
   include external/libcxx/libcxx.mk
   ifeq ($$(art_target_or_host),target)
     include $(BUILD_EXECUTABLE)
-    ART_TARGET_EXECUTABLES := $(ART_TARGET_EXECUTABLES) $(TARGET_OUT_EXECUTABLES)/$$(LOCAL_MODULE)
+    ART_TARGET_EXECUTABLES := $(ART_TARGET_EXECUTABLES) $$(foreach name,$$(art_out_binary_name),$(TARGET_OUT_EXECUTABLES)/$$(name))
   else # host
     LOCAL_IS_HOST_MODULE := true
     include $(BUILD_HOST_EXECUTABLE)
-    ART_HOST_EXECUTABLES := $(ART_HOST_EXECUTABLES) $(HOST_OUT_EXECUTABLES)/$$(LOCAL_MODULE)
+    ART_HOST_EXECUTABLES := $(ART_HOST_EXECUTABLES) $$(foreach name,$$(art_out_binary_name),$(HOST_OUT_EXECUTABLES)/$$(name))
   endif
 
+  # Clear out local variables now that we're done with them.
+  art_executable :=
+  art_source :=
+  art_shared_libraries :=
+  art_c_includes :=
+  art_target_or_host :=
+  art_ndebug_or_debug :=
+  art_multilib :=
+  art_out_binary_name :=
+
+endef
+
+#
+# Build many art executables from multiple variations (debug/ndebug, host/target, 32/64bit).
+# By default only either 32-bit or 64-bit is built (but not both -- see multilib arg).
+# All other variations are gated by ANDROID_BUILD_(TARGET|HOST)_[N]DEBUG.
+# The result must be eval-uated.
+#
+# $(1): executable name
+# $(2): source files
+# $(3): library dependencies (common); debug prefix is added on as necessary automatically.
+# $(4): library dependencies (target only)
+# $(5): library dependencies (host only)
+# $(6): extra include directories
+# $(7): multilib (default: empty), valid values: {,32,64,both})
+define build-art-multi-executable
+  $(foreach debug_flavor,ndebug debug,
+    $(foreach target_flavor,host target,
+      art-multi-binary-name := $(1)
+      art-multi-source-files := $(2)
+      art-multi-lib-dependencies := $(3)
+      art-multi-lib-dependencies-target := $(4)
+      art-multi-lib-dependencies-host := $(5)
+      art-multi-include-extra := $(6)
+      art-multi-multilib := $(7)
+
+      # Add either -host or -target specific lib dependencies to the lib dependencies.
+      art-multi-lib-dependencies += $$(art-multi-lib-dependencies-$(target_flavor))
+
+      # Replace libart- prefix with libartd- for debug flavor.
+      ifeq ($(debug_flavor),debug)
+        art-multi-lib-dependencies := $$(subst libart-,libartd-,$$(art-multi-lib-dependencies))
+      endif
+
+      # Build the env guard var name, e.g. ART_BUILD_HOST_NDEBUG.
+      art-multi-env-guard := $$(call art-string-to-uppercase,ART_BUILD_$(target_flavor)_$(debug_flavor))
+
+      # Build the art executable only if the corresponding env guard was set.
+      ifeq ($$($$(art-multi-env-guard)),true)
+        $$(eval $$(call build-art-executable,$$(art-multi-binary-name),$$(art-multi-source-files),$$(art-multi-lib-dependencies),$$(art-multi-include-extra),$(target_flavor),$(debug_flavor),$$(art-multi-multilib)))
+      endif
+
+      # Clear locals now they've served their purpose.
+      art-multi-binary-name :=
+      art-multi-source-files :=
+      art-multi-lib-dependencies :=
+      art-multi-lib-dependencies-target :=
+      art-multi-lib-dependencies-host :=
+      art-multi-include-extra :=
+      art-multi-multilib :=
+      art-multi-env-guard :=
+    )
+  )
 endef