Skip to content

Commit

Permalink
Revert "Reland "[Clank SSM]: Implement NativeUnwinderAndroid.""
Browse files Browse the repository at this point in the history
This reverts commit 4eee528.

Reason for revert: base_unittests failures (https://ci.chromium.org/p/chromium/builders/ci/Lollipop%20Phone%20Tester/25027).

Original change's description:
> Reland "[Clank SSM]: Implement NativeUnwinderAndroid."
> 
> This is a reland of 38e3a62
> 
> Reason for revert: Official build failure crbug/1071307
> Fix: Compile NativeUnwinderAndroid + tests only on arm/arm64
> 
> Original change's description:
> > [Clank SSM]: Implement NativeUnwinderAndroid.
> >
> > This CL implements NativeUnwinderAndroid & tests for android
> > unwinding support. It also enables StackSamplingProfilerTest
> > on Android.
> >
> > A new target source_set is added, native_unwinder_android
> > that contains NativeUnwinderAndroid.
> > StackSamplingProfilerTest depends on it for android.
> >
> > Bug: 989102
> > Change-Id: Ie38fd99ca5fb053e1881d0977924b70a6fbc1e9b
> > Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2055743
> > Commit-Queue: Etienne Pierre-Doray <etiennep@chromium.org>
> > Reviewed-by: Nico Weber <thakis@chromium.org>
> > Reviewed-by: Mike Wittman <wittman@chromium.org>
> > Cr-Commit-Position: refs/heads/master@{#759283}
> 
> Bug: 989102, 1071307
> Change-Id: I03345dc46b205f3c1b211ffa9aeb6d51fdacaacf
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2151727
> Commit-Queue: Etienne Pierre-Doray <etiennep@chromium.org>
> Reviewed-by: Mike Wittman <wittman@chromium.org>
> Reviewed-by: Nico Weber <thakis@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#759777}

TBR=gab@chromium.org,thakis@chromium.org,wittman@chromium.org,etiennep@chromium.org

Bug: 989102, 1071768
Change-Id: I90411b354f4f357de7a1dffcd194051eac2eb820
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2154186
Reviewed-by: Boris Sazonov <bsazonov@chromium.org>
Commit-Queue: Boris Sazonov <bsazonov@chromium.org>
Cr-Commit-Position: refs/heads/master@{#760019}
  • Loading branch information
Boris Sazonov authored and Commit Bot committed Apr 17, 2020
1 parent 3eb1bea commit 61ba7bb
Show file tree
Hide file tree
Showing 12 changed files with 99 additions and 843 deletions.
61 changes: 9 additions & 52 deletions base/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -1213,6 +1213,8 @@ jumbo_component("base") {
"message_loop/message_pump_android.h",
"os_compat_android.cc",
"os_compat_android.h",
"profiler/native_unwinder_android.cc",
"profiler/native_unwinder_android.h",
"profiler/stack_sampler_android.cc",
"threading/platform_thread_android.cc",
"trace_event/cpufreq_monitor_android.cc",
Expand Down Expand Up @@ -2383,29 +2385,13 @@ if (is_win) {
}
}

if ((is_win && current_cpu != "x86") || is_mac ||
(is_android && (current_cpu == "arm" || current_cpu == "arm64"))) {
# Must be a loadable module so that it can be loaded/unloaded at runtime
# during testing.
loadable_module("base_profiler_test_support_library") {
testonly = true
sources = [ "profiler/test_support_library.cc" ]
}
}

if (is_android && (current_cpu == "arm" || current_cpu == "arm64")) {
source_set("native_unwinder_android") {
sources = [
"profiler/native_unwinder_android.cc",
"profiler/native_unwinder_android.h",
"profiler/unwindstack_internal_android.cc",
"profiler/unwindstack_internal_android.h",
]

include_dirs = [ "//third_party/libunwindstack/src/libunwindstack/include" ]

public_deps = [ ":base" ]
deps = [ "//third_party/libunwindstack" ]
if (is_win || is_mac) {
if (current_cpu == "x64" || (current_cpu == "arm64" && is_win)) {
# Must be a shared library so that it can be unloaded during testing.
loadable_module("base_profiler_test_support_library") {
testonly = true
sources = [ "profiler/test_support_library.cc" ]
}
}
}

Expand Down Expand Up @@ -2947,17 +2933,6 @@ test("base_unittests") {
if (current_cpu == "arm") {
sources += [ "profiler/chrome_unwinder_android_unittest.cc" ]
}
if (current_cpu == "arm" || current_cpu == "arm64") {
sources += [ "profiler/native_unwinder_android_unittest.cc" ]
include_dirs =
[ "//third_party/libunwindstack/src/libunwindstack/include" ]
deps += [
":base_profiler_test_support_java",
":base_profiler_test_support_jni_headers",
":base_profiler_test_support_library",
":native_unwinder_android",
]
}

sources += [
"android/android_image_reader_compat_unittest.cc",
Expand Down Expand Up @@ -3679,24 +3654,6 @@ if (is_android) {
]
}

generate_jni("base_profiler_test_support_jni_headers") {
testonly = true
sources =
[ "android/javatests/src/org/chromium/base/profiler/TestSupport.java" ]
}

android_library("base_profiler_test_support_java") {
testonly = true
sources =
[ "android/javatests/src/org/chromium/base/profiler/TestSupport.java" ]

annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
deps = [
"//base:base_java",
"//base:jni_java",
]
}

generate_build_config_srcjar("base_build_config_gen") {
use_final_fields = false
}
Expand Down
1 change: 0 additions & 1 deletion base/DEPS
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ include_rules = [
"+third_party/lss",
"+third_party/modp_b64",
"+third_party/tcmalloc",
"+third_party/libunwindstack/src/libunwindstack/include",

# These are implicitly brought in from the root, and we don't want them.
"-ipc",
Expand Down

This file was deleted.

209 changes: 4 additions & 205 deletions base/profiler/native_unwinder_android.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,226 +4,25 @@

#include "base/profiler/native_unwinder_android.h"

#include <string>
#include <vector>

#include <sys/mman.h>

#include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/Elf.h"
#include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/Maps.h"
#include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/Memory.h"
#include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/Regs.h"

#include "base/memory/ptr_util.h"
#include "base/profiler/module_cache.h"
#include "base/profiler/native_unwinder.h"
#include "base/profiler/profile_builder.h"
#include "base/profiler/unwindstack_internal_android.h"
#include "build/build_config.h"

#if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
#include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/MachineArm.h"
#include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/RegsArm.h"
#elif defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_64_BITS)
#include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/MachineArm64.h"
#include "third_party/libunwindstack/src/libunwindstack/include/unwindstack/RegsArm64.h"
#endif // #if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)

namespace base {
namespace {

class AndroidModule : public ModuleCache::Module {
public:
AndroidModule(unwindstack::MapInfo* map_info)
: start_(map_info->start),
size_(map_info->end - map_info->start),
build_id_(map_info->GetBuildID()),
name_(map_info->name) {}
~AndroidModule() override = default;

uintptr_t GetBaseAddress() const override { return start_; }

std::string GetId() const override { return build_id_; }

FilePath GetDebugBasename() const override { return FilePath(name_); }

// Gets the size of the module.
size_t GetSize() const override { return size_; }

// True if this is a native module.
bool IsNative() const override { return true; }

const uintptr_t start_;
const size_t size_;
const std::string build_id_;
const std::string name_;
};

std::unique_ptr<unwindstack::Regs> CreateFromRegisterContext(
RegisterContext* thread_context) {
#if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
return WrapUnique<unwindstack::Regs>(unwindstack::RegsArm::Read(
reinterpret_cast<void*>(&thread_context->arm_r0)));
#elif defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_64_BITS)
return WrapUnique<unwindstack::Regs>(unwindstack::RegsArm64::Read(
reinterpret_cast<void*>(&thread_context->regs[0])));
#else // #if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
NOTREACHED();
return nullptr;
#endif // #if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
}

void CopyToRegisterContext(unwindstack::Regs* regs,
RegisterContext* thread_context) {
#if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
memcpy(reinterpret_cast<void*>(&thread_context->arm_r0), regs->RawData(),
unwindstack::ARM_REG_LAST * sizeof(uint32_t));
#elif defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_64_BITS)
memcpy(reinterpret_cast<void*>(&thread_context->regs[0]), regs->RawData(),
unwindstack::ARM64_REG_LAST * sizeof(uint32_t));
#else // #if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
NOTREACHED();
#endif // #if defined(ARCH_CPU_ARM_FAMILY) && defined(ARCH_CPU_32_BITS)
}

} // namespace

// static
std::unique_ptr<unwindstack::Maps> NativeUnwinderAndroid::CreateMaps() {
auto maps = std::make_unique<unwindstack::LocalMaps>();
if (maps->Parse())
return maps;
return nullptr;
}

// static
std::unique_ptr<unwindstack::Memory>
NativeUnwinderAndroid::CreateProcessMemory() {
return std::make_unique<unwindstack::MemoryLocal>();
}

void NativeUnwinderAndroid::AddInitialModulesFromMaps(
const unwindstack::Maps& memory_regions_map,
ModuleCache* module_cache) {
for (const auto& region : memory_regions_map) {
// Only add executable regions.
if (!(region->flags & PROT_EXEC))
continue;
module_cache->AddCustomNativeModule(
std::make_unique<AndroidModule>(region.get()));
}
}

NativeUnwinderAndroid::NativeUnwinderAndroid(
unwindstack::Maps* memory_regions_map,
unwindstack::Memory* process_memory,
uintptr_t exclude_module_with_base_address)
: memory_regions_map_(memory_regions_map),
process_memory_(process_memory),
exclude_module_with_base_address_(exclude_module_with_base_address) {}

NativeUnwinderAndroid::~NativeUnwinderAndroid() = default;

void NativeUnwinderAndroid::AddInitialModules(ModuleCache* module_cache) {
AddInitialModulesFromMaps(*memory_regions_map_, module_cache);
}

bool NativeUnwinderAndroid::CanUnwindFrom(const Frame& current_frame) const {
return current_frame.module && current_frame.module->IsNative() &&
current_frame.module->GetBaseAddress() !=
exclude_module_with_base_address_;
return false;
}

UnwindResult NativeUnwinderAndroid::TryUnwind(RegisterContext* thread_context,
uintptr_t stack_top,
ModuleCache* module_cache,
std::vector<Frame>* stack) const {
auto regs = CreateFromRegisterContext(thread_context);
DCHECK(regs);
unwindstack::ArchEnum arch = regs->Arch();

do {
uint64_t cur_pc = regs->pc();
uint64_t cur_sp = regs->sp();
unwindstack::MapInfo* map_info = memory_regions_map_->Find(cur_pc);
if (map_info == nullptr ||
map_info->flags & unwindstack::MAPS_FLAGS_DEVICE_MAP) {
break;
}

unwindstack::Elf* elf =
map_info->GetElf({process_memory_, [](unwindstack::Memory*) {}}, arch);
if (!elf->valid())
break;

UnwindStackMemoryAndroid stack_memory(cur_sp, stack_top);
uintptr_t rel_pc = elf->GetRelPc(cur_pc, map_info);
bool finished = false;
bool stepped =
elf->Step(rel_pc, rel_pc, regs.get(), &stack_memory, &finished);
if (stepped && finished)
return UnwindResult::COMPLETED;

if (!stepped) {
// Stepping failed. Try unwinding using return address.
if (stack->size() == 1) {
if (!regs->SetPcFromReturnAddress(&stack_memory))
return UnwindResult::ABORTED;
} else {
break;
}
}

// If the pc and sp didn't change, then consider everything stopped.
if (cur_pc == regs->pc() && cur_sp == regs->sp())
return UnwindResult::ABORTED;

// Exclusive range of expected stack pointer values after the unwind.
struct {
uintptr_t start;
uintptr_t end;
} expected_stack_pointer_range = {cur_sp, stack_top};
if (regs->sp() < expected_stack_pointer_range.start ||
regs->sp() >= expected_stack_pointer_range.end) {
return UnwindResult::ABORTED;
}

if (regs->dex_pc() != 0) {
// Add a frame to represent the dex file.
EmitDexFrame(regs->dex_pc(), module_cache, stack);

// Clear the dex pc so that we don't repeat this frame later.
regs->set_dex_pc(0);
}

// Add the frame to |stack|.
const ModuleCache::Module* module =
module_cache->GetModuleForAddress(regs->pc());
stack->emplace_back(regs->pc(), module);
} while (CanUnwindFrom(stack->back()));

// Restore registers necessary for further unwinding in |thread_context|.
CopyToRegisterContext(regs.get(), thread_context);
return UnwindResult::UNRECOGNIZED_FRAME;
return UnwindResult::ABORTED;
}

void NativeUnwinderAndroid::EmitDexFrame(uintptr_t dex_pc,
ModuleCache* module_cache,
std::vector<Frame>* stack) const {
const ModuleCache::Module* module = module_cache->GetModuleForAddress(dex_pc);
if (!module) {
// The region containing |dex_pc| may not be in |module_cache| since it's
// usually not executable (.dex file). Since non-executable regions
// are used much less commonly, it's lazily added here instead of from
// AddInitialModules().
unwindstack::MapInfo* map_info = memory_regions_map_->Find(dex_pc);
if (map_info) {
auto new_module = std::make_unique<AndroidModule>(map_info);
module = new_module.get();
module_cache->AddCustomNativeModule(std::move(new_module));
}
}
stack->emplace_back(dex_pc, module);
std::unique_ptr<Unwinder> CreateNativeUnwinder(ModuleCache* module_cache) {
return std::make_unique<NativeUnwinderAndroid>();
}

} // namespace base
Loading

0 comments on commit 61ba7bb

Please sign in to comment.