[llvm-objcopy][MachO] Support indirect symbol table

Summary:
Parse the indirect symbol table and update the indexes of
symbol entries in the table in the writer in case they have
been changed.

Reviewers: alexshap, rupprecht, jhenderson

Reviewed By: alexshap, rupprecht

Subscribers: jakehehrlich, abrachet, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D66280
This commit is contained in:
Seiya Nuta 2019-10-30 15:12:17 +09:00
parent 358c2918d6
commit 1e589f67ef
No known key found for this signature in database
GPG Key ID: 82737BC094EC908C
4 changed files with 96 additions and 9 deletions

View File

@ -0,0 +1,64 @@
## Show that llvm-objcopy copies the indirect symbol table properly.
# RUN: llvm-mc -assemble -triple x86_64-apple-darwin9 -filetype=obj %s -o %t
# RUN: llvm-objcopy %t %t.copy
# RUN: llvm-readobj --symbols --macho-indirect-symbols %t.copy \
# RUN: | FileCheck %s
# __DATA,__nl_symbol_ptr
.non_lazy_symbol_pointer
bar:
.long 0
baz:
.long 0
.indirect_symbol bar
# __DATA,__la_symbol_ptr
.lazy_symbol_pointer
foo:
.long 0
.indirect_symbol foo
# CHECK: Symbols [
# CHECK-NEXT: Symbol {
# CHECK-NEXT: Name: bar (5)
# CHECK-NEXT: Type: Section (0xE)
# CHECK-NEXT: Section: __nl_symbol_ptr (0x2)
# CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
# CHECK-NEXT: Flags [ (0x0)
# CHECK-NEXT: ]
# CHECK-NEXT: Value: 0x0
# CHECK-NEXT: }
# CHECK-NEXT: Symbol {
# CHECK-NEXT: Name: baz (1)
# CHECK-NEXT: Type: Section (0xE)
# CHECK-NEXT: Section: __nl_symbol_ptr (0x2)
# CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
# CHECK-NEXT: Flags [ (0x0)
# CHECK-NEXT: ]
# CHECK-NEXT: Value: 0x4
# CHECK-NEXT: }
# CHECK-NEXT: Symbol {
# CHECK-NEXT: Name: foo (9)
# CHECK-NEXT: Type: Section (0xE)
# CHECK-NEXT: Section: __la_symbol_ptr (0x3)
# CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
# CHECK-NEXT: Flags [ (0x0)
# CHECK-NEXT: ]
# CHECK-NEXT: Value: 0x8
# CHECK-NEXT: }
# CHECK-NEXT: ]
# CHECK-NEXT: Indirect Symbols {
# CHECK-NEXT: Number: 2
# CHECK-NEXT: Symbols [
# CHECK-NEXT: Entry {
# CHECK-NEXT: Entry Index: 0
# CHECK-NEXT: Symbol Index: 0x80000000
# CHECK-NEXT: }
# CHECK-NEXT: Entry {
# CHECK-NEXT: Entry Index: 1
# CHECK-NEXT: Symbol Index: 0x2
# CHECK-NEXT: }
# CHECK-NEXT: ]
# CHECK-NEXT: }

View File

@ -256,9 +256,16 @@ void MachOReader::readFunctionStartsData(Object &O) const {
void MachOReader::readIndirectSymbolTable(Object &O) const {
MachO::dysymtab_command DySymTab = MachOObj.getDysymtabLoadCommand();
for (uint32_t i = 0; i < DySymTab.nindirectsyms; ++i)
O.IndirectSymTable.Symbols.push_back(
MachOObj.getIndirectSymbolTableEntry(DySymTab, i));
constexpr uint32_t AbsOrLocalMask =
MachO::INDIRECT_SYMBOL_LOCAL | MachO::INDIRECT_SYMBOL_ABS;
for (uint32_t i = 0; i < DySymTab.nindirectsyms; ++i) {
uint32_t Index = MachOObj.getIndirectSymbolTableEntry(DySymTab, i);
if ((Index & AbsOrLocalMask) != 0)
O.IndirectSymTable.Symbols.emplace_back(Index, None);
else
O.IndirectSymTable.Symbols.emplace_back(
Index, O.SymTable.getSymbolByIndex(Index));
}
}
std::unique_ptr<Object> MachOReader::create() const {

View File

@ -369,11 +369,14 @@ void MachOWriter::writeIndirectSymbolTable() {
O.LoadCommands[*O.DySymTabCommandIndex]
.MachOLoadCommand.dysymtab_command_data;
char *Out = (char *)B.getBufferStart() + DySymTabCommand.indirectsymoff;
assert((DySymTabCommand.nindirectsyms == O.IndirectSymTable.Symbols.size()) &&
"Incorrect indirect symbol table size");
memcpy(Out, O.IndirectSymTable.Symbols.data(),
sizeof(uint32_t) * O.IndirectSymTable.Symbols.size());
uint32_t *Out =
(uint32_t *)(B.getBufferStart() + DySymTabCommand.indirectsymoff);
for (const IndirectSymbolEntry &Sym : O.IndirectSymTable.Symbols) {
uint32_t Entry = (Sym.Symbol) ? (*Sym.Symbol)->Index : Sym.OriginalIndex;
if (IsLittleEndian != sys::IsLittleEndianHost)
sys::swapByteOrder(Entry);
*Out++ = Entry;
}
}
void MachOWriter::writeDataInCodeData() {

View File

@ -112,8 +112,21 @@ struct SymbolTable {
const SymbolEntry *getSymbolByIndex(uint32_t Index) const;
};
struct IndirectSymbolEntry {
// The original value in an indirect symbol table. Higher bits encode extra
// information (INDIRECT_SYMBOL_LOCAL and INDIRECT_SYMBOL_ABS).
uint32_t OriginalIndex;
/// The Symbol referenced by this entry. It's None if the index is
/// INDIRECT_SYMBOL_LOCAL or INDIRECT_SYMBOL_ABS.
Optional<const SymbolEntry *> Symbol;
IndirectSymbolEntry(uint32_t OriginalIndex,
Optional<const SymbolEntry *> Symbol)
: OriginalIndex(OriginalIndex), Symbol(Symbol) {}
};
struct IndirectSymbolTable {
std::vector<uint32_t> Symbols;
std::vector<IndirectSymbolEntry> Symbols;
};
/// The location of the string table inside the binary is described by LC_SYMTAB