summaryrefslogtreecommitdiffstats
path: root/llvm/tools/llvm-objcopy
diff options
context:
space:
mode:
authorMartin Storsjo <martin@martin.st>2019-01-22 10:58:09 +0000
committerMartin Storsjo <martin@martin.st>2019-01-22 10:58:09 +0000
commit9ec18a37187cbe31a0e7d012b7e8193f293a1b67 (patch)
tree1b42eaef22e1d8f5ac074fd904ed133549334f87 /llvm/tools/llvm-objcopy
parent8010c6beaf638653cb73d8db18c1d9784be5a0de (diff)
downloadbcm5719-llvm-9ec18a37187cbe31a0e7d012b7e8193f293a1b67.tar.gz
bcm5719-llvm-9ec18a37187cbe31a0e7d012b7e8193f293a1b67.zip
[llvm-objcopy] [COFF] Update symbol indices in weak externals
Differential Revision: https://reviews.llvm.org/D57006 llvm-svn: 351800
Diffstat (limited to 'llvm/tools/llvm-objcopy')
-rw-r--r--llvm/tools/llvm-objcopy/COFF/Object.h2
-rw-r--r--llvm/tools/llvm-objcopy/COFF/Reader.cpp24
-rw-r--r--llvm/tools/llvm-objcopy/COFF/Reader.h2
-rw-r--r--llvm/tools/llvm-objcopy/COFF/Writer.cpp16
-rw-r--r--llvm/tools/llvm-objcopy/COFF/Writer.h2
5 files changed, 40 insertions, 6 deletions
diff --git a/llvm/tools/llvm-objcopy/COFF/Object.h b/llvm/tools/llvm-objcopy/COFF/Object.h
index 8e200369f0b..0630f9c5ff8 100644
--- a/llvm/tools/llvm-objcopy/COFF/Object.h
+++ b/llvm/tools/llvm-objcopy/COFF/Object.h
@@ -11,6 +11,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/BinaryFormat/COFF.h"
@@ -47,6 +48,7 @@ struct Symbol {
std::vector<uint8_t> AuxData;
ssize_t TargetSectionId;
ssize_t AssociativeComdatTargetSectionId = 0;
+ Optional<size_t> WeakTargetSymbolId;
size_t UniqueId;
size_t RawIndex;
bool Referenced;
diff --git a/llvm/tools/llvm-objcopy/COFF/Reader.cpp b/llvm/tools/llvm-objcopy/COFF/Reader.cpp
index 20ff32a59dc..2446277cc2b 100644
--- a/llvm/tools/llvm-objcopy/COFF/Reader.cpp
+++ b/llvm/tools/llvm-objcopy/COFF/Reader.cpp
@@ -121,12 +121,18 @@ Error COFFReader::readSymbols(Object &Obj, bool IsBigObj) const {
// For section definitions, check if it is comdat associative, and if
// it is, find the target section unique id.
const coff_aux_section_definition *SD = SymRef.getSectionDefinition();
+ const coff_aux_weak_external *WE = SymRef.getWeakExternal();
if (SD && SD->Selection == IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
int32_t Index = SD->getNumber(IsBigObj);
if (Index <= 0 || static_cast<uint32_t>(Index - 1) >= Sections.size())
return createStringError(object_error::parse_failed,
"Unexpected associative section index");
Sym.AssociativeComdatTargetSectionId = Sections[Index - 1].UniqueId;
+ } else if (WE) {
+ // This is a raw symbol index for now, but store it in the Symbol
+ // until we've added them to the Object, which assigns the final
+ // unique ids.
+ Sym.WeakTargetSymbolId = WE->TagIndex;
}
I += 1 + SymRef.getNumberOfAuxSymbols();
}
@@ -134,13 +140,27 @@ Error COFFReader::readSymbols(Object &Obj, bool IsBigObj) const {
return Error::success();
}
-Error COFFReader::setRelocTargets(Object &Obj) const {
+Error COFFReader::setSymbolTargets(Object &Obj) const {
std::vector<const Symbol *> RawSymbolTable;
for (const Symbol &Sym : Obj.getSymbols()) {
RawSymbolTable.push_back(&Sym);
for (size_t I = 0; I < Sym.Sym.NumberOfAuxSymbols; I++)
RawSymbolTable.push_back(nullptr);
}
+ for (Symbol &Sym : Obj.getMutableSymbols()) {
+ // Convert WeakTargetSymbolId from the original raw symbol index to
+ // a proper unique id.
+ if (Sym.WeakTargetSymbolId) {
+ if (*Sym.WeakTargetSymbolId >= RawSymbolTable.size())
+ return createStringError(object_error::parse_failed,
+ "Weak external reference out of range");
+ const Symbol *Target = RawSymbolTable[*Sym.WeakTargetSymbolId];
+ if (Target == nullptr)
+ return createStringError(object_error::parse_failed,
+ "Invalid SymbolTableIndex");
+ Sym.WeakTargetSymbolId = Target->UniqueId;
+ }
+ }
for (Section &Sec : Obj.getMutableSections()) {
for (Relocation &R : Sec.Relocs) {
if (R.Reloc.SymbolTableIndex >= RawSymbolTable.size())
@@ -184,7 +204,7 @@ Expected<std::unique_ptr<Object>> COFFReader::create() const {
return std::move(E);
if (Error E = readSymbols(*Obj, IsBigObj))
return std::move(E);
- if (Error E = setRelocTargets(*Obj))
+ if (Error E = setSymbolTargets(*Obj))
return std::move(E);
return std::move(Obj);
diff --git a/llvm/tools/llvm-objcopy/COFF/Reader.h b/llvm/tools/llvm-objcopy/COFF/Reader.h
index 4493705e73c..ec15369db0b 100644
--- a/llvm/tools/llvm-objcopy/COFF/Reader.h
+++ b/llvm/tools/llvm-objcopy/COFF/Reader.h
@@ -28,7 +28,7 @@ class COFFReader {
Error readExecutableHeaders(Object &Obj) const;
Error readSections(Object &Obj) const;
Error readSymbols(Object &Obj, bool IsBigObj) const;
- Error setRelocTargets(Object &Obj) const;
+ Error setSymbolTargets(Object &Obj) const;
public:
explicit COFFReader(const COFFObjectFile &O) : COFFObj(O) {}
diff --git a/llvm/tools/llvm-objcopy/COFF/Writer.cpp b/llvm/tools/llvm-objcopy/COFF/Writer.cpp
index 0321f94a896..4f57131d5ab 100644
--- a/llvm/tools/llvm-objcopy/COFF/Writer.cpp
+++ b/llvm/tools/llvm-objcopy/COFF/Writer.cpp
@@ -38,7 +38,7 @@ Error COFFWriter::finalizeRelocTargets() {
return Error::success();
}
-Error COFFWriter::finalizeSectionNumbers() {
+Error COFFWriter::finalizeSymbolContents() {
for (Symbol &Sym : Obj.getMutableSymbols()) {
if (Sym.TargetSectionId <= 0) {
// Undefined, or a special kind of symbol. These negative values
@@ -75,6 +75,18 @@ Error COFFWriter::finalizeSectionNumbers() {
SD->NumberHighPart = static_cast<uint16_t>(SDSectionNumber >> 16);
}
}
+ // Check that we actually have got AuxData to match the weak symbol target
+ // we want to set. Only >= 1 would be required, but only == 1 makes sense.
+ if (Sym.WeakTargetSymbolId && Sym.Sym.NumberOfAuxSymbols == 1) {
+ coff_aux_weak_external *WE =
+ reinterpret_cast<coff_aux_weak_external *>(Sym.AuxData.data());
+ const Symbol *Target = Obj.findSymbol(*Sym.WeakTargetSymbolId);
+ if (Target == nullptr)
+ return createStringError(object_error::invalid_symbol_index,
+ "Symbol '%s' is missing its weak target",
+ Sym.Name.str().c_str());
+ WE->TagIndex = Target->RawIndex;
+ }
}
return Error::success();
}
@@ -137,7 +149,7 @@ std::pair<size_t, size_t> COFFWriter::finalizeSymbolTable() {
Error COFFWriter::finalize(bool IsBigObj) {
if (Error E = finalizeRelocTargets())
return E;
- if (Error E = finalizeSectionNumbers())
+ if (Error E = finalizeSymbolContents())
return E;
size_t SizeOfHeaders = 0;
diff --git a/llvm/tools/llvm-objcopy/COFF/Writer.h b/llvm/tools/llvm-objcopy/COFF/Writer.h
index a967a103df9..9b1cfa91d00 100644
--- a/llvm/tools/llvm-objcopy/COFF/Writer.h
+++ b/llvm/tools/llvm-objcopy/COFF/Writer.h
@@ -31,7 +31,7 @@ class COFFWriter {
StringTableBuilder StrTabBuilder;
Error finalizeRelocTargets();
- Error finalizeSectionNumbers();
+ Error finalizeSymbolContents();
void layoutSections();
size_t finalizeStringTable();
template <class SymbolTy> std::pair<size_t, size_t> finalizeSymbolTable();
OpenPOWER on IntegriCloud