Skip to content

Commit

Permalink
[llvm-objcopy] [COFF] Update symbol indices in weak externals
Browse files Browse the repository at this point in the history
Differential Revision: https://reviews.llvm.org/D57006

llvm-svn: 351800
  • Loading branch information
mstorsjo committed Jan 22, 2019
1 parent 8010c6b commit 9ec18a3
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 6 deletions.
49 changes: 49 additions & 0 deletions llvm/test/tools/llvm-objcopy/COFF/weak-external.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# RUN: yaml2obj %s > %t.in.o

# RUN: llvm-objdump -t %t.in.o | FileCheck %s --check-prefixes=SYMBOLS,SYMBOLS-PRE

# RUN: llvm-objcopy -N func %t.in.o %t.out.o
# RUN: llvm-objdump -t %t.out.o | FileCheck %s --check-prefixes=SYMBOLS,SYMBOLS-POST

# RUN: not llvm-objcopy -N .weak.foobar.file1 %t.in.o %t.err.o 2>&1 | FileCheck %s --check-prefix=ERROR

# SYMBOLS: SYMBOL TABLE:
# SYMBOLS-PRE-NEXT: func
# SYMBOLS-NEXT: .weak.foobar.file1
# SYMBOLS-NEXT: foobar
# SYMBOLS-PRE-NEXT: AUX indx 1
# SYMBOLS-POST-NEXT: AUX indx 0
# SYMBOLS-EMPTY:

# ERROR: Symbol 'foobar' is missing its weak target

--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: [ ]
sections:
- Name: .text
Characteristics: [ ]
symbols:
- Name: func
Value: 0
SectionNumber: 1
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- Name: .weak.foobar.file1
Value: 1
SectionNumber: 1
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- Name: foobar
Value: 0
SectionNumber: 0
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_FUNCTION
StorageClass: IMAGE_SYM_CLASS_WEAK_EXTERNAL
WeakExternal:
TagIndex: 1
Characteristics: IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY
...
2 changes: 2 additions & 0 deletions llvm/tools/llvm-objcopy/COFF/Object.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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;
Expand Down
24 changes: 22 additions & 2 deletions llvm/tools/llvm-objcopy/COFF/Reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,26 +121,46 @@ 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();
}
Obj.addSymbols(Symbols);
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())
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion llvm/tools/llvm-objcopy/COFF/Reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) {}
Expand Down
16 changes: 14 additions & 2 deletions llvm/tools/llvm-objcopy/COFF/Writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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();
}
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion llvm/tools/llvm-objcopy/COFF/Writer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down

0 comments on commit 9ec18a3

Please sign in to comment.