From d49d8eec1266740d2c902e699b5fb31d4f11cd97 Mon Sep 17 00:00:00 2001 From: Justin Bogner Date: Fri, 5 Jun 2015 01:23:42 +0000 Subject: [PATCH] InstrProf: Fix reading of consecutive 32 bit coverage maps When we generate coverage data, we explicitly set each coverage map's alignment to 8 (See InstrProfiling::lowerCoverageData), but when we read the coverage data, we assume consecutive maps are exactly adjacent. When we're dealing with 32 bit, maps can end on a 4 byte boundary, causing us to think the padding is part of the next record. Fix this by adjusting the buffer to an appropriately aligned address between records. This is pretty awkward to test, as it requires a binary with multiple coverage maps to hit, so we'd need to check in multiple source files and a binary blob as inputs. llvm-svn: 239129 --- llvm/include/llvm/Support/MathExtras.h | 4 ++-- llvm/lib/ProfileData/CoverageMappingReader.cpp | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/Support/MathExtras.h b/llvm/include/llvm/Support/MathExtras.h index e3166165a483..2cf7e0e5d0b3 100644 --- a/llvm/include/llvm/Support/MathExtras.h +++ b/llvm/include/llvm/Support/MathExtras.h @@ -562,7 +562,7 @@ inline uint64_t MinAlign(uint64_t A, uint64_t B) { /// /// Alignment should be a power of two. This method rounds up, so /// alignAddr(7, 4) == 8 and alignAddr(8, 4) == 8. -inline uintptr_t alignAddr(void *Addr, size_t Alignment) { +inline uintptr_t alignAddr(const void *Addr, size_t Alignment) { assert(Alignment && isPowerOf2_64((uint64_t)Alignment) && "Alignment is not a power of two!"); @@ -573,7 +573,7 @@ inline uintptr_t alignAddr(void *Addr, size_t Alignment) { /// \brief Returns the necessary adjustment for aligning \c Ptr to \c Alignment /// bytes, rounding up. -inline size_t alignmentAdjustment(void *Ptr, size_t Alignment) { +inline size_t alignmentAdjustment(const void *Ptr, size_t Alignment) { return alignAddr(Ptr, Alignment) - (uintptr_t)Ptr; } diff --git a/llvm/lib/ProfileData/CoverageMappingReader.cpp b/llvm/lib/ProfileData/CoverageMappingReader.cpp index cf6cd58f9533..ec531c3753ec 100644 --- a/llvm/lib/ProfileData/CoverageMappingReader.cpp +++ b/llvm/lib/ProfileData/CoverageMappingReader.cpp @@ -19,6 +19,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/Endian.h" #include "llvm/Support/LEB128.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -358,8 +359,12 @@ std::error_code readCoverageMappingData( const char *CovBuf = Buf; Buf += CoverageSize; const char *CovEnd = Buf; + if (Buf > End) return coveragemap_error::malformed; + // Each coverage map has an alignment of 8, so we need to adjust alignment + // before reading the next map. + Buf += alignmentAdjustment(Buf, 8); while (FunBuf < FunEnd) { // Read the function information