diff options
-rw-r--r-- | llvm/test/tools/llvm-objcopy/MachO/indirect-symbol-table-copy.s | 64 | ||||
-rw-r--r-- | llvm/tools/llvm-objcopy/MachO/MachOReader.cpp | 13 | ||||
-rw-r--r-- | llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp | 13 | ||||
-rw-r--r-- | llvm/tools/llvm-objcopy/MachO/Object.h | 15 |
4 files changed, 96 insertions, 9 deletions
diff --git a/llvm/test/tools/llvm-objcopy/MachO/indirect-symbol-table-copy.s b/llvm/test/tools/llvm-objcopy/MachO/indirect-symbol-table-copy.s new file mode 100644 index 00000000000..e1a0b1836a0 --- /dev/null +++ b/llvm/test/tools/llvm-objcopy/MachO/indirect-symbol-table-copy.s @@ -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: } diff --git a/llvm/tools/llvm-objcopy/MachO/MachOReader.cpp b/llvm/tools/llvm-objcopy/MachO/MachOReader.cpp index ed2b3eb3aad..7e2ebdc46b3 100644 --- a/llvm/tools/llvm-objcopy/MachO/MachOReader.cpp +++ b/llvm/tools/llvm-objcopy/MachO/MachOReader.cpp @@ -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 { diff --git a/llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp b/llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp index 4ec91cc9eb7..59d57f7f2db 100644 --- a/llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp +++ b/llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp @@ -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() { diff --git a/llvm/tools/llvm-objcopy/MachO/Object.h b/llvm/tools/llvm-objcopy/MachO/Object.h index 36b0f7eb96d..bf802531a4f 100644 --- a/llvm/tools/llvm-objcopy/MachO/Object.h +++ b/llvm/tools/llvm-objcopy/MachO/Object.h @@ -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 |