Reland protobuf tombstones.

This reverts the following commits:
    e156ede145a7fc671c705d045d89b49922a758b5.
    eda96eddcbdda9632166232b2363c7b84da0994d.
    5ec54d1e843729cd1e38a2f791f001226a653e95.
    1e45d3f2239333217d3252f78151f4294fda4e80.
    a50f61f8fa903117a6df82d164628de310f16ae9.

Test: treehugger
Test: atest -c CtsSeccompHostTestCases:android.seccomp.cts.SeccompHostJUnit4DeviceTest#testAppZygoteSyscalls
Change-Id: Ic2b1f489ac9f1fec7d7a33c845c29891f4306bbd
diff --git a/debuggerd/libdebuggerd/utility.cpp b/debuggerd/libdebuggerd/utility.cpp
index 7826efc..f406ad4 100644
--- a/debuggerd/libdebuggerd/utility.cpp
+++ b/debuggerd/libdebuggerd/utility.cpp
@@ -126,56 +126,56 @@
 #define MEMORY_BYTES_TO_DUMP 256
 #define MEMORY_BYTES_PER_LINE 16
 
-void dump_memory(log_t* log, unwindstack::Memory* memory, uint64_t addr, const std::string& label) {
+ssize_t dump_memory(void* out, size_t len, size_t* start_offset, uint64_t* addr,
+                    unwindstack::Memory* memory) {
   // Align the address to the number of bytes per line to avoid confusing memory tag output if
   // memory is tagged and we start from a misaligned address. Start 32 bytes before the address.
-  addr &= ~(MEMORY_BYTES_PER_LINE - 1);
-  if (addr >= 4128) {
-    addr -= 32;
+  *addr &= ~(MEMORY_BYTES_PER_LINE - 1);
+  if (*addr >= 4128) {
+    *addr -= 32;
   }
 
   // We don't want the address tag to appear in the addresses in the memory dump.
-  addr = untag_address(addr);
+  *addr = untag_address(*addr);
 
   // Don't bother if the address would overflow, taking tag bits into account. Note that
   // untag_address truncates to 32 bits on 32-bit platforms as a side effect of returning a
   // uintptr_t, so this also checks for 32-bit overflow.
-  if (untag_address(addr + MEMORY_BYTES_TO_DUMP - 1) < addr) {
-    return;
+  if (untag_address(*addr + MEMORY_BYTES_TO_DUMP - 1) < *addr) {
+    return -1;
   }
 
-  // Dump 256 bytes
-  uintptr_t data[MEMORY_BYTES_TO_DUMP/sizeof(uintptr_t)];
-  memset(data, 0, MEMORY_BYTES_TO_DUMP);
-  size_t bytes = memory->Read(addr, reinterpret_cast<uint8_t*>(data), sizeof(data));
+  memset(out, 0, len);
+
+  size_t bytes = memory->Read(*addr, reinterpret_cast<uint8_t*>(out), len);
   if (bytes % sizeof(uintptr_t) != 0) {
     // This should never happen, but just in case.
     ALOGE("Bytes read %zu, is not a multiple of %zu", bytes, sizeof(uintptr_t));
     bytes &= ~(sizeof(uintptr_t) - 1);
   }
 
-  uint64_t start = 0;
+  *start_offset = 0;
   bool skip_2nd_read = false;
   if (bytes == 0) {
     // In this case, we might want to try another read at the beginning of
     // the next page only if it's within the amount of memory we would have
     // read.
     size_t page_size = sysconf(_SC_PAGE_SIZE);
-    start = ((addr + (page_size - 1)) & ~(page_size - 1)) - addr;
-    if (start == 0 || start >= MEMORY_BYTES_TO_DUMP) {
+    *start_offset = ((*addr + (page_size - 1)) & ~(page_size - 1)) - *addr;
+    if (*start_offset == 0 || *start_offset >= len) {
       skip_2nd_read = true;
     }
   }
 
-  if (bytes < MEMORY_BYTES_TO_DUMP && !skip_2nd_read) {
+  if (bytes < len && !skip_2nd_read) {
     // Try to do one more read. This could happen if a read crosses a map,
     // but the maps do not have any break between them. Or it could happen
     // if reading from an unreadable map, but the read would cross back
     // into a readable map. Only requires one extra read because a map has
     // to contain at least one page, and the total number of bytes to dump
     // is smaller than a page.
-    size_t bytes2 = memory->Read(addr + start + bytes, reinterpret_cast<uint8_t*>(data) + bytes,
-                                 sizeof(data) - bytes - start);
+    size_t bytes2 = memory->Read(*addr + *start_offset + bytes, static_cast<uint8_t*>(out) + bytes,
+                                 len - bytes - *start_offset);
     bytes += bytes2;
     if (bytes2 > 0 && bytes % sizeof(uintptr_t) != 0) {
       // This should never happen, but we'll try and continue any way.
@@ -185,9 +185,21 @@
   }
 
   // If we were unable to read anything, it probably means that the register doesn't contain a
-  // valid pointer. In that case, skip the output for this register entirely rather than emitting 16
-  // lines of dashes.
+  // valid pointer.
   if (bytes == 0) {
+    return -1;
+  }
+
+  return bytes;
+}
+
+void dump_memory(log_t* log, unwindstack::Memory* memory, uint64_t addr, const std::string& label) {
+  // Dump 256 bytes
+  uintptr_t data[MEMORY_BYTES_TO_DUMP / sizeof(uintptr_t)];
+  size_t start_offset = 0;
+
+  ssize_t bytes = dump_memory(data, sizeof(data), &start_offset, &addr, memory);
+  if (bytes == -1) {
     return;
   }
 
@@ -201,7 +213,7 @@
   // words are of course presented differently.
   uintptr_t* data_ptr = data;
   size_t current = 0;
-  size_t total_bytes = start + bytes;
+  size_t total_bytes = start_offset + bytes;
   for (size_t line = 0; line < MEMORY_BYTES_TO_DUMP / MEMORY_BYTES_PER_LINE; line++) {
     uint64_t tagged_addr = addr;
     long tag = memory->ReadTag(addr);
@@ -214,7 +226,7 @@
     addr += MEMORY_BYTES_PER_LINE;
     std::string ascii;
     for (size_t i = 0; i < MEMORY_BYTES_PER_LINE / sizeof(uintptr_t); i++) {
-      if (current >= start && current + sizeof(uintptr_t) <= total_bytes) {
+      if (current >= start_offset && current + sizeof(uintptr_t) <= total_bytes) {
         android::base::StringAppendF(&logline, " %" PRIPTR, static_cast<uint64_t>(*data_ptr));
 
         // Fill out the ascii string from the data.