Index: llvm/trunk/test/tools/sancov/print_coverage_pcs.test =================================================================== --- llvm/trunk/test/tools/sancov/print_coverage_pcs.test +++ llvm/trunk/test/tools/sancov/print_coverage_pcs.test @@ -2,6 +2,7 @@ RUN: sancov -print-coverage-pcs %p/Inputs/test-linux_x86_64 | FileCheck %s --check-prefix=LINUX RUN: llvm-objdump -d %p/Inputs/test-windows_x86_64 | FileCheck %s --check-prefix=DISAS_WIN RUN: sancov -print-coverage-pcs %p/Inputs/test-windows_x86_64 | FileCheck %s --check-prefix=WINDOWS +RUN: sancov -print-coverage-pcs %p/Inputs/test-darwin_x86_64 | FileCheck %s --check-prefix=DARWIN LINUX: 0x4e132b LINUX: 0x4e1472 @@ -34,3 +35,26 @@ WINDOWS: 0x140001668 DISAS_WIN: 1400016f2: {{.*}} callq {{.*}} <__sanitizer_cov> WINDOWS: 0x1400016f6 + +CHECK: 0x4e132b +CHECK: 0x4e1472 +CHECK: 0x4e14c2 +CHECK: 0x4e1520 +CHECK: 0x4e1553 +CHECK: 0x4e1586 +CHECK: 0x4e1635 +CHECK: 0x4e1690 +CHECK: 0x4e178c + +DARWIN: 0x100001527 +DARWIN: 0x100001668 +DARWIN: 0x1000016b7 +DARWIN: 0x1000016dd +DARWIN: 0x10000179d +DARWIN: 0x1000017cc +DARWIN: 0x10000189d +DARWIN: 0x1000018e0 +DARWIN: 0x100001906 +DARWIN: 0x1000019dc +DARWIN: 0x100001a28 +>>>>>>> [sancov] MachO indirect symbols support. Index: llvm/trunk/tools/sancov/sancov.cc =================================================================== --- llvm/trunk/tools/sancov/sancov.cc +++ llvm/trunk/tools/sancov/sancov.cc @@ -27,6 +27,7 @@ #include "llvm/Object/Binary.h" #include "llvm/Object/COFF.h" #include "llvm/Object/ELFObjectFile.h" +#include "llvm/Object/MachO.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" @@ -322,7 +323,49 @@ static bool isCoveragePointSymbol(StringRef Name) { return Name == "__sanitizer_cov" || Name == "__sanitizer_cov_with_check" || - Name == "__sanitizer_cov_trace_func_enter"; + Name == "__sanitizer_cov_trace_func_enter" || + // Mac has '___' prefix + Name == "___sanitizer_cov" || Name == "___sanitizer_cov_with_check" || + Name == "___sanitizer_cov_trace_func_enter"; +} + +// Locate __sanitizer_cov* function addresses inside the stubs table on MachO. +static void findMachOIndirectCovFunctions(const object::MachOObjectFile &O, + std::set *Result) { + MachO::dysymtab_command Dysymtab = O.getDysymtabLoadCommand(); + MachO::symtab_command Symtab = O.getSymtabLoadCommand(); + + for (const auto &Load : O.load_commands()) { + if (Load.C.cmd == MachO::LC_SEGMENT_64) { + MachO::segment_command_64 Seg = O.getSegment64LoadCommand(Load); + for (unsigned J = 0; J < Seg.nsects; ++J) { + MachO::section_64 Sec = O.getSection64(Load, J); + + uint32_t SectionType = Sec.flags & MachO::SECTION_TYPE; + if (SectionType == MachO::S_SYMBOL_STUBS) { + uint32_t Stride = Sec.reserved2; + uint32_t Cnt = Sec.size / Stride; + uint32_t N = Sec.reserved1; + for (uint32_t J = 0; J < Cnt && N + J < Dysymtab.nindirectsyms; J++) { + uint32_t IndirectSymbol = + O.getIndirectSymbolTableEntry(Dysymtab, N + J); + uint64_t Addr = Sec.addr + J * Stride; + if (IndirectSymbol < Symtab.nsyms) { + object::SymbolRef Symbol = *(O.getSymbolByIndex(IndirectSymbol)); + Expected Name = Symbol.getName(); + FailIfError(Name); + if (isCoveragePointSymbol(Name.get())) { + Result->insert(Addr); + } + } + } + } + } + } + if (Load.C.cmd == MachO::LC_SEGMENT) { + errs() << "ERROR: 32 bit MachO binaries not supported\n"; + } + } } // Locate __sanitizer_cov* function addresses that are used for coverage @@ -333,15 +376,16 @@ for (const object::SymbolRef &Symbol : O.symbols()) { Expected AddressOrErr = Symbol.getAddress(); - FailIfError(errorToErrorCode(AddressOrErr.takeError())); + FailIfError(AddressOrErr); + uint64_t Address = AddressOrErr.get(); Expected NameOrErr = Symbol.getName(); - FailIfError(errorToErrorCode(NameOrErr.takeError())); + FailIfError(NameOrErr); StringRef Name = NameOrErr.get(); - if (isCoveragePointSymbol(Name)) { - if (!(Symbol.getFlags() & object::BasicSymbolRef::SF_Undefined)) - Result.insert(AddressOrErr.get()); + if (!(Symbol.getFlags() & object::BasicSymbolRef::SF_Undefined) && + isCoveragePointSymbol(Name)) { + Result.insert(Address); } } @@ -361,6 +405,10 @@ } } + if (const auto *MO = dyn_cast(&O)) { + findMachOIndirectCovFunctions(*MO, &Result); + } + return Result; } @@ -446,7 +494,7 @@ Error Err; for (auto &C : A.children(Err)) { Expected> ChildOrErr = C.getAsBinary(); - FailIfError(errorToErrorCode(ChildOrErr.takeError())); + FailIfError(ChildOrErr); if (auto *O = dyn_cast(&*ChildOrErr.get())) Fn(*O); else @@ -461,7 +509,7 @@ Expected> BinaryOrErr = object::createBinary(FileName); if (!BinaryOrErr) - FailIfError(errorToErrorCode(BinaryOrErr.takeError())); + FailIfError(BinaryOrErr); object::Binary &Binary = *BinaryOrErr.get().getBinary(); if (object::Archive *A = dyn_cast(&Binary))