std::vector<ArchiveFile *> elf::archiveFiles;
std::vector<BinaryFile *> elf::binaryFiles;
std::vector<BitcodeFile *> elf::bitcodeFiles;
-std::vector<LazyObjFile *> elf::lazyObjFiles;
+std::vector<BitcodeFile *> elf::lazyBitcodeFiles;
std::vector<ELFFileBase *> elf::objectFiles;
std::vector<SharedFile *> elf::sharedFiles;
}
// Lazy object file
- if (auto *f = dyn_cast<LazyObjFile>(file)) {
- lazyObjFiles.push_back(f);
- f->parse<ELFT>();
+ if (file->lazy) {
+ if (auto *f = dyn_cast<BitcodeFile>(file)) {
+ lazyBitcodeFiles.push_back(f);
+ f->parseLazy();
+ } else {
+ cast<ObjFile<ELFT>>(file)->parseLazy();
+ }
return;
}
// defined symbol in a .eh_frame becomes dangling symbols.
if (sec == &InputSection::discarded) {
Undefined und{this, name, binding, stOther, type, secIdx};
- // !ArchiveFile::parsed or LazyObjFile::extracted means that the file
+ // !ArchiveFile::parsed or !LazyObjFile::lazy means that the file
// containing this object has not finished processing, i.e. this symbol is
// a result of a lazy symbol extract. We should demote the lazy symbol to
// an Undefined so that any relocations outside of the group to it will
// trigger a discarded section error.
if ((sym->symbolKind == Symbol::LazyArchiveKind &&
!cast<ArchiveFile>(sym->file)->parsed) ||
- (sym->symbolKind == Symbol::LazyObjectKind &&
- cast<LazyObjFile>(sym->file)->extracted)) {
+ (sym->symbolKind == Symbol::LazyObjectKind && !sym->file->lazy)) {
sym->replace(und);
// Prevent LTO from internalizing the symbol in case there is a
// reference to this symbol from this file.
}
BitcodeFile::BitcodeFile(MemoryBufferRef mb, StringRef archiveName,
- uint64_t offsetInArchive)
+ uint64_t offsetInArchive, bool lazy)
: InputFile(BitcodeKind, mb) {
this->archiveName = archiveName;
+ this->lazy = lazy;
std::string path = mb.getBufferIdentifier().str();
if (config->thinLTOIndexOnly)
addDependentLibrary(l, this);
}
+void BitcodeFile::parseLazy() {
+ for (const lto::InputFile::Symbol &sym : obj->symbols())
+ if (!sym.isUndefined())
+ symtab->addSymbol(LazyObject{*this, saver.save(sym.getName())});
+}
+
void BinaryFile::parse() {
ArrayRef<uint8_t> data = arrayRefFromStringRef(mb.getBuffer());
auto *section = make<InputSection>(this, SHF_ALLOC | SHF_WRITE, SHT_PROGBITS,
InputFile *elf::createObjectFile(MemoryBufferRef mb, StringRef archiveName,
uint64_t offsetInArchive) {
if (isBitcode(mb))
- return make<BitcodeFile>(mb, archiveName, offsetInArchive);
+ return make<BitcodeFile>(mb, archiveName, offsetInArchive, /*lazy=*/false);
switch (getELFKind(mb, archiveName)) {
case ELF32LEKind:
}
}
-void LazyObjFile::extract() {
- if (extracted)
- return;
- extracted = true;
-
- InputFile *file = createObjectFile(mb, archiveName, offsetInArchive);
- file->groupId = groupId;
-
- // Copy symbol vector so that the new InputFile doesn't have to
- // insert the same defined symbols to the symbol table again.
- file->symbols = std::move(symbols);
+InputFile *elf::createLazyFile(MemoryBufferRef mb, StringRef archiveName,
+ uint64_t offsetInArchive) {
+ if (isBitcode(mb))
+ return make<BitcodeFile>(mb, archiveName, offsetInArchive, /*lazy=*/true);
- parseFile(file);
+ auto *file =
+ cast<ELFFileBase>(createObjectFile(mb, archiveName, offsetInArchive));
+ file->lazy = true;
+ return file;
}
-template <class ELFT> void LazyObjFile::parse() {
+template <class ELFT> void ObjFile<ELFT>::parseLazy() {
using Elf_Sym = typename ELFT::Sym;
- // A lazy object file wraps either a bitcode file or an ELF file.
- if (isBitcode(this->mb)) {
- std::unique_ptr<lto::InputFile> obj =
- CHECK(lto::InputFile::create(this->mb), this);
- for (const lto::InputFile::Symbol &sym : obj->symbols()) {
- if (sym.isUndefined())
- continue;
- symtab->addSymbol(LazyObject{*this, saver.save(sym.getName())});
- }
- return;
- }
-
- if (getELFKind(this->mb, archiveName) != config->ekind) {
- error("incompatible file: " + this->mb.getBufferIdentifier());
- return;
- }
-
// Find a symbol table.
ELFFile<ELFT> obj = check(ELFFile<ELFT>::create(mb.getBuffer()));
ArrayRef<typename ELFT::Shdr> sections = CHECK(obj.sections(), this);
continue;
sym->resolve(LazyObject{*this, sym->getName()});
- // If extracted, stop iterating because this->symbols has been transferred
- // to the instantiated ObjFile.
- if (extracted)
+ // If extracted, stop iterating because the symbol resolution has been
+ // done by ObjFile::parse.
+ if (!lazy)
return;
}
return;
}
}
-bool LazyObjFile::shouldExtractForCommon(const StringRef &name) {
+bool InputFile::shouldExtractForCommon(StringRef name) {
if (isBitcode(mb))
return isBitcodeNonCommonDef(mb, name, archiveName);
template void BitcodeFile::parse<ELF64LE>();
template void BitcodeFile::parse<ELF64BE>();
-template void LazyObjFile::parse<ELF32LE>();
-template void LazyObjFile::parse<ELF32BE>();
-template void LazyObjFile::parse<ELF64LE>();
-template void LazyObjFile::parse<ELF64BE>();
-
template class elf::ObjFile<ELF32LE>;
template class elf::ObjFile<ELF32BE>;
template class elf::ObjFile<ELF64LE>;
// Get filename to use for linker script processing.
StringRef getNameForScript() const;
+ // Check if a non-common symbol should be extracted to override a common
+ // definition.
+ bool shouldExtractForCommon(StringRef name);
+
// If not empty, this stores the name of the archive containing this file.
// We use this string for creating error messages.
SmallString<0> archiveName;
ELFKind ekind = ELFNoneKind;
uint8_t osabi = 0;
uint8_t abiVersion = 0;
+
+ // True if this is a relocatable object file/bitcode file between --start-lib
+ // and --end-lib.
+ bool lazy = false;
+
// True if this is an argument for --just-symbols. Usually false.
bool justSymbols = false;
}
void parse(bool ignoreComdats = false);
+ void parseLazy();
StringRef getShtGroupSignature(ArrayRef<Elf_Shdr> sections,
const Elf_Shdr &sec);
llvm::once_flag initDwarf;
};
-// LazyObjFile is analogous to ArchiveFile in the sense that
-// the file contains lazy symbols. The difference is that
-// LazyObjFile wraps a single file instead of multiple files.
-//
-// This class is used for --start-lib and --end-lib options which
-// instruct the linker to link object files between them with the
-// archive file semantics.
-class LazyObjFile : public InputFile {
-public:
- LazyObjFile(MemoryBufferRef m, StringRef archiveName,
- uint64_t offsetInArchive)
- : InputFile(LazyObjKind, m), offsetInArchive(offsetInArchive) {
- this->archiveName = archiveName;
- }
-
- static bool classof(const InputFile *f) { return f->kind() == LazyObjKind; }
-
- template <class ELFT> void parse();
- void extract();
-
- // Check if a non-common symbol should be extracted to override a common
- // definition.
- bool shouldExtractForCommon(const StringRef &name);
-
- bool extracted = false;
-
-private:
- uint64_t offsetInArchive;
-};
-
// An ArchiveFile object represents a .a file.
class ArchiveFile : public InputFile {
public:
class BitcodeFile : public InputFile {
public:
BitcodeFile(MemoryBufferRef m, StringRef archiveName,
- uint64_t offsetInArchive);
+ uint64_t offsetInArchive, bool lazy);
static bool classof(const InputFile *f) { return f->kind() == BitcodeKind; }
template <class ELFT> void parse();
+ void parseLazy();
std::unique_ptr<llvm::lto::InputFile> obj;
};
InputFile *createObjectFile(MemoryBufferRef mb, StringRef archiveName = "",
uint64_t offsetInArchive = 0);
+InputFile *createLazyFile(MemoryBufferRef mb, StringRef archiveName,
+ uint64_t offsetInArchive);
inline bool isBitcode(MemoryBufferRef mb) {
return identify_magic(mb.getBuffer()) == llvm::file_magic::bitcode;
extern std::vector<ArchiveFile *> archiveFiles;
extern std::vector<BinaryFile *> binaryFiles;
extern std::vector<BitcodeFile *> bitcodeFiles;
-extern std::vector<LazyObjFile *> lazyObjFiles;
+extern std::vector<BitcodeFile *> lazyBitcodeFiles;
extern std::vector<ELFFileBase *> objectFiles;
extern std::vector<SharedFile *> sharedFiles;