Merge "Use fstab in the source build"
diff --git a/core/Makefile b/core/Makefile
index 65b4f18..92f1fb6 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -682,7 +682,7 @@
 endif
 
 ifeq ($(BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE),squashfs)
-INTERNAL_USERIMAGES_DEPS += $(MAKE_SQUASHFS) $(MKSQUASHFSUSERIMG)
+INTERNAL_USERIMAGES_DEPS += $(MAKE_SQUASHFS) $(MKSQUASHFSUSERIMG) $(IMG2SIMG)
 endif
 
 INTERNAL_USERIMAGES_BINARY_PATHS := $(sort $(dir $(INTERNAL_USERIMAGES_DEPS)))
@@ -1267,6 +1267,7 @@
   $(HOST_OUT_EXECUTABLES)/build_verity_tree \
   $(HOST_OUT_EXECUTABLES)/verity_signer \
   $(HOST_OUT_EXECUTABLES)/append2simg \
+  $(HOST_OUT_EXECUTABLES)/img2simg \
   $(HOST_OUT_EXECUTABLES)/boot_signer
 
 # Shared libraries.
@@ -1475,6 +1476,10 @@
 	# OTA scripts are only interested in fingerprint related properties
 	$(hide) echo "oem_fingerprint_properties=$(OEM_THUMBPRINT_PROPERTIES)" >> $(zip_root)/META/misc_info.txt
 endif
