|
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 |
|
@@ -233,24 +235,68 @@ OptionArgParser::DoToAddress(const ExecutionContext *exe_ctx, llvm::StringRef s,
|
233 | 235 | // Since the compiler can't handle things like "main + 12" we should try to
|
234 | 236 | // do this for now. The compiler doesn't like adding offsets to function
|
235 | 237 | // pointer types.
|
| 238 | + // Some languages also don't have a natural representation for register |
| 239 | + // values (e.g. swift) so handle simple uses of them here as well. |
| 240 | + // We use a regex to parse these forms, the regex handles: |
| 241 | + // $reg_name |
| 242 | + // $reg_name+offset |
| 243 | + // symbol_name+offset |
| 244 | + // |
| 245 | + // The important matching elements in the regex below are: |
| 246 | + // 1: The reg name if there's no +offset |
| 247 | + // 3: The symbol/reg name if there is an offset |
| 248 | + // 4: +/- |
| 249 | + // 5: The offset value. |
236 | 250 | static RegularExpression g_symbol_plus_offset_regex(
|
237 |
| - "^(.*)([-\\+])[[:space:]]*(0x[0-9A-Fa-f]+|[0-9]+)[[:space:]]*$"); |
| 251 | + "^(\\$[^ +-]+)|(([^ +-]+)([-\\+])[[:space:]]*(0x[0-9A-Fa-f]+|[0-9]+)[[:space:]]*)$"); |
238 | 252 |
|
239 | 253 | llvm::SmallVector<llvm::StringRef, 4> matches;
|
240 | 254 | if (g_symbol_plus_offset_regex.Execute(sref, &matches)) {
|
241 | 255 | uint64_t offset = 0;
|
242 |
| - llvm::StringRef name = matches[1]; |
243 |
| - llvm::StringRef sign = matches[2]; |
244 |
| - llvm::StringRef str_offset = matches[3]; |
245 |
| - if (!str_offset.getAsInteger(0, offset)) { |
| 256 | + llvm::StringRef name; |
| 257 | + if (!matches[1].empty()) |
| 258 | + name = matches[1]; |
| 259 | + else |
| 260 | + name = matches[3]; |
| 261 | + |
| 262 | + llvm::StringRef sign = matches[4]; |
| 263 | + llvm::StringRef str_offset = matches[5]; |
| 264 | + |
| 265 | + // Some languages don't have a natural type for register values, but it |
| 266 | + // is still useful to look them up here: |
| 267 | + std::optional<lldb::addr_t> register_value; |
| 268 | + StackFrame *frame = exe_ctx->GetFramePtr(); |
| 269 | + llvm::StringRef reg_name = name; |
| 270 | + if (frame && reg_name.consume_front("$")) { |
| 271 | + RegisterContextSP reg_ctx_sp = frame->GetRegisterContext(); |
| 272 | + if (reg_ctx_sp) { |
| 273 | + const RegisterInfo *reg_info = reg_ctx_sp->GetRegisterInfoByName(reg_name); |
| 274 | + if (reg_info) { |
| 275 | + RegisterValue reg_val; |
| 276 | + bool success = reg_ctx_sp->ReadRegister(reg_info, reg_val); |
| 277 | + if (success && reg_val.GetType() != RegisterValue::eTypeInvalid) { |
| 278 | + register_value = reg_val.GetAsUInt64(0, &success); |
| 279 | + if (!success) |
| 280 | + register_value.reset(); |
| 281 | + } |
| 282 | + } |
| 283 | + } |
| 284 | + } |
| 285 | + if (!str_offset.empty() && !str_offset.getAsInteger(0, offset)) { |
246 | 286 | Status error;
|
247 |
| - addr = ToAddress(exe_ctx, name, LLDB_INVALID_ADDRESS, &error); |
| 287 | + if (register_value) |
| 288 | + addr = register_value.value(); |
| 289 | + else |
| 290 | + addr = ToAddress(exe_ctx, name, LLDB_INVALID_ADDRESS, &error); |
248 | 291 | if (addr != LLDB_INVALID_ADDRESS) {
|
249 | 292 | if (sign[0] == '+')
|
250 | 293 | return addr + offset;
|
251 | 294 | return addr - offset;
|
252 | 295 | }
|
253 |
| - } |
| 296 | + } else if (register_value) |
| 297 | + // In the case of register values, someone might just want to get the |
| 298 | + // value in a language whose expression parser doesn't support registers. |
| 299 | + return register_value.value(); |
254 | 300 | }
|
255 | 301 |
|
256 | 302 | if (error_ptr)
|
|
0 commit comments