Skip to content

Commit 0236cb6

Browse files
authored
[lldb] Enable "frame diagnose" on linux (#123217)
.. by changing the signal stop reason format 🤦 The reason this did not work is because the code in `StopInfo::GetCrashingDereference` was looking for the string "address=" to extract the address of the crash. Macos stop reason strings have the form ``` EXC_BAD_ACCESS (code=1, address=0xdead) ``` while on linux they look like: ``` signal SIGSEGV: address not mapped to object (fault address: 0xdead) ``` Extracting the address from a string sounds like a bad idea, but I suppose there's some value in using a consistent format across platforms, so this patch changes the signal format to use the equals sign as well. All of the diagnose tests pass except one, which appears to fail due to something similar #115453 (disassembler reports unrelocated call targets). I've left the tests disabled on windows, as the stop reason reporting code works very differently there, and I suspect it won't work out of the box. If I'm wrong -- the XFAIL will let us know.
1 parent 3ea2b54 commit 0236cb6

File tree

18 files changed

+46
-28
lines changed

18 files changed

+46
-28
lines changed

lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -326,14 +326,14 @@ void NativeThreadLinux::AnnotateSyncTagCheckFault(lldb::addr_t fault_addr) {
326326
}
327327

328328
// We assume that the stop description is currently:
329-
// signal SIGSEGV: sync tag check fault (fault address: <addr>)
329+
// signal SIGSEGV: sync tag check fault (fault address=<addr>)
330330
// Remove the closing )
331331
m_stop_description.pop_back();
332332

333333
std::stringstream ss;
334334
std::unique_ptr<MemoryTagManager> manager(std::move(details->manager));
335335

336-
ss << " logical tag: 0x" << std::hex << manager->GetLogicalTag(fault_addr);
336+
ss << " logical tag=0x" << std::hex << manager->GetLogicalTag(fault_addr);
337337

338338
std::vector<uint8_t> allocation_tag_data;
339339
// The fault address may not be granule aligned. ReadMemoryTags will granule
@@ -347,7 +347,7 @@ void NativeThreadLinux::AnnotateSyncTagCheckFault(lldb::addr_t fault_addr) {
347347
llvm::Expected<std::vector<lldb::addr_t>> allocation_tag =
348348
manager->UnpackTagsData(allocation_tag_data, 1);
349349
if (allocation_tag) {
350-
ss << " allocation tag: 0x" << std::hex << allocation_tag->front() << ")";
350+
ss << " allocation tag=0x" << std::hex << allocation_tag->front() << ")";
351351
} else {
352352
llvm::consumeError(allocation_tag.takeError());
353353
ss << ")";

lldb/source/Target/UnixSignals.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ UnixSignals::GetSignalDescription(int32_t signo, std::optional<int32_t> code,
163163
break;
164164
case SignalCodePrintOption::Address:
165165
if (addr)
166-
strm << " (fault address: 0x" << std::hex << *addr << ")";
166+
strm << " (fault address=0x" << std::hex << *addr << ")";
167167
break;
168168
case SignalCodePrintOption::Bounds:
169169
if (lower && upper && addr) {
@@ -172,9 +172,9 @@ UnixSignals::GetSignalDescription(int32_t signo, std::optional<int32_t> code,
172172
else
173173
strm << "upper bound violation ";
174174

175-
strm << "(fault address: 0x" << std::hex << *addr;
176-
strm << ", lower bound: 0x" << std::hex << *lower;
177-
strm << ", upper bound: 0x" << std::hex << *upper;
175+
strm << "(fault address=0x" << std::hex << *addr;
176+
strm << ", lower bound=0x" << std::hex << *lower;
177+
strm << ", upper bound=0x" << std::hex << *upper;
178178
strm << ")";
179179
} else
180180
strm << sc.m_description.str();

lldb/test/API/commands/frame/diagnose/array/TestArray.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111

1212
class TestArray(TestBase):
13-
@skipUnlessDarwin
13+
@expectedFailureAll(oslist=["windows"])
1414
@skipIf(
1515
archs=no_match(["x86_64"])
1616
) # <rdar://problem/33842388> frame diagnose doesn't work for armv7 or arm64

lldb/test/API/commands/frame/diagnose/bad-reference/TestBadReference.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111

1212
class TestBadReference(TestBase):
13-
@skipUnlessDarwin
13+
@expectedFailureAll(oslist=["windows"])
1414
@skipIf(
1515
archs=no_match(["x86_64"])
1616
) # <rdar://problem/33842388> frame diagnose doesn't work for armv7 or arm64

lldb/test/API/commands/frame/diagnose/complicated-expression/TestComplicatedExpression.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111

1212
class TestDiagnoseDereferenceArgument(TestBase):
13-
@skipUnlessDarwin
13+
@expectedFailureAll(oslist=["windows"])
1414
@skipIf(
1515
archs=no_match(["x86_64"])
1616
) # <rdar://problem/33842388> frame diagnose doesn't work for armv7 or arm64

lldb/test/API/commands/frame/diagnose/dereference-argument/TestDiagnoseDereferenceArgument.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111

1212
class TestDiagnoseDereferenceArgument(TestBase):
13-
@skipUnlessDarwin
13+
@expectedFailureAll(oslist=["windows"])
1414
@skipIf(
1515
archs=no_match(["x86_64"])
1616
) # <rdar://problem/33842388> frame diagnose doesn't work for armv7 or arm64

lldb/test/API/commands/frame/diagnose/dereference-function-return/TestDiagnoseDereferenceFunctionReturn.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111

1212
class TestDiagnoseDereferenceFunctionReturn(TestBase):
13-
@skipUnlessDarwin
13+
@expectedFailureAll(oslist=no_match(lldbplatformutil.getDarwinOSTriples()))
1414
@skipIf(
1515
archs=no_match(["x86_64"])
1616
) # <rdar://problem/33842388> frame diagnose doesn't work for armv7 or arm64

lldb/test/API/commands/frame/diagnose/dereference-this/TestDiagnoseDereferenceThis.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111

1212
class TestDiagnoseDereferenceThis(TestBase):
13-
@skipUnlessDarwin
13+
@expectedFailureAll(oslist=["windows"])
1414
@skipIf(
1515
archs=no_match(["x86_64"])
1616
) # <rdar://problem/33842388> frame diagnose doesn't work for armv7 or arm64

lldb/test/API/commands/frame/diagnose/inheritance/TestDiagnoseInheritance.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111

1212
class TestDiagnoseInheritance(TestBase):
13-
@skipUnlessDarwin
13+
@expectedFailureAll(oslist=["windows"])
1414
@skipIf(
1515
archs=no_match(["x86_64"])
1616
) # <rdar://problem/33842388> frame diagnose doesn't work for armv7 or arm64

lldb/test/API/commands/frame/diagnose/local-variable/TestLocalVariable.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111

1212
class TestLocalVariable(TestBase):
13-
@skipUnlessDarwin
13+
@expectedFailureAll(oslist=["windows"])
1414
@skipIf(
1515
archs=no_match(["x86_64"])
1616
) # <rdar://problem/33842388> frame diagnose doesn't work for armv7 or arm64

lldb/test/API/commands/frame/diagnose/virtual-method-call/TestDiagnoseDereferenceVirtualMethodCall.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111

1212
class TestDiagnoseVirtualMethodCall(TestBase):
13-
@skipUnlessDarwin
13+
@expectedFailureAll(oslist=["windows"])
1414
@skipIf(
1515
archs=no_match(["x86_64"])
1616
) # <rdar://problem/33842388> frame diagnose doesn't work for armv7 or arm64

lldb/test/API/linux/aarch64/mte_core_file/TestAArch64LinuxMTEMemoryTagCoreFile.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ def test_mte_tag_fault_reason(self):
215215
self.expect(
216216
"bt",
217217
substrs=[
218-
"* thread #1, name = 'a.out.mte', stop reason = SIGSEGV: sync tag check fault (fault address: 0xffff82c74010)"
218+
"* thread #1, name = 'a.out.mte', stop reason = SIGSEGV: sync tag check fault (fault address=0xffff82c74010)"
219219
],
220220
)
221221

lldb/test/API/linux/aarch64/mte_tag_faults/TestAArch64LinuxMTEMemoryTagFaults.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ def test_mte_tag_fault_sync(self):
5151
"continue",
5252
patterns=[
5353
"\* thread #1, name = 'a.out', stop reason = signal SIGSEGV: "
54-
"sync tag check fault \(fault address: 0x9[0-9A-Fa-f]+11\ "
55-
"logical tag: 0x9 allocation tag: 0xa\)"
54+
"sync tag check fault \(fault address=0x9[0-9A-Fa-f]+11\ "
55+
"logical tag=0x9 allocation tag=0xa\)"
5656
],
5757
)
5858

lldb/test/API/linux/aarch64/non_address_bit_memory_access/TestAArch64LinuxNonAddressBitMemoryAccess.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ def test_non_address_bit_memory_corefile(self):
202202
"thread list",
203203
substrs=[
204204
"stopped",
205-
"stop reason = SIGSEGV: address not mapped to object (fault address: 0x0)",
205+
"stop reason = SIGSEGV: address not mapped to object (fault address=0x0)",
206206
],
207207
)
208208

lldb/test/Shell/Register/Core/x86-32-linux-multithread.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# RUN: %lldb -b -s %s -c %p/Inputs/x86-32-linux-multithread.core | FileCheck %s
22

33
thread list
4-
# CHECK: * thread #1: tid = 330633, 0x080492d2, name = 'a.out', stop reason = SIGSEGV: address not mapped to object (fault address: 0x0)
4+
# CHECK: * thread #1: tid = 330633, 0x080492d2, name = 'a.out', stop reason = SIGSEGV: address not mapped to object (fault address=0x0)
55
# CHECK-NEXT: thread #2: tid = 330634, 0x080492dd, stop reason = signal 0
66
# CHECK-NEXT: thread #3: tid = 330635, 0x080492dd, stop reason = signal 0
77
# CHECK-NEXT: thread #4: tid = 330632, 0xf7f59549, stop reason = signal 0

lldb/test/Shell/Register/Core/x86-64-linux-multithread.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# RUN: %lldb -b -s %s -c %p/Inputs/x86-64-linux-multithread.core | FileCheck %s
22

33
thread list
4-
# CHECK: * thread #1: tid = 329384, 0x0000000000401262, name = 'a.out', stop reason = SIGSEGV: address not mapped to object (fault address: 0x0)
4+
# CHECK: * thread #1: tid = 329384, 0x0000000000401262, name = 'a.out', stop reason = SIGSEGV: address not mapped to object (fault address=0x0)
55
# CHECK-NEXT: thread #2: tid = 329385, 0x000000000040126d, stop reason = signal 0
66
# CHECK-NEXT: thread #3: tid = 329386, 0x000000000040126d, stop reason = signal 0
77
# CHECK-NEXT: thread #4: tid = 329383, 0x00007fcf5582f762, stop reason = signal 0

lldb/unittests/Signals/UnixSignalsTest.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ TEST(UnixSignalsTest, GetAsString) {
119119
ASSERT_EQ("SIG16: a specific type of SIG16",
120120
signals.GetSignalDescription(16, 1, 0xCAFEF00D));
121121
// Known code that should.
122-
ASSERT_EQ("SIG16: SIG16 with a fault address (fault address: 0xcafef00d)",
122+
ASSERT_EQ("SIG16: SIG16 with a fault address (fault address=0xcafef00d)",
123123
signals.GetSignalDescription(16, 2, 0xCAFEF00D));
124124
// No address given just print the code description.
125125
ASSERT_EQ("SIG16: SIG16 with a fault address",
@@ -131,11 +131,11 @@ TEST(UnixSignalsTest, GetAsString) {
131131
ASSERT_EQ(expected, signals.GetSignalDescription(16, 3, 0xcafef00d));
132132
ASSERT_EQ(expected, signals.GetSignalDescription(16, 3, 0xcafef00d, 0x1234));
133133

134-
ASSERT_EQ("SIG16: upper bound violation (fault address: 0x5679, lower bound: "
135-
"0x1234, upper bound: 0x5678)",
134+
ASSERT_EQ("SIG16: upper bound violation (fault address=0x5679, lower bound="
135+
"0x1234, upper bound=0x5678)",
136136
signals.GetSignalDescription(16, 3, 0x5679, 0x1234, 0x5678));
137-
ASSERT_EQ("SIG16: lower bound violation (fault address: 0x1233, lower bound: "
138-
"0x1234, upper bound: 0x5678)",
137+
ASSERT_EQ("SIG16: lower bound violation (fault address=0x1233, lower bound="
138+
"0x1234, upper bound=0x5678)",
139139
signals.GetSignalDescription(16, 3, 0x1233, 0x1234, 0x5678));
140140
}
141141

llvm/docs/ReleaseNotes.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ Changes to LLDB
532532

533533
New:
534534
```
535-
* thread #1: tid = 329384, 0x0000000000401262, name = 'a.out', stop reason = SIGSEGV: address not mapped to object (fault address: 0x0)
535+
* thread #1: tid = 329384, 0x0000000000401262, name = 'a.out', stop reason = SIGSEGV: address not mapped to object (fault address=0x0)
536536
537537
0x7f1e3193e0a7 <+23>: ja 0x7f1e3193e100 ; <+112>
538538
```
@@ -555,6 +555,24 @@ Changes to LLDB
555555

556556
* Incorrect floating-point register dwarf number for LoongArch is [fixed](https://github.com/llvm/llvm-project/pull/120391).
557557

558+
* The `frame diagnose` now works on ELF-based systems. After a crash, LLDB will
559+
try to determine the likely cause of the signal, matching Darwin behavior.
560+
This feature requires using a new `lldb-server` version and (like Darwin) only
561+
works on x86 binaries.
562+
563+
```
564+
* thread #1, name = 'a.out', stop reason = signal SIGSEGV: address not mapped to object (fault address=0x4)
565+
frame #0: 0x00005555555551aa a.out`GetSum(f=0x0000555555558018) at main.c:21:37
566+
18 }
567+
19
568+
20 int GetSum(struct Foo *f) {
569+
-> 21 return SumTwoIntegers(f->a, f->b->d ? 0 : 1);
570+
22 }
571+
23
572+
24 int main() {
573+
Likely cause: f->b->d accessed 0x4
574+
```
575+
558576
Changes to BOLT
559577
---------------------------------
560578

0 commit comments

Comments
 (0)