diff --git a/include/llvm/Support/MachO.def b/include/llvm/Support/MachO.def index 9ca6440dd82b..57522897d0fc 100644 --- a/include/llvm/Support/MachO.def +++ b/include/llvm/Support/MachO.def @@ -15,27 +15,37 @@ HANDLE_LOAD_COMMAND(LC_SEGMENT, 0x00000001u, segment_command) HANDLE_LOAD_COMMAND(LC_SYMTAB, 0x00000002u, symtab_command) +// LC_SYMSEG is obsolete and no longer supported. HANDLE_LOAD_COMMAND(LC_SYMSEG, 0x00000003u, symseg_command) HANDLE_LOAD_COMMAND(LC_THREAD, 0x00000004u, thread_command) HANDLE_LOAD_COMMAND(LC_UNIXTHREAD, 0x00000005u, thread_command) +// LC_LOADFVMLIB is obsolete and no longer supported. HANDLE_LOAD_COMMAND(LC_LOADFVMLIB, 0x00000006u, fvmlib_command) +// LC_IDFVMLIB is obsolete and no longer supported. HANDLE_LOAD_COMMAND(LC_IDFVMLIB, 0x00000007u, fvmlib_command) +// LC_IDENT is obsolete and no longer supported. HANDLE_LOAD_COMMAND(LC_IDENT, 0x00000008u, ident_command) +// LC_FVMFILE is obsolete and no longer supported. HANDLE_LOAD_COMMAND(LC_FVMFILE, 0x00000009u, fvmfile_command) +// LC_PREPAGE is obsolete and no longer supported. HANDLE_LOAD_COMMAND(LC_PREPAGE, 0x0000000Au, load_command) HANDLE_LOAD_COMMAND(LC_DYSYMTAB, 0x0000000Bu, dysymtab_command) HANDLE_LOAD_COMMAND(LC_LOAD_DYLIB, 0x0000000Cu, dylib_command) HANDLE_LOAD_COMMAND(LC_ID_DYLIB, 0x0000000Du, dylib_command) HANDLE_LOAD_COMMAND(LC_LOAD_DYLINKER, 0x0000000Eu, dylinker_command) HANDLE_LOAD_COMMAND(LC_ID_DYLINKER, 0x0000000Fu, dylinker_command) +// LC_PREBOUND_DYLIB is obsolete and no longer supported. HANDLE_LOAD_COMMAND(LC_PREBOUND_DYLIB, 0x00000010u, prebound_dylib_command) HANDLE_LOAD_COMMAND(LC_ROUTINES, 0x00000011u, routines_command) HANDLE_LOAD_COMMAND(LC_SUB_FRAMEWORK, 0x00000012u, sub_framework_command) HANDLE_LOAD_COMMAND(LC_SUB_UMBRELLA, 0x00000013u, sub_umbrella_command) HANDLE_LOAD_COMMAND(LC_SUB_CLIENT, 0x00000014u, sub_client_command) HANDLE_LOAD_COMMAND(LC_SUB_LIBRARY, 0x00000015u, sub_library_command) +// LC_TWOLEVEL_HINTS is obsolete and no longer supported. HANDLE_LOAD_COMMAND(LC_TWOLEVEL_HINTS, 0x00000016u, twolevel_hints_command) +// LC_PREBIND_CKSUM is obsolete and no longer supported. HANDLE_LOAD_COMMAND(LC_PREBIND_CKSUM, 0x00000017u, prebind_cksum_command) +// LC_LOAD_WEAK_DYLIB is obsolete and no longer supported. HANDLE_LOAD_COMMAND(LC_LOAD_WEAK_DYLIB, 0x80000018u, dylib_command) HANDLE_LOAD_COMMAND(LC_SEGMENT_64, 0x00000019u, segment_command_64) HANDLE_LOAD_COMMAND(LC_ROUTINES_64, 0x0000001Au, routines_command_64) diff --git a/include/llvm/Support/MachO.h b/include/llvm/Support/MachO.h index c56a6aa850de..d7729755d69f 100644 --- a/include/llvm/Support/MachO.h +++ b/include/llvm/Support/MachO.h @@ -578,6 +578,7 @@ namespace llvm { uint32_t header_addr; }; + // The fvmlib_command is obsolete and no longer supported. struct fvmlib_command { uint32_t cmd; uint32_t cmdsize; @@ -621,6 +622,7 @@ namespace llvm { uint32_t sub_library; }; + // The prebound_dylib_command is obsolete and no longer supported. struct prebound_dylib_command { uint32_t cmd; uint32_t cmdsize; @@ -740,6 +742,7 @@ namespace llvm { flags:8; }; + // The twolevel_hints_command is obsolete and no longer supported. struct twolevel_hints_command { uint32_t cmd; uint32_t cmdsize; @@ -747,11 +750,13 @@ namespace llvm { uint32_t nhints; }; + // The twolevel_hints_command is obsolete and no longer supported. struct twolevel_hint { uint32_t isub_image:8, itoc:24; }; + // The prebind_cksum_command is obsolete and no longer supported. struct prebind_cksum_command { uint32_t cmd; uint32_t cmdsize; @@ -835,6 +840,7 @@ namespace llvm { uint32_t count; }; + // The symseg_command is obsolete and no longer supported. struct symseg_command { uint32_t cmd; uint32_t cmdsize; @@ -842,11 +848,13 @@ namespace llvm { uint32_t size; }; + // The ident_command is obsolete and no longer supported. struct ident_command { uint32_t cmd; uint32_t cmdsize; }; + // The fvmfile_command is obsolete and no longer supported. struct fvmfile_command { uint32_t cmd; uint32_t cmdsize; @@ -1268,12 +1276,14 @@ namespace llvm { sys::swapByteOrder(C); } + // The prebind_cksum_command is obsolete and no longer supported. inline void swapStruct(prebind_cksum_command &C) { sys::swapByteOrder(C.cmd); sys::swapByteOrder(C.cmdsize); sys::swapByteOrder(C.cksum); } + // The twolevel_hints_command is obsolete and no longer supported. inline void swapStruct(twolevel_hints_command &C) { sys::swapByteOrder(C.cmd); sys::swapByteOrder(C.cmdsize); @@ -1281,6 +1291,7 @@ namespace llvm { sys::swapByteOrder(C.nhints); } + // The prebound_dylib_command is obsolete and no longer supported. inline void swapStruct(prebound_dylib_command &C) { sys::swapByteOrder(C.cmd); sys::swapByteOrder(C.cmdsize); @@ -1289,6 +1300,7 @@ namespace llvm { sys::swapByteOrder(C.linked_modules); } + // The fvmfile_command is obsolete and no longer supported. inline void swapStruct(fvmfile_command &C) { sys::swapByteOrder(C.cmd); sys::swapByteOrder(C.cmdsize); @@ -1296,6 +1308,7 @@ namespace llvm { sys::swapByteOrder(C.header_addr); } + // The symseg_command is obsolete and no longer supported. inline void swapStruct(symseg_command &C) { sys::swapByteOrder(C.cmd); sys::swapByteOrder(C.cmdsize); @@ -1303,6 +1316,7 @@ namespace llvm { sys::swapByteOrder(C.size); } + // The ident_command is obsolete and no longer supported. inline void swapStruct(ident_command &C) { sys::swapByteOrder(C.cmd); sys::swapByteOrder(C.cmdsize); @@ -1314,6 +1328,7 @@ namespace llvm { sys::swapByteOrder(C.header_addr); } + // The fvmlib_command is obsolete and no longer supported. inline void swapStruct(fvmlib_command &C) { sys::swapByteOrder(C.cmd); sys::swapByteOrder(C.cmdsize); diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 5bfc51ecf620..8bb55175efa0 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -912,6 +912,23 @@ static Error checkTwoLevelHintsCommand(const MachOObjectFile *Obj, return Error::success(); } +// Returns true if the libObject code does not support the load command and its +// contents. The cmd value it is treated as an unknown load command but with +// an error message that says the cmd value is obsolete. +static bool isLoadCommandObsolete(uint32_t cmd) { + if (cmd == MachO::LC_SYMSEG || + cmd == MachO::LC_LOADFVMLIB || + cmd == MachO::LC_IDFVMLIB || + cmd == MachO::LC_IDENT || + cmd == MachO::LC_FVMFILE || + cmd == MachO::LC_PREPAGE || + cmd == MachO::LC_PREBOUND_DYLIB || + cmd == MachO::LC_TWOLEVEL_HINTS || + cmd == MachO::LC_PREBIND_CKSUM) + return true; + return false; +} + Expected> MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits, uint32_t UniversalCputype, @@ -1250,11 +1267,20 @@ MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, } else if (Load.C.cmd == MachO::LC_THREAD) { if ((Err = checkThreadCommand(this, Load, I, "LC_THREAD"))) return; + // Note: LC_TWOLEVEL_HINTS is really obsolete and is not supported. } else if (Load.C.cmd == MachO::LC_TWOLEVEL_HINTS) { if ((Err = checkTwoLevelHintsCommand(this, Load, I, &TwoLevelHintsLoadCmd))) return; + } else if (isLoadCommandObsolete(Load.C.cmd)) { + Err = malformedError("load command " + Twine(I) + " for cmd value of: " + + Twine(Load.C.cmd) + " is obsolete and not " + "supported"); + return; } + // TODO: generate a error for unknown load commands by default. But still + // need work out an approach to allow or not allow unknown values like this + // as an option for some uses like lldb. if (I < LoadCommandCount - 1) { if (auto LoadOrErr = getNextLoadCommandInfo(this, I, Load)) Load = *LoadOrErr; diff --git a/test/Object/Inputs/macho-invalid-fvmfile-obsolete b/test/Object/Inputs/macho-invalid-fvmfile-obsolete new file mode 100644 index 000000000000..10e0df5b5441 Binary files /dev/null and b/test/Object/Inputs/macho-invalid-fvmfile-obsolete differ diff --git a/test/Object/Inputs/macho-invalid-ident-obsolete b/test/Object/Inputs/macho-invalid-ident-obsolete new file mode 100644 index 000000000000..74d61677d685 Binary files /dev/null and b/test/Object/Inputs/macho-invalid-ident-obsolete differ diff --git a/test/Object/Inputs/macho-invalid-idfvmlib-obsolete b/test/Object/Inputs/macho-invalid-idfvmlib-obsolete new file mode 100644 index 000000000000..bf83e5b4a53a Binary files /dev/null and b/test/Object/Inputs/macho-invalid-idfvmlib-obsolete differ diff --git a/test/Object/Inputs/macho-invalid-loadfvmlib-obsolete b/test/Object/Inputs/macho-invalid-loadfvmlib-obsolete new file mode 100644 index 000000000000..bac12a2e5f4d Binary files /dev/null and b/test/Object/Inputs/macho-invalid-loadfvmlib-obsolete differ diff --git a/test/Object/Inputs/macho-invalid-prebind_cksum-obsolete b/test/Object/Inputs/macho-invalid-prebind_cksum-obsolete new file mode 100644 index 000000000000..6fa90d030a54 Binary files /dev/null and b/test/Object/Inputs/macho-invalid-prebind_cksum-obsolete differ diff --git a/test/Object/Inputs/macho-invalid-prebound_dylib-obsolete b/test/Object/Inputs/macho-invalid-prebound_dylib-obsolete new file mode 100644 index 000000000000..04d9f82bf3e2 Binary files /dev/null and b/test/Object/Inputs/macho-invalid-prebound_dylib-obsolete differ diff --git a/test/Object/Inputs/macho-invalid-prepage-obsolete b/test/Object/Inputs/macho-invalid-prepage-obsolete new file mode 100644 index 000000000000..cfd6bae900eb Binary files /dev/null and b/test/Object/Inputs/macho-invalid-prepage-obsolete differ diff --git a/test/Object/Inputs/macho-invalid-symseg-obsolete b/test/Object/Inputs/macho-invalid-symseg-obsolete new file mode 100644 index 000000000000..6330997e4091 Binary files /dev/null and b/test/Object/Inputs/macho-invalid-symseg-obsolete differ diff --git a/test/Object/macho-invalid.test b/test/Object/macho-invalid.test index 897b28e4a0f9..f95eebc315a9 100644 --- a/test/Object/macho-invalid.test +++ b/test/Object/macho-invalid.test @@ -409,3 +409,27 @@ INVALID-TWOLEVELHINTS-OFFSET-HNINTS: macho-invalid-twolevelhints-offset-nhints': RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-fat_cputype 2>&1 | FileCheck -check-prefix INVALID-FAT-CPUTYPE %s INVALID-FAT-CPUTYPE: macho-invalid-fat_cputype': truncated or malformed object (universal header architecture: 0's cputype does not match object file's mach header) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-prebind_cksum-obsolete 2>&1 | FileCheck -check-prefix INVALID-PREBIND_CKSUM-OBSOLETE %s +INVALID-PREBIND_CKSUM-OBSOLETE: macho-invalid-prebind_cksum-obsolete': truncated or malformed object (load command 0 for cmd value of: 23 is obsolete and not supported) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-symseg-obsolete 2>&1 | FileCheck -check-prefix INVALID-SYMSEG-OBSOLETE %s +INVALID-SYMSEG-OBSOLETE: macho-invalid-symseg-obsolete': truncated or malformed object (load command 0 for cmd value of: 3 is obsolete and not supported) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-idfvmlib-obsolete 2>&1 | FileCheck -check-prefix INVALID-IDFVMLIB-OBSOLETE %s +INVALID-IDFVMLIB-OBSOLETE: macho-invalid-idfvmlib-obsolete': truncated or malformed object (load command 0 for cmd value of: 7 is obsolete and not supported) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-loadfvmlib-obsolete 2>&1 | FileCheck -check-prefix INVALID-LOADFVMLIB-OBSOLETE %s +INVALID-LOADFVMLIB-OBSOLETE: macho-invalid-loadfvmlib-obsolete': truncated or malformed object (load command 0 for cmd value of: 6 is obsolete and not supported) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-prebound_dylib-obsolete 2>&1 | FileCheck -check-prefix INVALID-PREBOUND_DYLIB-OBSOLETE %s +INVALID-PREBOUND_DYLIB-OBSOLETE: macho-invalid-prebound_dylib-obsolete': truncated or malformed object (load command 0 for cmd value of: 16 is obsolete and not supported) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-ident-obsolete 2>&1 | FileCheck -check-prefix INVALID-IDENT-OBSOLETE %s +INVALID-IDENT-OBSOLETE: macho-invalid-ident-obsolete': truncated or malformed object (load command 0 for cmd value of: 8 is obsolete and not supported) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-fvmfile-obsolete 2>&1 | FileCheck -check-prefix INVALID-FVMFILE-OBSOLETE %s +INVALID-FVMFILE-OBSOLETE: macho-invalid-fvmfile-obsolete': truncated or malformed object (load command 0 for cmd value of: 9 is obsolete and not supported) + +RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-prepage-obsolete 2>&1 | FileCheck -check-prefix INVALID-PREPAGE-OBSOLETE %s +INVALID-PREPAGE-OBSOLETE: macho-invalid-prepage-obsolete': truncated or malformed object (load command 0 for cmd value of: 10 is obsolete and not supported)