Skip to content

Commit 3c4d60a

Browse files
committedAug 12, 2016
[sancov] MachO indirect symbols support.
Differential Revision: https://reviews.llvm.org/D23338 llvm-svn: 278551
1 parent 683a35d commit 3c4d60a

File tree

3 files changed

+80
-8
lines changed

3 files changed

+80
-8
lines changed
 
16.6 KB
Binary file not shown.

‎llvm/test/tools/sancov/print_coverage_pcs.test

+24
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ REQUIRES: x86-registered-target
22
RUN: sancov -print-coverage-pcs %p/Inputs/test-linux_x86_64 | FileCheck %s --check-prefix=LINUX
33
RUN: llvm-objdump -d %p/Inputs/test-windows_x86_64 | FileCheck %s --check-prefix=DISAS_WIN
44
RUN: sancov -print-coverage-pcs %p/Inputs/test-windows_x86_64 | FileCheck %s --check-prefix=WINDOWS
5+
RUN: sancov -print-coverage-pcs %p/Inputs/test-darwin_x86_64 | FileCheck %s --check-prefix=DARWIN
56

67
LINUX: 0x4e132b
78
LINUX: 0x4e1472
@@ -34,3 +35,26 @@ DISAS_WIN: 140001664: {{.*}} callq {{.*}} <__sanitizer_cov>
3435
WINDOWS: 0x140001668
3536
DISAS_WIN: 1400016f2: {{.*}} callq {{.*}} <__sanitizer_cov>
3637
WINDOWS: 0x1400016f6
38+
39+
CHECK: 0x4e132b
40+
CHECK: 0x4e1472
41+
CHECK: 0x4e14c2
42+
CHECK: 0x4e1520
43+
CHECK: 0x4e1553
44+
CHECK: 0x4e1586
45+
CHECK: 0x4e1635
46+
CHECK: 0x4e1690
47+
CHECK: 0x4e178c
48+
49+
DARWIN: 0x100001527
50+
DARWIN: 0x100001668
51+
DARWIN: 0x1000016b7
52+
DARWIN: 0x1000016dd
53+
DARWIN: 0x10000179d
54+
DARWIN: 0x1000017cc
55+
DARWIN: 0x10000189d
56+
DARWIN: 0x1000018e0
57+
DARWIN: 0x100001906
58+
DARWIN: 0x1000019dc
59+
DARWIN: 0x100001a28
60+
>>>>>>> [sancov] MachO indirect symbols support.

‎llvm/tools/sancov/sancov.cc

