[PECOFF] Fix exported symbol in the import library

There are two ways to specify a symbol to be exported in the module
definition file.

1) EXPORT <external name> = <symbol>
2) EXPORT <symbol>

In (1), you give both external name and internal name. In that case,
the linker tries to find a symbol using the internal name, and write
that address to the export table with the external name. Thus, from
the outer world, the symbol seems to be exported as the external name.

In (2), internal name is basically the same as the external name
with an exception: if you give an undecorated symbol to the EXPORT
directive, and if the linker finds a decorated symbol, the external
name for the symbol will become the decorated symbol.

LLD didn't implement that exception correctly. This patch fixes that.

llvm-svn: 220333
This commit is contained in:
Rui Ueyama 2014-10-21 21:41:28 +00:00
parent 0c6fed5716
commit 8bae8189b2
6 changed files with 15 additions and 8 deletions

View File

@ -61,8 +61,15 @@ public:
struct ExportDesc {
ExportDesc()
: ordinal(-1), noname(false), isData(false), isPrivate(false) {}
bool operator<(const ExportDesc &other) const {
return name.compare(other.name) < 0;
return getExternalName().compare(other.getExternalName()) < 0;
}
StringRef getExternalName() const {
if (!externalName.empty())
return externalName;
return name;
}
std::string name;

View File

@ -392,7 +392,6 @@ static bool parseExport(StringRef option,
return false;
if (name.find('=') == StringRef::npos) {
ret.name = name;
ret.externalName = name;
} else {
std::tie(ret.externalName, ret.name) = name.split("=");
if (ret.name.empty())

View File

@ -197,13 +197,13 @@ bool Parser::parseExport(PECOFFLinkingContext::ExportDesc &result) {
return false;
}
result.name = _tok._range;
result.externalName = result.name;
consumeToken();
if (_tok._kind == Kind::equal) {
consumeToken();
if (_tok._kind != Kind::identifier)
return false;
result.externalName = result.name;
result.name = _tok._range;
} else {
ungetToken();

View File

@ -62,7 +62,8 @@ static bool getExportedAtoms(PECOFFLinkingContext &ctx, MutableFile *file,
// One can export a symbol with a different name than the symbol
// name used in DLL. If such name is specified, use it in the
// .edata section.
ret.push_back(TableEntry(desc.externalName, desc.ordinal, atom, desc.noname));
ret.push_back(TableEntry(desc.getExternalName(), desc.ordinal, atom,
desc.noname));
}
std::sort(ret.begin(), ret.end(),
[](const TableEntry &a, const TableEntry &b) {

View File

@ -30,7 +30,7 @@ createModuleDefinitionFile(const PECOFFLinkingContext &ctx) {
<< "EXPORTS\n";
for (const PECOFFLinkingContext::ExportDesc &desc : ctx.getDllExports()) {
os << " " << desc.externalName;
os << " " << desc.getExternalName();
if (!desc.isPrivate)
os << " @" << desc.ordinal;
if (desc.noname)

View File

@ -58,7 +58,7 @@ CHECK5-NEXT: 1 0x2010 exportfn7
CHECK6: Export Table:
CHECK6: DLL name: export.test.tmp6.dll
CHECK6: Ordinal RVA Name
CHECK6-NEXT: 1 0x2010 exportfn8
CHECK6-NEXT: 1 0x2010 ?exportfn8@@YAXXZ
# RUN: lld -flavor link /out:%t6.dll /dll /entry:init \
# RUN: /export:exportfn8 /export:exportfn8 -- %t.obj
@ -67,8 +67,8 @@ CHECK6-NEXT: 1 0x2010 exportfn8
DUP: Export Table:
DUP: DLL name: export.test.tmp6.dll
DUP: Ordinal RVA Name
DUP: 1 0x2010 exportfn8
DUP-NOT: 1 0x2010 exportfn8
DUP: 1 0x2010 ?exportfn8@@YAXXZ
DUP-NOT: 1 0x2010 ?exportfn8@@YAXXZ
# RUN: yaml2obj %p/Inputs/export.obj.yaml > %t.obj
#