diff --git a/llvm/docs/CommandGuide/llvm-addr2line.rst b/llvm/docs/CommandGuide/llvm-addr2line.rst --- a/llvm/docs/CommandGuide/llvm-addr2line.rst +++ b/llvm/docs/CommandGuide/llvm-addr2line.rst @@ -17,6 +17,9 @@ Here are some of those differences: +- Requires addresses to be in hexadecimal (with an optional leading ``0x``) + instead of interpreting them as C literals. + - Defaults not to print function names. Use `-f`_ to enable that. - Defaults not to demangle function names. Use `-C`_ to switch the diff --git a/llvm/test/lit.cfg.py b/llvm/test/lit.cfg.py --- a/llvm/test/lit.cfg.py +++ b/llvm/test/lit.cfg.py @@ -145,7 +145,7 @@ # FIXME: Why do we have both `lli` and `%lli` that do slightly different things? tools.extend([ - 'dsymutil', 'lli', 'lli-child-target', 'llvm-ar', 'llvm-as', + 'dsymutil', 'lli', 'lli-child-target', 'llvm-ar', 'llvm-as', 'llvm-addr2line', 'llvm-bcanalyzer', 'llvm-config', 'llvm-cov', 'llvm-cxxdump', 'llvm-cvtres', 'llvm-diff', 'llvm-dis', 'llvm-dwarfdump', 'llvm-exegesis', 'llvm-extract', 'llvm-isel-fuzzer', 'llvm-ifs', 'llvm-install-name-tool', diff --git a/llvm/test/tools/llvm-symbolizer/input-base.test b/llvm/test/tools/llvm-symbolizer/input-base.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-symbolizer/input-base.test @@ -0,0 +1,17 @@ +llvm-symbolizer infers the number base from the form of the address. +RUN: llvm-symbolizer -e /dev/null -a 0x1234 | FileCheck %s +RUN: llvm-symbolizer -e /dev/null -a 4660 | FileCheck %s +RUN: llvm-symbolizer -e /dev/null -a 011064 | FileCheck %s +RUN: llvm-symbolizer -e /dev/null -a 0b1001000110100 | FileCheck %s +RUN: llvm-symbolizer -e /dev/null -a 0o11064 | FileCheck %s + +llvm-addr2line always assumes hexadecimal, but accepts an optional 0x prefix. +RUN: llvm-addr2line -e /dev/null -a 0x1234 | FileCheck %s +RUN: llvm-addr2line -e /dev/null -a 1234 | FileCheck %s +RUN: llvm-addr2line -e /dev/null -a 01234 | FileCheck %s +RUN: llvm-addr2line -e /dev/null -a 0b1010 | FileCheck %s --check-prefix=HEXADECIMAL-NOT-BINARY +RUN: llvm-addr2line -e /dev/null -a 0o1234 | FileCheck %s --check-prefix=INVALID-NOT-OCTAL + +CHECK: 0x1234 +HEXADECIMAL-NOT-BINARY: 0xb1010 +INVALID-NOT-OCTAL: 0o1234 diff --git a/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp b/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp --- a/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp +++ b/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp @@ -183,7 +183,7 @@ Frame, }; -static bool parseCommand(StringRef InputString, Command &Cmd, +static bool parseCommand(bool IsAddr2Line, StringRef InputString, Command &Cmd, std::string &ModuleName, uint64_t &ModuleOffset) { const char kDelimiters[] = " \n\r"; ModuleName = ""; @@ -220,15 +220,21 @@ // Skip delimiters and parse module offset. pos += strspn(pos, kDelimiters); int offset_length = strcspn(pos, kDelimiters); - return !StringRef(pos, offset_length).getAsInteger(0, ModuleOffset); + StringRef offset(pos, offset_length); + // GNU addr2line assumes the offset is hexadecimal and allows a redundant + // "0x" or "0X" prefix; do the same for compatibility. + if (IsAddr2Line) + offset.consume_front("0x") || offset.consume_front("0X"); + return !offset.getAsInteger(IsAddr2Line ? 16 : 0, ModuleOffset); } -static void symbolizeInput(StringRef InputString, LLVMSymbolizer &Symbolizer, - DIPrinter &Printer) { +static void symbolizeInput(bool IsAddr2Line, StringRef InputString, + LLVMSymbolizer &Symbolizer, DIPrinter &Printer) { Command Cmd; std::string ModuleName; uint64_t Offset = 0; - if (!parseCommand(StringRef(InputString), Cmd, ModuleName, Offset)) { + if (!parseCommand(IsAddr2Line, StringRef(InputString), Cmd, ModuleName, + Offset)) { outs() << InputString << "\n"; return; } @@ -335,12 +341,12 @@ std::remove_if(StrippedInputString.begin(), StrippedInputString.end(), [](char c) { return c == '\r' || c == '\n'; }), StrippedInputString.end()); - symbolizeInput(StrippedInputString, Symbolizer, Printer); + symbolizeInput(IsAddr2Line, StrippedInputString, Symbolizer, Printer); outs().flush(); } } else { for (StringRef Address : ClInputAddresses) - symbolizeInput(Address, Symbolizer, Printer); + symbolizeInput(IsAddr2Line, Address, Symbolizer, Printer); } return 0;