Use cmdline instead for enabling heapprofd.
Because we also want to profile Java applications, which have longer
names, the character limit of comm is a problem. To avoid complexity, it
is preferable to apply the same logic for finding running processes
(which includes Java apps), and determining whether to profile a process
from startup.
Test: m
Test: flash sailfish
Test: setprop heapprofd.enable 1
setprop heapprofd.enable.ls 1
ls
/system/bin/ls
/system/bin/ls /
Bug: 120175590
Change-Id: Id0859d4a333efcb05883e611ea6a31a51468f82c
diff --git a/libc/bionic/malloc_common.cpp b/libc/bionic/malloc_common.cpp
index 8d8d420..031b0aa 100644
--- a/libc/bionic/malloc_common.cpp
+++ b/libc/bionic/malloc_common.cpp
@@ -252,8 +252,10 @@
#if !defined(LIBC_STATIC)
#include <dlfcn.h>
+#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h>
#include <async_safe/log.h>
#include <sys/system_properties.h>
@@ -470,6 +472,64 @@
return true;
}
+static bool GetHeapprofdProgramProperty(char* data, size_t size) {
+ constexpr char prefix[] = "heapprofd.enable.";
+ // - 1 to skip nullbyte, which we will write later.
+ constexpr size_t prefix_size = sizeof(prefix) - 1;
+ if (size < prefix_size) {
+ error_log("%s: Overflow constructing heapprofd property", getprogname());
+ return false;
+ }
+ memcpy(data, prefix, prefix_size);
+
+ int fd = open("/proc/self/cmdline", O_RDONLY | O_CLOEXEC);
+ if (fd == -1) {
+ error_log("%s: Failed to open /proc/self/cmdline", getprogname());
+ return false;
+ }
+ char cmdline[128];
+ ssize_t rd = read(fd, cmdline, sizeof(cmdline) - 1);
+ close(fd);
+ if (rd == -1) {
+ error_log("%s: Failed to read /proc/self/cmdline", getprogname());
+ return false;
+ }
+ cmdline[rd] = '\0';
+ char* first_arg = static_cast<char*>(memchr(cmdline, '\0', rd));
+ if (first_arg == nullptr || first_arg == cmdline + size - 1) {
+ error_log("%s: Overflow reading cmdline", getprogname());
+ return false;
+ }
+ // For consistency with what we do with Java app cmdlines, trim everything
+ // after the @ sign of the first arg.
+ char* first_at = static_cast<char*>(memchr(cmdline, '@', rd));
+ if (first_at != nullptr && first_at < first_arg) {
+ *first_at = '\0';
+ first_arg = first_at;
+ }
+
+ char* start = static_cast<char*>(memrchr(cmdline, '/', first_arg - cmdline));
+ if (start == first_arg) {
+ // The first argument ended in a slash.
+ error_log("%s: cmdline ends in /", getprogname());
+ return false;
+ } else if (start == nullptr) {
+ start = cmdline;
+ } else {
+ // Skip the /.
+ start++;
+ }
+
+ size_t name_size = static_cast<size_t>(first_arg - start);
+ if (name_size >= size - prefix_size) {
+ error_log("%s: overflow constructing heapprofd property.", getprogname());
+ return false;
+ }
+ // + 1 to also copy the trailing null byte.
+ memcpy(data + prefix_size, start, name_size + 1);
+ return true;
+}
+
static bool CheckLoadHeapprofd() {
// First check for heapprofd.enable. If it is set to "all", enable
// heapprofd for all processes. Otherwise, check heapprofd.enable.${prog},
@@ -483,23 +543,13 @@
}
char program_property[128];
- int ret = snprintf(program_property, sizeof(program_property), "%s.%s",
- HEAPPROFD_PROPERTY_ENABLE, getprogname());
-
- if (ret < 0 || static_cast<size_t>(ret) >= sizeof(program_property)) {
- if (ret < 0) {
- error_log("Failed to concatenate heapprofd property %s.%s: %s",
- HEAPPROFD_PROPERTY_ENABLE, getprogname(), strerror(errno));
- } else {
- error_log("Overflow in concatenating heapprofd property");
- }
+ if (!GetHeapprofdProgramProperty(program_property,
+ sizeof(program_property))) {
return false;
}
-
if (__system_property_get(program_property, property_value) == 0) {
return false;
}
-
return program_property[0] != '\0';
}