|
9 | 9 | #include "lldb/Interpreter/OptionArgParser.h"
|
10 | 10 | #include "lldb/DataFormatters/FormatManager.h"
|
11 | 11 | #include "lldb/Target/ABI.h"
|
| 12 | +#include "lldb/Target/RegisterContext.h" |
12 | 13 | #include "lldb/Target/Target.h"
|
| 14 | +#include "lldb/Utility/RegisterValue.h" |
13 | 15 | #include "lldb/Utility/Status.h"
|
14 | 16 | #include "lldb/Utility/StreamString.h"
|
15 | 17 |
|
@@ -234,24 +236,68 @@ OptionArgParser::DoToAddress(const ExecutionContext *exe_ctx, llvm::StringRef s,
|
234 | 236 | // Since the compiler can't handle things like "main + 12" we should try to
|
235 | 237 | // do this for now. The compiler doesn't like adding offsets to function
|
236 | 238 | // 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. |
237 | 251 | 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:]]*)$"); |
239 | 253 |
|
240 | 254 | llvm::SmallVector<llvm::StringRef, 4> matches;
|
241 | 255 | if (g_symbol_plus_offset_regex.Execute(sref, &matches)) {
|
242 | 256 | 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)) { |
247 | 287 | 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); |
249 | 292 | if (addr != LLDB_INVALID_ADDRESS) {
|
250 | 293 | if (sign[0] == '+')
|
251 | 294 | return addr + offset;
|
252 | 295 | return addr - offset;
|
253 | 296 | }
|
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(); |
255 | 301 | }
|
256 | 302 |
|
257 | 303 | if (error_ptr)
|
|
0 commit comments