Merge "Do not encode newline characters for abort/log." into main
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
index 3257a2c..0e62ceb 100644
--- a/debuggerd/Android.bp
+++ b/debuggerd/Android.bp
@@ -505,6 +505,7 @@
         "libbase",
         "libdebuggerd_client",
         "liblog",
+        "libprocessgroup",
         "libprocinfo",
     ],
 
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp
index 15e8319..00b861a 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -22,9 +22,14 @@
 #include <sys/ptrace.h>
 #include <sys/types.h>
 #include <sys/un.h>
+#include <sys/user.h>
 #include <sys/wait.h>
 #include <unistd.h>
 
+#if defined(__i386__)
+#include <asm/ldt.h>
+#endif
+
 #include <cstdint>
 #include <limits>
 #include <map>
@@ -430,18 +435,12 @@
   return true;
 }
 
-static bool GetGuestRegistersFromCrashedProcess([[maybe_unused]] pid_t tid,
-                                                NativeBridgeGuestRegs* guest_regs) {
+static bool GetGuestRegistersFromCrashedProcess(pid_t tid, NativeBridgeGuestRegs* guest_regs) {
   auto process_memory = unwindstack::Memory::CreateProcessMemoryCached(tid);
 
   uintptr_t header_ptr = 0;
   uintptr_t base = 0;
-#if defined(__x86_64__)
-  if (!PtracePeek(PTRACE_PEEKUSER, tid, offsetof(user_regs_struct, fs_base), nullptr,
-                  "failed to read thread register for thread " + std::to_string(tid), &base)) {
-    return false;
-  }
-#elif defined(__aarch64__)
+#if defined(__aarch64__)
   // base is implicitly casted to uint64_t.
   struct iovec pt_iov {
     .iov_base = &base, .iov_len = sizeof(base),
@@ -451,6 +450,26 @@
     PLOG(ERROR) << "failed to read thread register for thread " << tid;
     return false;
   }
+#elif defined(__arm__)
+  if (ptrace(PTRACE_GET_THREAD_AREA, tid, nullptr, &base) == 0) {
+    PLOG(ERROR) << "failed to get thread area for thread " << tid;
+    return false;
+  }
+#elif defined(__i386__)
+  struct user_regs_struct regs;
+  struct iovec pt_iov = {.iov_base = &regs, .iov_len = sizeof(regs)};
+  if (ptrace(PTRACE_GETREGSET, tid, NT_PRSTATUS, &pt_iov) != 0) {
+    PLOG(ERROR) << "failed to get registers for thread " << tid;
+    return false;
+  }
+
+  struct user_desc desc;
+  desc.entry_number = regs.xgs >> 3;
+  if (ptrace(PTRACE_GET_THREAD_AREA, tid, desc.entry_number, &desc) != 0) {
+    PLOG(ERROR) << "failed to get thread area for thread " << tid;
+    return false;
+  }
+  base = desc.base_addr;
 #elif defined(__riscv)
   struct user_regs_struct regs;
   struct iovec pt_iov = {.iov_base = &regs, .iov_len = sizeof(regs)};
@@ -459,6 +478,11 @@
     return false;
   }
   base = reinterpret_cast<uintptr_t>(regs.tp);
+#elif defined(__x86_64__)
+  if (!PtracePeek(PTRACE_PEEKUSER, tid, offsetof(user_regs_struct, fs_base), nullptr,
+                  "failed to read thread register for thread " + std::to_string(tid), &base)) {
+    return false;
+  }
 #else
   // TODO(b/339287219): Add case for Riscv host.
   return false;
@@ -487,9 +511,7 @@
   return true;
 }
 
