forked from OSchip/llvm-project
[PECOFF] Parse /manifest command line option.
The manifest file is an XML file that conveys some information to the loader, such as whether the executable needs to run as Administrator or not. This patch is to parse command line option for manifest file. Actual XML file generation will be done in a separate patch. llvm-svn: 193141
This commit is contained in:
parent
12075f71f9
commit
139ae4c931
|
@ -38,6 +38,8 @@ public:
|
||||||
_allowBind(true), _allowIsolation(true), _swapRunFromCD(false),
|
_allowBind(true), _allowIsolation(true), _swapRunFromCD(false),
|
||||||
_swapRunFromNet(false), _baseRelocationEnabled(true),
|
_swapRunFromNet(false), _baseRelocationEnabled(true),
|
||||||
_terminalServerAware(true), _dynamicBaseEnabled(true),
|
_terminalServerAware(true), _dynamicBaseEnabled(true),
|
||||||
|
_createManifest(true), _embedManifest(false), _manifestId(1),
|
||||||
|
_manifestLevel("'asInvoker'"), _manifestUiAccess(false),
|
||||||
_imageType(ImageType::IMAGE_EXE) {
|
_imageType(ImageType::IMAGE_EXE) {
|
||||||
setDeadStripping(true);
|
setDeadStripping(true);
|
||||||
}
|
}
|
||||||
|
@ -147,6 +149,21 @@ public:
|
||||||
void setDynamicBaseEnabled(bool val) { _dynamicBaseEnabled = val; }
|
void setDynamicBaseEnabled(bool val) { _dynamicBaseEnabled = val; }
|
||||||
bool getDynamicBaseEnabled() const { return _dynamicBaseEnabled; }
|
bool getDynamicBaseEnabled() const { return _dynamicBaseEnabled; }
|
||||||
|
|
||||||
|
void setCreateManifest(bool val) { _createManifest = val; }
|
||||||
|
bool getCreateManifest() const { return _createManifest; }
|
||||||
|
|
||||||
|
void setEmbedManifest(bool val) { _embedManifest = val; }
|
||||||
|
bool getEmbedManifest() const { return _embedManifest; }
|
||||||
|
|
||||||
|
void setManifestId(int val) { _manifestId = val; }
|
||||||
|
int getManifestId() const { return _manifestId; }
|
||||||
|
|
||||||
|
void setManifestLevel(std::string val) { _manifestLevel = std::move(val); }
|
||||||
|
const std::string &getManifestLevel() const { return _manifestLevel; }
|
||||||
|
|
||||||
|
void setManifestUiAccess(bool val) { _manifestUiAccess = val; }
|
||||||
|
bool getManifestUiAccess() const { return _manifestUiAccess; }
|
||||||
|
|
||||||
void setImageType(ImageType type) { _imageType = type; }
|
void setImageType(ImageType type) { _imageType = type; }
|
||||||
ImageType getImageType() const { return _imageType; }
|
ImageType getImageType() const { return _imageType; }
|
||||||
|
|
||||||
|
@ -205,6 +222,11 @@ private:
|
||||||
bool _baseRelocationEnabled;
|
bool _baseRelocationEnabled;
|
||||||
bool _terminalServerAware;
|
bool _terminalServerAware;
|
||||||
bool _dynamicBaseEnabled;
|
bool _dynamicBaseEnabled;
|
||||||
|
bool _createManifest;
|
||||||
|
bool _embedManifest;
|
||||||
|
int _manifestId;
|
||||||
|
std::string _manifestLevel;
|
||||||
|
bool _manifestUiAccess;
|
||||||
ImageType _imageType;
|
ImageType _imageType;
|
||||||
|
|
||||||
// The set to store /nodefaultlib arguments.
|
// The set to store /nodefaultlib arguments.
|
||||||
|
|
|
@ -139,6 +139,33 @@ llvm::COFF::MachineTypes stringToMachineType(StringRef str) {
|
||||||
.Default(llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN);
|
.Default(llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse /manifest:EMBED[,ID=#]|NO.
|
||||||
|
bool parseManifest(StringRef option, raw_ostream &diagnostics, bool &enable,
|
||||||
|
bool &embed, int &id) {
|
||||||
|
std::string optionLower = option.lower();
|
||||||
|
if (optionLower == "no") {
|
||||||
|
enable = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!StringRef(optionLower).startswith("embed"))
|
||||||
|
goto parse_error;
|
||||||
|
|
||||||
|
embed = true;
|
||||||
|
optionLower = optionLower.substr(strlen("embed"));
|
||||||
|
if (optionLower.empty())
|
||||||
|
return true;
|
||||||
|
if (!StringRef(optionLower).startswith(",id="))
|
||||||
|
goto parse_error;
|
||||||
|
optionLower = optionLower.substr(strlen(",id="));
|
||||||
|
if (StringRef(optionLower).getAsInteger(0, id))
|
||||||
|
goto parse_error;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
parse_error:
|
||||||
|
diagnostics << "Unknown argument for /manifest: " << option << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Handle /failifmismatch option.
|
// Handle /failifmismatch option.
|
||||||
bool handleFailIfMismatchOption(StringRef option,
|
bool handleFailIfMismatchOption(StringRef option,
|
||||||
std::map<StringRef, StringRef> &mustMatch,
|
std::map<StringRef, StringRef> &mustMatch,
|
||||||
|
@ -395,6 +422,23 @@ WinLinkDriver::parse(int argc, const char *argv[], PECOFFLinkingContext &ctx,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case OPT_manifest:
|
||||||
|
// Do nothing. This is default.
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPT_manifest_colon: {
|
||||||
|
// Parse /manifest:EMBED[,ID=#]|NO.
|
||||||
|
bool enable = true;
|
||||||
|
bool embed = false;
|
||||||
|
int id = 1;
|
||||||
|
if (!parseManifest(inputArg->getValue(), diagnostics, enable, embed, id))
|
||||||
|
return false;
|
||||||
|
ctx.setCreateManifest(enable);
|
||||||
|
ctx.setEmbedManifest(embed);
|
||||||
|
ctx.setManifestId(id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case OPT_failifmismatch:
|
case OPT_failifmismatch:
|
||||||
if (handleFailIfMismatchOption(inputArg->getValue(), failIfMismatchMap,
|
if (handleFailIfMismatchOption(inputArg->getValue(), failIfMismatchMap,
|
||||||
diagnostics))
|
diagnostics))
|
||||||
|
|
|
@ -31,6 +31,10 @@ def machine : P<"machine", "Specify target platform">;
|
||||||
def version : P<"version", "Specify a version number in the PE header">;
|
def version : P<"version", "Specify a version number in the PE header">;
|
||||||
def subsystem : P<"subsystem", "Specify subsystem">;
|
def subsystem : P<"subsystem", "Specify subsystem">;
|
||||||
|
|
||||||
|
def manifest : F<"manifest">;
|
||||||
|
def manifest_colon : P<"manifest", "Create manifest file">;
|
||||||
|
def manifestuac : P<"manifestuac", "User access control">;
|
||||||
|
|
||||||
// We cannot use multiclass P because class name "incl" is different
|
// We cannot use multiclass P because class name "incl" is different
|
||||||
// from its command line option name. We do this because "include" is
|
// from its command line option name. We do this because "include" is
|
||||||
// a reserved keyword in tablegen.
|
// a reserved keyword in tablegen.
|
||||||
|
|
|
@ -60,6 +60,11 @@ TEST_F(WinLinkParserTest, Basic) {
|
||||||
EXPECT_TRUE(_context.getBaseRelocationEnabled());
|
EXPECT_TRUE(_context.getBaseRelocationEnabled());
|
||||||
EXPECT_TRUE(_context.isTerminalServerAware());
|
EXPECT_TRUE(_context.isTerminalServerAware());
|
||||||
EXPECT_TRUE(_context.getDynamicBaseEnabled());
|
EXPECT_TRUE(_context.getDynamicBaseEnabled());
|
||||||
|
EXPECT_TRUE(_context.getCreateManifest());
|
||||||
|
EXPECT_FALSE(_context.getEmbedManifest());
|
||||||
|
EXPECT_EQ(1, _context.getManifestId());
|
||||||
|
EXPECT_EQ("'asInvoker'", _context.getManifestLevel());
|
||||||
|
EXPECT_EQ(false, _context.getManifestUiAccess());
|
||||||
EXPECT_TRUE(_context.deadStrip());
|
EXPECT_TRUE(_context.deadStrip());
|
||||||
EXPECT_FALSE(_context.logInputFiles());
|
EXPECT_FALSE(_context.logInputFiles());
|
||||||
}
|
}
|
||||||
|
@ -366,6 +371,41 @@ TEST_F(WinLinkParserTest, FailIfMismatch_Mismatch) {
|
||||||
"/failifmismatch:foo=baz", "a.out", nullptr));
|
"/failifmismatch:foo=baz", "a.out", nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Tests for /manifest.
|
||||||
|
//
|
||||||
|
TEST_F(WinLinkParserTest, Manifest_Default) {
|
||||||
|
EXPECT_TRUE(parse("link.exe", "/manifest", "a.out", nullptr));
|
||||||
|
EXPECT_TRUE(_context.getCreateManifest());
|
||||||
|
EXPECT_FALSE(_context.getEmbedManifest());
|
||||||
|
EXPECT_EQ(1, _context.getManifestId());
|
||||||
|
EXPECT_EQ("'asInvoker'", _context.getManifestLevel());
|
||||||
|
EXPECT_EQ(false, _context.getManifestUiAccess());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(WinLinkParserTest, Manifest_No) {
|
||||||
|
EXPECT_TRUE(parse("link.exe", "/manifest:no", "a.out", nullptr));
|
||||||
|
EXPECT_FALSE(_context.getCreateManifest());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(WinLinkParserTest, Manifest_Embed) {
|
||||||
|
EXPECT_TRUE(parse("link.exe", "/manifest:embed", "a.out", nullptr));
|
||||||
|
EXPECT_TRUE(_context.getCreateManifest());
|
||||||
|
EXPECT_TRUE(_context.getEmbedManifest());
|
||||||
|
EXPECT_EQ(1, _context.getManifestId());
|
||||||
|
EXPECT_EQ("'asInvoker'", _context.getManifestLevel());
|
||||||
|
EXPECT_EQ(false, _context.getManifestUiAccess());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(WinLinkParserTest, Manifest_Embed_ID42) {
|
||||||
|
EXPECT_TRUE(parse("link.exe", "/manifest:embed,id=42", "a.out", nullptr));
|
||||||
|
EXPECT_TRUE(_context.getCreateManifest());
|
||||||
|
EXPECT_TRUE(_context.getEmbedManifest());
|
||||||
|
EXPECT_EQ(42, _context.getManifestId());
|
||||||
|
EXPECT_EQ("'asInvoker'", _context.getManifestLevel());
|
||||||
|
EXPECT_EQ(false, _context.getManifestUiAccess());
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Test for command line flags that are ignored.
|
// Test for command line flags that are ignored.
|
||||||
//
|
//
|
||||||
|
|
Loading…
Reference in New Issue