Skip to content

Commit f86065d

Browse files
Merge pull request #8470 from jimingham/addr-expression-swift
Add an <address-expression> fallback that handles register expressions
2 parents cda1f7f + d9bc681 commit f86065d

File tree

7 files changed

+129
-7
lines changed

7 files changed

+129
-7
lines changed

lldb/source/Interpreter/OptionArgParser.cpp

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
#include "lldb/Interpreter/OptionArgParser.h"
1010
#include "lldb/DataFormatters/FormatManager.h"
1111
#include "lldb/Target/ABI.h"
12+
#include "lldb/Target/RegisterContext.h"
1213
#include "lldb/Target/Target.h"
14+
#include "lldb/Utility/RegisterValue.h"
1315
#include "lldb/Utility/Status.h"
1416
#include "lldb/Utility/StreamString.h"
1517

@@ -234,24 +236,68 @@ OptionArgParser::DoToAddress(const ExecutionContext *exe_ctx, llvm::StringRef s,
234236
// Since the compiler can't handle things like "main + 12" we should try to
235237
// do this for now. The compiler doesn't like adding offsets to function
236238
// pointer types.
239+
// Some languages also don't have a natural representation for register
240+
// values (e.g. swift) so handle simple uses of them here as well.
241+
// We use a regex to parse these forms, the regex handles:
242+
// $reg_name
243+
// $reg_name+offset
244+
// symbol_name+offset
245+
//
246+
// The important matching elements in the regex below are:
247+
// 1: The reg name if there's no +offset
248+
// 3: The symbol/reg name if there is an offset
249+
// 4: +/-
250+
// 5: The offset value.
237251
static RegularExpression g_symbol_plus_offset_regex(
238-
"^(.*)([-\\+])[[:space:]]*(0x[0-9A-Fa-f]+|[0-9]+)[[:space:]]*$");
252+
"^(\\$[^ +-]+)|(([^ +-]+)([-\\+])[[:space:]]*(0x[0-9A-Fa-f]+|[0-9]+)[[:space:]]*)$");
239253

240254
llvm::SmallVector<llvm::StringRef, 4> matches;
241255
if (g_symbol_plus_offset_regex.Execute(sref, &matches)) {
242256
uint64_t offset = 0;
243-
llvm::StringRef name = matches[1];
244-
llvm::StringRef sign = matches[2];
245-
llvm::StringRef str_offset = matches[3];
246-
if (!str_offset.getAsInteger(0, offset)) {
257+
llvm::StringRef name;
258+
if (!matches[1].empty())
259+
name = matches[1];
260+
else
261+
name = matches[3];
262+
263+
llvm::StringRef sign = matches[4];
264+
llvm::StringRef str_offset = matches[5];
265+
266+
// Some languages don't have a natural type for register values, but it
267+
// is still useful to look them up here:
268+
std::optional<lldb::addr_t> register_value;
269+
StackFrame *frame = exe_ctx->GetFramePtr();
270+
llvm::StringRef reg_name = name;
271+
if (frame && reg_name.consume_front("$")) {
272+
RegisterContextSP reg_ctx_sp = frame->GetRegisterContext();
273+
if (reg_ctx_sp) {
274+
const RegisterInfo *reg_info = reg_ctx_sp->GetRegisterInfoByName(reg_name);
275+
if (reg_info) {
276+
RegisterValue reg_val;
277+
bool success = reg_ctx_sp->ReadRegister(reg_info, reg_val);
278+
if (success && reg_val.GetType() != RegisterValue::eTypeInvalid) {
279+
register_value = reg_val.GetAsUInt64(0, &success);
280+
if (!success)
281+
register_value.reset();
282+
}
283+
}
284+
}
285+
}
286+
if (!str_offset.empty() && !str_offset.getAsInteger(0, offset)) {
247287
Status error;
248-
addr = ToAddress(exe_ctx, name, LLDB_INVALID_ADDRESS, &error);
288+
if (register_value)
289+
addr = register_value.value();
290+
else
291+
addr = ToAddress(exe_ctx, name, LLDB_INVALID_ADDRESS, &error);
249292
if (addr != LLDB_INVALID_ADDRESS) {
250293
if (sign[0] == '+')
251294
return addr + offset;
252295
return addr - offset;
253296
}
254-
}
297+
} else if (register_value)
298+
// In the case of register values, someone might just want to get the
299+
// value in a language whose expression parser doesn't support registers.
300+
return register_value.value();
255301
}
256302

257303
if (error_ptr)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
C_SOURCES := main.c
2+
CFLAGS_EXTRAS := -std=c99
3+
4+
include Makefile.rules
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
"""
2+
Make sure that "target modules lookup -va $pc" works
3+
"""
4+
5+
6+
import lldb
7+
import lldbsuite.test.lldbutil as lldbutil
8+
from lldbsuite.test.lldbtest import *
9+
10+
11+
class TestImageLookupPCInC(TestBase):
12+
def test_sample_rename_this(self):
13+
"""There can be many tests in a test case - describe this test here."""
14+
self.build()
15+
self.main_source_file = lldb.SBFileSpec("main.c")
16+
self.sample_test()
17+
18+
def sample_test(self):
19+
"""Make sure the address expression resolves to the right function"""
20+
21+
(target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
22+
self, "Set a breakpoint here", self.main_source_file
23+
)
24+
25+
self.expect("target modules lookup -va $pc", substrs=["doSomething"])
26+
self.expect("target modules lookup -va $pc+4", substrs=["doSomething"])
27+
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#include <stdio.h>
2+
3+
void
4+
doSomething()
5+
{
6+
printf ("Set a breakpoint here.\n");
7+
printf ("Need a bit more code.\n");
8+
}
9+
10+
int
11+
main()
12+
{
13+
doSomething();
14+
return 0;
15+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
SWIFT_SOURCES := main.swift
2+
SWIFTFLAGS_EXTRAS := -O
3+
4+
include Makefile.rules
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import lldb
2+
from lldbsuite.test.lldbtest import *
3+
from lldbsuite.test.decorators import *
4+
import lldbsuite.test.lldbutil as lldbutil
5+
import unittest2
6+
7+
8+
class SwiftAddressExpressionTest(TestBase):
9+
@swiftTest
10+
def test(self):
11+
"""Test that you can use register names in image lookup in a swift frame."""
12+
self.build()
13+
(target, process, thread, breakpoint) = lldbutil.run_to_source_breakpoint(self,
14+
"break here to check image lookup", lldb.SBFileSpec("main.swift"))
15+
# I don't want to be too specific in what we print for image lookup,
16+
# we're testing that the address expression for the pc worked.
17+
self.expect("image lookup -va $pc", substrs=["doSomething"])
18+
self.expect("image lookup -va $pc+4", substrs=["doSomething"])
19+
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
func doSomething() {
2+
print("break here to check image lookup");
3+
print("I need another line of code here");
4+
}
5+
6+
doSomething()
7+

0 commit comments

Comments
 (0)