-static void ReadGuestRegisters([[maybe_unused]] std::unique_ptr<unwindstack::Regs>* regs,
-                               pid_t tid) {
-  // TODO: remove [[maybe_unused]], when the ARM32 case is removed from the native bridge support.
+static void ReadGuestRegisters(std::unique_ptr<unwindstack::Regs>* regs, pid_t tid) {
   NativeBridgeGuestRegs guest_regs;
   if (!GetGuestRegistersFromCrashedProcess(tid, &guest_regs)) {
     return;
@@ -521,6 +543,17 @@
       g_guest_arch = Architecture::RISCV64;
       break;
     }
+#else
+    case NATIVE_BRIDGE_ARCH_ARM: {
+      unwindstack::arm_user_regs arm_user_regs = {};
+      regs->reset(unwindstack::RegsArm::Read(&arm_user_regs));
+      for (size_t i = 0; i < unwindstack::ARM_REG_LAST; i++) {
+        arm_user_regs.regs[i] = guest_regs.regs_arm.r[i];
+      }
+
+      g_guest_arch = Architecture::ARM32;
+      break;
+    }
 #endif
     default:
       break;
@@ -796,16 +829,17 @@
       ATRACE_NAME("engrave_tombstone");
       unwindstack::ArchEnum regs_arch = unwindstack::ARCH_UNKNOWN;
       switch (g_guest_arch) {
-        case Architecture::ARM64: {
+        case Architecture::ARM32:
+          regs_arch = unwindstack::ARCH_ARM;
+          break;
+        case Architecture::ARM64:
           regs_arch = unwindstack::ARCH_ARM64;
           break;
-        }
-        case Architecture::RISCV64: {
+        case Architecture::RISCV64:
           regs_arch = unwindstack::ARCH_RISCV64;
           break;
-        }
-        default: {
-        }
+        default:
+          break;
       }
       if (regs_arch == unwindstack::ARCH_UNKNOWN) {
         engrave_tombstone(std::move(g_output_fd), std::move(g_proto_fd), &unwinder, thread_info,
diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp
index 0d4b91f..7a2500c 100644
--- a/debuggerd/debuggerd.cpp
+++ b/debuggerd/debuggerd.cpp
@@ -23,11 +23,11 @@
 #include <string_view>
 #include <thread>
 
-#include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/parseint.h>
 #include <android-base/unique_fd.h>
 #include <debuggerd/client.h>
+#include <processgroup/processgroup.h>
 #include <procinfo/process.h>
 #include "util.h"
 
@@ -92,13 +92,8 @@
   }
 
   // unfreeze if pid is frozen.
-  const std::string freeze_file = android::base::StringPrintf(
-      "/sys/fs/cgroup/uid_%d/pid_%d/cgroup.freeze", proc_info.uid, proc_info.pid);
-  if (std::string freeze_status;
-      android::base::ReadFileToString(freeze_file, &freeze_status) && freeze_status[0] == '1') {
-    android::base::WriteStringToFile("0", freeze_file);
-    // we don't restore the frozen state as this is considered a benign change.
-  }
+  SetProcessProfiles(proc_info.uid, proc_info.pid, {"Unfrozen"});
+  // we don't restore the frozen state as this is considered a benign change.
 
   unique_fd output_fd(fcntl(STDOUT_FILENO, F_DUPFD_CLOEXEC, 0));
   if (output_fd.get() == -1) {
diff --git a/gatekeeperd/fuzzer/GateKeeperServiceFuzzer.cpp b/gatekeeperd/fuzzer/GateKeeperServiceFuzzer.cpp
index bc0d5fe..a3cc3f3 100644
--- a/gatekeeperd/fuzzer/GateKeeperServiceFuzzer.cpp
+++ b/gatekeeperd/fuzzer/GateKeeperServiceFuzzer.cpp
@@ -22,6 +22,8 @@
 using android::GateKeeperProxy;
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    // TODO(b/183141167): need to rewrite 'dump' to avoid SIGPIPE.
+    signal(SIGPIPE, SIG_IGN);
     auto gatekeeperService = new GateKeeperProxy();
     fuzzService(gatekeeperService, FuzzedDataProvider(data, size));
     return 0;
diff --git a/init/Android.bp b/init/Android.bp
index 4ee3be2..ed19b4b 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -268,7 +268,6 @@
 
 cc_defaults {
     name: "init_second_stage_defaults",
-    recovery_available: true,
     stem: "init",
     defaults: ["init_defaults"],
     srcs: ["main.cpp"],
@@ -280,37 +279,38 @@
     defaults: ["init_second_stage_defaults"],
     static_libs: ["libinit"],
     visibility: ["//visibility:any_system_partition"],
-    target: {
-        platform: {
-            required: [
-                "init.rc",
-                "ueventd.rc",
-                "e2fsdroid",
-                "extra_free_kbytes",
-                "make_f2fs",
-                "mke2fs",
-                "sload_f2fs",
-            ],
-        },
-        recovery: {
-            cflags: ["-DRECOVERY"],
-            exclude_static_libs: [
-                "libxml2",
-            ],
-            exclude_shared_libs: [
-                "libbinder",
-                "libutils",
-            ],
-            required: [
-                "init_recovery.rc",
-                "ueventd.rc.recovery",
-                "e2fsdroid.recovery",
-                "make_f2fs.recovery",
-                "mke2fs.recovery",
-                "sload_f2fs.recovery",
-            ],
-        },
-    },
+    required: [
+        "init.rc",
+        "ueventd.rc",
+        "e2fsdroid",
+        "extra_free_kbytes",
+        "make_f2fs",
+        "mke2fs",
+        "sload_f2fs",
+    ],
+}
+
+cc_binary {
+    name: "init_second_stage.recovery",
+    defaults: ["init_second_stage_defaults"],
+    static_libs: ["libinit"],
+    recovery: true,
+    cflags: ["-DRECOVERY"],
+    exclude_static_libs: [
+        "libxml2",
+    ],
+    exclude_shared_libs: [
+        "libbinder",
+        "libutils",
+    ],
+    required: [
+        "init_recovery.rc",
+        "ueventd.rc.recovery",
+        "e2fsdroid.recovery",
+        "make_f2fs.recovery",
+        "mke2fs.recovery",
+        "sload_f2fs.recovery",
+    ],
 }
 
 cc_binary {
@@ -319,7 +319,6 @@
         "avf_build_flags_cc",
         "init_second_stage_defaults",
     ],
-    recovery_available: false,
     static_libs: ["libinit.microdroid"],
     cflags: ["-DMICRODROID=1"],
     no_full_install: true,
diff --git a/libprocessgroup/cgrouprc/Android.bp b/libprocessgroup/cgrouprc/Android.bp
index 9e46b8e..d5214c1 100644
--- a/libprocessgroup/cgrouprc/Android.bp
+++ b/libprocessgroup/cgrouprc/Android.bp
@@ -18,7 +18,6 @@
 
 cc_library {
     name: "libcgrouprc",
-    host_supported: true,
     // Do not ever mark this as vendor_available; otherwise, vendor modules
     // that links to the static library will behave unexpectedly. All on-device
     // modules should use libprocessgroup which links to the LL-NDK library
diff --git a/libprocessgroup/cgrouprc/include/android/cgrouprc.h b/libprocessgroup/cgrouprc/include/android/cgrouprc.h
index e704a36..6fc2659 100644
--- a/libprocessgroup/cgrouprc/include/android/cgrouprc.h
+++ b/libprocessgroup/cgrouprc/include/android/cgrouprc.h
@@ -21,11 +21,6 @@
 
 __BEGIN_DECLS
 
-// For host builds, __INTRODUCED_IN is not defined.
-#ifndef __INTRODUCED_IN
-#define __INTRODUCED_IN(x)
-#endif
-
 struct ACgroupController;
 typedef struct ACgroupController ACgroupController;
 
diff --git a/libprocessgroup/include/processgroup/processgroup.h b/libprocessgroup/include/processgroup/processgroup.h
index 6a026a7..28b17c1 100644
--- a/libprocessgroup/include/processgroup/processgroup.h
+++ b/libprocessgroup/include/processgroup/processgroup.h
@@ -29,6 +29,8 @@
 bool CgroupGetControllerPath(const std::string& cgroup_name, std::string* path);
 bool CgroupGetControllerFromPath(const std::string& path, std::string* cgroup_name);
 bool CgroupGetAttributePath(const std::string& attr_name, std::string* path);
+// Provides the path for an attribute in a specific process group
+// Returns false in case of error, true in case of success
 bool CgroupGetAttributePathForTask(const std::string& attr_name, pid_t tid, std::string* path);
 
 bool SetTaskProfiles(pid_t tid, const std::vector<std::string>& profiles,
@@ -81,10 +83,6 @@
 
 void removeAllEmptyProcessGroups(void);
 
-// Provides the path for an attribute in a specific process group
-// Returns false in case of error, true in case of success
-bool getAttributePathForTask(const std::string& attr_name, pid_t tid, std::string* path);
-
 // Check if a profile can be applied without failing.
 // Returns true if it can be applied without failing, false otherwise
 bool isProfileValidForProcess(const std::string& profile_name, uid_t uid, pid_t pid);
diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp
index 9522159..53168e3 100644
--- a/libprocessgroup/processgroup.cpp
+++ b/libprocessgroup/processgroup.cpp
@@ -746,10 +746,6 @@
     return SetProcessGroupValue(pid, "MemLimit", limit_in_bytes);
 }
 
-bool getAttributePathForTask(const std::string& attr_name, pid_t tid, std::string* path) {
-    return CgroupGetAttributePathForTask(attr_name, tid, path);
-}
-
 bool isProfileValidForProcess(const std::string& profile_name, uid_t uid, pid_t pid) {
     const TaskProfile* tp = TaskProfiles::GetInstance().GetProfile(profile_name);
 
diff --git a/reboot/Android.bp b/reboot/Android.bp
index 7b243bd..1cca824 100644
--- a/reboot/Android.bp
+++ b/reboot/Android.bp
@@ -4,10 +4,25 @@
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
-cc_binary {
-    name: "reboot",
+cc_defaults {
+    name: "reboot_defaults",
     srcs: ["reboot.c"],
     shared_libs: ["libcutils"],
     cflags: ["-Werror"],
-    recovery_available: true,
+}
+
+cc_binary {
+    name: "reboot",
+    defaults: [
+        "reboot_defaults",
+    ],
+}
+
+cc_binary {
+    name: "reboot.recovery",
+    defaults: [
+        "reboot_defaults",
+    ],
+    recovery: true,
+    stem: "reboot",
 }
diff --git a/rootdir/Android.bp b/rootdir/Android.bp
index 44acbba..d3db2ff 100644
--- a/rootdir/Android.bp
+++ b/rootdir/Android.bp
@@ -47,7 +47,13 @@
 prebuilt_etc {
     name: "ueventd.rc",
     src: "ueventd.rc",
-    recovery_available: true,
+}
+
+prebuilt_etc {
+    name: "ueventd.rc.recovery",
+    src: "ueventd.rc",
+    recovery: true,
+    filename: "ueventd.rc",
 }
 
 filegroup {
diff --git a/shell_and_utilities/Android.bp b/shell_and_utilities/Android.bp
index 1f5c179..0a1f7c5 100644
--- a/shell_and_utilities/Android.bp
+++ b/shell_and_utilities/Android.bp
@@ -43,9 +43,10 @@
     required: [
         "sh.recovery",
         "toolbox.recovery",
-        "toybox.recovery",
+        "toybox_recovery",
         "ziptool.recovery",
     ],
+    recovery: true,
 }
 
 phony {
diff --git a/toolbox/Android.bp b/toolbox/Android.bp
index 120cc6e..3142542 100644
--- a/toolbox/Android.bp
+++ b/toolbox/Android.bp
@@ -68,11 +68,17 @@
 cc_binary {
     name: "toolbox",
     defaults: ["toolbox_binary_defaults"],
-    recovery_available: true,
     vendor_ramdisk_available: true,
 }
 
 cc_binary {
+    name: "toolbox.recovery",
+    defaults: ["toolbox_binary_defaults"],
+    recovery: true,
+    stem: "toolbox",
+}
+
+cc_binary {
     name: "toolbox_vendor",
     stem: "toolbox",
     vendor: true,
diff --git a/watchdogd/Android.bp b/watchdogd/Android.bp
index 0388208..bc7ffb6 100644
--- a/watchdogd/Android.bp
+++ b/watchdogd/Android.bp
@@ -2,9 +2,8 @@
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
-cc_binary {
-    name: "watchdogd",
-    recovery_available: true,
+cc_defaults {
+    name: "watchdogd_defaults",
     srcs: ["watchdogd.cpp"],
     cflags: [
         "-Wall",
@@ -16,3 +15,19 @@
         misc_undefined: ["signed-integer-overflow"],
     },
 }
+
+cc_binary {
+    name: "watchdogd",
+    defaults: [
+        "watchdogd_defaults",
+    ],
+}
+
+cc_binary {
+    name: "watchdogd.recovery",
+    defaults: [
+        "watchdogd_defaults",
+    ],
+    recovery: true,
+    stem: "watchdogd",
+}