+ifeq ($(SANITIZE_TARGET),address)
+	# We need to create userdata.img with real data because the instrumented libraries are in userdata.img.
+	$(hide) echo "userdata_img_with_data=true" >> $(zip_root)/META/misc_info.txt
+endif
 	$(call generate-userimage-prop-dictionary, $(zip_root)/META/misc_info.txt)
 	$(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH MKBOOTIMG=$(MKBOOTIMG) \
 	    ./build/tools/releasetools/make_recovery_patch $(zip_root) $(zip_root)
diff --git a/core/config.mk b/core/config.mk
index 07c392a..88a1bcb 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -419,6 +419,7 @@
 MAKE_F2FS := $(HOST_OUT_EXECUTABLES)/make_f2fs$(HOST_EXECUTABLE_SUFFIX)
 MKF2FSUSERIMG := $(HOST_OUT_EXECUTABLES)/mkf2fsuserimg.sh
 SIMG2IMG := $(HOST_OUT_EXECUTABLES)/simg2img$(HOST_EXECUTABLE_SUFFIX)
+IMG2SIMG := $(HOST_OUT_EXECUTABLES)/img2simg$(HOST_EXECUTABLE_SUFFIX)
 E2FSCK := $(HOST_OUT_EXECUTABLES)/e2fsck$(HOST_EXECUTABLE_SUFFIX)
 MKTARBALL := build/tools/mktarball.sh
 TUNE2FS := $(HOST_OUT_EXECUTABLES)/tune2fs$(HOST_EXECUTABLE_SUFFIX)
diff --git a/core/config_sanitizers.mk b/core/config_sanitizers.mk
index e8ffc1b..b43b1cc 100644
--- a/core/config_sanitizers.mk
+++ b/core/config_sanitizers.mk
@@ -34,6 +34,20 @@
   my_sanitize :=
 endif
 
+# Undefined symbols can occur if a non-sanitized library links
+# sanitized static libraries. That's OK, because the executable
+# always depends on the ASan runtime library, which defines these
+# symbols.
+ifneq ($(strip $(SANITIZE_TARGET)),)
+  ifndef LOCAL_IS_HOST_MODULE
+    ifeq ($(LOCAL_MODULE_CLASS),SHARED_LIBRARIES)
+      ifeq ($(my_sanitize),)
+        my_allow_undefined_symbols := true
+      endif
+    endif
+  endif
+endif
+
 # Sanitizers can only be used with clang.
 ifneq ($(my_clang),true)
   ifneq ($(my_sanitize),)
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index eab8113..dee5a69 100755
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -30,6 +30,7 @@
 
 import errno
 import os
+import shutil
 import tempfile
 import zipfile
 
@@ -153,7 +154,13 @@
 
 
 def AddUserdata(output_zip, prefix="IMAGES/"):
-  """Create an empty userdata image and store it in output_zip."""
+  """Create a userdata image and store it in output_zip.
+
+  In most case we just create and store an empty userdata.img;
+  But the invoker can also request to create userdata.img with real
+  data from the target files, by setting "userdata_img_with_data=true"
+  in OPTIONS.info_dict.
+  """
 
   prebuilt_path = os.path.join(OPTIONS.input_tmp, prefix, "userdata.img")
   if os.path.exists(prebuilt_path):
@@ -172,10 +179,19 @@
 
   # The name of the directory it is making an image out of matters to
   # mkyaffs2image.  So we create a temp dir, and within it we create an
-  # empty dir named "data", and build the image from that.
+  # empty dir named "data", or a symlink to the DATA dir,
+  # and build the image from that.
   temp_dir = tempfile.mkdtemp()
   user_dir = os.path.join(temp_dir, "data")
-  os.mkdir(user_dir)
+  empty = (OPTIONS.info_dict.get("userdata_img_with_data") != "true")
+  if empty:
+    # Create an empty dir.
+    os.mkdir(user_dir)
+  else:
+    # Symlink to the DATA dir.
+    os.symlink(os.path.join(OPTIONS.input_tmp, "DATA"),
+               user_dir)
+
   img = tempfile.NamedTemporaryFile()
 
   fstab = OPTIONS.info_dict["fstab"]
@@ -187,8 +203,7 @@
   common.CheckSize(img.name, "userdata.img", OPTIONS.info_dict)
   common.ZipWrite(output_zip, img.name, prefix + "userdata.img")
   img.close()
-  os.rmdir(user_dir)
-  os.rmdir(temp_dir)
+  shutil.rmtree(temp_dir)
 
 
 def AddCache(output_zip, prefix="IMAGES/"):
diff --git a/tools/releasetools/build_image.py b/tools/releasetools/build_image.py
index cbcad6d..594479e 100755
--- a/tools/releasetools/build_image.py
+++ b/tools/releasetools/build_image.py
@@ -31,7 +31,7 @@
 FIXED_SALT = "aee087a5be3b982978c923f566a94613496b417f2af592639bc80d141e34dfe7"
 
 def RunCommand(cmd):
-  """ Echo and run the given command
+  """ Echo and run the given command.
 
   Args:
     cmd: the command represented as a list of strings.
@@ -268,6 +268,7 @@
   elif fs_type.startswith("squash"):
     build_command = ["mksquashfsimage.sh"]
     build_command.extend([in_dir, out_file])
+    build_command.extend(["-s"])
     build_command.extend(["-m", prop_dict["mount_point"]])
     if "selinux_fc" in prop_dict:
       build_command.extend(["-c", prop_dict["selinux_fc"]])
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index f4e25d5..ae449c3 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -199,12 +199,13 @@
 
 def LoadRecoveryFSTab(read_helper, fstab_version):
   class Partition(object):
-    def __init__(self, mount_point, fs_type, device, length, device2):
+    def __init__(self, mount_point, fs_type, device, length, device2, context):
       self.mount_point = mount_point
       self.fs_type = fs_type
       self.device = device
       self.length = length
       self.device2 = device2
+      self.context = context
 
   try:
     data = read_helper("RECOVERY/RAMDISK/etc/recovery.fstab")
@@ -253,6 +254,7 @@
       line = line.strip()
       if not line or line.startswith("#"):
         continue
+      # <src> <mnt_point> <type> <mnt_flags and options> <fs_mgr_flags>
       pieces = line.split()
       if len(pieces) != 5:
         raise ValueError("malformed recovery.fstab line: \"%s\"" % (line,))
@@ -272,9 +274,17 @@
           # Ignore all unknown options in the unified fstab
           continue
 
+      mount_flags = pieces[3]
+      # Honor the SELinux context if present.
+      context = None
+      for i in mount_flags.split(","):
+        if i.startswith("context="):
+          context = i
+
       mount_point = pieces[1]
       d[mount_point] = Partition(mount_point=mount_point, fs_type=pieces[2],
-                                 device=pieces[0], length=length, device2=None)
+                                 device=pieces[0], length=length,
+                                 device2=None, context=context)
 
   else:
     raise ValueError("Unknown fstab_version: \"%d\"" % (fstab_version,))
diff --git a/tools/releasetools/edify_generator.py b/tools/releasetools/edify_generator.py
index a2a32a7..8964720 100644
--- a/tools/releasetools/edify_generator.py
+++ b/tools/releasetools/edify_generator.py
@@ -181,9 +181,12 @@
           if "=" in option:
             key, value = option.split("=", 1)
             mount_dict[key] = value
+      mount_flags = mount_dict.get(p.fs_type, "")
+      if p.context is not None:
+        mount_flags = p.context + ("," + mount_flags if mount_flags else "")
       self.script.append('mount("%s", "%s", "%s", "%s", "%s");' % (
           p.fs_type, common.PARTITION_TYPES[p.fs_type], p.device,
-          p.mount_point, mount_dict.get(p.fs_type, "")))
+          p.mount_point, mount_flags))
       self.mounts.add(p.mount_point)
 
   def UnpackPackageDir(self, src, dst):