[MCJIT] Fix a bug RuntimeDyldImpl's read/writeBytesUnaligned methods.
[oota-llvm.git] / lib / ProfileData / CoverageMappingReader.cpp
index 72dbb6c7808f70d4b0ee381c5403e09d44a2a57d..8d1508b03706347809e28cf406d37a82687eaab1 100644 (file)
@@ -160,9 +160,6 @@ std::error_code RawCoverageMappingReader::readMappingRegionsSubArray(
         case CounterMappingRegion::CodeRegion:
           // Don't do anything when we have a code region with a zero counter.
           break;
-        case CounterMappingRegion::EmptyRegion:
-          Kind = CounterMappingRegion::EmptyRegion;
-          break;
         case CounterMappingRegion::SkippedRegion:
           Kind = CounterMappingRegion::SkippedRegion;
           break;
@@ -173,13 +170,17 @@ std::error_code RawCoverageMappingReader::readMappingRegionsSubArray(
     }
 
     // Read the source range.
-    uint64_t LineStartDelta, ColumnStart, NumLines, ColumnEnd;
+    uint64_t LineStartDelta, CodeBeforeColumnStart, NumLines, ColumnEnd;
     if (auto Err =
             readIntMax(LineStartDelta, std::numeric_limits<unsigned>::max()))
       return Err;
-    if (auto Err =
-            readIntMax(ColumnStart, std::numeric_limits<unsigned>::max()))
+    if (auto Err = readULEB128(CodeBeforeColumnStart))
       return Err;
+    bool HasCodeBefore = CodeBeforeColumnStart & 1;
+    uint64_t ColumnStart = CodeBeforeColumnStart >>
+                           CounterMappingRegion::EncodingHasCodeBeforeBits;
+    if (ColumnStart > std::numeric_limits<unsigned>::max())
+      return error(instrprof_error::malformed);
     if (auto Err = readIntMax(NumLines, std::numeric_limits<unsigned>::max()))
       return Err;
     if (auto Err = readIntMax(ColumnEnd, std::numeric_limits<unsigned>::max()))
@@ -197,9 +198,9 @@ std::error_code RawCoverageMappingReader::readMappingRegionsSubArray(
       ColumnStart = 1;
       ColumnEnd = std::numeric_limits<unsigned>::max();
     }
-    MappingRegions.push_back(
-        CounterMappingRegion(C, InferredFileID, LineStart, ColumnStart,
-                             LineStart + NumLines, ColumnEnd, Kind));
+    MappingRegions.push_back(CounterMappingRegion(
+        C, InferredFileID, LineStart, ColumnStart, LineStart + NumLines,
+        ColumnEnd, HasCodeBefore, Kind));
     MappingRegions.back().ExpandedFileID = ExpandedFileID;
   }
   return success();
