-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[Hashing] Use a non-deterministic seed if LLVM_ENABLE_ABI_BREAKING_CHECKS #96282
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 6 commits
95ccd3c
a1978b5
0f3db68
cff5591
7bc2967
e13096e
a341e03
a99e183
a61163c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -44,6 +44,7 @@ | |
#ifndef LLVM_ADT_HASHING_H | ||
#define LLVM_ADT_HASHING_H | ||
|
||
#include "llvm/Config/abi-breaking.h" | ||
#include "llvm/Support/DataTypes.h" | ||
#include "llvm/Support/ErrorHandling.h" | ||
#include "llvm/Support/SwapByteOrder.h" | ||
|
@@ -126,23 +127,6 @@ hash_code hash_value(const std::basic_string<T> &arg); | |
/// Compute a hash_code for a standard string. | ||
template <typename T> hash_code hash_value(const std::optional<T> &arg); | ||
|
||
/// Override the execution seed with a fixed value. | ||
/// | ||
/// This hashing library uses a per-execution seed designed to change on each | ||
/// run with high probability in order to ensure that the hash codes are not | ||
/// attackable and to ensure that output which is intended to be stable does | ||
/// not rely on the particulars of the hash codes produced. | ||
/// | ||
/// That said, there are use cases where it is important to be able to | ||
/// reproduce *exactly* a specific behavior. To that end, we provide a function | ||
/// which will forcibly set the seed to a fixed value. This must be done at the | ||
/// start of the program, before any hashes are computed. Also, it cannot be | ||
/// undone. This makes it thread-hostile and very hard to use outside of | ||
/// immediately on start of a simple program designed for reproducible | ||
/// behavior. | ||
void set_fixed_execution_hash_seed(uint64_t fixed_value); | ||
|
||
|
||
// All of the implementation details of actually computing the various hash | ||
// code values are held within this namespace. These routines are included in | ||
// the header file mainly to allow inlining and constant propagation. | ||
|
@@ -322,24 +306,20 @@ struct hash_state { | |
} | ||
}; | ||
|
||
|
||
/// A global, fixed seed-override variable. | ||
/// | ||
/// This variable can be set using the \see llvm::set_fixed_execution_seed | ||
/// function. See that function for details. Do not, under any circumstances, | ||
/// set or read this variable. | ||
extern uint64_t fixed_seed_override; | ||
|
||
/// In LLVM_ENABLE_ABI_BREAKING_CHECKS builds, the seed is non-deterministic | ||
/// (address of a variable) to prevent having users depend on the particular | ||
/// hash values. On platforms without ASLR, this is still likely | ||
/// non-deterministic per build. | ||
inline uint64_t get_execution_seed() { | ||
// FIXME: This needs to be a per-execution seed. This is just a placeholder | ||
// implementation. Switching to a per-execution seed is likely to flush out | ||
// instability bugs and so will happen as its own commit. | ||
// | ||
// However, if there is a fixed seed override set the first time this is | ||
// called, return that instead of the per-execution seed. | ||
const uint64_t seed_prime = 0xff51afd7ed558ccdULL; | ||
static uint64_t seed = fixed_seed_override ? fixed_seed_override : seed_prime; | ||
return seed; | ||
[[maybe_unused]] static const char seed = 0; | ||
// Work around x86-64 negative offset folding for old Clang -fno-pic | ||
// https://reviews.llvm.org/D93931 | ||
#if LLVM_ENABLE_ABI_BREAKING_CHECKS && \ | ||
(!defined(__clang__) || __clang_major__ > 11) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it an ABI problem that this ifdef exists? I mean, LLVM libraries built with clang<11 can't be used by programs built with clang>11. With LLVM_ENABLE_ABI_BREAKING_CHECKS, I guess it's unlikely to cause issues, though. (I guess you could use an empty inline asm as a workaround if you wanted to.) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The clang condition introduced a slight ABI problem when mixing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wouldn't this affect any access to a DenseMap across the boundary for example? That is any API where LLVM would initialize a DenseMap and return a reference to it to the user which then access elements by computing key hashes? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is definitely a problem for LLVM built using GCC and an external project, based on LLVM, built using CLANG 11. Is there a reliable check that we can add (e.g. in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. LLVM built with GCC are typically release builds and LLVM_ENABLE_ABI_BREAKING_CHECKS is 0. The If we want to be over-cautious, this condition can be refined to: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe it would make sense to move the function to the source file for the LLVM_ENABLE_ABI_BREAKING_CHECKS case? It will add cost, but it's okay for assertion-enabled builds. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In my case it is a Could you please explain how There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We are still dealing with the fallout from this change in Triton. It seems that breaking the ABI across different compilers is acceptable, but it would be good to detect this and error out. We already detect mismatches of |
||
return static_cast<uint64_t>(reinterpret_cast<uintptr_t>(&seed)); | ||
#else | ||
return 0xff51afd7ed558ccdULL; | ||
#endif | ||
} | ||
|
||
|
||
|
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move this inside the
#if
?