Files
swift-mirror/include/swift/Remote/RemoteAddress.h
Augusto Noronha 2abdcc9db0 Merge pull request #83040 from augusto2112/sub-remote-addr
[NFC][RemoteInspection] Subtracting remote addresses should return int
2025-07-24 14:32:27 -07:00

283 lines
8.8 KiB
C++

//===--- RemoteAddress.h - Address of remote memory -------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file defines the RemoteAddress type, which abstracts over an
// address in a remote process.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_REMOTE_REMOTEADDRESS_H
#define SWIFT_REMOTE_REMOTEADDRESS_H
#include "swift/ABI/MetadataRef.h"
#include "swift/Basic/RelativePointer.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/Hashing.h"
#include <cassert>
#include <cstdint>
#include <functional>
#include <iostream>
#include <llvm/ADT/StringRef.h>
#include <ostream>
#include <sstream>
#include <string>
namespace swift {
namespace remote {
/// An abstract address in the remote process's address space.
class RemoteAddress {
public:
// The default address space, meaning the remote process address space.
static constexpr uint8_t DefaultAddressSpace = 0;
explicit RemoteAddress(uint64_t addressData, uint8_t addressSpace)
: Data(addressData), AddressSpace(addressSpace) {}
explicit RemoteAddress() {}
explicit operator bool() const { return Data != 0; }
bool operator==(const RemoteAddress rhs) const {
return Data == rhs.Data && AddressSpace == rhs.AddressSpace;
}
bool operator!=(const RemoteAddress other) const {
return !operator==(other);
}
bool inRange(const RemoteAddress &begin, const RemoteAddress &end) const {
assert(begin.AddressSpace == end.AddressSpace &&
"Unexpected address spaces");
if (AddressSpace != begin.AddressSpace)
return false;
return begin <= *this && *this < end;
}
bool operator<(const RemoteAddress rhs) const {
assert(AddressSpace == rhs.AddressSpace &&
"Comparing remote addresses of different address spaces");
return Data < rhs.Data;
}
/// Less than operator to be used for ordering purposes. The default less than
/// operator asserts if the address spaces are different, this one takes it
/// into account to determine the order of the addresses.
bool orderedLessThan(const RemoteAddress rhs) const {
if (AddressSpace == rhs.AddressSpace)
return Data < rhs.Data;
return AddressSpace < rhs.AddressSpace;
}
bool operator<=(const RemoteAddress rhs) const {
assert(AddressSpace == rhs.AddressSpace &&
"Comparing remote addresses of different address spaces");
return Data <= rhs.Data;
}
/// Less than or equal operator to be used for ordering purposes. The default
/// less than or equal operator asserts if the address spaces are different,
/// this one takes it into account to determine the order of the addresses.
bool orderedLessThanOrEqual(const RemoteAddress rhs) const {
if (AddressSpace == rhs.AddressSpace)
return Data <= rhs.Data;
return AddressSpace <= rhs.AddressSpace;
}
bool operator>(const RemoteAddress &rhs) const {
assert(AddressSpace == rhs.AddressSpace &&
"Comparing remote addresses of different address spaces");
return Data > rhs.Data;
}
bool operator>=(const RemoteAddress &rhs) const { return Data >= rhs.Data; }
template <typename IntegerType>
RemoteAddress &operator+=(const IntegerType rhs) {
Data += rhs;
return *this;
}
template <typename IntegerType>
RemoteAddress operator+(const IntegerType &rhs) const {
return RemoteAddress(Data + rhs, getAddressSpace());
}
template <typename IntegerType>
RemoteAddress operator-(const IntegerType &rhs) const {
return RemoteAddress(Data - rhs, getAddressSpace());
}
uint64_t operator-(const RemoteAddress &rhs) const {
assert(AddressSpace == rhs.AddressSpace &&
"Comparing remote addresses of different address spaces");
return Data - rhs.Data;
}
template <typename IntegerType>
RemoteAddress operator^(const IntegerType &rhs) const {
return RemoteAddress(Data ^ rhs, getAddressSpace());
}
template <class IntegerType>
RemoteAddress operator&(IntegerType other) const {
return RemoteAddress(Data & other, getAddressSpace());
}
template <typename IntegerType>
RemoteAddress &operator&=(const IntegerType rhs) {
Data &= rhs;
return *this;
}
template <typename IntegerType>
RemoteAddress &operator|=(const IntegerType rhs) {
Data |= rhs;
return *this;
}
template <typename IntegerType>
IntegerType operator>>(const IntegerType rhs) const {
return (IntegerType)Data >> rhs;
}
uint64_t getRawAddress() const { return Data; }
uint8_t getAddressSpace() const { return AddressSpace; }
template <class IntegerType>
RemoteAddress applyRelativeOffset(IntegerType offset) const {
auto atOffset = detail::applyRelativeOffset((const char *)Data, offset);
return RemoteAddress(atOffset, getAddressSpace());
}
template <typename T, bool Nullable, typename Offset>
RemoteAddress getRelative(
const RelativeDirectPointer<T, Nullable, Offset> *relative) const {
auto ptr = relative->getRelative((void *)Data);
return RemoteAddress((uint64_t)ptr, getAddressSpace());
}
template <class T>
const T *getLocalPointer() const {
return reinterpret_cast<const T *>(static_cast<uintptr_t>(Data));
}
std::string getDescription() const {
std::stringstream sstream;
// FIXME: this should print the address space too, but because Node can't
// carry the address space yet, comparing the strings produced by this type
// and a Node that carries an address would produce incorrect results.
// Revisit this once Node carries the address space.
sstream << std::hex << Data;
return sstream.str();
}
friend llvm::hash_code hash_value(const RemoteAddress &address) {
using llvm::hash_value;
return hash_value(address.Data);
}
friend struct std::hash<swift::remote::RemoteAddress>;
private:
uint64_t Data = 0;
uint8_t AddressSpace = 0;
};
/// A symbolic relocated absolute pointer value.
class RemoteAbsolutePointer {
/// The symbol name that the pointer refers to. Empty if only an absolute
/// address is available.
std::string Symbol;
/// The offset from the symbol.
int64_t Offset = 0;
/// The resolved remote address.
RemoteAddress Address = RemoteAddress();
public:
RemoteAbsolutePointer() = default;
RemoteAbsolutePointer(std::nullptr_t) : RemoteAbsolutePointer() {}
RemoteAbsolutePointer(llvm::StringRef Symbol, int64_t Offset,
RemoteAddress Address)
: Symbol(Symbol), Offset(Offset), Address(Address) {}
RemoteAbsolutePointer(RemoteAddress Address) : Address(Address) {}
llvm::StringRef getSymbol() const { return Symbol; }
int64_t getOffset() const { return Offset; }
RemoteAddress getResolvedAddress() const { return Address; }
explicit operator bool() const {
return Address || !Symbol.empty();
}
};
template <typename Runtime>
class RemoteTargetProtocolDescriptorRef {
TargetProtocolDescriptorRef<Runtime> ProtocolRef;
RemoteAddress address;
public:
RemoteTargetProtocolDescriptorRef(RemoteAddress address)
: ProtocolRef(address.getRawAddress()), address(address) {}
bool isObjC() const { return ProtocolRef.isObjC(); }
RemoteAddress getObjCProtocol() const {
auto pointer = ProtocolRef.getObjCProtocol();
return RemoteAddress(pointer, address.getAddressSpace());
}
RemoteAddress getSwiftProtocol() const {
auto pointer = ProtocolRef.getSwiftProtocol();
return RemoteAddress(pointer, address.getAddressSpace());
}
};
} // end namespace remote
} // end namespace swift
namespace std {
template <>
struct hash<swift::remote::RemoteAddress> {
size_t operator()(const swift::remote::RemoteAddress &address) const {
return llvm::hash_combine(address.Data, address.AddressSpace);
}
};
} // namespace std
namespace llvm {
template <>
struct DenseMapInfo<swift::remote::RemoteAddress> {
static swift::remote::RemoteAddress getEmptyKey() {
return swift::remote::RemoteAddress(DenseMapInfo<uint64_t>::getEmptyKey(),
0);
}
static swift::remote::RemoteAddress getTombstoneKey() {
return swift::remote::RemoteAddress(
DenseMapInfo<uint64_t>::getTombstoneKey(), 0);
}
static unsigned getHashValue(swift::remote::RemoteAddress address) {
return std::hash<swift::remote::RemoteAddress>()(address);
}
static bool isEqual(swift::remote::RemoteAddress lhs,
swift::remote::RemoteAddress rhs) {
return lhs == rhs;
}
};
} // namespace llvm
#endif // SWIFT_REMOTE_REMOTEADDRESS_H