diff --git a/llvm/test/tools/llvm-objdump/X86/macho-cstring-dump.test b/llvm/test/tools/llvm-objdump/X86/macho-cstring-dump.test index 869462da233c..3dfa4e34b262 100644 --- a/llvm/test/tools/llvm-objdump/X86/macho-cstring-dump.test +++ b/llvm/test/tools/llvm-objdump/X86/macho-cstring-dump.test @@ -1,4 +1,4 @@ RUN: llvm-objdump -m -section __TEXT,__cstring %p/Inputs/hello.obj.macho-x86_64 | FileCheck %s CHECK: Contents of (__TEXT,__cstring) section -CHECK: 0x000000000000003b Hello world\n +CHECK: 000000000000003b Hello world\n diff --git a/llvm/test/tools/llvm-objdump/X86/macho-literal-pointers-i386.test b/llvm/test/tools/llvm-objdump/X86/macho-literal-pointers-i386.test new file mode 100644 index 000000000000..0069668c9909 --- /dev/null +++ b/llvm/test/tools/llvm-objdump/X86/macho-literal-pointers-i386.test @@ -0,0 +1,34 @@ +# RUN: llvm-mc < %s -triple i386-apple-darwin -filetype=obj | llvm-objdump -m -section __DATA,__litp - | FileCheck %s + +.cstring +L1: .asciz "Hello world\n" + +.literal4 +.align 2 +L2: .float 4.0 + +.literal8 +.align 3 +L3: .double 8.0 + +.literal16 +.align 4 +L4: .long 0x10000016, 0x20000016, 0x30000016, 0x40000016 + +.const +L5: .asciz "const non-literal string" + +.section __DATA,__litp, literal_pointers +.align 2 +.long L1 +.long L2 +.long L3 +.long L4 +.long L5 + +# CHECK: Contents of (__DATA,__litp) section +# CHECK: 0000004c __TEXT:__cstring:Hello world\n +# CHECK: 00000050 __TEXT:__literal4:0x40800000 +# CHECK: 00000054 __TEXT:__literal8:0x00000000 0x40200000 +# CHECK: 00000058 __TEXT:__literal16:0x10000016 0x20000016 0x30000016 0x40000016 +# CHECK: 0000005c 0x30 (not in a literal section) diff --git a/llvm/test/tools/llvm-objdump/X86/macho-literal-pointers-x86_64.test b/llvm/test/tools/llvm-objdump/X86/macho-literal-pointers-x86_64.test new file mode 100644 index 000000000000..b403b8154de3 --- /dev/null +++ b/llvm/test/tools/llvm-objdump/X86/macho-literal-pointers-x86_64.test @@ -0,0 +1,34 @@ +# RUN: llvm-mc < %s -triple x86_64-apple-darwin -filetype=obj | llvm-objdump -m -section __DATA,__litp - | FileCheck %s + +.cstring +L1: .asciz "Hello world\n" + +.literal4 +.align 2 +L2: .float 4.0 + +.literal8 +.align 3 +L3: .double 8.0 + +.literal16 +.align 4 +L4: .long 0x10000016, 0x20000016, 0x30000016, 0x40000016 + +.const +L5: .asciz "const non-literal string" + +.section __DATA,__litp, literal_pointers +.align 3 +.quad L1 +.quad L2 +.quad L3 +.quad L4 +.quad L5 + +# CHECK: Contents of (__DATA,__litp) section +# CHECK: 0000000000000050 __TEXT:__cstring:Hello world\n +# CHECK: 0000000000000058 __TEXT:__literal4:0x40800000 +# CHECK: 0000000000000060 __TEXT:__literal8:0x00000000 0x40200000 +# CHECK: 0000000000000068 __TEXT:__literal16:0x10000016 0x20000016 0x30000016 0x40000016 +# CHECK: 0000000000000070 0x30 (not in a literal section) diff --git a/llvm/test/tools/llvm-objdump/X86/macho-literals.test b/llvm/test/tools/llvm-objdump/X86/macho-literals.test index 2acac7d43b64..4824453a9767 100644 --- a/llvm/test/tools/llvm-objdump/X86/macho-literals.test +++ b/llvm/test/tools/llvm-objdump/X86/macho-literals.test @@ -11,12 +11,12 @@ .long 0x7f800001 # CHECK-LIT4: Contents of (__TEXT,__literal4) section -# CHECK-LIT4: 0x0000000000000000 0x40200000 -# CHECK-LIT4: 0x0000000000000004 0x41040000 -# CHECK-LIT4: 0x0000000000000008 0x7f800000 -# CHECK-LIT4: 0x000000000000000c 0xff800000 -# CHECK-LIT4: 0x0000000000000010 0x7fc00000 -# CHECK-LIT4: 0x0000000000000014 0x7f800001 +# CHECK-LIT4: 0000000000000000 0x40200000 +# CHECK-LIT4: 0000000000000004 0x41040000 +# CHECK-LIT4: 0000000000000008 0x7f800000 +# CHECK-LIT4: 000000000000000c 0xff800000 +# CHECK-LIT4: 0000000000000010 0x7fc00000 +# CHECK-LIT4: 0000000000000014 0x7f800001 .literal8 .double 2.5 @@ -31,12 +31,12 @@ .long 0x7ff00000 # CHECK-LIT8: Contents of (__TEXT,__literal8) section -# CHECK-LIT8: 0x0000000000000018 0x00000000 0x40040000 -# CHECK-LIT8: 0x0000000000000020 0x00000000 0x40208000 -# CHECK-LIT8: 0x0000000000000028 0x00000000 0x7ff00000 -# CHECK-LIT8: 0x0000000000000030 0x00000000 0xfff00000 -# CHECK-LIT8: 0x0000000000000038 0x00000000 0x7ff80000 -# CHECK-LIT8: 0x0000000000000040 0x00000001 0x7ff00000 +# CHECK-LIT8: 0000000000000018 0x00000000 0x40040000 +# CHECK-LIT8: 0000000000000020 0x00000000 0x40208000 +# CHECK-LIT8: 0000000000000028 0x00000000 0x7ff00000 +# CHECK-LIT8: 0000000000000030 0x00000000 0xfff00000 +# CHECK-LIT8: 0000000000000038 0x00000000 0x7ff80000 +# CHECK-LIT8: 0000000000000040 0x00000001 0x7ff00000 .literal16 .long 1 @@ -45,4 +45,4 @@ .long 4 # CHECK-LIT16: Contents of (__TEXT,__literal16) section -# CHECK-LIT16: 0x0000000000000050 0x00000001 0x00000002 0x00000003 0x00000004 +# CHECK-LIT16: 0000000000000050 0x00000001 0x00000002 0x00000003 0x00000004 diff --git a/llvm/tools/llvm-objdump/MachODump.cpp b/llvm/tools/llvm-objdump/MachODump.cpp index 1fa7ccd41d5c..cae43567b02b 100644 --- a/llvm/tools/llvm-objdump/MachODump.cpp +++ b/llvm/tools/llvm-objdump/MachODump.cpp @@ -537,22 +537,25 @@ static const char *GuessSymbolName(uint64_t value, SymbolAddressMap *AddrMap) { return SymbolName; } +static void DumpCstringChar(const char c) { + char p[2]; + p[0] = c; + p[1] = '\0'; + outs().write_escaped(p); +} + static void DumpCstringSection(MachOObjectFile *O, const char *sect, uint32_t sect_size, uint64_t sect_addr, bool print_addresses) { for (uint32_t i = 0; i < sect_size; i++) { if (print_addresses) { if (O->is64Bit()) - outs() << format("0x%016" PRIx64, sect_addr + i) << " "; + outs() << format("%016" PRIx64, sect_addr + i) << " "; else - outs() << format("0x%08" PRIx64, sect_addr + i) << " "; - } - for (; i < sect_size && sect[i] != '\0'; i++) { - char p[2]; - p[0] = sect[i]; - p[1] = '\0'; - outs().write_escaped(p); + outs() << format("%08" PRIx64, sect_addr + i) << " "; } + for (; i < sect_size && sect[i] != '\0'; i++) + DumpCstringChar(sect[i]); if (i < sect_size && sect[i] == '\0') outs() << "\n"; } @@ -580,9 +583,9 @@ static void DumpLiteral4Section(MachOObjectFile *O, const char *sect, for (uint32_t i = 0; i < sect_size; i += sizeof(float)) { if (print_addresses) { if (O->is64Bit()) - outs() << format("0x%016" PRIx64, sect_addr + i) << " "; + outs() << format("%016" PRIx64, sect_addr + i) << " "; else - outs() << format("0x%08" PRIx64, sect_addr + i) << " "; + outs() << format("%08" PRIx64, sect_addr + i) << " "; } float f; memcpy(&f, sect + i, sizeof(float)); @@ -628,9 +631,9 @@ static void DumpLiteral8Section(MachOObjectFile *O, const char *sect, for (uint32_t i = 0; i < sect_size; i += sizeof(double)) { if (print_addresses) { if (O->is64Bit()) - outs() << format("0x%016" PRIx64, sect_addr + i) << " "; + outs() << format("%016" PRIx64, sect_addr + i) << " "; else - outs() << format("0x%08" PRIx64, sect_addr + i) << " "; + outs() << format("%08" PRIx64, sect_addr + i) << " "; } double d; memcpy(&d, sect + i, sizeof(double)); @@ -647,15 +650,22 @@ static void DumpLiteral8Section(MachOObjectFile *O, const char *sect, } } +static void DumpLiteral16(uint32_t l0, uint32_t l1, uint32_t l2, uint32_t l3) { + outs() << format("0x%08" PRIx32, l0) << " "; + outs() << format("0x%08" PRIx32, l1) << " "; + outs() << format("0x%08" PRIx32, l2) << " "; + outs() << format("0x%08" PRIx32, l3) << "\n"; +} + static void DumpLiteral16Section(MachOObjectFile *O, const char *sect, uint32_t sect_size, uint64_t sect_addr, bool print_addresses) { for (uint32_t i = 0; i < sect_size; i += 16) { if (print_addresses) { if (O->is64Bit()) - outs() << format("0x%016" PRIx64, sect_addr + i) << " "; + outs() << format("%016" PRIx64, sect_addr + i) << " "; else - outs() << format("0x%08" PRIx64, sect_addr + i) << " "; + outs() << format("%08" PRIx64, sect_addr + i) << " "; } uint32_t l0, l1, l2, l3; memcpy(&l0, sect + i, sizeof(uint32_t)); @@ -668,10 +678,174 @@ static void DumpLiteral16Section(MachOObjectFile *O, const char *sect, sys::swapByteOrder(l2); sys::swapByteOrder(l3); } - outs() << format("0x%08" PRIx32, l0) << " "; - outs() << format("0x%08" PRIx32, l1) << " "; - outs() << format("0x%08" PRIx32, l2) << " "; - outs() << format("0x%08" PRIx32, l3) << "\n"; + DumpLiteral16(l0, l1, l2, l3); + } +} + +static void DumpLiteralPointerSection(MachOObjectFile *O, + const SectionRef &Section, + const char *sect, uint32_t sect_size, + uint64_t sect_addr, + bool print_addresses) { + // Collect the literal sections in this Mach-O file. + std::vector LiteralSections; + for (const SectionRef &Section : O->sections()) { + DataRefImpl Ref = Section.getRawDataRefImpl(); + uint32_t section_type; + if (O->is64Bit()) { + const MachO::section_64 Sec = O->getSection64(Ref); + section_type = Sec.flags & MachO::SECTION_TYPE; + } else { + const MachO::section Sec = O->getSection(Ref); + section_type = Sec.flags & MachO::SECTION_TYPE; + } + if (section_type == MachO::S_CSTRING_LITERALS || + section_type == MachO::S_4BYTE_LITERALS || + section_type == MachO::S_8BYTE_LITERALS || + section_type == MachO::S_16BYTE_LITERALS) + LiteralSections.push_back(Section); + } + + // Set the size of the literal pointer. + uint32_t lp_size = O->is64Bit() ? 8 : 4; + + // Collect the external relocation symbols for the the literal pointers. + std::vector> Relocs; + for (const RelocationRef &Reloc : Section.relocations()) { + DataRefImpl Rel; + MachO::any_relocation_info RE; + bool isExtern = false; + Rel = Reloc.getRawDataRefImpl(); + RE = O->getRelocation(Rel); + isExtern = O->getPlainRelocationExternal(RE); + if (isExtern) { + uint64_t RelocOffset; + Reloc.getOffset(RelocOffset); + symbol_iterator RelocSym = Reloc.getSymbol(); + Relocs.push_back(std::make_pair(RelocOffset, *RelocSym)); + } + } + array_pod_sort(Relocs.begin(), Relocs.end()); + + // Dump each literal pointer. + for (uint32_t i = 0; i < sect_size; i += lp_size) { + if (print_addresses) { + if (O->is64Bit()) + outs() << format("%016" PRIx64, sect_addr + i) << " "; + else + outs() << format("%08" PRIx64, sect_addr + i) << " "; + } + uint64_t lp; + if (O->is64Bit()) { + memcpy(&lp, sect + i, sizeof(uint64_t)); + if (O->isLittleEndian() != sys::IsLittleEndianHost) + sys::swapByteOrder(lp); + } else { + uint32_t li; + memcpy(&li, sect + i, sizeof(uint32_t)); + if (O->isLittleEndian() != sys::IsLittleEndianHost) + sys::swapByteOrder(li); + lp = li; + } + + // First look for an external relocation entry for this literal pointer. + bool reloc_found = false; + for (unsigned j = 0, e = Relocs.size(); j != e; ++j) { + if (Relocs[i].first == i) { + symbol_iterator RelocSym = Relocs[j].second; + StringRef SymName; + RelocSym->getName(SymName); + outs() << "external relocation entry for symbol:" << SymName << "\n"; + reloc_found = true; + } + } + if (reloc_found == true) + continue; + + // For local references see what the section the literal pointer points to. + bool found = false; + for (unsigned SectIdx = 0; SectIdx != LiteralSections.size(); SectIdx++) { + uint64_t SectAddress = LiteralSections[SectIdx].getAddress(); + uint64_t SectSize = LiteralSections[SectIdx].getSize(); + if (lp >= SectAddress && lp < SectAddress + SectSize) { + found = true; + + StringRef SectName; + LiteralSections[SectIdx].getName(SectName); + DataRefImpl Ref = LiteralSections[SectIdx].getRawDataRefImpl(); + StringRef SegmentName = O->getSectionFinalSegmentName(Ref); + outs() << SegmentName << ":" << SectName << ":"; + + uint32_t section_type; + if (O->is64Bit()) { + const MachO::section_64 Sec = O->getSection64(Ref); + section_type = Sec.flags & MachO::SECTION_TYPE; + } else { + const MachO::section Sec = O->getSection(Ref); + section_type = Sec.flags & MachO::SECTION_TYPE; + } + + StringRef BytesStr; + LiteralSections[SectIdx].getContents(BytesStr); + const char *Contents = reinterpret_cast(BytesStr.data()); + + switch (section_type) { + case MachO::S_CSTRING_LITERALS: + for (uint64_t i = lp - SectAddress; + i < SectSize && Contents[i] != '\0'; i++) { + DumpCstringChar(Contents[i]); + } + outs() << "\n"; + break; + case MachO::S_4BYTE_LITERALS: + float f; + memcpy(&f, Contents + (lp - SectAddress), sizeof(float)); + uint32_t l; + memcpy(&l, Contents + (lp - SectAddress), sizeof(uint32_t)); + if (O->isLittleEndian() != sys::IsLittleEndianHost) { + sys::swapByteOrder(f); + sys::swapByteOrder(l); + } + DumpLiteral4(l, f); + break; + case MachO::S_8BYTE_LITERALS: { + double d; + memcpy(&d, Contents + (lp - SectAddress), sizeof(double)); + uint32_t l0, l1; + memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t)); + memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t), + sizeof(uint32_t)); + if (O->isLittleEndian() != sys::IsLittleEndianHost) { + sys::swapByteOrder(f); + sys::swapByteOrder(l0); + sys::swapByteOrder(l1); + } + DumpLiteral8(O, l0, l1, d); + break; + } + case MachO::S_16BYTE_LITERALS: { + uint32_t l0, l1, l2, l3; + memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t)); + memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t), + sizeof(uint32_t)); + memcpy(&l2, Contents + (lp - SectAddress) + 2 * sizeof(uint32_t), + sizeof(uint32_t)); + memcpy(&l3, Contents + (lp - SectAddress) + 3 * sizeof(uint32_t), + sizeof(uint32_t)); + if (O->isLittleEndian() != sys::IsLittleEndianHost) { + sys::swapByteOrder(l0); + sys::swapByteOrder(l1); + sys::swapByteOrder(l2); + sys::swapByteOrder(l3); + } + DumpLiteral16(l0, l1, l2, l3); + break; + } + } + } + } + if (found == false) + outs() << format("0x%" PRIx64, lp) << " (not in a literal section)\n"; } } @@ -826,6 +1000,10 @@ static void DumpSectionContents(StringRef Filename, MachOObjectFile *O, case MachO::S_16BYTE_LITERALS: DumpLiteral16Section(O, sect, sect_size, sect_addr, verbose); break; + case MachO::S_LITERAL_POINTERS: + DumpLiteralPointerSection(O, Section, sect, sect_size, sect_addr, + verbose); + break; case MachO::S_MOD_INIT_FUNC_POINTERS: case MachO::S_MOD_TERM_FUNC_POINTERS: DumpInitTermPointerSection(O, sect, sect_size, sect_addr, &AddrMap,