Skip to content

Add an <address-expression> fallback that handles register expressions #8470

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 53 additions & 7 deletions lldb/source/Interpreter/OptionArgParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/DataFormatters/FormatManager.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"

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

llvm::SmallVector<llvm::StringRef, 4> matches;
if (g_symbol_plus_offset_regex.Execute(sref, &matches)) {
uint64_t offset = 0;
llvm::StringRef name = matches[1];
llvm::StringRef sign = matches[2];
llvm::StringRef str_offset = matches[3];
if (!str_offset.getAsInteger(0, offset)) {
llvm::StringRef name;
if (!matches[1].empty())
name = matches[1];
else
name = matches[3];

llvm::StringRef sign = matches[4];
llvm::StringRef str_offset = matches[5];

// Some languages don't have a natural type for register values, but it
// is still useful to look them up here:
std::optional<lldb::addr_t> register_value;
StackFrame *frame = exe_ctx->GetFramePtr();
llvm::StringRef reg_name = name;
if (frame && reg_name.consume_front("$")) {
RegisterContextSP reg_ctx_sp = frame->GetRegisterContext();
if (reg_ctx_sp) {
const RegisterInfo *reg_info = reg_ctx_sp->GetRegisterInfoByName(reg_name);
if (reg_info) {
RegisterValue reg_val;
bool success = reg_ctx_sp->ReadRegister(reg_info, reg_val);
if (success && reg_val.GetType() != RegisterValue::eTypeInvalid) {
register_value = reg_val.GetAsUInt64(0, &success);
if (!success)
register_value.reset();
}
}
}
}
if (!str_offset.empty() && !str_offset.getAsInteger(0, offset)) {
Status error;
addr = ToAddress(exe_ctx, name, LLDB_INVALID_ADDRESS, &error);
if (register_value)
addr = register_value.value();
else
addr = ToAddress(exe_ctx, name, LLDB_INVALID_ADDRESS, &error);
if (addr != LLDB_INVALID_ADDRESS) {
if (sign[0] == '+')
return addr + offset;
return addr - offset;
}
}
} else if (register_value)
// In the case of register values, someone might just want to get the
// value in a language whose expression parser doesn't support registers.
return register_value.value();
}

if (error_ptr)
Expand Down
4 changes: 4 additions & 0 deletions lldb/test/API/commands/target/modules/lookup/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
C_SOURCES := main.c
CFLAGS_EXTRAS := -std=c99

include Makefile.rules
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"""
Make sure that "target modules lookup -va $pc" works
"""


import lldb
import lldbsuite.test.lldbutil as lldbutil
from lldbsuite.test.lldbtest import *


class TestImageLookupPCInC(TestBase):
def test_sample_rename_this(self):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably forgot to rename this test name and the comment below?

"""There can be many tests in a test case - describe this test here."""
self.build()
self.main_source_file = lldb.SBFileSpec("main.c")
self.sample_test()

def sample_test(self):
"""Make sure the address expression resolves to the right function"""

(target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
self, "Set a breakpoint here", self.main_source_file
)

self.expect("target modules lookup -va $pc", substrs=["doSomething"])
self.expect("target modules lookup -va $pc+4", substrs=["doSomething"])

15 changes: 15 additions & 0 deletions lldb/test/API/commands/target/modules/lookup/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#include <stdio.h>

void
doSomething()
{
printf ("Set a breakpoint here.\n");
printf ("Need a bit more code.\n");
}

int
main()
{
doSomething();
return 0;
}
4 changes: 4 additions & 0 deletions lldb/test/API/commands/target/modules/swift/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
SWIFT_SOURCES := main.swift
SWIFTFLAGS_EXTRAS := -O

include Makefile.rules
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import lldb
from lldbsuite.test.lldbtest import *
from lldbsuite.test.decorators import *
import lldbsuite.test.lldbutil as lldbutil
import unittest2


class SwiftAddressExpressionTest(TestBase):
@swiftTest
def test(self):
"""Test that you can use register names in image lookup in a swift frame."""
self.build()
(target, process, thread, breakpoint) = lldbutil.run_to_source_breakpoint(self,
"break here to check image lookup", lldb.SBFileSpec("main.swift"))
# I don't want to be too specific in what we print for image lookup,
# we're testing that the address expression for the pc worked.
self.expect("image lookup -va $pc", substrs=["doSomething"])
self.expect("image lookup -va $pc+4", substrs=["doSomething"])

7 changes: 7 additions & 0 deletions lldb/test/API/commands/target/modules/swift/main.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
func doSomething() {
print("break here to check image lookup");
print("I need another line of code here");
}

doSomething()