forked from OSchip/llvm-project
[PECOFF] Parse /export optional arguments.
/EXPORT command line option can take an ordinal, NONAME flag, and DATA flag. This patch is to parse these optional arguments. llvm-svn: 197217
This commit is contained in:
parent
37d25de459
commit
fa561713f3
|
@ -57,6 +57,14 @@ public:
|
|||
int minorVersion;
|
||||
};
|
||||
|
||||
struct ExportDesc {
|
||||
ExportDesc() : ordinal(-1), noname(false), isData(false) {}
|
||||
std::string name;
|
||||
int ordinal;
|
||||
bool noname;
|
||||
bool isData;
|
||||
};
|
||||
|
||||
/// \brief Casting support
|
||||
static inline bool classof(const LinkingContext *info) { return true; }
|
||||
|
||||
|
@ -219,8 +227,8 @@ public:
|
|||
void setDosStub(ArrayRef<uint8_t> data) { _dosStub = data; }
|
||||
ArrayRef<uint8_t> getDosStub() const { return _dosStub; }
|
||||
|
||||
void addDllExport(StringRef sym) { _dllExports.insert(sym); }
|
||||
const std::set<std::string> &getDllExports() const { return _dllExports; }
|
||||
void addDllExport(ExportDesc &desc) { _dllExports.push_back(desc); }
|
||||
const std::vector<ExportDesc> &getDllExports() const { return _dllExports; }
|
||||
|
||||
StringRef allocate(StringRef ref) const {
|
||||
char *x = _allocator.Allocate<char>(ref.size() + 1);
|
||||
|
@ -301,7 +309,7 @@ private:
|
|||
std::map<std::string, uint32_t> _sectionClearMask;
|
||||
|
||||
// DLLExport'ed symbols.
|
||||
std::set<std::string> _dllExports;
|
||||
std::vector<ExportDesc> _dllExports;
|
||||
|
||||
// List of files that will be removed on destruction.
|
||||
std::vector<std::unique_ptr<llvm::FileRemover> > _tempFiles;
|
||||
|
|
|
@ -300,6 +300,41 @@ bool parseManifestUac(StringRef option, llvm::Optional<std::string> &level,
|
|||
}
|
||||
}
|
||||
|
||||
// Parse /export:name[,@ordinal[,NONAME]][,DATA].
|
||||
bool parseExport(StringRef option, PECOFFLinkingContext::ExportDesc &ret) {
|
||||
StringRef name;
|
||||
StringRef rest;
|
||||
llvm::tie(name, rest) = option.split(",");
|
||||
if (name.empty())
|
||||
return false;
|
||||
ret.name = name;
|
||||
|
||||
for (;;) {
|
||||
if (rest.empty())
|
||||
return true;
|
||||
StringRef arg;
|
||||
llvm::tie(arg, rest) = rest.split(",");
|
||||
if (arg.equals_lower("noname")) {
|
||||
if (ret.ordinal < 0)
|
||||
return false;
|
||||
ret.noname = true;
|
||||
continue;
|
||||
}
|
||||
if (arg.equals_lower("data")) {
|
||||
ret.isData = true;
|
||||
continue;
|
||||
}
|
||||
if (arg.startswith("@")) {
|
||||
int ordinal;
|
||||
if (arg.substr(1).getAsInteger(0, ordinal))
|
||||
return false;
|
||||
ret.ordinal = ordinal;
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
StringRef replaceExtension(PECOFFLinkingContext &ctx,
|
||||
StringRef path, StringRef extension) {
|
||||
SmallString<128> val = path;
|
||||
|
@ -840,9 +875,15 @@ WinLinkDriver::parse(int argc, const char *argv[], PECOFFLinkingContext &ctx,
|
|||
ctx.setEntrySymbolName(ctx.allocate(inputArg->getValue()));
|
||||
break;
|
||||
|
||||
case OPT_export:
|
||||
ctx.addDllExport(inputArg->getValue());
|
||||
case OPT_export: {
|
||||
PECOFFLinkingContext::ExportDesc desc;
|
||||
if (!parseExport(inputArg->getValue(), desc)) {
|
||||
diagnostics << "Error: malformed /export option\n";
|
||||
return false;
|
||||
}
|
||||
ctx.addDllExport(desc);
|
||||
break;
|
||||
}
|
||||
|
||||
case OPT_libpath:
|
||||
ctx.appendInputSearchPath(ctx.allocate(inputArg->getValue()));
|
||||
|
|
|
@ -30,10 +30,10 @@ static bool getExportedAtoms(const PECOFFLinkingContext &ctx, MutableFile *file,
|
|||
for (const DefinedAtom *atom : file->defined())
|
||||
definedAtoms[atom->name()] = atom;
|
||||
|
||||
for (StringRef dllExport : ctx.getDllExports()) {
|
||||
auto it = definedAtoms.find(ctx.decorateSymbol(dllExport));
|
||||
for (const PECOFFLinkingContext::ExportDesc &desc : ctx.getDllExports()) {
|
||||
auto it = definedAtoms.find(ctx.decorateSymbol(desc.name));
|
||||
if (it == definedAtoms.end()) {
|
||||
llvm::errs() << "Symbol <" << dllExport
|
||||
llvm::errs() << "Symbol <" << desc.name
|
||||
<< "> is exported but not defined.\n";
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -157,10 +157,30 @@ TEST_F(WinLinkParserTest, AlternateName) {
|
|||
}
|
||||
|
||||
TEST_F(WinLinkParserTest, Export) {
|
||||
EXPECT_TRUE(parse("link.exe", "/export:_foo", "a.out", nullptr));
|
||||
const std::set<std::string> &exports = _context.getDllExports();
|
||||
EXPECT_TRUE(exports.count("_foo") == 1);
|
||||
EXPECT_TRUE(exports.count("nosuchsym") == 0);
|
||||
EXPECT_TRUE(parse("link.exe", "/export:foo", "a.out", nullptr));
|
||||
const std::vector<PECOFFLinkingContext::ExportDesc> &exports =
|
||||
_context.getDllExports();
|
||||
EXPECT_TRUE(exports.size() == 1);
|
||||
EXPECT_EQ("foo", exports[0].name);
|
||||
EXPECT_EQ(-1, exports[0].ordinal);
|
||||
EXPECT_FALSE(exports[0].noname);
|
||||
EXPECT_FALSE(exports[0].isData);
|
||||
}
|
||||
|
||||
TEST_F(WinLinkParserTest, ExportWithOptions) {
|
||||
EXPECT_TRUE(parse("link.exe", "/export:foo,@8,noname,data",
|
||||
"/export:bar,@10,data", "a.out", nullptr));
|
||||
const std::vector<PECOFFLinkingContext::ExportDesc> &exports =
|
||||
_context.getDllExports();
|
||||
EXPECT_TRUE(exports.size() == 2);
|
||||
EXPECT_EQ("foo", exports[0].name);
|
||||
EXPECT_EQ(8, exports[0].ordinal);
|
||||
EXPECT_TRUE(exports[0].noname);
|
||||
EXPECT_TRUE(exports[0].isData);
|
||||
EXPECT_EQ("bar", exports[1].name);
|
||||
EXPECT_EQ(10, exports[1].ordinal);
|
||||
EXPECT_FALSE(exports[1].noname);
|
||||
EXPECT_TRUE(exports[1].isData);
|
||||
}
|
||||
|
||||
TEST_F(WinLinkParserTest, MachineX86) {
|
||||
|
|
Loading…
Reference in New Issue