27
27
#include " llvm/Object/Binary.h"
28
28
#include " llvm/Object/COFF.h"
29
29
#include " llvm/Object/ELFObjectFile.h"
30
+ #include " llvm/Object/MachO.h"
30
31
#include " llvm/Object/ObjectFile.h"
31
32
#include " llvm/Support/Casting.h"
32
33
#include " llvm/Support/CommandLine.h"
@@ -322,7 +323,49 @@ static std::vector<AddrInfo> getAddrInfo(const std::string &ObjectFile,
322
323
323
324
static bool isCoveragePointSymbol (StringRef Name) {
324
325
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
+ }
326
369
}
327
370
328
371
// Locate __sanitizer_cov* function addresses that are used for coverage
@@ -333,15 +376,16 @@ findSanitizerCovFunctions(const object::ObjectFile &O) {
333
376
334
377
for (const object::SymbolRef &Symbol : O.symbols ()) {
335
378
Expected<uint64_t > AddressOrErr = Symbol.getAddress ();
336
- FailIfError (errorToErrorCode (AddressOrErr.takeError ()));
379
+ FailIfError (AddressOrErr);
380
+ uint64_t Address = AddressOrErr.get ();
337
381
338
382
Expected<StringRef> NameOrErr = Symbol.getName ();
339
- FailIfError (errorToErrorCode ( NameOrErr. takeError ()) );
383
+ FailIfError (NameOrErr);
340
384
StringRef Name = NameOrErr.get ();
341
385
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 );
345
389
}
346
390
}
347
391
@@ -361,6 +405,10 @@ findSanitizerCovFunctions(const object::ObjectFile &O) {
361
405
}
362
406
}
363
407
408
+ if (const auto *MO = dyn_cast<object::MachOObjectFile>(&O)) {
409
+ findMachOIndirectCovFunctions (*MO, &Result);
410
+ }
411
+
364
412
return Result;
365
413
}
366
414
@@ -446,7 +494,7 @@ visitObjectFiles(const object::Archive &A,
446
494
Error Err;
447
495
for (auto &C : A.children (Err)) {
448
496
Expected<std::unique_ptr<object::Binary>> ChildOrErr = C.getAsBinary ();
449
- FailIfError (errorToErrorCode ( ChildOrErr. takeError ()) );
497
+ FailIfError (ChildOrErr);
450
498
if (auto *O = dyn_cast<object::ObjectFile>(&*ChildOrErr.get ()))
451
499
Fn (*O);
452
500
else
@@ -461,7 +509,7 @@ visitObjectFiles(const std::string &FileName,
461
509
Expected<object::OwningBinary<object::Binary>> BinaryOrErr =
462
510
object::createBinary (FileName);
463
511
if (!BinaryOrErr)
464
- FailIfError (errorToErrorCode ( BinaryOrErr. takeError ()) );
512
+ FailIfError (BinaryOrErr);
465
513
466
514
object::Binary &Binary = *BinaryOrErr.get ().getBinary ();
467
515
if (object::Archive *A = dyn_cast<object::Archive>(&Binary))
0 commit comments