@@ -159,7 +159,7 @@ static Error makeStringError(StringRef Msg) {
159159static Error parseCommand (StringRef BinaryName, bool IsAddr2Line,
160160 StringRef InputString, Command &Cmd,
161161 std::string &ModuleName, object::BuildID &BuildID,
162- StringRef &Symbol, uint64_t &ModuleOffset ) {
162+ StringRef &Symbol, uint64_t &Offset ) {
163163 ModuleName = BinaryName;
164164 if (InputString.consume_front (" CODE " )) {
165165 Cmd = Command::Code;
@@ -224,25 +224,51 @@ static Error parseCommand(StringRef BinaryName, bool IsAddr2Line,
224224 return makeStringError (" no input filename has been specified" );
225225 }
226226
227- // Parse module offset, which can be specified as a number or as a symbol.
228- InputString = InputString.ltrim ();
227+ // Parse address specification, which can be an offset in module or a
228+ // symbol with optional offset.
229+ InputString = InputString.trim ();
229230 if (InputString.empty ())
230231 return makeStringError (" no module offset has been specified" );
231232
232233 // If input string contains a space, ignore everything after it. This behavior
233234 // is consistent with GNU addr2line.
234- int OffsetLength = InputString.find_first_of (" \n\r " );
235- StringRef Offset = InputString.substr (0 , OffsetLength);
235+ int AddrSpecLength = InputString.find_first_of (" \n\r " );
236+ StringRef AddrSpec = InputString.substr (0 , AddrSpecLength);
237+ bool StartsWithDigit = std::isdigit (AddrSpec.front ());
236238
237- // GNU addr2line assumes the offset is hexadecimal and allows a redundant
239+ // GNU addr2line assumes the address is hexadecimal and allows a redundant
238240 // "0x" or "0X" prefix; do the same for compatibility.
239241 if (IsAddr2Line)
240- Offset .consume_front (" 0x" ) || Offset .consume_front (" 0X" );
242+ AddrSpec .consume_front (" 0x" ) || AddrSpec .consume_front (" 0X" );
241243
242- // If the input is not a number, treat it is a symbol.
243- if (Offset.getAsInteger (IsAddr2Line ? 16 : 0 , ModuleOffset)) {
244- Symbol = Offset;
245- ModuleOffset = 0 ;
244+ // If address specification is a number, treat it as a module offset.
245+ if (!AddrSpec.getAsInteger (IsAddr2Line ? 16 : 0 , Offset)) {
246+ // Module offset is an address.
247+ Symbol = StringRef ();
248+ return Error::success ();
249+ }
250+
251+ // If address specification starts with a digit, but is not a number, consider
252+ // it as invalid.
253+ if (StartsWithDigit || AddrSpec.empty ())
254+ return makeStringError (" expected a number as module offset" );
255+
256+ // Otherwise it is a symbol name, potentially with an offset.
257+ Symbol = AddrSpec;
258+ Offset = 0 ;
259+
260+ // If the address specification contains '+', try treating it as
261+ // "symbol + offset".
262+ size_t Plus = AddrSpec.rfind (' +' );
263+ if (Plus != StringRef::npos) {
264+ StringRef SymbolStr = AddrSpec.take_front (Plus);
265+ StringRef OffsetStr = AddrSpec.substr (Plus + 1 );
266+ if (!SymbolStr.empty () && !OffsetStr.empty () &&
267+ !OffsetStr.getAsInteger (0 , Offset)) {
268+ Symbol = SymbolStr;
269+ return Error::success ();
270+ }
271+ // The found '+' is not an offset delimiter.
246272 }
247273
248274 return Error::success ();
@@ -268,7 +294,7 @@ void executeCommand(StringRef ModuleName, const T &ModuleSpec, Command Cmd,
268294 print (SymRequest, ResOrErr, Printer);
269295 } else if (!Symbol.empty ()) {
270296 Expected<std::vector<DILineInfo>> ResOrErr =
271- Symbolizer.findSymbol (ModuleSpec, Symbol);
297+ Symbolizer.findSymbol (ModuleSpec, Symbol, Offset );
272298 print (SymRequest, ResOrErr, Printer);
273299 } else if (ShouldInline) {
274300 Expected<DIInliningInfo> ResOrErr =
0 commit comments