mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Until recently, `MemoryReader` had a single function `resovlePointer` which did two things, and has a somewhat vague name. The two things were: 1. Tool-specific mapping between real addresses and tagged addresses (first implemented in `swift-reflection-dump` and then later in lldb) 2. Finding a "symbol" for a given address Recently, `resolvePointerAsSymbol` was added, which overloaded the term "resolve" and it added another way to deal with symbols for addresses. Symbols themselves were a bit muddled, as `swift-reflection-dump` was dealing with dynamic symbols aka bindings, while lldb was dealing in regular (static) symbols. This change separates these two parts of functionality, and also divides symbol lookup into two cases. The API surface will now be: 1. `resolvePointer` for mapping/tagging addresses 3. `getSymbol` for looking up a symbol for an address 4. `getDynamicSymbol` for looking up a dyld binding for an address Note: each of these names could be improved. Some alternative terms: `lookup` instead of `get`, `Binding` or `BindingName` instead of `DynamicSymbol`. Maybe even another term instead of "resolve". Suggestions welcome! Currently, `swift-reflection-dump` supports `getDynamicSymbol` but not `getSymbol`. For lldb it's the reverse, `getSymbol` is supported but `getDynamicSymbol` needs to be implemented. For everything but lldb, this change is NFC. For lldb it fixes a bug where `LLDBMemoryReader` returns regular symbols where we should instead be returning dynamic symbols.
156 lines
4.7 KiB
C++
156 lines
4.7 KiB
C++
//===---------------- ObjectFileContext.h - Swift Compiler ---------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2021 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SWIFT_OBJECT_FILE_CONTEXT_H
|
|
#define SWIFT_OBJECT_FILE_CONTEXT_H
|
|
|
|
#include "swift/Reflection/ReflectionContext.h"
|
|
|
|
namespace llvm {
|
|
namespace object {
|
|
template <typename Type>
|
|
class ELFObjectFile;
|
|
class ELFObjectFileBase;
|
|
class MachOObjectFile;
|
|
} // namespace object
|
|
} // namespace llvm
|
|
|
|
namespace swift {
|
|
namespace static_mirror {
|
|
|
|
using ReadBytesResult = swift::remote::MemoryReader::ReadBytesResult;
|
|
|
|
class Image {
|
|
private:
|
|
struct Segment {
|
|
uint64_t Addr;
|
|
StringRef Contents;
|
|
};
|
|
const llvm::object::ObjectFile *O;
|
|
uint64_t HeaderAddress;
|
|
std::vector<Segment> Segments;
|
|
struct DynamicRelocation {
|
|
StringRef Symbol;
|
|
uint64_t Offset;
|
|
};
|
|
llvm::DenseMap<uint64_t, DynamicRelocation> DynamicRelocations;
|
|
|
|
void scanMachO(const llvm::object::MachOObjectFile *O);
|
|
|
|
template <typename ELFT>
|
|
void scanELFType(const llvm::object::ELFObjectFile<ELFT> *O);
|
|
|
|
void scanELF(const llvm::object::ELFObjectFileBase *O);
|
|
|
|
void scanCOFF(const llvm::object::COFFObjectFile *O);
|
|
|
|
bool isMachOWithPtrAuth() const;
|
|
|
|
public:
|
|
explicit Image(const llvm::object::ObjectFile *O);
|
|
|
|
const llvm::object::ObjectFile *getObjectFile() const { return O; }
|
|
|
|
unsigned getBytesInAddress() const { return O->getBytesInAddress(); }
|
|
|
|
uint64_t getStartAddress() const { return HeaderAddress; }
|
|
|
|
uint64_t getEndAddress() const;
|
|
|
|
StringRef getContentsAtAddress(uint64_t Addr, uint64_t Size) const;
|
|
|
|
remote::RemoteAbsolutePointer resolvePointer(uint64_t Addr,
|
|
uint64_t pointerValue) const;
|
|
|
|
remote::RemoteAbsolutePointer getDynamicSymbol(uint64_t Addr) const;
|
|
};
|
|
|
|
/// MemoryReader that reads from the on-disk representation of an executable
|
|
/// or dynamic library image.
|
|
///
|
|
/// This reader uses a remote addressing scheme where the most significant
|
|
/// 16 bits of the address value serve as an index into the array of loaded
|
|
/// images, and the low 48 bits correspond to the preferred virtual address
|
|
/// mapping of the image.
|
|
class ObjectMemoryReader : public reflection::MemoryReader {
|
|
struct ImageEntry {
|
|
Image TheImage;
|
|
uint64_t Slide;
|
|
};
|
|
std::vector<ImageEntry> Images;
|
|
|
|
std::pair<const Image *, uint64_t>
|
|
decodeImageIndexAndAddress(uint64_t Addr) const;
|
|
|
|
uint64_t encodeImageIndexAndAddress(const Image *image,
|
|
uint64_t imageAddr) const;
|
|
|
|
StringRef getContentsAtAddress(uint64_t Addr, uint64_t Size);
|
|
|
|
public:
|
|
explicit ObjectMemoryReader(
|
|
const std::vector<const llvm::object::ObjectFile *> &ObjectFiles);
|
|
|
|
ArrayRef<ImageEntry> getImages() const { return Images; }
|
|
|
|
bool queryDataLayout(DataLayoutQueryType type, void *inBuffer,
|
|
void *outBuffer) override;
|
|
|
|
reflection::RemoteAddress getImageStartAddress(unsigned i) const;
|
|
|
|
// TODO: We could consult the dynamic symbol tables of the images to
|
|
// implement this.
|
|
reflection::RemoteAddress getSymbolAddress(const std::string &name) override {
|
|
return reflection::RemoteAddress(nullptr);
|
|
}
|
|
|
|
ReadBytesResult readBytes(reflection::RemoteAddress Addr,
|
|
uint64_t Size) override;
|
|
|
|
bool readString(reflection::RemoteAddress Addr, std::string &Dest) override;
|
|
|
|
remote::RemoteAbsolutePointer resolvePointer(reflection::RemoteAddress Addr,
|
|
uint64_t pointerValue) override;
|
|
|
|
remote::RemoteAbsolutePointer
|
|
getDynamicSymbol(reflection::RemoteAddress Addr) override;
|
|
};
|
|
|
|
using ReflectionContextOwner = std::unique_ptr<void, void (*)(void *)>;
|
|
|
|
struct ReflectionContextHolder {
|
|
ReflectionContextOwner Owner;
|
|
reflection::TypeRefBuilder &Builder;
|
|
ObjectMemoryReader &Reader;
|
|
uint8_t PointerSize;
|
|
};
|
|
|
|
template <typename T>
|
|
T unwrap(llvm::Expected<T> value) {
|
|
if (value)
|
|
return std::move(value.get());
|
|
llvm::errs() << "swift-reflection-test error: " << toString(value.takeError())
|
|
<< "\n";
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
std::unique_ptr<ReflectionContextHolder> makeReflectionContextForObjectFiles(
|
|
const std::vector<const llvm::object::ObjectFile *> &objectFiles);
|
|
|
|
std::unique_ptr<ReflectionContextHolder> makeReflectionContextForMetadataReader(
|
|
std::shared_ptr<ObjectMemoryReader> reader);
|
|
|
|
} // end namespace static_mirror
|
|
} // end namespace swift
|
|
|
|
#endif // SWIFT_OBJECT_FILE_CONTEXT_H
|