diff --git a/lld/lib/ReaderWriter/PECOFF/Atoms.h b/lld/lib/ReaderWriter/PECOFF/Atoms.h index 49d77887891c..6d3a71c5ed9d 100644 --- a/lld/lib/ReaderWriter/PECOFF/Atoms.h +++ b/lld/lib/ReaderWriter/PECOFF/Atoms.h @@ -58,25 +58,19 @@ private: class COFFAbsoluteAtom : public AbsoluteAtom { public: - COFFAbsoluteAtom(const File &f, StringRef n, const coff_symbol *s) - : _owningFile(f), _name(n), _symbol(s) {} + COFFAbsoluteAtom(const File &f, StringRef name, Scope scope, uint64_t value) + : _owningFile(f), _name(name), _scope(scope), _value(value) {} virtual const File &file() const { return _owningFile; } - - virtual Scope scope() const { - if (_symbol->StorageClass == llvm::COFF::IMAGE_SYM_CLASS_STATIC) - return scopeTranslationUnit; - return scopeGlobal; - } - + virtual Scope scope() const { return _scope; } virtual StringRef name() const { return _name; } - - virtual uint64_t value() const { return _symbol->Value; } + virtual uint64_t value() const { return _value; } private: const File &_owningFile; StringRef _name; - const coff_symbol *_symbol; + Scope _scope; + uint64_t _value; }; class COFFUndefinedAtom : public UndefinedAtom { @@ -85,9 +79,7 @@ public: : _owningFile(f), _name(n) {} virtual const File &file() const { return _owningFile; } - virtual StringRef name() const { return _name; } - virtual CanBeNull canBeNull() const { return CanBeNull::canBeNullNever; } private: @@ -156,71 +148,40 @@ private: /// subclasses; one for the regular atom and another for the BSS atom. class COFFDefinedFileAtom : public COFFBaseDefinedAtom { public: - 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), _sectionName(sectionName), + COFFDefinedFileAtom(const File &file, StringRef name, StringRef sectionName, + Scope scope, ContentType contentType, + ContentPermissions perms, uint64_t ordinal) + : COFFBaseDefinedAtom(file, name, Kind::File), _sectionName(sectionName), + _scope(scope), _contentType(contentType), _permissions(perms), _ordinal(ordinal) {} - virtual uint64_t ordinal() const { return _ordinal; } - virtual StringRef getSectionName() const { return _sectionName; } - static bool classof(const COFFBaseDefinedAtom *atom) { return atom->getKind() == Kind::File; } - virtual Scope scope() const { - if (!_symbol) - return scopeTranslationUnit; - switch (_symbol->StorageClass) { - case llvm::COFF::IMAGE_SYM_CLASS_EXTERNAL: - return scopeGlobal; - case llvm::COFF::IMAGE_SYM_CLASS_STATIC: - case llvm::COFF::IMAGE_SYM_CLASS_LABEL: - return scopeTranslationUnit; - } - llvm_unreachable("Unknown scope!"); - } - - virtual ContentType contentType() const { - if (_section->Characteristics & llvm::COFF::IMAGE_SCN_CNT_CODE) - return typeCode; - if (_section->Characteristics & llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA) - return typeData; - if (_section->Characteristics & - llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) - return typeZeroFill; - return typeUnknown; - } - - virtual ContentPermissions permissions() const { - if (_section->Characteristics & llvm::COFF::IMAGE_SCN_MEM_READ && - _section->Characteristics & llvm::COFF::IMAGE_SCN_MEM_WRITE) - return permRW_; - if (_section->Characteristics & llvm::COFF::IMAGE_SCN_MEM_READ && - _section->Characteristics & llvm::COFF::IMAGE_SCN_MEM_EXECUTE) - return permR_X; - if (_section->Characteristics & llvm::COFF::IMAGE_SCN_MEM_READ) - return permR__; - return perm___; - } + virtual StringRef getSectionName() const { return _sectionName; } + virtual Scope scope() const { return _scope; } + virtual ContentType contentType() const { return _contentType; } + virtual ContentPermissions permissions() const { return _permissions; } + virtual uint64_t ordinal() const { return _ordinal; } private: - const coff_symbol *_symbol; - const coff_section *_section; StringRef _sectionName; - std::vector> _references; + Scope _scope; + ContentType _contentType; + ContentPermissions _permissions; uint64_t _ordinal; + std::vector> _references; }; // 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 data, - StringRef sectionName, uint64_t ordinal) - : COFFDefinedFileAtom(file, name, symbol, section, sectionName, ordinal), + COFFDefinedAtom(const File &file, StringRef name, StringRef sectionName, + Scope scope, ContentType type, ContentPermissions perms, + ArrayRef data, uint64_t ordinal) + : COFFDefinedFileAtom(file, name, sectionName, scope, type, perms, + ordinal), _dataref(data) {} virtual uint64_t size() const { return _dataref.size(); } @@ -233,13 +194,12 @@ private: // A COFFDefinedAtom represents an atom for BSS section. class COFFBSSAtom : public COFFDefinedFileAtom { public: - COFFBSSAtom(const File &file, StringRef name, const coff_symbol *symbol, - uint32_t size, uint64_t ordinal) - : COFFDefinedFileAtom(file, name, symbol, nullptr, "", ordinal), + COFFBSSAtom(const File &file, StringRef name, Scope scope, + ContentPermissions perms, uint32_t size, uint64_t ordinal) + : COFFDefinedFileAtom(file, name, "", scope, typeZeroFill, perms, + ordinal), _size(size) {} - virtual ContentPermissions permissions() const { return permRW_; } - virtual ContentType contentType() const { return typeZeroFill; } virtual Merge merge() const { return mergeNo; } virtual uint64_t size() const { return _size; } virtual ArrayRef rawContent() const { return _contents; } diff --git a/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp b/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp index c9cd43dd08a3..c48cc3d4346a 100644 --- a/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp +++ b/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp @@ -44,7 +44,40 @@ using llvm::object::coff_symbol; using namespace lld; -namespace { // anonymous +namespace { + +Atom::Scope getScope(const coff_symbol *symbol) { + switch (symbol->StorageClass) { + case llvm::COFF::IMAGE_SYM_CLASS_EXTERNAL: + return Atom::scopeGlobal; + case llvm::COFF::IMAGE_SYM_CLASS_STATIC: + case llvm::COFF::IMAGE_SYM_CLASS_LABEL: + return Atom::scopeTranslationUnit; + } + llvm_unreachable("Unknown scope"); +} + +DefinedAtom::ContentType getContentType(const coff_section *section) { + if (section->Characteristics & llvm::COFF::IMAGE_SCN_CNT_CODE) + return DefinedAtom::typeCode; + if (section->Characteristics & llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA) + return DefinedAtom::typeData; + if (section->Characteristics & llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) + return DefinedAtom::typeZeroFill; + return DefinedAtom::typeUnknown; +} + +DefinedAtom::ContentPermissions getPermissions(const coff_section *section) { + if (section->Characteristics & llvm::COFF::IMAGE_SCN_MEM_READ && + section->Characteristics & llvm::COFF::IMAGE_SCN_MEM_WRITE) + return DefinedAtom::permRW_; + if (section->Characteristics & llvm::COFF::IMAGE_SCN_MEM_READ && + section->Characteristics & llvm::COFF::IMAGE_SCN_MEM_EXECUTE) + return DefinedAtom::permR_X; + if (section->Characteristics & llvm::COFF::IMAGE_SCN_MEM_READ) + return DefinedAtom::permR__; + return DefinedAtom::perm___; +} class FileCOFF : public File { private: @@ -143,7 +176,9 @@ private: for (const coff_symbol *sym : symbols) { if (sym->SectionNumber != llvm::COFF::IMAGE_SYM_ABSOLUTE) continue; - auto *atom = new (_alloc) COFFAbsoluteAtom(*this, _symbolName[sym], sym); + auto *atom = new (_alloc) COFFAbsoluteAtom( + *this, _symbolName[sym], getScope(sym), sym->Value); + result.push_back(atom); _symbolAtom[sym] = atom; } @@ -177,7 +212,8 @@ private: sym->Value > 0) { StringRef name = _symbolName[sym]; uint32_t size = sym->Value; - auto *atom = new (_alloc) COFFBSSAtom(*this, name, sym, size, 0); + auto *atom = new (_alloc) COFFBSSAtom( + *this, name, getScope(sym), DefinedAtom::permRW_, size, 0); result.push_back(atom); continue; } @@ -242,7 +278,8 @@ private: ? section->SizeOfRawData - sym->Value : si[1]->Value - sym->Value; auto *atom = new (_alloc) COFFBSSAtom( - *this, _symbolName[sym], sym, size, ++ordinal); + *this, _symbolName[sym], getScope(sym), getPermissions(section), + size, ++ordinal); atoms.push_back(atom); _symbolAtom[sym] = atom; } @@ -265,11 +302,15 @@ private: if (section->Characteristics & llvm::COFF::IMAGE_SCN_LNK_REMOVE) return error_code::success(); + DefinedAtom::ContentType type = getContentType(section); + DefinedAtom::ContentPermissions perms = getPermissions(section); + // Create an atom for the entire section. if (symbols.empty()) { - ArrayRef Data(secData.data(), secData.size()); - auto *atom = new (_alloc) COFFDefinedAtom(*this, "", nullptr, section, - Data, sectionName, 0); + ArrayRef data(secData.data(), secData.size()); + auto *atom = new (_alloc) COFFDefinedAtom( + *this, "", sectionName, Atom::scopeTranslationUnit, type, perms, + data, 0); atoms.push_back(atom); _definedAtomLocations[section][0] = atom; return error_code::success(); @@ -281,7 +322,8 @@ private: uint64_t size = symbols[0]->Value; ArrayRef data(secData.data(), size); auto *atom = new (_alloc) COFFDefinedAtom( - *this, "", nullptr, section, data, sectionName, ++ordinal); + *this, "", sectionName, Atom::scopeTranslationUnit, type, perms, + data, ++ordinal); atoms.push_back(atom); _definedAtomLocations[section][0] = atom; } @@ -294,7 +336,8 @@ private: : secData.data() + (*(si + 1))->Value; ArrayRef data(start, end); auto *atom = new (_alloc) COFFDefinedAtom( - *this, _symbolName[*si], *si, section, data, sectionName, ++ordinal); + *this, _symbolName[*si], sectionName, getScope(*si), type, perms, + data, ++ordinal); atoms.push_back(atom); _symbolAtom[*si] = atom; _definedAtomLocations[section][(*si)->Value] = atom;