PECOFF: Fix symbol aliases

Weak aliases defined using /alternatename command line option were getting
wrong RVAs in the final output because of wrong atom ordinal. Alias atoms
were assigned large ordinals than any other regular atoms because they were
instantiated after other atoms and just got new (larger) ordinals.

Atoms are sorted by its file and atom ordinals in the order pass. Alias
atoms were located after all other atoms in the same file.

An alias atom's ordinal needs to be smaller than its alias target but larger
than the atom appeared before the target -- so that the alias is located
between the two. Since an alias has no size, the alias target will be located
at the same location as the alias.

In this patch, I made a gap between two regular atoms so that we can put
aliases after instantiating them (without re-numbering existing atoms).

llvm-svn: 229762
This commit is contained in:
Rui Ueyama 2015-02-18 23:11:48 +00:00
parent 1028dcb1d0
commit 92b5979cb5
2 changed files with 18 additions and 14 deletions

View File

@ -83,7 +83,7 @@ public:
FileCOFF(std::unique_ptr<MemoryBuffer> mb, PECOFFLinkingContext &ctx) FileCOFF(std::unique_ptr<MemoryBuffer> mb, PECOFFLinkingContext &ctx)
: File(mb->getBufferIdentifier(), kindObject), _mb(std::move(mb)), : File(mb->getBufferIdentifier(), kindObject), _mb(std::move(mb)),
_compatibleWithSEH(false), _ordinal(0), _compatibleWithSEH(false), _ordinal(1),
_machineType(llvm::COFF::MT_Invalid), _ctx(ctx) {} _machineType(llvm::COFF::MT_Invalid), _ctx(ctx) {}
std::error_code doParse() override; std::error_code doParse() override;
@ -108,11 +108,6 @@ public:
void beforeLink() override; void beforeLink() override;
void addDefinedAtom(AliasAtom *atom) {
atom->setOrdinal(_ordinal++);
_definedAtoms._atoms.push_back(atom);
}
void addUndefinedSymbol(StringRef sym) { void addUndefinedSymbol(StringRef sym) {
_undefinedAtoms._atoms.push_back(new (_alloc) COFFUndefinedAtom(*this, sym)); _undefinedAtoms._atoms.push_back(new (_alloc) COFFUndefinedAtom(*this, sym));
} }
@ -168,6 +163,7 @@ private:
std::error_code addRelocationReferenceToAtoms(); std::error_code addRelocationReferenceToAtoms();
std::error_code findSection(StringRef name, const coff_section *&result); std::error_code findSection(StringRef name, const coff_section *&result);
StringRef ArrayRefToString(ArrayRef<uint8_t> array); StringRef ArrayRefToString(ArrayRef<uint8_t> array);
uint64_t getNextOrdinal();
std::unique_ptr<const llvm::object::COFFObjectFile> _obj; std::unique_ptr<const llvm::object::COFFObjectFile> _obj;
std::unique_ptr<MemoryBuffer> _mb; std::unique_ptr<MemoryBuffer> _mb;
@ -555,7 +551,7 @@ FileCOFF::createDefinedSymbols(const SymbolVectorT &symbols,
uint32_t size = sym.getValue(); uint32_t size = sym.getValue();
auto *atom = new (_alloc) auto *atom = new (_alloc)
COFFBSSAtom(*this, name, getScope(sym), DefinedAtom::permRW_, COFFBSSAtom(*this, name, getScope(sym), DefinedAtom::permRW_,
DefinedAtom::mergeAsWeakAndAddressUsed, size, _ordinal++); DefinedAtom::mergeAsWeakAndAddressUsed, size, getNextOrdinal());
// Common symbols should be aligned on natural boundaries with the maximum // Common symbols should be aligned on natural boundaries with the maximum
// of 32 byte. It's not documented anywhere, but it's what MSVC link.exe // of 32 byte. It's not documented anywhere, but it's what MSVC link.exe
@ -669,7 +665,7 @@ std::error_code FileCOFF::AtomizeDefinedSymbolsInSection(
: si[1].getValue() - sym.getValue(); : si[1].getValue() - sym.getValue();
auto *atom = new (_alloc) COFFBSSAtom( auto *atom = new (_alloc) COFFBSSAtom(
*this, _symbolName[sym], getScope(sym), getPermissions(section), *this, _symbolName[sym], getScope(sym), getPermissions(section),
DefinedAtom::mergeAsWeakAndAddressUsed, size, _ordinal++); DefinedAtom::mergeAsWeakAndAddressUsed, size, getNextOrdinal());
atoms.push_back(atom); atoms.push_back(atom);
_symbolAtom[sym] = atom; _symbolAtom[sym] = atom;
} }
@ -704,7 +700,7 @@ std::error_code FileCOFF::AtomizeDefinedSymbolsInSection(
ArrayRef<uint8_t> data(secData.data(), secData.size()); ArrayRef<uint8_t> data(secData.data(), secData.size());
auto *atom = new (_alloc) COFFDefinedAtom( auto *atom = new (_alloc) COFFDefinedAtom(
*this, "", sectionName, Atom::scopeTranslationUnit, type, isComdat, *this, "", sectionName, Atom::scopeTranslationUnit, type, isComdat,
perms, _merge[section], data, _ordinal++); perms, _merge[section], data, getNextOrdinal());
atoms.push_back(atom); atoms.push_back(atom);
_definedAtomLocations[section][0].push_back(atom); _definedAtomLocations[section][0].push_back(atom);
return std::error_code(); return std::error_code();
@ -717,7 +713,7 @@ std::error_code FileCOFF::AtomizeDefinedSymbolsInSection(
ArrayRef<uint8_t> data(secData.data(), size); ArrayRef<uint8_t> data(secData.data(), size);
auto *atom = new (_alloc) COFFDefinedAtom( auto *atom = new (_alloc) COFFDefinedAtom(
*this, "", sectionName, Atom::scopeTranslationUnit, type, isComdat, *this, "", sectionName, Atom::scopeTranslationUnit, type, isComdat,
perms, _merge[section], data, _ordinal++); perms, _merge[section], data, getNextOrdinal());
atoms.push_back(atom); atoms.push_back(atom);
_definedAtomLocations[section][0].push_back(atom); _definedAtomLocations[section][0].push_back(atom);
} }
@ -730,7 +726,7 @@ std::error_code FileCOFF::AtomizeDefinedSymbolsInSection(
ArrayRef<uint8_t> data(start, end); ArrayRef<uint8_t> data(start, end);
auto *atom = new (_alloc) COFFDefinedAtom( auto *atom = new (_alloc) COFFDefinedAtom(
*this, _symbolName[*si], sectionName, getScope(*si), type, isComdat, *this, _symbolName[*si], sectionName, getScope(*si), type, isComdat,
perms, _merge[section], data, _ordinal++); perms, _merge[section], data, getNextOrdinal());
atoms.push_back(atom); atoms.push_back(atom);
_symbolAtom[*si] = atom; _symbolAtom[*si] = atom;
_definedAtomLocations[section][si->getValue()].push_back(atom); _definedAtomLocations[section][si->getValue()].push_back(atom);
@ -868,6 +864,7 @@ AliasAtom *FileCOFF::createAlias(StringRef name,
alias->setMerge(DefinedAtom::mergeAsWeak); alias->setMerge(DefinedAtom::mergeAsWeak);
if (target->contentType() == DefinedAtom::typeCode) if (target->contentType() == DefinedAtom::typeCode)
alias->setDeadStrip(DefinedAtom::deadStripNever); alias->setDeadStrip(DefinedAtom::deadStripNever);
alias->setOrdinal(target->ordinal() - 1);
return alias; return alias;
} }
@ -879,7 +876,7 @@ void FileCOFF::createAlternateNameAtoms() {
aliases.push_back(createAlias(it->second, atom)); aliases.push_back(createAlias(it->second, atom));
} }
for (AliasAtom *alias : aliases) for (AliasAtom *alias : aliases)
addDefinedAtom(alias); _definedAtoms._atoms.push_back(alias);
} }
// Interpret the contents of .drectve section. If exists, the section contains // Interpret the contents of .drectve section. If exists, the section contains
@ -988,7 +985,7 @@ std::error_code FileCOFF::maybeCreateSXDataAtoms() {
auto *atom = new (_alloc) COFFDefinedAtom( auto *atom = new (_alloc) COFFDefinedAtom(
*this, "", ".sxdata", Atom::scopeTranslationUnit, DefinedAtom::typeData, *this, "", ".sxdata", Atom::scopeTranslationUnit, DefinedAtom::typeData,
false /*isComdat*/, DefinedAtom::permR__, DefinedAtom::mergeNo, false /*isComdat*/, DefinedAtom::permR__, DefinedAtom::mergeNo,
sxdata, _ordinal++); sxdata, getNextOrdinal());
const ulittle32_t *symbolIndex = const ulittle32_t *symbolIndex =
reinterpret_cast<const ulittle32_t *>(sxdata.data()); reinterpret_cast<const ulittle32_t *>(sxdata.data());
@ -1064,6 +1061,13 @@ StringRef FileCOFF::ArrayRefToString(ArrayRef<uint8_t> array) {
return StringRef(*contents).trim(); return StringRef(*contents).trim();
} }
// getNextOrdinal returns a monotonically increasaing uint64_t number
// starting from 1. There's a large gap between two numbers returned
// from this function, so that you can put other atoms between them.
uint64_t FileCOFF::getNextOrdinal() {
return _ordinal++ << 32;
}
class COFFObjectReader : public Reader { class COFFObjectReader : public Reader {
public: public:
COFFObjectReader(PECOFFLinkingContext &ctx) : _ctx(ctx) {} COFFObjectReader(PECOFFLinkingContext &ctx) : _ctx(ctx) {}

View File

@ -33,7 +33,7 @@ WWINMAIN: _wWinMainCRTStartup
# RUN: /alternatename:_mainCRTStartup=_bar -- %t.obj # RUN: /alternatename:_mainCRTStartup=_bar -- %t.obj
# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=MAINADDR %s # RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=MAINADDR %s
MAINADDR: AddressOfEntryPoint: 0x100C MAINADDR: AddressOfEntryPoint: 0x1004
# RUN: lld -flavor link /out:%t.exe /subsystem:console /entry:baz -- %t.obj # RUN: lld -flavor link /out:%t.exe /subsystem:console /entry:baz -- %t.obj
# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=MANGLE %s # RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=MANGLE %s