Skip to content

Commit

Permalink
[lldb/breakpad] Fix register resolution on arm
Browse files Browse the repository at this point in the history
In breakpad, only x86 (and mips) registers have a leading '$' in their
names. Arm architectures use plain register names.

Previously, lldb was assuming all registers have a '$'. Fix the code to
match the (unfortunately, inconsistent) reality.
  • Loading branch information
labath committed Mar 26, 2020
1 parent 2ca7fe3 commit e22f0da
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 11 deletions.
31 changes: 20 additions & 11 deletions lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
Expand Up @@ -408,20 +408,25 @@ GetRule(llvm::StringRef &unwind_rules) {
}

static const RegisterInfo *
ResolveRegister(const SymbolFile::RegisterInfoResolver &resolver,
ResolveRegister(const llvm::Triple &triple,
const SymbolFile::RegisterInfoResolver &resolver,
llvm::StringRef name) {
if (name.consume_front("$"))
return resolver.ResolveName(name);

return nullptr;
if (triple.isX86() || triple.isMIPS()) {
// X86 and MIPS registers have '$' in front of their register names. Arm and
// AArch64 don't.
if (!name.consume_front("$"))
return nullptr;
}
return resolver.ResolveName(name);
}

static const RegisterInfo *
ResolveRegisterOrRA(const SymbolFile::RegisterInfoResolver &resolver,
ResolveRegisterOrRA(const llvm::Triple &triple,
const SymbolFile::RegisterInfoResolver &resolver,
llvm::StringRef name) {
if (name == ".ra")
return resolver.ResolveNumber(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
return ResolveRegister(resolver, name);
return ResolveRegister(triple, resolver, name);
}

llvm::ArrayRef<uint8_t> SymbolFileBreakpad::SaveAsDWARF(postfix::Node &node) {
Expand All @@ -440,6 +445,7 @@ bool SymbolFileBreakpad::ParseCFIUnwindRow(llvm::StringRef unwind_rules,
Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS);

llvm::BumpPtrAllocator node_alloc;
llvm::Triple triple = m_objfile_sp->GetArchitecture().GetTriple();
while (auto rule = GetRule(unwind_rules)) {
node_alloc.Reset();
llvm::StringRef lhs = rule->first;
Expand All @@ -455,7 +461,8 @@ bool SymbolFileBreakpad::ParseCFIUnwindRow(llvm::StringRef unwind_rules,
if (name == ".cfa" && lhs != ".cfa")
return postfix::MakeNode<postfix::InitialValueNode>(node_alloc);

if (const RegisterInfo *info = ResolveRegister(resolver, name)) {
if (const RegisterInfo *info =
ResolveRegister(triple, resolver, name)) {
return postfix::MakeNode<postfix::RegisterNode>(
node_alloc, info->kinds[eRegisterKindLLDB]);
}
Expand All @@ -470,7 +477,8 @@ bool SymbolFileBreakpad::ParseCFIUnwindRow(llvm::StringRef unwind_rules,
llvm::ArrayRef<uint8_t> saved = SaveAsDWARF(*rhs);
if (lhs == ".cfa") {
row.GetCFAValue().SetIsDWARFExpression(saved.data(), saved.size());
} else if (const RegisterInfo *info = ResolveRegisterOrRA(resolver, lhs)) {
} else if (const RegisterInfo *info =
ResolveRegisterOrRA(triple, resolver, lhs)) {
UnwindPlan::Row::RegisterLocation loc;
loc.SetIsDWARFExpression(saved.data(), saved.size());
row.SetRegisterInfo(info->kinds[eRegisterKindLLDB], loc);
Expand Down Expand Up @@ -574,14 +582,15 @@ SymbolFileBreakpad::ParseWinUnwindPlan(const Bookmark &bookmark,
return nullptr;
}
auto it = program.begin();
llvm::Triple triple = m_objfile_sp->GetArchitecture().GetTriple();
const auto &symbol_resolver =
[&](postfix::SymbolNode &symbol) -> postfix::Node * {
llvm::StringRef name = symbol.GetName();
for (const auto &rule : llvm::make_range(program.begin(), it)) {
if (rule.first == name)
return rule.second;
}
if (const RegisterInfo *info = ResolveRegister(resolver, name))
if (const RegisterInfo *info = ResolveRegister(triple, resolver, name))
return postfix::MakeNode<postfix::RegisterNode>(
node_alloc, info->kinds[eRegisterKindLLDB]);
return nullptr;
Expand Down Expand Up @@ -611,7 +620,7 @@ SymbolFileBreakpad::ParseWinUnwindPlan(const Bookmark &bookmark,

// Now process the rest of the assignments.
for (++it; it != program.end(); ++it) {
const RegisterInfo *info = ResolveRegister(resolver, it->first);
const RegisterInfo *info = ResolveRegister(triple, resolver, it->first);
// It is not an error if the resolution fails because the program may
// contain temporary variables.
if (!info)
Expand Down
5 changes: 5 additions & 0 deletions lldb/test/Shell/SymbolFile/Breakpad/Inputs/stack-cfi-arm.syms
@@ -0,0 +1,5 @@
MODULE Linux arm E5894855C35DCCCCCCCCCCCCCCCCCCCC0 linux.out
INFO CODE_ID E35C283BC327C28762DB788BF5A4078BE2351448
FUNC 0 2 0 func0
STACK CFI INIT 0 2 .cfa: sp 0 + .ra: lr
STACK CFI 2 .cfa: sp 8 + .ra: .cfa -4 + ^ r7: .cfa -8 + ^
32 changes: 32 additions & 0 deletions lldb/test/Shell/SymbolFile/Breakpad/stack-cfi-arm.yaml
@@ -0,0 +1,32 @@
# REQUIRES: arm

# RUN: yaml2obj %s >%t
# RUN: %lldb -c %t -o "target symbols add %S/Inputs/stack-cfi-arm.syms" \
# RUN: -o "image show-unwind -n func0" -b | FileCheck %s

# CHECK: Symbol file UnwindPlan:
# CHECK: row[0]: 0: CFA=DW_OP_breg13 +0, DW_OP_consts +0, DW_OP_plus => pc=DW_OP_breg14 +0
# CHECK-NEXT: row[1]: 2: CFA=DW_OP_breg13 +0, DW_OP_consts +8, DW_OP_plus => r7=DW_OP_pick 0x00, DW_OP_consts -8, DW_OP_plus , DW_OP_deref pc=DW_OP_pick 0x00, DW_OP_consts -4, DW_OP_plus , DW_OP_deref
#

--- !minidump
Streams:
- Type: ThreadList
Threads:
- Thread Id: 0x00003E81
Context: DEAD
Stack:
Start of Memory Range: 0x00007FFCEB34A000
Content: DEAD
- Type: ModuleList
Modules:
- Base of Image: 0x0000000000400000
Size of Image: 0x00001000
Module Name: '/tmp/stack-cfi-arm.out'
CodeView Record: 4C457042E35C283BC327C28762DB788BF5A4078BE2351448
- Type: SystemInfo
Processor Arch: ARM
Platform ID: Linux
CPU:
CPUID: 0
...

0 comments on commit e22f0da

Please sign in to comment.