COFF supports a feature similar to ELF's section groups. This patch implements it. In ELF, section groups are identified by their names, and they are treated somewhat differently from regular symbols. In COFF, the feature is realized in a more straightforward way. A section can have an annotation saying "if Nth section is linked, link this section too." Implementing such feature is easy. We can add a reference from a target atom to an original atom, so that if the target is linked, the original atom is also linked. If not linked, both will be dead-stripped. So they are treated as a group. I added a new reference type, kindAssociate. It does nothing except preventing referenced atoms from being dead-stripped. No change to the Resolver is needed. Reviewers: Bigcheese, shankarke, atanasyan Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D3946 llvm-svn: 210240
116 lines
3.7 KiB
C++
116 lines
3.7 KiB
C++
//===- lib/ReaderWriter/Reader.cpp ----------------------------------------===//
|
|
//
|
|
// The LLVM Linker
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "lld/ReaderWriter/Reader.h"
|
|
|
|
#include "llvm/ADT/StringRef.h"
|
|
#include "llvm/Support/FileUtilities.h"
|
|
#include "llvm/Support/MemoryBuffer.h"
|
|
#include "llvm/Support/Path.h"
|
|
#include "llvm/Support/system_error.h"
|
|
|
|
#include <memory>
|
|
|
|
namespace lld {
|
|
|
|
YamlIOTaggedDocumentHandler::~YamlIOTaggedDocumentHandler() {}
|
|
|
|
void Registry::add(std::unique_ptr<Reader> reader) {
|
|
_readers.push_back(std::move(reader));
|
|
}
|
|
|
|
void Registry::add(std::unique_ptr<YamlIOTaggedDocumentHandler> handler) {
|
|
_yamlHandlers.push_back(std::move(handler));
|
|
}
|
|
|
|
error_code
|
|
Registry::parseFile(std::unique_ptr<MemoryBuffer> &mb,
|
|
std::vector<std::unique_ptr<File>> &result) const {
|
|
// Get file type.
|
|
StringRef content(mb->getBufferStart(), mb->getBufferSize());
|
|
llvm::sys::fs::file_magic fileType = llvm::sys::fs::identify_magic(content);
|
|
// Get file extension.
|
|
StringRef extension = llvm::sys::path::extension(mb->getBufferIdentifier());
|
|
|
|
// Ask each registered reader if it can handle this file type or extension.
|
|
for (const std::unique_ptr<Reader> &reader : _readers)
|
|
if (reader->canParse(fileType, extension, *mb))
|
|
return reader->parseFile(mb, *this, result);
|
|
|
|
// No Reader could parse this file.
|
|
return llvm::make_error_code(llvm::errc::executable_format_error);
|
|
}
|
|
|
|
static const Registry::KindStrings kindStrings[] = {
|
|
{Reference::kindInGroup, "in-group"},
|
|
{Reference::kindLayoutAfter, "layout-after"},
|
|
{Reference::kindLayoutBefore, "layout-before"},
|
|
{Reference::kindGroupChild, "group-child"},
|
|
{Reference::kindAssociate, "associate"},
|
|
LLD_KIND_STRING_END};
|
|
|
|
Registry::Registry() {
|
|
addKindTable(Reference::KindNamespace::all, Reference::KindArch::all,
|
|
kindStrings);
|
|
}
|
|
|
|
bool Registry::handleTaggedDoc(llvm::yaml::IO &io,
|
|
const lld::File *&file) const {
|
|
for (const std::unique_ptr<YamlIOTaggedDocumentHandler> &h : _yamlHandlers)
|
|
if (h->handledDocTag(io, file))
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
|
|
void Registry::addKindTable(Reference::KindNamespace ns,
|
|
Reference::KindArch arch,
|
|
const KindStrings array[]) {
|
|
KindEntry entry = { ns, arch, array };
|
|
_kindEntries.push_back(entry);
|
|
}
|
|
|
|
bool Registry::referenceKindFromString(StringRef inputStr,
|
|
Reference::KindNamespace &ns,
|
|
Reference::KindArch &arch,
|
|
Reference::KindValue &value) const {
|
|
for (const KindEntry &entry : _kindEntries) {
|
|
for (const KindStrings *pair = entry.array; !pair->name.empty(); ++pair) {
|
|
if (!inputStr.equals(pair->name))
|
|
continue;
|
|
ns = entry.ns;
|
|
arch = entry.arch;
|
|
value = pair->value;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Registry::referenceKindToString(Reference::KindNamespace ns,
|
|
Reference::KindArch arch,
|
|
Reference::KindValue value,
|
|
StringRef &str) const {
|
|
for (const KindEntry &entry : _kindEntries) {
|
|
if (entry.ns != ns)
|
|
continue;
|
|
if (entry.arch != arch)
|
|
continue;
|
|
for (const KindStrings *pair = entry.array; !pair->name.empty(); ++pair) {
|
|
if (pair->value != value)
|
|
continue;
|
|
str = pair->name;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
} // end namespace lld
|