@@ -254,15 +255,19 @@ std::error_code RawCoverageMappingReader::read(CoverageMappingRecord &Record) {
   // from the expanded file.
   // Perform multiple passes to correctly propagate the counters through
   // all the nested expansion regions.
+  SmallVector<CounterMappingRegion *, 8> FileIDExpansionRegionMapping;
+  FileIDExpansionRegionMapping.resize(VirtualFileMapping.size(), nullptr);
   for (unsigned Pass = 1, S = VirtualFileMapping.size(); Pass < S; ++Pass) {
-    for (auto &I : MappingRegions) {
-      if (I.Kind == CounterMappingRegion::ExpansionRegion) {
-        for (const auto &J : MappingRegions) {
-          if (J.FileID == I.ExpandedFileID) {
-            I.Count = J.Count;
-            break;
-          }
-        }
+    for (auto &R : MappingRegions) {
+      if (R.Kind != CounterMappingRegion::ExpansionRegion)
+        continue;
+      assert(!FileIDExpansionRegionMapping[R.ExpandedFileID]);
+      FileIDExpansionRegionMapping[R.ExpandedFileID] = &R;
+    }
+    for (auto &R : MappingRegions) {
+      if (FileIDExpansionRegionMapping[R.FileID]) {
+        FileIDExpansionRegionMapping[R.FileID]->Count = R.Count;
+        FileIDExpansionRegionMapping[R.FileID] = nullptr;
       }
     }
   }
@@ -281,17 +286,7 @@ ObjectFileCoverageMappingReader::ObjectFileCoverageMappingReader(
   if (!File)
     error(File.getError());
   else
-    Object.reset(File.get());
-}
-
-ObjectFileCoverageMappingReader::ObjectFileCoverageMappingReader(
-    std::unique_ptr<MemoryBuffer> &ObjectBuffer, sys::fs::file_magic Type)
-    : CurrentRecord(0) {
-  auto File = llvm::object::ObjectFile::createObjectFile(ObjectBuffer, Type);
-  if (!File)
-    error(File.getError());
-  else
-    Object.reset(File.get());
+    Object = std::move(File.get());
 }
 
 namespace {
@@ -301,6 +296,7 @@ template <typename IntPtrT> struct CoverageMappingFunctionRecord {
   IntPtrT FunctionNamePtr;
   uint32_t FunctionNameSize;
   uint32_t CoverageMappingSize;
+  uint64_t FunctionHash;
 };
 
 /// \brief The coverage mapping data for a single translation unit.
@@ -339,19 +335,11 @@ struct SectionData {
 
 template <typename T>
 std::error_code readCoverageMappingData(
-    SectionRef &ProfileNames, SectionRef &CoverageMapping,
+    SectionData &ProfileNames, StringRef Data,
     std::vector<ObjectFileCoverageMappingReader::ProfileMappingRecord> &Records,
     std::vector<StringRef> &Filenames) {
   llvm::DenseSet<T> UniqueFunctionMappingData;
 
-  // Get the contents of the given sections.
-  StringRef Data;
-  if (auto Err = CoverageMapping.getContents(Data))
-    return Err;
-  SectionData ProfileNamesData;
-  if (auto Err = ProfileNamesData.load(ProfileNames))
-    return Err;
-
   // Read the records in the coverage data section.
   while (!Data.empty()) {
     if (Data.size() < sizeof(CoverageMappingTURecord<T>))
@@ -410,30 +398,88 @@ std::error_code readCoverageMappingData(
         continue;
       UniqueFunctionMappingData.insert(MappingRecord.FunctionNamePtr);
       StringRef FunctionName;
-      if (auto Err = ProfileNamesData.get(MappingRecord.FunctionNamePtr,
-                                          MappingRecord.FunctionNameSize,
-                                          FunctionName))
+      if (auto Err =
+              ProfileNames.get(MappingRecord.FunctionNamePtr,
+                               MappingRecord.FunctionNameSize, FunctionName))
         return Err;
       Records.push_back(ObjectFileCoverageMappingReader::ProfileMappingRecord(
-          Version, FunctionName, Mapping, FilenamesBegin,
-          Filenames.size() - FilenamesBegin));
+          Version, FunctionName, MappingRecord.FunctionHash, Mapping,
+          FilenamesBegin, Filenames.size() - FilenamesBegin));
     }
   }
 
   return instrprof_error::success;
 }
 
+static const char *TestingFormatMagic = "llvmcovmtestdata";
+
+static std::error_code decodeTestingFormat(StringRef Data,
+                                           SectionData &ProfileNames,
+                                           StringRef &CoverageMapping) {
+  Data = Data.substr(StringRef(TestingFormatMagic).size());
+  if (Data.size() < 1)
+    return instrprof_error::truncated;
+  unsigned N = 0;
+  auto ProfileNamesSize =
+      decodeULEB128(reinterpret_cast<const uint8_t *>(Data.data()), &N);
+  if (N > Data.size())
+    return instrprof_error::malformed;
+  Data = Data.substr(N);
+  if (Data.size() < 1)
+    return instrprof_error::truncated;
+  N = 0;
+  ProfileNames.Address =
+      decodeULEB128(reinterpret_cast<const uint8_t *>(Data.data()), &N);
+  if (N > Data.size())
+    return instrprof_error::malformed;
+  Data = Data.substr(N);
+  if (Data.size() < ProfileNamesSize)
+    return instrprof_error::malformed;
+  ProfileNames.Data = Data.substr(0, ProfileNamesSize);
+  CoverageMapping = Data.substr(ProfileNamesSize);
+  return instrprof_error::success;
+}
+
+ObjectFileCoverageMappingReader::ObjectFileCoverageMappingReader(
+    std::unique_ptr<MemoryBuffer> &ObjectBuffer, sys::fs::file_magic Type)
+    : CurrentRecord(0) {
+  if (ObjectBuffer->getBuffer().startswith(TestingFormatMagic)) {
+    // This is a special format used for testing.
+    SectionData ProfileNames;
+    StringRef CoverageMapping;
+    if (auto Err = decodeTestingFormat(ObjectBuffer->getBuffer(), ProfileNames,
+                                       CoverageMapping)) {
+      error(Err);
+      return;
+    }
+    error(readCoverageMappingData<uint64_t>(ProfileNames, CoverageMapping,
+                                            MappingRecords, Filenames));
+    Object = OwningBinary<ObjectFile>(std::unique_ptr<ObjectFile>(),
+                                      std::move(ObjectBuffer));
+    return;
+  }
+
+  auto File = object::ObjectFile::createObjectFile(
+      ObjectBuffer->getMemBufferRef(), Type);
+  if (!File)
+    error(File.getError());
+  else
+    Object = OwningBinary<ObjectFile>(std::move(File.get()),
+                                      std::move(ObjectBuffer));
+}
+
 std::error_code ObjectFileCoverageMappingReader::readHeader() {
-  if (!Object)
+  ObjectFile *OF = Object.getBinary().get();
+  if (!OF)
     return getError();
-  auto BytesInAddress = Object->getBytesInAddress();
+  auto BytesInAddress = OF->getBytesInAddress();
   if (BytesInAddress != 4 && BytesInAddress != 8)
     return error(instrprof_error::malformed);
 
   // Look for the sections that we are interested in.
   int FoundSectionCount = 0;
   SectionRef ProfileNames, CoverageMapping;
-  for (const auto &Section : Object->sections()) {
+  for (const auto &Section : OF->sections()) {
     StringRef Name;
     if (auto Err = Section.getName(Name))
       return Err;
@@ -448,13 +494,21 @@ std::error_code ObjectFileCoverageMappingReader::readHeader() {
   if (FoundSectionCount != 2)
     return error(instrprof_error::bad_header);
 
+  // Get the contents of the given sections.
+  StringRef Data;
+  if (auto Err = CoverageMapping.getContents(Data))
+    return Err;
+  SectionData ProfileNamesData;
+  if (auto Err = ProfileNamesData.load(ProfileNames))
+    return Err;
+
   // Load the data from the found sections.
   std::error_code Err;
   if (BytesInAddress == 4)
-    Err = readCoverageMappingData<uint32_t>(ProfileNames, CoverageMapping,
+    Err = readCoverageMappingData<uint32_t>(ProfileNamesData, Data,
                                             MappingRecords, Filenames);
   else
-    Err = readCoverageMappingData<uint64_t>(ProfileNames, CoverageMapping,
+    Err = readCoverageMappingData<uint64_t>(ProfileNamesData, Data,
                                             MappingRecords, Filenames);
   if (Err)
     return error(Err);
@@ -477,6 +531,7 @@ ObjectFileCoverageMappingReader::readNextRecord(CoverageMappingRecord &Record) {
       FunctionsFilenames, Expressions, MappingRegions);
   if (auto Err = Reader.read(Record))
     return Err;
+  Record.FunctionHash = R.FunctionHash;
   ++CurrentRecord;
   return success();
 }