Expand Up
@@ -32,6 +32,7 @@
#include " llvm/Support/COM.h"
#include " llvm/Support/CommandLine.h"
#include " llvm/Support/Debug.h"
#include " llvm/Support/Errc.h"
#include " llvm/Support/FileSystem.h"
#include " llvm/Support/InitLLVM.h"
#include " llvm/Support/LLVMDriver.h"
Expand Down
Expand Up
@@ -80,10 +81,10 @@ class SymbolizerOptTable : public opt::GenericOptTable {
static std::string ToolName;
static void printError (const ErrorInfoBase &EI, StringRef Path ) {
static void printError (const ErrorInfoBase &EI, StringRef AuxInfo ) {
WithColor::error (errs (), ToolName);
if (!EI. isA <FileError> ())
errs () << " '" << Path << " ': " ;
if (!AuxInfo. empty ())
errs () << " '" << AuxInfo << " ': " ;
EI.log (errs ());
errs () << ' \n ' ;
}
Expand Down
Expand Up
@@ -151,10 +152,14 @@ static StringRef getSpaceDelimitedWord(StringRef &Source) {
return Result;
}
static bool parseCommand (StringRef BinaryName, bool IsAddr2Line,
StringRef InputString, Command &Cmd,
std::string &ModuleName, object::BuildID &BuildID,
uint64_t &ModuleOffset) {
static Error makeStringError (StringRef Msg) {
return make_error<StringError>(Msg, inconvertibleErrorCode ());
}
static Error parseCommand (StringRef BinaryName, bool IsAddr2Line,
StringRef InputString, Command &Cmd,
std::string &ModuleName, object::BuildID &BuildID,
uint64_t &ModuleOffset) {
ModuleName = BinaryName;
if (InputString.consume_front (" CODE " )) {
Cmd = Command::Code;
Expand All
@@ -174,55 +179,69 @@ static bool parseCommand(StringRef BinaryName, bool IsAddr2Line,
InputString = InputString.ltrim ();
if (InputString.consume_front (" FILE:" )) {
if (HasFilePrefix || HasBuildIDPrefix)
// Input file specification prefix has already been seen.
return false ;
return makeStringError (" duplicate input file specification prefix" );
HasFilePrefix = true ;
continue ;
}
if (InputString.consume_front (" BUILDID:" )) {
if (HasBuildIDPrefix || HasFilePrefix)
// Input file specification prefix has already been seen.
return false ;
return makeStringError (" duplicate input file specification prefix" );
HasBuildIDPrefix = true ;
continue ;
}
break ;
}
// If an input file is not specified on the command line, try to extract it
// from the command.
if (HasBuildIDPrefix || HasFilePrefix) {
InputString = InputString.ltrim ();
if (InputString.empty ()) {
if (HasFilePrefix)
return makeStringError (" must be followed by an input file" );
else
return makeStringError (" must be followed by a hash" );
}
if (!BinaryName.empty () || !BuildID.empty ())
// Input file has already been specified on the command line.
return false ;
return makeStringError ( " input file has already been specified" );
StringRef Name = getSpaceDelimitedWord (InputString);
if (Name.empty ())
// Wrong name for module file.
return false ;
return makeStringError (" unbalanced quotes in input file name" );
if (HasBuildIDPrefix) {
BuildID = parseBuildID (Name);
if (BuildID.empty ())
// Wrong format of BuildID hash.
return false ;
return makeStringError (" wrong format of build-id" );
} else {
ModuleName = Name;
}
} else if (BinaryName.empty () && BuildID.empty ()) {
// No input file has been specified. If the input string contains at least
// two items, assume that the first item is a file name.
ModuleName = getSpaceDelimitedWord (InputString);
if (ModuleName.empty () || InputString.empty ())
// No input filename has been specified.
return false ;
if (ModuleName.empty ())
return makeStringError (" no input filename has been specified" );
}
// Skip delimiters and parse module offset.
// Parse module offset.
InputString = InputString.ltrim ();
if (InputString.empty ())
return makeStringError (" no module offset has been specified" );
int OffsetLength = InputString.find_first_of (" \n\r " );
StringRef Offset = InputString.substr (0 , OffsetLength);
// 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);
// If the input is not a valid module offset, it is not an error, but its
// lookup does not make sense. Return error of different kind to distinguish
// from error or success.
if (Offset.getAsInteger (IsAddr2Line ? 16 : 0 , ModuleOffset))
return errorCodeToError (errc::invalid_argument);
return Error::success ();
}
template <typename T>
Expand Down
Expand Up
@@ -268,6 +287,11 @@ void executeCommand(StringRef ModuleName, const T &ModuleSpec, Command Cmd,
Symbolizer.pruneCache ();
}
static void printUnknownLineInfo (std::string ModuleName, DIPrinter &Printer) {
Request SymRequest = {ModuleName, std::nullopt};
Printer.print (SymRequest, DILineInfo ());
}
static void symbolizeInput (const opt::InputArgList &Args,
object::BuildIDRef IncomingBuildID,
uint64_t AdjustVMA, bool IsAddr2Line,
Expand All
@@ -277,9 +301,16 @@ static void symbolizeInput(const opt::InputArgList &Args,
std::string ModuleName;
object::BuildID BuildID (IncomingBuildID.begin (), IncomingBuildID.end ());
uint64_t Offset = 0 ;
if (!parseCommand (Args.getLastArgValue (OPT_obj_EQ), IsAddr2Line,
StringRef (InputString), Cmd, ModuleName, BuildID, Offset)) {
Printer.printInvalidCommand ({ModuleName, std::nullopt}, InputString);
if (Error E = parseCommand (Args.getLastArgValue (OPT_obj_EQ), IsAddr2Line,
StringRef (InputString), Cmd, ModuleName, BuildID,
Offset)) {
handleAllErrors (
std::move (E),
[&](const StringError &EI) {
printError (EI, InputString);
printUnknownLineInfo (ModuleName, Printer);
},
[&](const ECError &EI) { printUnknownLineInfo (ModuleName, Printer); });
return ;
}
bool ShouldInline = Args.hasFlag (OPT_inlines, OPT_no_inlines, !IsAddr2Line);
Expand Down