mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
283 lines
8.8 KiB
C++
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
|