[PECOFF] Fix /export option in the .drectve section.

/EXPORT option has slightly different semantics if it appears in the .drectve
section. This patch implements it.

llvm-svn: 197970
This commit is contained in:
Rui Ueyama 2013-12-24 09:15:57 +00:00
parent ce7a12be8f
commit 090a7cd76d
6 changed files with 24 additions and 7 deletions

View File

@ -98,6 +98,7 @@ public:
StringRef searchLibraryFile(StringRef path) const;
StringRef decorateSymbol(StringRef name) const;
StringRef undecorateSymbol(StringRef name) const;
void setEntrySymbolName(StringRef name) {
if (!name.empty())

View File

@ -892,6 +892,15 @@ WinLinkDriver::parse(int argc, const char *argv[], PECOFFLinkingContext &ctx,
<< inputArg->getValue() << "\n";
return false;
}
// Mangle the symbol name only if it is reading user-supplied command line
// arguments. Because the symbol name in the .drectve section is already
// mangled by the compiler, we shouldn't add a leading undescore here.
// It's odd that the command line option has different semantics in the
// .drectve section, but this behavior is needed for compatibility with
// MSVC's link.exe.
if (!isReadingDirectiveSection)
desc.name = ctx.decorateSymbol(desc.name);
ctx.addDllExport(desc);
break;
}

View File

@ -39,7 +39,7 @@ static bool getExportedAtoms(const PECOFFLinkingContext &ctx, MutableFile *file,
definedAtoms[atom->name()] = atom;
for (const PECOFFLinkingContext::ExportDesc &desc : ctx.getDllExports()) {
auto it = definedAtoms.find(ctx.decorateSymbol(desc.name));
auto it = definedAtoms.find(desc.name);
if (it == definedAtoms.end()) {
llvm::errs() << "Symbol <" << desc.name
<< "> is exported but not defined.\n";
@ -86,8 +86,8 @@ EdataPass::createNamePointerTable(const PECOFFLinkingContext &ctx,
size_t offset = 0;
for (const TableEntry &e : entries) {
auto *stringAtom = new (_alloc)
COFFStringAtom(_file, _stringOrdinal++, ".edata", e.exportName);
auto *stringAtom = new (_alloc) COFFStringAtom(
_file, _stringOrdinal++, ".edata", ctx.undecorateSymbol(e.exportName));
file->addAtom(*stringAtom);
addDir32NBReloc(table, stringAtom, offset);
offset += sizeof(uint32_t);

View File

@ -219,6 +219,13 @@ StringRef PECOFFLinkingContext::decorateSymbol(StringRef name) const {
return allocate(str);
}
StringRef PECOFFLinkingContext::undecorateSymbol(StringRef name) const {
if (_machineType != llvm::COFF::IMAGE_FILE_MACHINE_I386)
return name;
assert(name.startswith("_"));
return name.substr(1);
}
Writer &PECOFFLinkingContext::writer() const { return *_writer; }

View File

@ -42,7 +42,7 @@ createModuleDefinitionFile(const PECOFFLinkingContext &ctx,
<< "EXPORTS\n";
for (const PECOFFLinkingContext::ExportDesc &desc : ctx.getDllExports()) {
os << " " << desc.name << " @" << desc.ordinal;
os << " " << ctx.undecorateSymbol(desc.name) << " @" << desc.ordinal;
if (desc.noname)
os << " NONAME";
if (desc.isData)

View File

@ -161,7 +161,7 @@ TEST_F(WinLinkParserTest, Export) {
const std::vector<PECOFFLinkingContext::ExportDesc> &exports =
_context.getDllExports();
EXPECT_TRUE(exports.size() == 1);
EXPECT_EQ("foo", exports[0].name);
EXPECT_EQ("_foo", exports[0].name);
EXPECT_EQ(1, exports[0].ordinal);
EXPECT_FALSE(exports[0].noname);
EXPECT_FALSE(exports[0].isData);
@ -173,11 +173,11 @@ TEST_F(WinLinkParserTest, ExportWithOptions) {
const std::vector<PECOFFLinkingContext::ExportDesc> &exports =
_context.getDllExports();
EXPECT_TRUE(exports.size() == 2);
EXPECT_EQ("foo", exports[0].name);
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("_bar", exports[1].name);
EXPECT_EQ(10, exports[1].ordinal);
EXPECT_FALSE(exports[1].noname);
EXPECT_TRUE(exports[1].isData);