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

Commit e2a6738e authored by Christopher Ferris's avatar Christopher Ferris Committed by android-build-merger
Browse files

Merge "Load libbacktrace_test.so explicitly." am: 15a5c9c4

am: 10ac2557

Change-Id: I3070a17b5eb20c734a2878c854d32f5662fbbc67
parents 70827f6b 10ac2557
Loading
Loading
Loading
Loading
+21 −23
Original line number Original line Diff line number Diff line
@@ -27,15 +27,6 @@ cc_defaults {
            enabled: false,
            enabled: false,
        },
        },
    },
    },

    multilib: {
        lib32: {
            suffix: "32",
        },
        lib64: {
            suffix: "64",
        },
    },
}
}


libbacktrace_sources = [
libbacktrace_sources = [
@@ -108,7 +99,7 @@ cc_library {
    whole_static_libs: ["libdemangle"],
    whole_static_libs: ["libdemangle"],
}
}


cc_library_shared {
cc_test_library {
    name: "libbacktrace_test",
    name: "libbacktrace_test",
    defaults: ["libbacktrace_common"],
    defaults: ["libbacktrace_common"],
    host_supported: true,
    host_supported: true,
@@ -121,6 +112,21 @@ cc_library_shared {
    shared_libs: [
    shared_libs: [
        "libunwindstack",
        "libunwindstack",
    ],
    ],
    relative_install_path: "backtrace_test_libs",

    target: {
        linux_glibc: {
            // The host uses rosegment, which isn't supported yet.
            ldflags: [
                "-Wl,--no-rosegment",
            ],
            // This forces the creation of eh_frame with unwind information
            // for host.
            cflags: [
                "-fcxx-exceptions"
            ],
        },
    },
}
}


//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
@@ -128,12 +134,12 @@ cc_library_shared {
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
cc_test {
cc_test {
    name: "backtrace_test",
    name: "backtrace_test",
    isolated: true,
    defaults: ["libbacktrace_common"],
    defaults: ["libbacktrace_common"],
    host_supported: true,
    host_supported: true,
    srcs: [
    srcs: [
        "backtrace_offline_test.cpp",
        "backtrace_offline_test.cpp",
        "backtrace_test.cpp",
        "backtrace_test.cpp",
        "GetPss.cpp",
    ],
    ],


    cflags: [
    cflags: [
@@ -143,7 +149,6 @@ cc_test {
    ],
    ],


    shared_libs: [
    shared_libs: [
        "libbacktrace_test",
        "libbacktrace",
        "libbacktrace",
        "libbase",
        "libbase",
        "liblog",
        "liblog",
@@ -152,17 +157,10 @@ cc_test {


    group_static_libs: true,
    group_static_libs: true,


    target: {
    // So that the dlopen can find the libbacktrace_test.so.
        android: {
    ldflags: [
            cflags: ["-DENABLE_PSS_TESTS"],
        "-Wl,--rpath,${ORIGIN}/../backtrace_test_libs",
            shared_libs: [
                "libutils",
    ],
    ],
        },
        linux_glibc: {
            static_libs: ["libutils"],
        },
    },


    test_suites: ["device-tests"],
    test_suites: ["device-tests"],
    data: [
    data: [
+78 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2013 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.
 */

#ifndef _LIBBACKTRACE_BACKTRACE_TEST_H
#define _LIBBACKTRACE_BACKTRACE_TEST_H

#include <dlfcn.h>

#include <gtest/gtest.h>

class BacktraceTest : public ::testing::Test {
 protected:
  static void SetUpTestCase() {
    dl_handle_ = dlopen("libbacktrace_test.so", RTLD_NOW | RTLD_LOCAL);

    test_level_one_ = reinterpret_cast<int (*)(int, int, int, int, void (*)(void*), void*)>(
        dlsym(dl_handle_, "test_level_one"));

    test_level_two_ = reinterpret_cast<int (*)(int, int, int, int, void (*)(void*), void*)>(
        dlsym(dl_handle_, "test_level_two"));

    test_level_three_ = reinterpret_cast<int (*)(int, int, int, int, void (*)(void*), void*)>(
        dlsym(dl_handle_, "test_level_three"));

    test_level_four_ = reinterpret_cast<int (*)(int, int, int, int, void (*)(void*), void*)>(
        dlsym(dl_handle_, "test_level_four"));

    test_recursive_call_ = reinterpret_cast<int (*)(int, void (*)(void*), void*)>(
        dlsym(dl_handle_, "test_recursive_call"));

    test_get_context_and_wait_ = reinterpret_cast<void (*)(void*, volatile int*)>(
        dlsym(dl_handle_, "test_get_context_and_wait"));

    test_signal_action_ =
        reinterpret_cast<void (*)(int, siginfo_t*, void*)>(dlsym(dl_handle_, "test_signal_action"));

    test_signal_handler_ =
        reinterpret_cast<void (*)(int)>(dlsym(dl_handle_, "test_signal_handler"));
  }

  void SetUp() override {
    ASSERT_TRUE(dl_handle_ != nullptr);
    ASSERT_TRUE(test_level_one_ != nullptr);
    ASSERT_TRUE(test_level_two_ != nullptr);
    ASSERT_TRUE(test_level_three_ != nullptr);
    ASSERT_TRUE(test_level_four_ != nullptr);
    ASSERT_TRUE(test_recursive_call_ != nullptr);
    ASSERT_TRUE(test_get_context_and_wait_ != nullptr);
    ASSERT_TRUE(test_signal_action_ != nullptr);
    ASSERT_TRUE(test_signal_handler_ != nullptr);
  }

 public:
  static void* dl_handle_;
  static int (*test_level_one_)(int, int, int, int, void (*)(void*), void*);
  static int (*test_level_two_)(int, int, int, int, void (*)(void*), void*);
  static int (*test_level_three_)(int, int, int, int, void (*)(void*), void*);
  static int (*test_level_four_)(int, int, int, int, void (*)(void*), void*);
  static int (*test_recursive_call_)(int, void (*)(void*), void*);
  static void (*test_get_context_and_wait_)(void*, volatile int*);
  static void (*test_signal_action_)(int, siginfo_t*, void*);
  static void (*test_signal_handler_)(int);
};

#endif  // _LIBBACKTRACE_BACKTRACE_TEST_H

libbacktrace/GetPss.cpp

deleted100644 → 0
+0 −94
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2014 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.
 */

#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>

// This is an extremely simplified version of libpagemap.

#define _BITS(x, offset, bits) (((x) >> (offset)) & ((1LL << (bits)) - 1))

#define PAGEMAP_PRESENT(x)     (_BITS(x, 63, 1))
#define PAGEMAP_SWAPPED(x)     (_BITS(x, 62, 1))
#define PAGEMAP_SHIFT(x)       (_BITS(x, 55, 6))
#define PAGEMAP_PFN(x)         (_BITS(x, 0, 55))
#define PAGEMAP_SWAP_OFFSET(x) (_BITS(x, 5, 50))
#define PAGEMAP_SWAP_TYPE(x)   (_BITS(x, 0,  5))

static bool ReadData(int fd, off_t place, uint64_t *data) {
  if (lseek(fd, place * sizeof(uint64_t), SEEK_SET) < 0) {
    return false;
  }
  if (read(fd, (void*)data, sizeof(uint64_t)) != (ssize_t)sizeof(uint64_t)) {
    return false;
  }
  return true;
}

size_t GetPssBytes() {
  FILE* maps = fopen("/proc/self/maps", "r");
  if (maps == nullptr) {
    return 0;
  }

  int pagecount_fd = open("/proc/kpagecount", O_RDONLY);
  if (pagecount_fd == -1) {
    fclose(maps);
    return 0;
  }

  int pagemap_fd = open("/proc/self/pagemap", O_RDONLY);
  if (pagemap_fd == -1) {
    fclose(maps);
    close(pagecount_fd);
    return 0;
  }

  char line[4096];
  size_t total_pss = 0;
  int pagesize = getpagesize();
  while (fgets(line, sizeof(line), maps)) {
    uintptr_t start, end;
    if (sscanf(line, "%" SCNxPTR "-%" SCNxPTR " ", &start, &end) != 2) {
      total_pss = 0;
      break;
    }
    for (off_t page = static_cast<off_t>(start/pagesize);
         page < static_cast<off_t>(end/pagesize); page++) {
      uint64_t data;
      if (ReadData(pagemap_fd, page, &data)) {
        if (PAGEMAP_PRESENT(data) && !PAGEMAP_SWAPPED(data)) {
          uint64_t count;
          if (ReadData(pagecount_fd, static_cast<off_t>(PAGEMAP_PFN(data)), &count)) {
            total_pss += (count >= 1) ? pagesize / count : 0;
          }
        }
      }
    }
  }

  fclose(maps);

  close(pagecount_fd);
  close(pagemap_fd);

  return total_pss;
}

libbacktrace/GetPss.h

deleted100644 → 0
+0 −22
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2014 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.
 */

#ifndef _LIBBACKTRACE_GET_PSS_H
#define _LIBBACKTRACE_GET_PSS_H

size_t GetPssBytes();

#endif // _LIBBACKTRACE_GET_PSS_H
+20 −27
Original line number Original line Diff line number Diff line
@@ -37,15 +37,7 @@


#include <gtest/gtest.h>
#include <gtest/gtest.h>


extern "C" {
#include "BacktraceTest.h"
// Prototypes for functions in the test library.
int test_level_one(int, int, int, int, void (*)(void*), void*);
int test_level_two(int, int, int, int, void (*)(void*), void*);
int test_level_three(int, int, int, int, void (*)(void*), void*);
int test_level_four(int, int, int, int, void (*)(void*), void*);
int test_recursive_call(int, void (*)(void*), void*);
void test_get_context_and_wait(void* context, volatile int* exit_flag);
}


struct FunctionSymbol {
struct FunctionSymbol {
  std::string name;
  std::string name;
@@ -56,12 +48,13 @@ struct FunctionSymbol {
static std::vector<FunctionSymbol> GetFunctionSymbols() {
static std::vector<FunctionSymbol> GetFunctionSymbols() {
  std::vector<FunctionSymbol> symbols = {
  std::vector<FunctionSymbol> symbols = {
      {"unknown_start", 0, 0},
      {"unknown_start", 0, 0},
      {"test_level_one", reinterpret_cast<uint64_t>(&test_level_one), 0},
      {"test_level_one", reinterpret_cast<uint64_t>(&BacktraceTest::test_level_one_), 0},
      {"test_level_two", reinterpret_cast<uint64_t>(&test_level_two), 0},
      {"test_level_two", reinterpret_cast<uint64_t>(&BacktraceTest::test_level_two_), 0},
      {"test_level_three", reinterpret_cast<uint64_t>(&test_level_three), 0},
      {"test_level_three", reinterpret_cast<uint64_t>(&BacktraceTest::test_level_three_), 0},
      {"test_level_four", reinterpret_cast<uint64_t>(&test_level_four), 0},
      {"test_level_four", reinterpret_cast<uint64_t>(&BacktraceTest::test_level_four_), 0},
      {"test_recursive_call", reinterpret_cast<uint64_t>(&test_recursive_call), 0},
      {"test_recursive_call", reinterpret_cast<uint64_t>(&BacktraceTest::test_recursive_call_), 0},
      {"test_get_context_and_wait", reinterpret_cast<uint64_t>(&test_get_context_and_wait), 0},
      {"test_get_context_and_wait",
       reinterpret_cast<uint64_t>(&BacktraceTest::test_get_context_and_wait_), 0},
      {"unknown_end", static_cast<uint64_t>(-1), static_cast<uint64_t>(-1)},
      {"unknown_end", static_cast<uint64_t>(-1), static_cast<uint64_t>(-1)},
  };
  };
  std::sort(
  std::sort(
@@ -100,7 +93,7 @@ struct OfflineThreadArg {
static void* OfflineThreadFunc(void* arg) {
static void* OfflineThreadFunc(void* arg) {
  OfflineThreadArg* fn_arg = reinterpret_cast<OfflineThreadArg*>(arg);
  OfflineThreadArg* fn_arg = reinterpret_cast<OfflineThreadArg*>(arg);
  fn_arg->tid = android::base::GetThreadId();
  fn_arg->tid = android::base::GetThreadId();
  test_get_context_and_wait(&fn_arg->ucontext, &fn_arg->exit_flag);
  BacktraceTest::test_get_context_and_wait_(&fn_arg->ucontext, &fn_arg->exit_flag);
  return nullptr;
  return nullptr;
}
}


@@ -109,7 +102,7 @@ std::string GetTestPath(const std::string& arch, const std::string& path) {
}
}


// This test is disable because it is for generating test data.
// This test is disable because it is for generating test data.
TEST(libbacktrace, DISABLED_generate_offline_testdata) {
TEST_F(BacktraceTest, DISABLED_generate_offline_testdata) {
  // Create a thread to generate the needed stack and registers information.
  // Create a thread to generate the needed stack and registers information.
  const size_t stack_size = 16 * 1024;
  const size_t stack_size = 16 * 1024;
  void* stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
  void* stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
@@ -304,22 +297,22 @@ static void BacktraceOfflineTest(std::string arch_str, const std::string& testli
}
}


// For now, these tests can only run on the given architectures.
// For now, these tests can only run on the given architectures.
TEST(libbacktrace, offline_eh_frame) {
TEST_F(BacktraceTest, offline_eh_frame) {
  BacktraceOfflineTest("arm64", "libbacktrace_test_eh_frame.so");
  BacktraceOfflineTest("arm64", "libbacktrace_test_eh_frame.so");
  BacktraceOfflineTest("x86_64", "libbacktrace_test_eh_frame.so");
  BacktraceOfflineTest("x86_64", "libbacktrace_test_eh_frame.so");
}
}


TEST(libbacktrace, offline_debug_frame) {
TEST_F(BacktraceTest, offline_debug_frame) {
  BacktraceOfflineTest("arm", "libbacktrace_test_debug_frame.so");
  BacktraceOfflineTest("arm", "libbacktrace_test_debug_frame.so");
  BacktraceOfflineTest("x86", "libbacktrace_test_debug_frame.so");
  BacktraceOfflineTest("x86", "libbacktrace_test_debug_frame.so");
}
}


TEST(libbacktrace, offline_gnu_debugdata) {
TEST_F(BacktraceTest, offline_gnu_debugdata) {
  BacktraceOfflineTest("arm", "libbacktrace_test_gnu_debugdata.so");
  BacktraceOfflineTest("arm", "libbacktrace_test_gnu_debugdata.so");
  BacktraceOfflineTest("x86", "libbacktrace_test_gnu_debugdata.so");
  BacktraceOfflineTest("x86", "libbacktrace_test_gnu_debugdata.so");
}
}


TEST(libbacktrace, offline_arm_exidx) {
TEST_F(BacktraceTest, offline_arm_exidx) {
  BacktraceOfflineTest("arm", "libbacktrace_test_arm_exidx.so");
  BacktraceOfflineTest("arm", "libbacktrace_test_arm_exidx.so");
}
}


@@ -373,32 +366,32 @@ static void LibUnwindingTest(const std::string& arch_str, const std::string& tes


// This test tests the situation that ranges of functions covered by .eh_frame and .ARM.exidx
// This test tests the situation that ranges of functions covered by .eh_frame and .ARM.exidx
// overlap with each other, which appears in /system/lib/libart.so.
// overlap with each other, which appears in /system/lib/libart.so.
TEST(libbacktrace, offline_unwind_mix_eh_frame_and_arm_exidx) {
TEST_F(BacktraceTest, offline_unwind_mix_eh_frame_and_arm_exidx) {
  LibUnwindingTest("arm", "offline_testdata_for_libart", "libart.so");
  LibUnwindingTest("arm", "offline_testdata_for_libart", "libart.so");
}
}


TEST(libbacktrace, offline_debug_frame_with_load_bias) {
TEST_F(BacktraceTest, offline_debug_frame_with_load_bias) {
  LibUnwindingTest("arm", "offline_testdata_for_libandroid_runtime", "libandroid_runtime.so");
  LibUnwindingTest("arm", "offline_testdata_for_libandroid_runtime", "libandroid_runtime.so");
}
}


TEST(libbacktrace, offline_try_armexidx_after_debug_frame) {
TEST_F(BacktraceTest, offline_try_armexidx_after_debug_frame) {
  LibUnwindingTest("arm", "offline_testdata_for_libGLESv2_adreno", "libGLESv2_adreno.so");
  LibUnwindingTest("arm", "offline_testdata_for_libGLESv2_adreno", "libGLESv2_adreno.so");
}
}


TEST(libbacktrace, offline_cie_with_P_augmentation) {
TEST_F(BacktraceTest, offline_cie_with_P_augmentation) {
  // Make sure we can unwind through functions with CIE entry containing P augmentation, which
  // Make sure we can unwind through functions with CIE entry containing P augmentation, which
  // makes unwinding library reading personality handler from memory. One example is
  // makes unwinding library reading personality handler from memory. One example is
  // /system/lib64/libskia.so.
  // /system/lib64/libskia.so.
  LibUnwindingTest("arm64", "offline_testdata_for_libskia", "libskia.so");
  LibUnwindingTest("arm64", "offline_testdata_for_libskia", "libskia.so");
}
}


TEST(libbacktrace, offline_empty_eh_frame_hdr) {
TEST_F(BacktraceTest, offline_empty_eh_frame_hdr) {
  // Make sure we can unwind through libraries with empty .eh_frame_hdr section. One example is
  // Make sure we can unwind through libraries with empty .eh_frame_hdr section. One example is
  // /vendor/lib64/egl/eglSubDriverAndroid.so.
  // /vendor/lib64/egl/eglSubDriverAndroid.so.
  LibUnwindingTest("arm64", "offline_testdata_for_eglSubDriverAndroid", "eglSubDriverAndroid.so");
  LibUnwindingTest("arm64", "offline_testdata_for_eglSubDriverAndroid", "eglSubDriverAndroid.so");
}
}


TEST(libbacktrace, offline_max_frames_limit) {
TEST_F(BacktraceTest, offline_max_frames_limit) {
  // The length of callchain can reach 256 when recording an application.
  // The length of callchain can reach 256 when recording an application.
  ASSERT_GE(MAX_BACKTRACE_FRAMES, 256);
  ASSERT_GE(MAX_BACKTRACE_FRAMES, 256);
}
}
Loading