summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/CodeGen/CodeGenPGO.cpp2
-rw-r--r--clang/lib/Frontend/ASTUnit.cpp4
-rw-r--r--lld/COFF/Writer.cpp2
-rw-r--r--lldb/source/Host/common/FileSystem.cpp4
-rw-r--r--lldb/source/Utility/DataExtractor.cpp4
-rw-r--r--llvm/include/llvm/Support/FileSystem.h11
-rw-r--r--llvm/include/llvm/Support/MD5.h36
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DIEHash.cpp12
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp7
-rw-r--r--llvm/lib/Support/MD5.cpp14
-rw-r--r--llvm/lib/Support/Path.cpp35
-rw-r--r--llvm/unittests/Support/MD5Test.cpp4
-rw-r--r--llvm/unittests/Support/Path.cpp14
13 files changed, 118 insertions, 31 deletions
diff --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp
index 90711b54794..6acedc033a6 100644
--- a/clang/lib/CodeGen/CodeGenPGO.cpp
+++ b/clang/lib/CodeGen/CodeGenPGO.cpp
@@ -612,7 +612,7 @@ uint64_t PGOHash::finalize() {
llvm::MD5::MD5Result Result;
MD5.final(Result);
using namespace llvm::support;
- return endian::read<uint64_t, little, unaligned>(Result);
+ return Result.low();
}
void CodeGenPGO::assignRegionCounters(GlobalDecl GD, llvm::Function *Fn) {
diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp
index 952992a9e8b..2acdc6494f8 100644
--- a/clang/lib/Frontend/ASTUnit.cpp
+++ b/clang/lib/Frontend/ASTUnit.cpp
@@ -1252,7 +1252,7 @@ ASTUnit::PreambleFileHash::createForFile(off_t Size, time_t ModTime) {
PreambleFileHash Result;
Result.Size = Size;
Result.ModTime = ModTime;
- memset(Result.MD5, 0, sizeof(Result.MD5));
+ Result.MD5 = {};
return Result;
}
@@ -1273,7 +1273,7 @@ namespace clang {
bool operator==(const ASTUnit::PreambleFileHash &LHS,
const ASTUnit::PreambleFileHash &RHS) {
return LHS.Size == RHS.Size && LHS.ModTime == RHS.ModTime &&
- memcmp(LHS.MD5, RHS.MD5, sizeof(LHS.MD5)) == 0;
+ LHS.MD5 == RHS.MD5;
}
} // namespace clang
diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index 05615bbeea4..a37241f5c4d 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -791,7 +791,7 @@ void Writer::writeBuildId() {
"only PDB 7.0 is supported");
assert(sizeof(Res) == sizeof(BuildId->DI->PDB70.Signature) &&
"signature size mismatch");
- memcpy(BuildId->DI->PDB70.Signature, Res,
+ memcpy(BuildId->DI->PDB70.Signature, Res.Bytes.data(),
sizeof(codeview::PDB70DebugInfo::Signature));
// TODO(compnerd) track the Age
BuildId->DI->PDB70.Age = 1;
diff --git a/lldb/source/Host/common/FileSystem.cpp b/lldb/source/Host/common/FileSystem.cpp
index 88f29b46f36..55092dc8400 100644
--- a/lldb/source/Host/common/FileSystem.cpp
+++ b/lldb/source/Host/common/FileSystem.cpp
@@ -67,9 +67,7 @@ bool FileSystem::CalculateMD5(const FileSpec &file_spec, uint64_t offset,
if (!CalcMD5(file_spec, offset, length, md5_result))
return false;
- const auto uint64_res = reinterpret_cast<const uint64_t *>(md5_result);
- high = uint64_res[0];
- low = uint64_res[1];
+ std::tie(high, low) = md5_result.words();
return true;
}
diff --git a/lldb/source/Utility/DataExtractor.cpp b/lldb/source/Utility/DataExtractor.cpp
index 5b59f0eaac3..5dc518beeaf 100644
--- a/lldb/source/Utility/DataExtractor.cpp
+++ b/lldb/source/Utility/DataExtractor.cpp
@@ -1233,6 +1233,6 @@ void DataExtractor::Checksum(llvm::SmallVectorImpl<uint8_t> &dest,
llvm::MD5::MD5Result result;
md5.final(result);
- dest.resize(16);
- std::copy(result, result + 16, dest.begin());
+ dest.clear();
+ dest.append(result.Bytes.begin(), result.Bytes.end());
}
diff --git a/llvm/include/llvm/Support/FileSystem.h b/llvm/include/llvm/Support/FileSystem.h
index ab8cbf7567d..ebb493d30ad 100644
--- a/llvm/include/llvm/Support/FileSystem.h
+++ b/llvm/include/llvm/Support/FileSystem.h
@@ -33,6 +33,7 @@
#include "llvm/Support/Chrono.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/MD5.h"
#include <cassert>
#include <cstdint>
#include <ctime>
@@ -399,6 +400,16 @@ std::error_code copy_file(const Twine &From, const Twine &To);
/// platform-specific error_code.
std::error_code resize_file(int FD, uint64_t Size);
+/// @brief Compute an MD5 hash of a file's contents.
+///
+/// @param FD Input file descriptor.
+/// @returns An MD5Result with the hash computed, if successful, otherwise a
+/// std::error_code.
+ErrorOr<MD5::MD5Result> md5_contents(int FD);
+
+/// @brief Version of compute_md5 that doesn't require an open file descriptor.
+ErrorOr<MD5::MD5Result> md5_contents(const Twine &Path);
+
/// @}
/// @name Physical Observers
/// @{
diff --git a/llvm/include/llvm/Support/MD5.h b/llvm/include/llvm/Support/MD5.h
index 190cf4cbc52..2c0dc76485f 100644
--- a/llvm/include/llvm/Support/MD5.h
+++ b/llvm/include/llvm/Support/MD5.h
@@ -52,7 +52,32 @@ class MD5 {
MD5_u32plus block[16];
public:
- typedef uint8_t MD5Result[16];
+ struct MD5Result {
+ std::array<uint8_t, 16> Bytes;
+
+ operator std::array<uint8_t, 16>() const { return Bytes; }
+
+ const uint8_t &operator[](size_t I) const { return Bytes[I]; }
+ uint8_t &operator[](size_t I) { return Bytes[I]; }
+
+ SmallString<32> digest() const;
+
+ uint64_t low() const {
+ // Our MD5 implementation returns the result in little endian, so the low
+ // word is first.
+ using namespace support;
+ return endian::read<uint64_t, little, unaligned>(Bytes.data());
+ }
+
+ uint64_t high() const {
+ using namespace support;
+ return endian::read<uint64_t, little, unaligned>(Bytes.data() + 8);
+ }
+ std::pair<uint64_t, uint64_t> words() const {
+ using namespace support;
+ return std::make_pair(high(), low());
+ }
+ };
MD5();
@@ -76,6 +101,10 @@ private:
const uint8_t *body(ArrayRef<uint8_t> Data);
};
+inline bool operator==(const MD5::MD5Result &LHS, const MD5::MD5Result &RHS) {
+ return LHS.Bytes == RHS.Bytes;
+}
+
/// Helper to compute and return lower 64 bits of the given string's MD5 hash.
inline uint64_t MD5Hash(StringRef Str) {
using namespace support;
@@ -84,9 +113,8 @@ inline uint64_t MD5Hash(StringRef Str) {
Hash.update(Str);
MD5::MD5Result Result;
Hash.final(Result);
- // Return the least significant 8 bytes. Our MD5 implementation returns the
- // result in little endian, so we may need to swap bytes.
- return endian::read<uint64_t, little, unaligned>(Result);
+ // Return the least significant word.
+ return Result.low();
}
} // end namespace llvm
diff --git a/llvm/lib/CodeGen/AsmPrinter/DIEHash.cpp b/llvm/lib/CodeGen/AsmPrinter/DIEHash.cpp
index d8ecc7ccfb9..8e3b88d0af0 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DIEHash.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DIEHash.cpp
@@ -490,9 +490,9 @@ uint64_t DIEHash::computeCUSignature(const DIE &Die) {
Hash.final(Result);
// ... take the least significant 8 bytes and return those. Our MD5
- // implementation always returns its results in little endian, swap bytes
- // appropriately.
- return support::endian::read64le(Result + 8);
+ // implementation always returns its results in little endian, so we actually
+ // need the "high" word.
+ return Result.high();
}
/// This is based on the type signature computation given in section 7.27 of the
@@ -514,7 +514,7 @@ uint64_t DIEHash::computeTypeSignature(const DIE &Die) {
Hash.final(Result);
// ... take the least significant 8 bytes and return those. Our MD5
- // implementation always returns its results in little endian, swap bytes
- // appropriately.
- return support::endian::read64le(Result + 8);
+ // implementation always returns its results in little endian, so we actually
+ // need the "high" word.
+ return Result.high();
}
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 0b9bacd86e5..15e5be2e65d 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -39,7 +39,6 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Dwarf.h"
-#include "llvm/Support/Endian.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/LEB128.h"
@@ -1945,11 +1944,11 @@ uint64_t DwarfDebug::makeTypeSignature(StringRef Identifier) {
MD5 Hash;
Hash.update(Identifier);
// ... take the least significant 8 bytes and return those. Our MD5
- // implementation always returns its results in little endian, swap bytes
- // appropriately.
+ // implementation always returns its results in little endian, so we actually
+ // need the "high" word.
MD5::MD5Result Result;
Hash.final(Result);
- return support::endian::read64le(Result + 8);
+ return Result.high();
}
void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
diff --git a/llvm/lib/Support/MD5.cpp b/llvm/lib/Support/MD5.cpp
index 809dbbce708..bdbf1d67793 100644
--- a/llvm/lib/Support/MD5.cpp
+++ b/llvm/lib/Support/MD5.cpp
@@ -261,10 +261,16 @@ void MD5::final(MD5Result &Result) {
support::endian::write32le(&Result[12], d);
}
-void MD5::stringifyResult(MD5Result &Result, SmallString<32> &Str) {
+SmallString<32> MD5::MD5Result::digest() const {
+ SmallString<32> Str;
raw_svector_ostream Res(Str);
for (int i = 0; i < 16; ++i)
- Res << format("%.2x", Result[i]);
+ Res << format("%.2x", Bytes[i]);
+ return Str;
+}
+
+void MD5::stringifyResult(MD5Result &Result, SmallString<32> &Str) {
+ Str = Result.digest();
}
std::array<uint8_t, 16> MD5::hash(ArrayRef<uint8_t> Data) {
@@ -273,7 +279,5 @@ std::array<uint8_t, 16> MD5::hash(ArrayRef<uint8_t> Data) {
MD5::MD5Result Res;
Hash.final(Res);
- std::array<uint8_t, 16> Arr;
- memcpy(Arr.data(), Res, sizeof(Res));
- return Arr;
+ return Res;
}
diff --git a/llvm/lib/Support/Path.cpp b/llvm/lib/Support/Path.cpp
index ffb8ab22088..9fd6652ce4b 100644
--- a/llvm/lib/Support/Path.cpp
+++ b/llvm/lib/Support/Path.cpp
@@ -11,13 +11,14 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/Support/Path.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/COFF.h"
-#include "llvm/Support/MachO.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Path.h"
+#include "llvm/Support/MachO.h"
#include "llvm/Support/Process.h"
#include <cctype>
#include <cstring>
@@ -924,6 +925,36 @@ std::error_code copy_file(const Twine &From, const Twine &To) {
return std::error_code();
}
+ErrorOr<MD5::MD5Result> md5_contents(int FD) {
+ MD5 Hash;
+
+ constexpr size_t BufSize = 4096;
+ std::vector<uint8_t> Buf(BufSize);
+ int BytesRead = 0;
+ for (;;) {
+ BytesRead = read(FD, Buf.data(), BufSize);
+ if (BytesRead <= 0)
+ break;
+ Hash.update(makeArrayRef(Buf.data(), BytesRead));
+ }
+
+ if (BytesRead < 0)
+ return std::error_code(errno, std::generic_category());
+ MD5::MD5Result Result;
+ Hash.final(Result);
+ return Result;
+}
+
+ErrorOr<MD5::MD5Result> md5_contents(const Twine &Path) {
+ int FD;
+ if (auto EC = openFileForRead(Path, FD))
+ return EC;
+
+ auto Result = md5_contents(FD);
+ close(FD);
+ return Result;
+}
+
bool exists(file_status status) {
return status_known(status) && status.type() != file_type::file_not_found;
}
diff --git a/llvm/unittests/Support/MD5Test.cpp b/llvm/unittests/Support/MD5Test.cpp
index 4d790254503..fa9372fde33 100644
--- a/llvm/unittests/Support/MD5Test.cpp
+++ b/llvm/unittests/Support/MD5Test.cpp
@@ -63,8 +63,10 @@ TEST(MD5HashTest, MD5) {
std::array<uint8_t, 16> Vec = MD5::hash(Input);
MD5::MD5Result MD5Res;
SmallString<32> Res;
- memcpy(MD5Res, Vec.data(), Vec.size());
+ memcpy(MD5Res.Bytes.data(), Vec.data(), Vec.size());
MD5::stringifyResult(MD5Res, Res);
EXPECT_EQ(Res, "c3fcd3d76192e4007dfb496cca67e13b");
+ EXPECT_EQ(0x3be167ca6c49fb7dULL, MD5Res.high());
+ EXPECT_EQ(0x00e49261d7d3fcc3ULL, MD5Res.low());
}
}
diff --git a/llvm/unittests/Support/Path.cpp b/llvm/unittests/Support/Path.cpp
index edda1cd6d24..4883adef165 100644
--- a/llvm/unittests/Support/Path.cpp
+++ b/llvm/unittests/Support/Path.cpp
@@ -1011,6 +1011,20 @@ TEST_F(FileSystemTest, Resize) {
ASSERT_NO_ERROR(fs::remove(TempPath));
}
+TEST_F(FileSystemTest, MD5) {
+ int FD;
+ SmallString<64> TempPath;
+ ASSERT_NO_ERROR(fs::createTemporaryFile("prefix", "temp", FD, TempPath));
+ StringRef Data("abcdefghijklmnopqrstuvwxyz");
+ write(FD, Data.data(), Data.size());
+ lseek(FD, 0, SEEK_SET);
+ auto Hash = fs::md5_contents(FD);
+ ::close(FD);
+ ASSERT_NO_ERROR(Hash.getError());
+
+ EXPECT_STREQ("c3fcd3d76192e4007dfb496cca67e13b", Hash->digest().c_str());
+}
+
TEST_F(FileSystemTest, FileMapping) {
// Create a temp file.
int FileDescriptor;
OpenPOWER on IntegriCloud