0

Revert "Reland "Android: Add code to parse the CFI info added to the apk""

This reverts commit 839ddb373b.

Reason for revert: <INSERT REASONING HERE>

Original change's description:
> Reland "Android: Add code to parse the CFI info added to the apk"
> 
> This reverts commit 88328b6800.
> 
> Reason for revert: seems to break "generate_build_files" step on several of our build bots, see e.g.:
> 
> https://build.chromium.org/deprecated/chromium.webrtc/builders/Linux%20Builder/builds/126662
> 
> Original change's description:
> > Revert "Android: Add code to parse the CFI info added to the apk"
> > 
> > This reverts commit 1d8b0c0096.
> > 
> > Reason for revert: https://crbug.com/826718
> > 
> > CL causes failures on Android CFI builder.
> > 
> > Original change's description:
> > > Android: Add code to parse the CFI info added to the apk
> > > 
> > > The previous CL added support for adding unwind tables in apk:
> > > https://chromium-review.googlesource.com/c/chromium/src/+/956971
> > > This CL parses and adds test for unwinding on base_unittests_apk.
> > > The non-official builds do not contain debug info since all bots set
> > > strip_debug_info=true. So, make sure base_unittests do not take this
> > > flag.
> > > 
> > > BUG=819888
> > > 
> > > Change-Id: Ib69909e14f9f8623ac07154ef60be248558b08a4
> > > Reviewed-on: https://chromium-review.googlesource.com/958326
> > > Commit-Queue: Siddhartha S <ssid@chromium.org>
> > > Reviewed-by: Daniel Cheng <dcheng@chromium.org>
> > > Reviewed-by: Primiano Tucci <primiano@chromium.org>
> > > Reviewed-by: Dirk Pranke <dpranke@chromium.org>
> > > Reviewed-by: agrieve <agrieve@chromium.org>
> > > Cr-Commit-Position: refs/heads/master@{#546343}
> > 
> > TBR=dcheng@chromium.org,primiano@chromium.org,dpranke@chromium.org,ssid@chromium.org,agrieve@chromium.org,dskiba@chromium.org
> > 
> > Change-Id: Ib9bcb81ffa30861ea91107c1a1f3ccb8f29a7f7d
> > No-Presubmit: true
> > No-Tree-Checks: true
> > No-Try: true
> > Bug: 819888
> > Reviewed-on: https://chromium-review.googlesource.com/983972
> > Reviewed-by: François Doray <fdoray@chromium.org>
> > Commit-Queue: François Doray <fdoray@chromium.org>
> > Cr-Commit-Position: refs/heads/master@{#546472}
> 
> TBR=dcheng@chromium.org,primiano@chromium.org,fdoray@chromium.org,dpranke@chromium.org,ssid@chromium.org,agrieve@chromium.org,dskiba@chromium.org
> 
> Change-Id: Ib39e4563c82264389d7a740a877d27edef343101
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Bug: 819888
> Reviewed-on: https://chromium-review.googlesource.com/984092
> Reviewed-by: Henrik Andreasson <henrika@chromium.org>
> Commit-Queue: Henrik Andreasson <henrika@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#546479}

TBR=dcheng@chromium.org,primiano@chromium.org,fdoray@chromium.org,dpranke@chromium.org,ssid@chromium.org,agrieve@chromium.org,dskiba@chromium.org,henrika@chromium.org

Change-Id: I1bbb46629fed0b9467482d66f88a548e4d949a24
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: 819888
Reviewed-on: https://chromium-review.googlesource.com/984013
Reviewed-by: Peter Mayo <petermayo@chromium.org>
Commit-Queue: Peter Mayo <petermayo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#546481}
This commit is contained in:
Peter Mayo
2018-03-28 14:35:56 +00:00
committed by Commit Bot
parent 5bd2969b2e
commit 19a53de61b
6 changed files with 3 additions and 536 deletions

@ -1274,13 +1274,6 @@ jumbo_component("base") {
# Needs to be a public config so that dependent targets link against it as
# well when doing a component build.
public_configs = [ ":android_system_libs" ]
if (can_unwind_with_cfi_table) {
sources += [
"trace_event/cfi_backtrace_android.cc",
"trace_event/cfi_backtrace_android.h",
]
}
}
# Chromeos.
@ -2469,20 +2462,6 @@ test("base_unittests") {
}
if (is_android) {
# Add unwind tables in base_unittests_apk test apk. The unwind tables are
# generated from debug info in the binary. Removing "default_symbols" and
# adding symbols config removes the "strip_debug" config that strips the
# debug info, on base unittests apk.
if (can_unwind_with_cfi_table) {
configs -= [ "//build/config/compiler:default_symbols" ]
if (symbol_level == 2) {
configs += [ "//build/config/compiler:symbols" ]
} else {
configs += [ "//build/config/compiler:minimal_symbols" ]
}
add_unwind_tables_in_apk = true
sources += [ "trace_event/cfi_backtrace_android_unittest.cc" ]
}
sources -= [
"process/process_unittest.cc",
"process/process_util_unittest.cc",

@ -1,277 +0,0 @@
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/trace_event/cfi_backtrace_android.h"
#include <sys/mman.h>
#include <sys/types.h>
#include "base/android/apk_assets.h"
#include "base/debug/stack_trace.h"
#if !defined(ARCH_CPU_ARMEL)
#error This file should not be built for this architecture.
#endif
/*
Basics of unwinding:
For each instruction in a function we need to know what is the offset of SP
(Stack Pointer) to reach the previous function's stack frame. To know which
function is being invoked, we need the return address of the next function. The
CFI information for an instruction is made up of 2 offsets, CFA (Call Frame
Address) offset and RA (Return Address) offset. The CFA offset is the change in
SP made by the function till the current instruction. This depends on amount of
memory allocated on stack by the function plus some registers that the function
stores that needs to be restored at the end of function. So, at each instruction
the CFA offset tells the offset from original SP before the function call. The
RA offset tells us the offset from the previous SP into the current function
where the return address is stored.
The unwind table contains rows of 64 bits each.
We have 2 types of rows, FUNCTION and CFI.
Each function with CFI info has a single FUNCTION row, followed by one or more
CFI rows. All the addresses of the CFI rows will be within the function.
1. FUNCTION. Bits in order of high to low represent:
31 bits: specifies function address, without the last bit (always 0).
1 bit : always 1. Last bit of the address, specifies the row type is
FUNCTION.
32 bits: length of the current function.
2. CFI. Bits in order of high to low represent:
31 bits: instruction address in the current function.
1 bit : always 0. Last bit of the address, specifies the row type is CFI.
30 bits: CFA offset / 4.
2 bits: RA offset / 4.
If the RA offset of a row is 0, then use the offset of the previous rows in the
same function.
TODO(ssid): Make sure RA offset is always present.
See extract_unwind_tables.py for details about how this data is extracted from
breakpad symbol files.
*/
extern "C" {
extern char __executable_start;
extern char _etext;
}
namespace base {
namespace trace_event {
namespace {
// The bit of the address that is used to specify the type of the row is
// FUNCTION or CFI type.
constexpr uint32_t kFunctionTypeMask = 0x1;
// The mask on the CFI row data that is used to get the high 30 bits and
// multiply it by 4 to get CFA offset. Since the last 2 bits are masked out, a
// shift is not necessary.
constexpr uint32_t kCFAMask = 0xfffffffc;
// The mask on the CFI row data that is used to get the low 2 bits and multiply
// it by 4 to get the RA offset.
constexpr uint32_t kRAMask = 0x3;
constexpr uint32_t kRAShift = 2;
// The code in this file assumes we are running in 32-bit builds since all the
// addresses in the unwind table are specified in 32 bits.
static_assert(sizeof(uintptr_t) == 4,
"The unwind table format is only valid for 32 bit builds.");
// The struct that corresponds to each row in the unwind table. The row can be
// of any type, CFI or FUNCTION. The first 4 bytes in the row represents the
// address and the next 4 bytes have data. The members of this struct is in
// order of the input format. We cast the memory map of the unwind table as an
// array of CFIUnwindInfo and use it to read data and search. So, the size of
// this struct should be 8 bytes and the order of the members is fixed according
// to the given format.
struct CFIUnwindInfo {
// The address is either the start address of the function or the instruction
// address where the CFI information changes in a function. If the last bit of
// the address is 1 then it specifies that the row is of type FUNCTION and if
// the last bit is 0 then it specifies the row is of type CFI.
uintptr_t addr;
// If the row type is function, |data| is |function_length|. If the row type
// is CFI, |data| is |cfi_data|.
union {
// Represents the total length of the function that start with the |addr|.
uintptr_t function_length;
// Represents the CFA and RA offsets to get information about next stack
// frame.
uintptr_t cfi_data;
} data;
bool is_function_type() const { return !!(addr & kFunctionTypeMask); }
// Returns the address of the current row, CFI or FUNCTION type.
uintptr_t address() const {
return is_function_type() ? (addr & ~kFunctionTypeMask) : addr;
}
// Return the RA offset when the current row is CFI type.
uintptr_t ra_offset() const {
DCHECK(!is_function_type());
return (data.cfi_data & kRAMask) << kRAShift;
}
// Returns the CFA offset if the current row is CFI type.
uintptr_t cfa_offset() const {
DCHECK(!is_function_type());
return data.cfi_data & kCFAMask;
}
// Returns true if the instruction is within the function address range, given
// that the current row is FUNCTION type and the |instruction_addr| is offset
// address of instruction from the start of the binary.
bool is_instruction_in_function(uintptr_t instruction_addr) const {
DCHECK(is_function_type());
return (instruction_addr >= address()) &&
(instruction_addr <= address() + data.function_length);
}
};
static_assert(
sizeof(CFIUnwindInfo) == 8,
"The CFIUnwindInfo struct must be exactly 8 bytes for searching.");
} // namespace
// static
CFIBacktraceAndroid* CFIBacktraceAndroid::GetInstance() {
static CFIBacktraceAndroid* instance = new CFIBacktraceAndroid();
return instance;
}
CFIBacktraceAndroid::CFIBacktraceAndroid() {
Initialize();
}
CFIBacktraceAndroid::~CFIBacktraceAndroid() {}
void CFIBacktraceAndroid::Initialize() {
// The address |_etext| gives the end of the .text section in the binary. This
// value is more accurate than parsing the memory map since the mapped
// regions are usualy larger than the .text section.
executable_end_addr_ = reinterpret_cast<uintptr_t>(&_etext);
// The address of |__executable_start| gives the start address of the
// executable. This value is used to find the offset address of the
// instruction in binary from PC.
executable_start_addr_ = reinterpret_cast<uintptr_t>(&__executable_start);
// This file name is defined by extract_unwind_tables.gni.
static constexpr char kCfiFileName[] = "assets/unwind_cfi";
MemoryMappedFile::Region cfi_region;
int fd = base::android::OpenApkAsset(kCfiFileName, &cfi_region);
if (fd < 0)
return;
cfi_mmap_ = std::make_unique<MemoryMappedFile>();
// The CFI region starts at |cfi_region.offset|.
if (!cfi_mmap_->Initialize(base::File(fd), cfi_region))
return;
// The CFI file should contain rows of 8 bytes each.
DCHECK_EQ(0u, cfi_region.size % sizeof(CFIUnwindInfo));
unwind_table_row_count_ = cfi_region.size / sizeof(CFIUnwindInfo);
can_unwind_stack_frames_ = true;
}
size_t CFIBacktraceAndroid::Unwind(const void** out_trace,
size_t max_depth) const {
// This function walks the stack using the call frame information to find the
// return addresses of all the functions that belong to current binary in call
// stack. For each function the CFI table defines the offset of the previous
// call frame and offset where the return address is stored.
if (!can_unwind_stack_frames())
return 0;
// Get the current register state. This register state can be taken at any
// point in the function and the unwind information would be for this point.
// Define local variables before trying to get the current PC and SP to make
// sure the register state obtained is consistent with each other.
uintptr_t pc = 0, sp = 0;
asm volatile("mov %0, pc" : "=r"(pc));
asm volatile("mov %0, sp" : "=r"(sp));
// We can only unwind as long as the pc is within the chrome.so.
size_t depth = 0;
while (pc > executable_start_addr_ && pc <= executable_end_addr_ &&
depth < max_depth) {
out_trace[depth++] = reinterpret_cast<void*>(pc);
// The offset of function from the start of the chrome.so binary:
uintptr_t func_addr = pc - executable_start_addr_;
CFIRow cfi{};
if (!FindCFIRowForPC(func_addr, &cfi))
break;
// The rules for unwinding using the CFI information are:
// SP_prev = SP_cur + cfa_offset and
// PC_prev = * (SP_prev - ra_offset).
sp = sp + cfi.cfa_offset;
memcpy(&pc, reinterpret_cast<uintptr_t*>(sp - cfi.ra_offset),
sizeof(uintptr_t));
}
return depth;
}
bool CFIBacktraceAndroid::FindCFIRowForPC(
uintptr_t func_addr,
CFIBacktraceAndroid::CFIRow* cfi) const {
// Consider the CFI mapped region as an array of CFIUnwindInfo since each row
// is 8 bytes long and it contains |cfi_region_size_| / 8 rows. We define
// start and end iterator on this array and use std::lower_bound() to binary
// search on this array. std::lower_bound() returns the row that corresponds
// to the first row that has address greater than the current value, since
// address is used in compartor.
const CFIUnwindInfo* start =
reinterpret_cast<const CFIUnwindInfo*>(cfi_mmap_->data());
const CFIUnwindInfo* end = start + unwind_table_row_count_;
const CFIUnwindInfo to_find = {func_addr, {0}};
const CFIUnwindInfo* found = std::lower_bound(
start, end, to_find,
[](const auto& a, const auto& b) { return a.addr < b.addr; });
*cfi = {0};
// The given address is less than the start address in the CFI table if
// lower_bound() returns start.
if (found == start)
return false;
// If the given address is equal to the found address, then use the found row.
// Otherwise the required row is always one less than the value returned by
// std::lower_bound().
if (found == end || found->address() != func_addr)
found--;
DCHECK_LE(found->address(), func_addr);
DCHECK(!found->is_function_type())
<< "Current PC cannot be start of a function";
// The CFIUnwindInfo::data field hold the CFI information since the row
// found should not correspond to function start address. So, interpret the
// data in the found row as CFI data which contains the CFA and RA offsets.
*cfi = {found->cfa_offset(), found->ra_offset()};
DCHECK(cfi->cfa_offset);
// Find the function data for the current row by iterating till we reach the a
// row of type FUNCTION, to check if the unwind information is valid. Also
// find the RA offset if we do not have it in the CFI row found.
const CFIUnwindInfo* it = found;
for (; !it->is_function_type() && it >= start; it--) {
// If ra offset of the last specified row should be used, if unspecified.
// TODO(ssid): This should be fixed in the format and we should always
// output ra offset.
if (!cfi->ra_offset)
cfi->ra_offset = it->ra_offset();
}
// If the given function adddress does not belong to the function found, then
// the unwind info is invalid.
if (!it->is_instruction_in_function(func_addr))
return false;
DCHECK(cfi->ra_offset);
return true;
}
} // namespace trace_event
} // namespace base

@ -1,103 +0,0 @@
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_TRACE_EVENT_CFI_BACKTRACE_ANDROID_H_
#define BASE_TRACE_EVENT_CFI_BACKTRACE_ANDROID_H_
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include "base/base_export.h"
#include "base/debug/debugging_buildflags.h"
#include "base/files/memory_mapped_file.h"
#include "base/gtest_prod_util.h"
namespace base {
namespace trace_event {
// This class is used to unwind stack frames in the current thread. The unwind
// information (dwarf debug info) is stripped from the chrome binary and we do
// not build with exception tables (ARM EHABI) in release builds. So, we use a
// custom unwind table which is generated and added to specific android builds,
// when add_unwind_tables_in_apk build option is specified. This unwind table
// contains information for unwinding stack frames when the functions calls are
// from lib[mono]chrome.so. The file is added as an asset to the apk and the
// table is used to unwind stack frames for profiling. This class implements
// methods to read and parse the unwind table and unwind stack frames using this
// data.
class BASE_EXPORT CFIBacktraceAndroid {
public:
// Creates and initializes the unwinder on first call.
static CFIBacktraceAndroid* GetInstance();
// Returns true if stack unwinding is possible using CFI unwind tables in apk.
// There is no need to check this before each unwind call. Will always return
// the same value based on CFI tables being present in the binary.
bool can_unwind_stack_frames() const { return can_unwind_stack_frames_; }
// Returns the program counters by unwinding stack in the current thread in
// order of latest call frame first. Unwinding works only if
// can_unwind_stack_frames() returns true. This function does not allocate
// memory from heap. For each stack frame, this method searches through the
// unwind table mapped in memory to find the unwind information for function
// and walks the stack to find all the return address. This only works until
// the last function call from the chrome.so. We do not have unwind
// information to unwind beyond any frame outside of chrome.so. Calls to
// Unwind() are thread safe and lock free, once Initialize() returns success.
size_t Unwind(const void** out_trace, size_t max_depth) const;
private:
FRIEND_TEST_ALL_PREFIXES(CFIBacktraceAndroidTest, TestFindCFIRow);
FRIEND_TEST_ALL_PREFIXES(CFIBacktraceAndroidTest, TestUnwinding);
// The CFI information that correspond to an instruction.
struct CFIRow {
bool operator==(const CFIBacktraceAndroid::CFIRow& o) const {
return cfa_offset == o.cfa_offset && ra_offset == o.ra_offset;
}
// The offset of the call frame address of previous function from the
// current stack pointer. Rule for unwinding SP: SP_prev = SP_cur +
// cfa_offset.
size_t cfa_offset = 0;
// The offset of location of return address from the previous call frame
// address. Rule for unwinding PC: PC_prev = * (SP_prev - ra_offset).
size_t ra_offset = 0;
};
CFIBacktraceAndroid();
~CFIBacktraceAndroid();
// Initializes unwind tables using the CFI asset file in the apk if present.
// Also stores the limits of mapped region of the lib[mono]chrome.so binary,
// since the unwind is only feasible for addresses within the .so file. Once
// initialized, the memory map of the unwind table is never cleared since we
// cannot guarantee that all the threads are done using the memory map when
// heap profiling is turned off. But since we keep the memory map is clean,
// the system can choose to evict the unused pages when needed. This would
// still reduce the total amount of address space available in process.
void Initialize();
// Finds the CFI row for the given |func_addr| in terms of offset from
// the start of the current binary.
bool FindCFIRowForPC(uintptr_t func_addr, CFIRow* out) const;
// Details about the memory mapped region which contains the libchrome.so
// library file.
uintptr_t executable_start_addr_ = 0;
uintptr_t executable_end_addr_ = 0;
// The start address of the memory mapped unwind table asset file. Unique ptr
// because it is replaced in tests.
std::unique_ptr<MemoryMappedFile> cfi_mmap_;
size_t unwind_table_row_count_ = 0;
bool can_unwind_stack_frames_ = false;
};
} // namespace trace_event
} // namespace base
#endif // BASE_TRACE_EVENT_CFI_BACKTRACE_ANDROID_H_

@ -1,117 +0,0 @@
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/trace_event/cfi_backtrace_android.h"
#include "base/files/file_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace base {
namespace trace_event {
namespace {
void* GetPC() {
return __builtin_return_address(0);
}
} // namespace
TEST(CFIBacktraceAndroidTest, TestUnwinding) {
auto* unwinder = CFIBacktraceAndroid::GetInstance();
EXPECT_TRUE(unwinder->can_unwind_stack_frames());
EXPECT_GT(unwinder->executable_start_addr_, 0u);
EXPECT_GT(unwinder->executable_end_addr_, unwinder->executable_start_addr_);
EXPECT_GT(unwinder->cfi_mmap_->length(), 0u);
const size_t kMaxFrames = 100;
const void* frames[kMaxFrames];
size_t unwind_count = unwinder->Unwind(frames, kMaxFrames);
// Expect at least 2 frames in the result.
ASSERT_GT(unwind_count, 2u);
EXPECT_LE(unwind_count, kMaxFrames);
const size_t kMaxCurrentFuncCodeSize = 50;
const uintptr_t current_pc = reinterpret_cast<uintptr_t>(GetPC());
const uintptr_t actual_frame = reinterpret_cast<uintptr_t>(frames[2]);
EXPECT_NEAR(current_pc, actual_frame, kMaxCurrentFuncCodeSize);
for (size_t i = 0; i < unwind_count; ++i) {
EXPECT_GT(reinterpret_cast<uintptr_t>(frames[i]),
unwinder->executable_start_addr_);
EXPECT_LT(reinterpret_cast<uintptr_t>(frames[i]),
unwinder->executable_end_addr_);
}
}
TEST(CFIBacktraceAndroidTest, TestFindCFIRow) {
auto* unwinder = CFIBacktraceAndroid::GetInstance();
size_t input[] = {// Function 1 - 0x1000
0x1001, 0x500,
0x1002, 0x111,
0x1008, 0x220,
0x1040, 0x330,
0x1050, 0x332,
0x1080, 0x330,
// Function 2 - 0x2000
0x2001, 0x22,
0x2004, 0x13,
0x2008, 0x23,
// Function 3 - 0x2024
0x2025, 0x100,
0x2030, 0x33,
0x2100, 0x40,
// Function 4 - 0x2200
0x2201, 0x10,
0x2204, 0x2e};
FilePath temp_path;
CreateTemporaryFile(&temp_path);
EXPECT_EQ(
static_cast<int>(sizeof(input)),
WriteFile(temp_path, reinterpret_cast<char*>(input), sizeof(input)));
unwinder->cfi_mmap_.reset(new MemoryMappedFile());
ASSERT_TRUE(unwinder->cfi_mmap_->Initialize(temp_path));
unwinder->unwind_table_row_count_ = sizeof(input) / (2 * sizeof(size_t));
CFIBacktraceAndroid::CFIRow cfi_row = {0};
EXPECT_FALSE(unwinder->FindCFIRowForPC(0x00, &cfi_row));
EXPECT_FALSE(unwinder->FindCFIRowForPC(0x100, &cfi_row));
EXPECT_FALSE(unwinder->FindCFIRowForPC(0x1501, &cfi_row));
EXPECT_FALSE(unwinder->FindCFIRowForPC(0x3000, &cfi_row));
EXPECT_FALSE(unwinder->FindCFIRowForPC(0x2023, &cfi_row));
EXPECT_FALSE(unwinder->FindCFIRowForPC(0x2215, &cfi_row));
const CFIBacktraceAndroid::CFIRow kRow1 = {0x110, 0x4};
const CFIBacktraceAndroid::CFIRow kRow2 = {0x220, 0x4};
const CFIBacktraceAndroid::CFIRow kRow3 = {0x330, 0x8};
const CFIBacktraceAndroid::CFIRow kRow4 = {0x30, 0xc};
const CFIBacktraceAndroid::CFIRow kRow5 = {0x2c, 0x8};
EXPECT_TRUE(unwinder->FindCFIRowForPC(0x1002, &cfi_row));
EXPECT_EQ(kRow1, cfi_row);
EXPECT_TRUE(unwinder->FindCFIRowForPC(0x1003, &cfi_row));
EXPECT_EQ(kRow1, cfi_row);
EXPECT_TRUE(unwinder->FindCFIRowForPC(0x1008, &cfi_row));
EXPECT_EQ(kRow2, cfi_row);
EXPECT_TRUE(unwinder->FindCFIRowForPC(0x1009, &cfi_row));
EXPECT_EQ(kRow2, cfi_row);
EXPECT_TRUE(unwinder->FindCFIRowForPC(0x1039, &cfi_row));
EXPECT_EQ(kRow2, cfi_row);
EXPECT_TRUE(unwinder->FindCFIRowForPC(0x1080, &cfi_row));
EXPECT_EQ(kRow3, cfi_row);
EXPECT_TRUE(unwinder->FindCFIRowForPC(0x1100, &cfi_row));
EXPECT_EQ(kRow3, cfi_row);
EXPECT_TRUE(unwinder->FindCFIRowForPC(0x2050, &cfi_row));
EXPECT_EQ(kRow4, cfi_row);
EXPECT_TRUE(unwinder->FindCFIRowForPC(0x2208, &cfi_row));
EXPECT_EQ(kRow5, cfi_row);
EXPECT_TRUE(unwinder->FindCFIRowForPC(0x2210, &cfi_row));
EXPECT_EQ(kRow5, cfi_row);
}
} // namespace trace_event
} // namespace base

@ -2096,6 +2096,9 @@ config("minimal_symbols") {
# TODO(thakis): Consider making clang emit DW_AT_linkage_name in -g1 mode;
# failing that consider doing this on non-Android too.
cflags += [ "-fdebug-info-for-profiling" ]
if (strip_debug_info) {
ldflags += [ "-Wl,--strip-debug" ]
}
}
# Note: -gsplit-dwarf implicitly turns on -g2 with clang, so don't pass it.
@ -2122,18 +2125,6 @@ config("default_symbols") {
} else {
assert(false)
}
# This config is removed by base unittests apk.
if (is_android && is_clang && strip_debug_info) {
configs += [ ":strip_debug" ]
}
}
config("strip_debug") {
if (!defined(ldflags)) {
ldflags = []
}
ldflags += [ "-Wl,--strip-debug" ]
}
if (is_ios || is_mac) {

@ -141,12 +141,6 @@ if (current_cpu == "arm" && arm_use_thumb) {
assert(!can_unwind_with_frame_pointers || enable_frame_pointers)
# Unwinding with CFI table is only possible on static library builds and
# requried only when frame pointers are not enabled.
can_unwind_with_cfi_table =
is_android && !is_component_build && !can_unwind_with_frame_pointers &&
current_cpu == "arm"
declare_args() {
# Whether or not the official builds should be built with full WPO. Enabled by
# default for the PGO and the x64 builds.