+56-8
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "llvm/Object/Binary.h"
2828
#include "llvm/Object/COFF.h"
2929
#include "llvm/Object/ELFObjectFile.h"
30+
#include "llvm/Object/MachO.h"
3031
#include "llvm/Object/ObjectFile.h"
3132
#include "llvm/Support/Casting.h"
3233
#include "llvm/Support/CommandLine.h"
@@ -322,7 +323,49 @@ static std::vector<AddrInfo> getAddrInfo(const std::string &ObjectFile,
322323

323324
static bool isCoveragePointSymbol(StringRef Name) {
324325
return Name == "__sanitizer_cov" || Name == "__sanitizer_cov_with_check" ||
325-
Name == "__sanitizer_cov_trace_func_enter";
326+
Name == "__sanitizer_cov_trace_func_enter" ||
327+
// Mac has '___' prefix
328+
Name == "___sanitizer_cov" || Name == "___sanitizer_cov_with_check" ||
329+
Name == "___sanitizer_cov_trace_func_enter";
330+
}
331+
332+
// Locate __sanitizer_cov* function addresses inside the stubs table on MachO.
333+
static void findMachOIndirectCovFunctions(const object::MachOObjectFile &O,
334+
std::set<uint64_t> *Result) {
335+
MachO::dysymtab_command Dysymtab = O.getDysymtabLoadCommand();
336+
MachO::symtab_command Symtab = O.getSymtabLoadCommand();
337+
338+
for (const auto &Load : O.load_commands()) {
339+
if (Load.C.cmd == MachO::LC_SEGMENT_64) {
340+
MachO::segment_command_64 Seg = O.getSegment64LoadCommand(Load);
341+
for (unsigned J = 0; J < Seg.nsects; ++J) {
342+
MachO::section_64 Sec = O.getSection64(Load, J);
343+
344+
uint32_t SectionType = Sec.flags & MachO::SECTION_TYPE;
345+
if (SectionType == MachO::S_SYMBOL_STUBS) {
346+
uint32_t Stride = Sec.reserved2;
347+
uint32_t Cnt = Sec.size / Stride;
348+
uint32_t N = Sec.reserved1;
349+
for (uint32_t J = 0; J < Cnt && N + J < Dysymtab.nindirectsyms; J++) {
350+
uint32_t IndirectSymbol =
351+
O.getIndirectSymbolTableEntry(Dysymtab, N + J);
352+
uint64_t Addr = Sec.addr + J * Stride;
353+
if (IndirectSymbol < Symtab.nsyms) {
354+
object::SymbolRef Symbol = *(O.getSymbolByIndex(IndirectSymbol));
355+
Expected<StringRef> Name = Symbol.getName();
356+
FailIfError(Name);
357+
if (isCoveragePointSymbol(Name.get())) {
358+
Result->insert(Addr);
359+
}
360+
}
361+
}
362+
}
363+
}
364+
}
365+
if (Load.C.cmd == MachO::LC_SEGMENT) {
366+
errs() << "ERROR: 32 bit MachO binaries not supported\n";
367+
}
368+
}
326369
}
327370

328371
// Locate __sanitizer_cov* function addresses that are used for coverage
@@ -333,15 +376,16 @@ findSanitizerCovFunctions(const object::ObjectFile &O) {
333376

334377
for (const object::SymbolRef &Symbol : O.symbols()) {
335378
Expected<uint64_t> AddressOrErr = Symbol.getAddress();
336-
FailIfError(errorToErrorCode(AddressOrErr.takeError()));
379+
FailIfError(AddressOrErr);
380+
uint64_t Address = AddressOrErr.get();
337381

338382
Expected<StringRef> NameOrErr = Symbol.getName();
339-
FailIfError(errorToErrorCode(NameOrErr.takeError()));
383+
FailIfError(NameOrErr);
340384
StringRef Name = NameOrErr.get();
341385

342-
if (isCoveragePointSymbol(Name)) {
343-
if (!(Symbol.getFlags() & object::BasicSymbolRef::SF_Undefined))
344-
Result.insert(AddressOrErr.get());
386+
if (!(Symbol.getFlags() & object::BasicSymbolRef::SF_Undefined) &&
387+
isCoveragePointSymbol(Name)) {
388+
Result.insert(Address);
345389
}
346390
}
347391

@@ -361,6 +405,10 @@ findSanitizerCovFunctions(const object::ObjectFile &O) {
361405
}
362406
}
363407

408+
if (const auto *MO = dyn_cast<object::MachOObjectFile>(&O)) {
409+
findMachOIndirectCovFunctions(*MO, &Result);
410+
}
411+
364412
return Result;
365413
}
366414

@@ -446,7 +494,7 @@ visitObjectFiles(const object::Archive &A,
446494
Error Err;
447495
for (auto &C : A.children(Err)) {
448496
Expected<std::unique_ptr<object::Binary>> ChildOrErr = C.getAsBinary();
449-
FailIfError(errorToErrorCode(ChildOrErr.takeError()));
497+
FailIfError(ChildOrErr);
450498
if (auto *O = dyn_cast<object::ObjectFile>(&*ChildOrErr.get()))
451499
Fn(*O);
452500
else
@@ -461,7 +509,7 @@ visitObjectFiles(const std::string &FileName,
461509
Expected<object::OwningBinary<object::Binary>> BinaryOrErr =
462510
object::createBinary(FileName);
463511
if (!BinaryOrErr)
464-
FailIfError(errorToErrorCode(BinaryOrErr.takeError()));
512+
FailIfError(BinaryOrErr);
465513

466514
object::Binary &Binary = *BinaryOrErr.get().getBinary();
467515
if (object::Archive *A = dyn_cast<object::Archive>(&Binary))

0 commit comments

Comments
 (0)
Please sign in to comment.