[PECOFF] Split COFFDefinedAtom to add COFFBSSAtom class.

The BSS atom is similar to the regular defined atom, but it's different
in the sense that it does not have contents. Until now we assumed all the
defined atoms have its contents. That did not fit well to the BSS atom.

llvm-svn: 187453
This commit is contained in:
Rui Ueyama 2013-07-30 21:54:10 +00:00
parent 3987806087
commit 7ae6ffd3d2
2 changed files with 56 additions and 22 deletions

View File

@ -152,21 +152,20 @@ private:
std::vector<std::unique_ptr<COFFReference>> _references;
};
/// A COFFDefinedAtom represents an atom read from a file.
class COFFDefinedAtom : public COFFBaseDefinedAtom {
/// This is the root class of the atom read from a file. This class have two
/// subclasses; one for the regular atom and another for the BSS atom.
class COFFDefinedFileAtom : public COFFBaseDefinedAtom {
public:
COFFDefinedAtom(const File &file, StringRef name, const coff_symbol *symbol,
const coff_section *section, ArrayRef<uint8_t> data,
StringRef sectionName, uint64_t ordinal)
COFFDefinedFileAtom(const File &file, StringRef name,
const coff_symbol *symbol, const coff_section *section,
StringRef sectionName, uint64_t ordinal)
: COFFBaseDefinedAtom(file, name, Kind::File), _symbol(symbol),
_section(section), _dataref(data), _sectionName(sectionName),
_section(section), _sectionName(sectionName),
_ordinal(ordinal) {}
virtual uint64_t ordinal() const { return _ordinal; }
uint64_t originalOffset() const { return _symbol->Value; }
virtual StringRef getSectionName() const { return _sectionName; }
virtual uint64_t size() const { return _dataref.size(); }
virtual ArrayRef<uint8_t> rawContent() const { return _dataref; }
static bool classof(const COFFBaseDefinedAtom *atom) {
return atom->getKind() == Kind::File;
@ -211,12 +210,44 @@ public:
private:
const coff_symbol *_symbol;
const coff_section *_section;
ArrayRef<uint8_t> _dataref;
StringRef _sectionName;
std::vector<std::unique_ptr<COFFReference>> _references;
uint64_t _ordinal;
};
// A COFFDefinedAtom represents an atom read from a file and has contents.
class COFFDefinedAtom : public COFFDefinedFileAtom {
public:
COFFDefinedAtom(const File &file, StringRef name, const coff_symbol *symbol,
const coff_section *section, ArrayRef<uint8_t> data,
StringRef sectionName, uint64_t ordinal)
: COFFDefinedFileAtom(file, name, symbol, section, sectionName, ordinal),
_dataref(data) {}
virtual uint64_t size() const { return _dataref.size(); }
virtual ArrayRef<uint8_t> rawContent() const { return _dataref; }
private:
ArrayRef<uint8_t> _dataref;
};
// A COFFDefinedAtom represents an atom for BSS section.
class COFFBSSAtom : public COFFDefinedFileAtom {
public:
COFFBSSAtom(const File &file, StringRef name, const coff_symbol *symbol,
const coff_section *section, uint32_t size,
StringRef sectionName, uint64_t ordinal)
: COFFDefinedFileAtom(file, name, symbol, section, sectionName, ordinal),
_size(size) {}
virtual uint64_t size() const { return _size; }
virtual ArrayRef<uint8_t> rawContent() const { return _contents; }
private:
uint32_t _size;
std::vector<uint8_t> _contents;
};
/// A COFFLinkerInternalAtom represents a defined atom created by the linker,
/// not read from file.
class COFFLinkerInternalAtom : public COFFBaseDefinedAtom {

View File

@ -31,7 +31,9 @@
using std::vector;
using lld::coff::COFFAbsoluteAtom;
using lld::coff::COFFBSSAtom;
using lld::coff::COFFDefinedAtom;
using lld::coff::COFFDefinedFileAtom;
using lld::coff::COFFReference;
using lld::coff::COFFUndefinedAtom;
using llvm::object::coff_relocation;
@ -47,7 +49,7 @@ private:
typedef vector<const coff_symbol *> SymbolVectorT;
typedef std::map<const coff_section *, SymbolVectorT> SectionToSymbolsT;
typedef std::map<const StringRef, Atom *> SymbolNameToAtomT;
typedef std::map<const coff_section *, vector<COFFDefinedAtom *> >
typedef std::map<const coff_section *, vector<COFFDefinedFileAtom *> >
SectionToAtomsT;
public:
@ -192,8 +194,8 @@ private:
error_code
AtomizeDefinedSymbolsInSection(const coff_section *section,
vector<const coff_symbol *> &symbols,
vector<COFFDefinedAtom *> &atoms) {
// Sort symbols by position.
vector<COFFDefinedFileAtom *> &atoms) {
// Sort symbols by position.
std::stable_sort(symbols.begin(), symbols.end(),
// For some reason MSVC fails to allow the lambda in this context with a
// "illegal use of local type in type instantiation". MSVC is clearly
@ -262,7 +264,7 @@ private:
for (auto &i : definedSymbols) {
const coff_section *section = i.first;
vector<const coff_symbol *> &symbols = i.second;
vector<COFFDefinedAtom *> atoms;
vector<COFFDefinedFileAtom *> atoms;
if (error_code ec =
AtomizeDefinedSymbolsInSection(section, symbols, atoms))
return ec;
@ -270,7 +272,7 @@ private:
// Connect atoms with layout-before/layout-after edges.
connectAtomsWithLayoutEdge(atoms);
for (COFFDefinedAtom *atom : atoms) {
for (COFFDefinedFileAtom *atom : atoms) {
_sectionAtoms[section].push_back(atom);
definedAtoms.push_back(atom);
}
@ -280,15 +282,16 @@ private:
/// Find the atom that is at \p targetOffset in \p section. It is assumed
/// that \p atoms are sorted by position in the section.
COFFDefinedAtom *findAtomAt(uint32_t targetOffset,
const vector<COFFDefinedAtom *> &atoms) const {
COFFDefinedFileAtom *
findAtomAt(uint32_t targetOffset,
const vector<COFFDefinedFileAtom *> &atoms) const {
assert(std::is_sorted(atoms.begin(), atoms.end(),
[](const COFFDefinedAtom * a,
const COFFDefinedAtom * b) -> bool {
[](const COFFDefinedFileAtom * a,
const COFFDefinedFileAtom * b) -> bool {
return a->originalOffset() < b->originalOffset();
}));
for (COFFDefinedAtom *atom : atoms)
for (COFFDefinedFileAtom *atom : atoms)
if (targetOffset < atom->originalOffset() + atom->size())
return atom;
llvm_unreachable("Relocation target out of range");
@ -311,7 +314,7 @@ private:
error_code
addRelocationReference(const coff_relocation *rel,
const coff_section *section,
const vector<COFFDefinedAtom *> &atoms) {
const vector<COFFDefinedFileAtom *> &atoms) {
assert(atoms.size() > 0);
// The address of the item which relocation is applied. Section's
// VirtualAddress needs to be added for historical reasons, but the value
@ -322,7 +325,7 @@ private:
if (error_code ec = getAtomBySymbolIndex(rel->SymbolTableIndex, targetAtom))
return ec;
COFFDefinedAtom *atom = findAtomAt(rel->VirtualAddress, atoms);
COFFDefinedFileAtom *atom = findAtomAt(rel->VirtualAddress, atoms);
uint32_t offsetInAtom = itemAddress - atom->originalOffset();
assert(offsetInAtom < atom->size());
atom->addReference(std::unique_ptr<COFFReference>(
@ -368,7 +371,7 @@ private:
std::map<const coff_symbol *, Atom *> _symbolAtom;
// A map from section to its atoms.
std::map<const coff_section *, vector<COFFDefinedAtom *>> _sectionAtoms;
std::map<const coff_section *, vector<COFFDefinedFileAtom *>> _sectionAtoms;
mutable llvm::BumpPtrAllocator _alloc;
const TargetInfo &_targetInfo;