Sign-extend addresses in CompactRingBuffer.

Summary:
This is neccessary to support solaris/sparc9 where some userspace
addresses have all top bits set, as well as, potentially, kernel memory
on aarch64.

This change does not update the compiler side (HWASan IR pass) which
needs to be done separately for the affected targets.

Reviewers: ro, vitalybuka

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D91827
This commit is contained in:
Evgenii Stepanov 2022-02-10 11:31:43 -08:00
parent dd75c0ea64
commit eeb6be144f
1 changed files with 9 additions and 4 deletions

View File

@ -86,10 +86,13 @@ class CompactRingBuffer {
// Lower bytes store the address of the next buffer element.
static constexpr int kPageSizeBits = 12;
static constexpr int kSizeShift = 56;
static constexpr int kSizeBits = 64 - kSizeShift;
static constexpr uptr kNextMask = (1ULL << kSizeShift) - 1;
uptr GetStorageSize() const { return (long_ >> kSizeShift) << kPageSizeBits; }
static uptr SignExtend(uptr x) { return ((sptr)x) << kSizeBits >> kSizeBits; }
void Init(void *storage, uptr size) {
CHECK_EQ(sizeof(CompactRingBuffer<T>), sizeof(void *));
CHECK(IsPowerOfTwo(size));
@ -97,12 +100,14 @@ class CompactRingBuffer {
CHECK_LE(size, 128 << kPageSizeBits);
CHECK_EQ(size % 4096, 0);
CHECK_EQ(size % sizeof(T), 0);
CHECK_EQ((uptr)storage % (size * 2), 0);
long_ = (uptr)storage | ((size >> kPageSizeBits) << kSizeShift);
uptr st = (uptr)storage;
CHECK_EQ(st % (size * 2), 0);
CHECK_EQ(st, SignExtend(st & kNextMask));
long_ = (st & kNextMask) | ((size >> kPageSizeBits) << kSizeShift);
}
void SetNext(const T *next) {
long_ = (long_ & ~kNextMask) | (uptr)next;
long_ = (long_ & ~kNextMask) | ((uptr)next & kNextMask);
}
public:
@ -119,7 +124,7 @@ class CompactRingBuffer {
SetNext((const T *)storage + Idx);
}
T *Next() const { return (T *)(long_ & kNextMask); }
T *Next() const { return (T *)(SignExtend(long_ & kNextMask)); }
void *StartOfStorage() const {
return (void *)((uptr)Next() & ~(GetStorageSize() - 1));