forked from OSchip/llvm-project
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:
parent
1028dcb1d0
commit
92b5979cb5
|
@ -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) {}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue