From 4e96e52cbe2d193988dc6a34d2d4f18ffbb0c4fc Mon Sep 17 00:00:00 2001 From: Kevin Enderby Date: Fri, 6 Feb 2015 23:25:38 +0000 Subject: [PATCH] Add code to llvm-objdump so the -section option with -macho will dump literal sections with the Mach-O S_{4,8,16}BYTE_LITERALS section types. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@228465 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Support/SwapByteOrder.h | 20 +++ .../llvm-objdump/X86/macho-literals.test | 48 ++++++ tools/llvm-objdump/MachODump.cpp | 140 +++++++++++++++++- 3 files changed, 202 insertions(+), 6 deletions(-) create mode 100644 test/tools/llvm-objdump/X86/macho-literals.test diff --git a/include/llvm/Support/SwapByteOrder.h b/include/llvm/Support/SwapByteOrder.h index 9c5a3c59122..70564be890e 100644 --- a/include/llvm/Support/SwapByteOrder.h +++ b/include/llvm/Support/SwapByteOrder.h @@ -94,6 +94,26 @@ inline signed long long getSwappedBytes(signed long long C) { return SwapByteOrder_64(C); } +inline float getSwappedBytes(float C) { + union { + uint32_t i; + float f; + } in, out; + in.f = C; + out.i = SwapByteOrder_32(in.i); + return out.f; +} + +inline float getSwappedBytes(double C) { + union { + uint64_t i; + double d; + } in, out; + in.d = C; + out.i = SwapByteOrder_64(in.i); + return out.d; +} + template inline void swapByteOrder(T &Value) { Value = getSwappedBytes(Value); diff --git a/test/tools/llvm-objdump/X86/macho-literals.test b/test/tools/llvm-objdump/X86/macho-literals.test new file mode 100644 index 00000000000..2acac7d43b6 --- /dev/null +++ b/test/tools/llvm-objdump/X86/macho-literals.test @@ -0,0 +1,48 @@ +# RUN: llvm-mc < %s -triple x86_64-apple-darwin -filetype=obj | llvm-objdump -m -section __TEXT,__literal4 - | FileCheck %s -check-prefix=CHECK-LIT4 +# RUN: llvm-mc < %s -triple x86_64-apple-darwin -filetype=obj | llvm-objdump -m -section __TEXT,__literal8 - | FileCheck %s -check-prefix=CHECK-LIT8 +# RUN: llvm-mc < %s -triple x86_64-apple-darwin -filetype=obj | llvm-objdump -m -section __TEXT,__literal16 - | FileCheck %s -check-prefix=CHECK-LIT16 + +.literal4 +.float 2.5 +.float 8.25 +.long 0x7f800000 +.long 0xff800000 +.long 0x7fc00000 +.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 + +.literal8 +.double 2.5 +.double 8.25 +.long 0 +.long 0x7ff00000 +.long 0 +.long 0xfff00000 +.long 0 +.long 0x7ff80000 +.long 1 +.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 + +.literal16 +.long 1 +.long 2 +.long 3 +.long 4 + +# CHECK-LIT16: Contents of (__TEXT,__literal16) section +# CHECK-LIT16: 0x0000000000000050 0x00000001 0x00000002 0x00000003 0x00000004 diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp index 7d2eeedd8e6..1fa7ccd41d5 100644 --- a/tools/llvm-objdump/MachODump.cpp +++ b/tools/llvm-objdump/MachODump.cpp @@ -539,13 +539,15 @@ static const char *GuessSymbolName(uint64_t value, SymbolAddressMap *AddrMap) { static void DumpCstringSection(MachOObjectFile *O, const char *sect, uint32_t sect_size, uint64_t sect_addr, - bool verbose) { + bool print_addresses) { for (uint32_t i = 0; i < sect_size; i++) { - if (O->is64Bit()) - outs() << format("0x%016" PRIx64, sect_addr + i) << " "; - else - outs() << format("0x%08" PRIx64, sect_addr + i) << " "; - for ( ; i < sect_size && sect[i] != '\0'; i++) { + if (print_addresses) { + if (O->is64Bit()) + outs() << format("0x%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'; @@ -556,6 +558,123 @@ static void DumpCstringSection(MachOObjectFile *O, const char *sect, } } +static void DumpLiteral4(uint32_t l, float f) { + outs() << format("0x%08" PRIx32, l); + if ((l & 0x7f800000) != 0x7f800000) + outs() << format(" (%.16e)\n", f); + else { + if (l == 0x7f800000) + outs() << " (+Infinity)\n"; + else if (l == 0xff800000) + outs() << " (-Infinity)\n"; + else if ((l & 0x00400000) == 0x00400000) + outs() << " (non-signaling Not-a-Number)\n"; + else + outs() << " (signaling Not-a-Number)\n"; + } +} + +static void DumpLiteral4Section(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 += sizeof(float)) { + if (print_addresses) { + if (O->is64Bit()) + outs() << format("0x%016" PRIx64, sect_addr + i) << " "; + else + outs() << format("0x%08" PRIx64, sect_addr + i) << " "; + } + float f; + memcpy(&f, sect + i, sizeof(float)); + if (O->isLittleEndian() != sys::IsLittleEndianHost) + sys::swapByteOrder(f); + uint32_t l; + memcpy(&l, sect + i, sizeof(uint32_t)); + if (O->isLittleEndian() != sys::IsLittleEndianHost) + sys::swapByteOrder(l); + DumpLiteral4(l, f); + } +} + +static void DumpLiteral8(MachOObjectFile *O, uint32_t l0, uint32_t l1, + double d) { + outs() << format("0x%08" PRIx32, l0) << " " << format("0x%08" PRIx32, l1); + uint32_t Hi, Lo; + if (O->isLittleEndian()) { + Hi = l1; + Lo = l0; + } else { + Hi = l0; + Lo = l1; + } + // Hi is the high word, so this is equivalent to if(isfinite(d)) + if ((Hi & 0x7ff00000) != 0x7ff00000) + outs() << format(" (%.16e)\n", d); + else { + if (Hi == 0x7ff00000 && Lo == 0) + outs() << " (+Infinity)\n"; + else if (Hi == 0xfff00000 && Lo == 0) + outs() << " (-Infinity)\n"; + else if ((Hi & 0x00080000) == 0x00080000) + outs() << " (non-signaling Not-a-Number)\n"; + else + outs() << " (signaling Not-a-Number)\n"; + } +} + +static void DumpLiteral8Section(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 += sizeof(double)) { + if (print_addresses) { + if (O->is64Bit()) + outs() << format("0x%016" PRIx64, sect_addr + i) << " "; + else + outs() << format("0x%08" PRIx64, sect_addr + i) << " "; + } + double d; + memcpy(&d, sect + i, sizeof(double)); + if (O->isLittleEndian() != sys::IsLittleEndianHost) + sys::swapByteOrder(d); + uint32_t l0, l1; + memcpy(&l0, sect + i, sizeof(uint32_t)); + memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t)); + if (O->isLittleEndian() != sys::IsLittleEndianHost) { + sys::swapByteOrder(l0); + sys::swapByteOrder(l1); + } + DumpLiteral8(O, l0, l1, d); + } +} + +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) << " "; + else + outs() << format("0x%08" PRIx64, sect_addr + i) << " "; + } + uint32_t l0, l1, l2, l3; + memcpy(&l0, sect + i, sizeof(uint32_t)); + memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t)); + memcpy(&l2, sect + i + 2 * sizeof(uint32_t), sizeof(uint32_t)); + memcpy(&l3, sect + i + 3 * sizeof(uint32_t), sizeof(uint32_t)); + if (O->isLittleEndian() != sys::IsLittleEndianHost) { + sys::swapByteOrder(l0); + sys::swapByteOrder(l1); + 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"; + } +} + static void DumpInitTermPointerSection(MachOObjectFile *O, const char *sect, uint32_t sect_size, uint64_t sect_addr, SymbolAddressMap *AddrMap, @@ -698,6 +817,15 @@ static void DumpSectionContents(StringRef Filename, MachOObjectFile *O, case MachO::S_CSTRING_LITERALS: DumpCstringSection(O, sect, sect_size, sect_addr, verbose); break; + case MachO::S_4BYTE_LITERALS: + DumpLiteral4Section(O, sect, sect_size, sect_addr, verbose); + break; + case MachO::S_8BYTE_LITERALS: + DumpLiteral8Section(O, sect, sect_size, sect_addr, verbose); + break; + case MachO::S_16BYTE_LITERALS: + DumpLiteral16Section(O, 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, -- 2.34.1