Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c71e0a65 authored by Peter Collingbourne's avatar Peter Collingbourne Committed by Christopher Ferris
Browse files

libunwindstack: Add Memory::ReadTag() function for reading memory tags.

This uses an experimental Linux kernel API for reading the tags across
processes using ptrace.

Bug: 135772972

Test: Unit tests pass.
Change-Id: Ib1a09d9219166011de80cf250b756bb8a4bcdb0a
parent 585ff019
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@ cc_defaults {
        "MapInfo.cpp",
        "Maps.cpp",
        "Memory.cpp",
        "MemoryMte.cpp",
        "LocalUnwinder.cpp",
        "Regs.cpp",
        "RegsArm.cpp",
@@ -101,6 +102,16 @@ cc_defaults {
        "liblog",
        "liblzma",
    ],

    header_libs: [
        "bionic_libc_platform_headers",
    ],

    product_variables: {
        experimental_mte: {
            cflags: ["-DANDROID_EXPERIMENTAL_MTE"],
        },
    },
}

cc_library {
@@ -213,6 +224,7 @@ cc_defaults {
        "tests/MemoryRangesTest.cpp",
        "tests/MemoryRemoteTest.cpp",
        "tests/MemoryTest.cpp",
        "tests/MemoryMteTest.cpp",
        "tests/RegsInfoTest.cpp",
        "tests/RegsIterateTest.cpp",
        "tests/RegsStepIfSignalHandlerTest.cpp",
@@ -268,6 +280,16 @@ cc_defaults {
        "tests/files/offline/straddle_arm/*",
        "tests/files/offline/straddle_arm64/*",
    ],

    header_libs: [
        "bionic_libc_platform_headers",
    ],

    product_variables: {
        experimental_mte: {
            cflags: ["-DANDROID_EXPERIMENTAL_MTE"],
        },
    },
}

cc_test {
+10 −0
Original line number Diff line number Diff line
@@ -324,6 +324,16 @@ size_t MemoryLocal::Read(uint64_t addr, void* dst, size_t size) {
  return ProcessVmRead(getpid(), addr, dst, size);
}

#if !defined(ANDROID_EXPERIMENTAL_MTE)
long MemoryRemote::ReadTag(uint64_t) {
  return -1;
}

long MemoryLocal::ReadTag(uint64_t) {
  return -1;
}
#endif

MemoryRange::MemoryRange(const std::shared_ptr<Memory>& memory, uint64_t begin, uint64_t length,
                         uint64_t offset)
    : memory_(memory), begin_(begin), length_(length), offset_(offset) {}
+1 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ class MemoryCache : public Memory {
  virtual ~MemoryCache() = default;

  size_t Read(uint64_t addr, void* dst, size_t size) override;
  long ReadTag(uint64_t addr) override { return impl_->ReadTag(addr); }

  void Clear() override { cache_.clear(); }

+1 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ class MemoryLocal : public Memory {
  bool IsLocal() const override { return true; }

  size_t Read(uint64_t addr, void* dst, size_t size) override;
  long ReadTag(uint64_t addr) override;
};

}  // namespace unwindstack
+57 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#if defined(ANDROID_EXPERIMENTAL_MTE)

#include <sys/ptrace.h>

#include <bionic/mte.h>
#include <bionic/mte_kernel.h>

#include "MemoryLocal.h"
#include "MemoryRemote.h"

namespace unwindstack {

long MemoryRemote::ReadTag(uint64_t addr) {
#if defined(__aarch64__)
  return ptrace(PTRACE_PEEKTAG, pid_, (void*)addr, nullptr);
#else
  (void)addr;
  return -1;
#endif
}

long MemoryLocal::ReadTag(uint64_t addr) {
#if defined(__aarch64__)
  // Check that the memory is readable first. This is racy with the ldg but there's not much
  // we can do about it.
  char data;
  if (!mte_supported() || !Read(addr, &data, 1)) {
    return -1;
  }

  __asm__ __volatile__(".arch_extension mte; ldg %0, [%0]" : "+r"(addr) : : "memory");
  return (addr >> 56) & 0xf;
#else
  (void)addr;
  return -1;
#endif
}

}  // namespace unwindstack

#endif
Loading