From 92b5979cb518667d29e1490debcbe81fe3d1cb38 Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Wed, 18 Feb 2015 23:11:48 +0000 Subject: [PATCH] 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 --- lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp | 30 +++++++++++++++++------------- lld/test/pecoff/entry.test | 2 +- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp b/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp index 67177b7..27d26c8 100644 --- a/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp +++ b/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp @@ -83,7 +83,7 @@ public: FileCOFF(std::unique_ptr mb, PECOFFLinkingContext &ctx) : File(mb->getBufferIdentifier(), kindObject), _mb(std::move(mb)), - _compatibleWithSEH(false), _ordinal(0), + _compatibleWithSEH(false), _ordinal(1), _machineType(llvm::COFF::MT_Invalid), _ctx(ctx) {} std::error_code doParse() override; @@ -108,11 +108,6 @@ public: void beforeLink() override; - void addDefinedAtom(AliasAtom *atom) { - atom->setOrdinal(_ordinal++); - _definedAtoms._atoms.push_back(atom); - } - void addUndefinedSymbol(StringRef sym) { _undefinedAtoms._atoms.push_back(new (_alloc) COFFUndefinedAtom(*this, sym)); } @@ -168,6 +163,7 @@ private: std::error_code addRelocationReferenceToAtoms(); std::error_code findSection(StringRef name, const coff_section *&result); StringRef ArrayRefToString(ArrayRef array); + uint64_t getNextOrdinal(); std::unique_ptr _obj; std::unique_ptr _mb; @@ -555,7 +551,7 @@ FileCOFF::createDefinedSymbols(const SymbolVectorT &symbols, uint32_t size = sym.getValue(); auto *atom = new (_alloc) 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 // 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(); auto *atom = new (_alloc) COFFBSSAtom( *this, _symbolName[sym], getScope(sym), getPermissions(section), - DefinedAtom::mergeAsWeakAndAddressUsed, size, _ordinal++); + DefinedAtom::mergeAsWeakAndAddressUsed, size, getNextOrdinal()); atoms.push_back(atom); _symbolAtom[sym] = atom; } @@ -704,7 +700,7 @@ std::error_code FileCOFF::AtomizeDefinedSymbolsInSection( ArrayRef data(secData.data(), secData.size()); auto *atom = new (_alloc) COFFDefinedAtom( *this, "", sectionName, Atom::scopeTranslationUnit, type, isComdat, - perms, _merge[section], data, _ordinal++); + perms, _merge[section], data, getNextOrdinal()); atoms.push_back(atom); _definedAtomLocations[section][0].push_back(atom); return std::error_code(); @@ -717,7 +713,7 @@ std::error_code FileCOFF::AtomizeDefinedSymbolsInSection( ArrayRef data(secData.data(), size); auto *atom = new (_alloc) COFFDefinedAtom( *this, "", sectionName, Atom::scopeTranslationUnit, type, isComdat, - perms, _merge[section], data, _ordinal++); + perms, _merge[section], data, getNextOrdinal()); atoms.push_back(atom); _definedAtomLocations[section][0].push_back(atom); } @@ -730,7 +726,7 @@ std::error_code FileCOFF::AtomizeDefinedSymbolsInSection( ArrayRef data(start, end); auto *atom = new (_alloc) COFFDefinedAtom( *this, _symbolName[*si], sectionName, getScope(*si), type, isComdat, - perms, _merge[section], data, _ordinal++); + perms, _merge[section], data, getNextOrdinal()); atoms.push_back(atom); _symbolAtom[*si] = atom; _definedAtomLocations[section][si->getValue()].push_back(atom); @@ -868,6 +864,7 @@ AliasAtom *FileCOFF::createAlias(StringRef name, alias->setMerge(DefinedAtom::mergeAsWeak); if (target->contentType() == DefinedAtom::typeCode) alias->setDeadStrip(DefinedAtom::deadStripNever); + alias->setOrdinal(target->ordinal() - 1); return alias; } @@ -879,7 +876,7 @@ void FileCOFF::createAlternateNameAtoms() { aliases.push_back(createAlias(it->second, atom)); } for (AliasAtom *alias : aliases) - addDefinedAtom(alias); + _definedAtoms._atoms.push_back(alias); } // 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( *this, "", ".sxdata", Atom::scopeTranslationUnit, DefinedAtom::typeData, false /*isComdat*/, DefinedAtom::permR__, DefinedAtom::mergeNo, - sxdata, _ordinal++); + sxdata, getNextOrdinal()); const ulittle32_t *symbolIndex = reinterpret_cast(sxdata.data()); @@ -1064,6 +1061,13 @@ StringRef FileCOFF::ArrayRefToString(ArrayRef array) { 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 { public: COFFObjectReader(PECOFFLinkingContext &ctx) : _ctx(ctx) {} diff --git a/lld/test/pecoff/entry.test b/lld/test/pecoff/entry.test index c833843..b48e5a0 100644 --- a/lld/test/pecoff/entry.test +++ b/lld/test/pecoff/entry.test @@ -33,7 +33,7 @@ WWINMAIN: _wWinMainCRTStartup # RUN: /alternatename:_mainCRTStartup=_bar -- %t.obj # 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: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=MANGLE %s -- 2.7.4