2019-01-10 22:28:24 +01:00
|
|
|
//===- Object.cpp ---------------------------------------------------------===//
|
|
|
|
//
|
2019-01-19 09:50:56 +01:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2019-01-10 22:28:24 +01:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "Object.h"
|
2019-01-19 20:42:35 +01:00
|
|
|
#include "llvm/ADT/DenseSet.h"
|
2019-01-10 22:28:24 +01:00
|
|
|
#include <algorithm>
|
|
|
|
|
|
|
|
namespace llvm {
|
|
|
|
namespace objcopy {
|
|
|
|
namespace coff {
|
|
|
|
|
|
|
|
using namespace object;
|
|
|
|
|
|
|
|
void Object::addSymbols(ArrayRef<Symbol> NewSymbols) {
|
|
|
|
for (Symbol S : NewSymbols) {
|
|
|
|
S.UniqueId = NextSymbolUniqueId++;
|
|
|
|
Symbols.emplace_back(S);
|
|
|
|
}
|
|
|
|
updateSymbols();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Object::updateSymbols() {
|
|
|
|
SymbolMap = DenseMap<size_t, Symbol *>(Symbols.size());
|
[llvm-objcopy] [COFF] Fix handling of aux symbols for big objects
The aux symbols were stored in an opaque std::vector<uint8_t>,
with contents interpreted according to the rest of the symbol.
All aux symbol types but one fit in 18 bytes (sizeof(coff_symbol16)),
and if written to a bigobj, two extra padding bytes are written (as
sizeof(coff_symbol32) is 20). In the storage agnostic intermediate
representation, store the aux symbols as a series of coff_symbol16
sized opaque blobs. (In practice, all such aux symbols only consist
of one aux symbol, so this is more flexible than what reality needs.)
The special case is the file aux symbols, which are written in
potentially more than one aux symbol slot, without any padding,
as one single long string. This can't be stored in the same opaque
vector of fixed sized aux symbol entries. The file aux symbols will
occupy a different number of aux symbol slots depending on the type
of output object file. As nothing in the intermediate process needs
to have accurate raw symbol indices, updating that is moved into the
writer class.
Differential Revision: https://reviews.llvm.org/D57009
llvm-svn: 351947
2019-01-23 12:54:51 +01:00
|
|
|
for (Symbol &Sym : Symbols)
|
2019-01-10 22:28:24 +01:00
|
|
|
SymbolMap[Sym.UniqueId] = &Sym;
|
|
|
|
}
|
|
|
|
|
|
|
|
const Symbol *Object::findSymbol(size_t UniqueId) const {
|
|
|
|
auto It = SymbolMap.find(UniqueId);
|
|
|
|
if (It == SymbolMap.end())
|
|
|
|
return nullptr;
|
|
|
|
return It->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Object::removeSymbols(function_ref<bool(const Symbol &)> ToRemove) {
|
|
|
|
Symbols.erase(
|
|
|
|
std::remove_if(std::begin(Symbols), std::end(Symbols),
|
|
|
|
[ToRemove](const Symbol &Sym) { return ToRemove(Sym); }),
|
|
|
|
std::end(Symbols));
|
|
|
|
updateSymbols();
|
|
|
|
}
|
|
|
|
|
|
|
|
Error Object::markSymbols() {
|
|
|
|
for (Symbol &Sym : Symbols)
|
|
|
|
Sym.Referenced = false;
|
|
|
|
for (const Section &Sec : Sections) {
|
|
|
|
for (const Relocation &R : Sec.Relocs) {
|
|
|
|
auto It = SymbolMap.find(R.Target);
|
|
|
|
if (It == SymbolMap.end())
|
2019-01-22 11:57:59 +01:00
|
|
|
return createStringError(object_error::invalid_symbol_index,
|
2019-05-22 15:23:26 +02:00
|
|
|
"relocation target %zu not found", R.Target);
|
2019-01-10 22:28:24 +01:00
|
|
|
It->second->Referenced = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Error::success();
|
|
|
|
}
|
|
|
|
|
2019-01-19 20:42:35 +01:00
|
|
|
void Object::addSections(ArrayRef<Section> NewSections) {
|
|
|
|
for (Section S : NewSections) {
|
|
|
|
S.UniqueId = NextSectionUniqueId++;
|
|
|
|
Sections.emplace_back(S);
|
|
|
|
}
|
|
|
|
updateSections();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Object::updateSections() {
|
|
|
|
SectionMap = DenseMap<ssize_t, Section *>(Sections.size());
|
|
|
|
size_t Index = 1;
|
|
|
|
for (Section &S : Sections) {
|
|
|
|
SectionMap[S.UniqueId] = &S;
|
|
|
|
S.Index = Index++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const Section *Object::findSection(ssize_t UniqueId) const {
|
|
|
|
auto It = SectionMap.find(UniqueId);
|
|
|
|
if (It == SectionMap.end())
|
|
|
|
return nullptr;
|
|
|
|
return It->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Object::removeSections(function_ref<bool(const Section &)> ToRemove) {
|
|
|
|
DenseSet<ssize_t> AssociatedSections;
|
|
|
|
auto RemoveAssociated = [&AssociatedSections](const Section &Sec) {
|
|
|
|
return AssociatedSections.count(Sec.UniqueId) == 1;
|
|
|
|
};
|
|
|
|
do {
|
|
|
|
DenseSet<ssize_t> RemovedSections;
|
|
|
|
Sections.erase(
|
|
|
|
std::remove_if(std::begin(Sections), std::end(Sections),
|
|
|
|
[ToRemove, &RemovedSections](const Section &Sec) {
|
|
|
|
bool Remove = ToRemove(Sec);
|
|
|
|
if (Remove)
|
|
|
|
RemovedSections.insert(Sec.UniqueId);
|
|
|
|
return Remove;
|
|
|
|
}),
|
|
|
|
std::end(Sections));
|
|
|
|
// Remove all symbols referring to the removed sections.
|
|
|
|
AssociatedSections.clear();
|
|
|
|
Symbols.erase(
|
|
|
|
std::remove_if(
|
|
|
|
std::begin(Symbols), std::end(Symbols),
|
|
|
|
[&RemovedSections, &AssociatedSections](const Symbol &Sym) {
|
|
|
|
// If there are sections that are associative to a removed
|
|
|
|
// section,
|
|
|
|
// remove those as well as nothing will include them (and we can't
|
|
|
|
// leave them dangling).
|
|
|
|
if (RemovedSections.count(Sym.AssociativeComdatTargetSectionId) ==
|
|
|
|
1)
|
|
|
|
AssociatedSections.insert(Sym.TargetSectionId);
|
|
|
|
return RemovedSections.count(Sym.TargetSectionId) == 1;
|
|
|
|
}),
|
|
|
|
std::end(Symbols));
|
|
|
|
ToRemove = RemoveAssociated;
|
|
|
|
} while (!AssociatedSections.empty());
|
|
|
|
updateSections();
|
|
|
|
updateSymbols();
|
|
|
|
}
|
|
|
|
|
2019-01-19 20:42:48 +01:00
|
|
|
void Object::truncateSections(function_ref<bool(const Section &)> ToTruncate) {
|
|
|
|
for (Section &Sec : Sections) {
|
|
|
|
if (ToTruncate(Sec)) {
|
2019-01-23 09:25:28 +01:00
|
|
|
Sec.clearContents();
|
2019-01-19 20:42:48 +01:00
|
|
|
Sec.Relocs.clear();
|
|
|
|
Sec.Header.SizeOfRawData = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-10 22:28:24 +01:00
|
|
|
} // end namespace coff
|
|
|
|
} // end namespace objcopy
|
|
|
|
} // end namespace llvm
|