1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
|
//===--- ImageInspectionCommon.cpp - Image inspection routines --*- 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
//
//===----------------------------------------------------------------------===//
///
/// \file
///
/// This file unifies common ELF and COFF image inspection routines
///
//===----------------------------------------------------------------------===//
#ifndef SWIFT_RUNTIME_IMAGEINSPECTIONCOMMON_H
#define SWIFT_RUNTIME_IMAGEINSPECTIONCOMMON_H
#if !defined(__MACH__)
#include "swift/shims/Visibility.h"
#include "swift/shims/MetadataSections.h"
#include "ImageInspection.h"
#include "swift/Basic/Lazy.h"
#include "swift/Runtime/Concurrent.h"
#include <algorithm>
#include <atomic>
#include <cstdlib>
namespace swift {
static Lazy<ConcurrentReadableArray<swift::MetadataSections *>> registered;
/// Adjust the \c baseAddress field of a metadata sections structure.
///
/// \param sections A pointer to a valid \c swift::MetadataSections structure.
///
/// This function should be called at least once before the structure or its
/// address is passed to code outside this file to ensure that the structure's
/// \c baseAddress field correctly points to the base address of the image it
/// is describing.
static void fixupMetadataSectionBaseAddress(swift::MetadataSections *sections) {
bool fixupNeeded = false;
#if defined(__ELF__)
// If the base address was set but the image is an ELF image, it is going to
// be __dso_handle which is not the value we expect (Dl_info::dli_fbase), so
// we need to fix it up.
fixupNeeded = true;
#elif !defined(__MACH__)
// For non-ELF, non-Apple platforms, if the base address is nullptr, it
// implies that this image was built against an older version of the runtime
// that did not capture any value for the base address.
auto oldBaseAddress = sections->baseAddress.load(std::memory_order_relaxed);
if (!oldBaseAddress) {
fixupNeeded = true;
}
#endif
if (fixupNeeded) {
// We need to fix up the base address. We'll need a known-good address in
// the same image: `sections` itself will work nicely.
auto symbolInfo = SymbolInfo::lookup(sections);
if (symbolInfo.has_value() && symbolInfo->getBaseAddress()) {
sections->baseAddress.store(symbolInfo->getBaseAddress(),
std::memory_order_relaxed);
}
}
}
}
SWIFT_RUNTIME_EXPORT
void swift_addNewDSOImage(swift::MetadataSections *sections) {
#if 0
// Ensure the base address of the sections structure is correct.
//
// Currently disabled because none of the registration functions below
// actually do anything with the baseAddress field. Instead,
// swift_enumerateAllMetadataSections() is called by other individual
// functions, lower in this file, that yield metadata section pointers.
//
// If one of these registration functions starts needing the baseAddress
// field, this call should be enabled and the calls elsewhere in the file can
// be removed.
swift::fixupMetadataSectionBaseAddress(sections);
#endif
auto baseAddress = sections->baseAddress.load(std::memory_order_relaxed);
const auto &protocols_section = sections->swift5_protocols;
const void *protocols = reinterpret_cast<void *>(protocols_section.start);
if (protocols_section.length)
swift::addImageProtocolsBlockCallback(baseAddress,
protocols, protocols_section.length);
const auto &protocol_conformances = sections->swift5_protocol_conformances;
const void *conformances =
reinterpret_cast<void *>(protocol_conformances.start);
if (protocol_conformances.length)
swift::addImageProtocolConformanceBlockCallback(baseAddress, conformances,
protocol_conformances.length);
const auto &type_metadata = sections->swift5_type_metadata;
const void *metadata = reinterpret_cast<void *>(type_metadata.start);
if (type_metadata.length)
swift::addImageTypeMetadataRecordBlockCallback(baseAddress,
metadata,
type_metadata.length);
const auto &dynamic_replacements = sections->swift5_replace;
const auto *replacements =
reinterpret_cast<void *>(dynamic_replacements.start);
if (dynamic_replacements.length) {
const auto &dynamic_replacements_some = sections->swift5_replac2;
const auto *replacements_some =
reinterpret_cast<void *>(dynamic_replacements_some.start);
swift::addImageDynamicReplacementBlockCallback(baseAddress,
replacements, dynamic_replacements.length, replacements_some,
dynamic_replacements_some.length);
}
const auto &accessible_funcs_section = sections->swift5_accessible_functions;
const void *functions =
reinterpret_cast<void *>(accessible_funcs_section.start);
if (accessible_funcs_section.length) {
swift::addImageAccessibleFunctionsBlockCallback(
baseAddress, functions, accessible_funcs_section.length);
}
// Register this section for future enumeration by clients. This should occur
// after this function has done all other relevant work to avoid a race
// condition when someone calls swift_enumerateAllMetadataSections() on
// another thread.
swift::registered->push_back(sections);
}
SWIFT_RUNTIME_EXPORT
void swift_enumerateAllMetadataSections(
bool (* body)(const swift::MetadataSections *sections, void *context),
void *context
) {
auto snapshot = swift::registered->snapshot();
for (swift::MetadataSections *sections : snapshot) {
// Ensure the base address is fixed up before yielding the pointer.
swift::fixupMetadataSectionBaseAddress(sections);
// Yield the pointer and (if the callback returns false) break the loop.
if (!(* body)(sections, context)) {
return;
}
}
}
void swift::initializeProtocolLookup() {
}
void swift::initializeProtocolConformanceLookup() {
}
void swift::initializeTypeMetadataRecordLookup() {
}
void swift::initializeDynamicReplacementLookup() {
}
void swift::initializeAccessibleFunctionsLookup() {
}
#ifndef NDEBUG
SWIFT_RUNTIME_EXPORT
const swift::MetadataSections *swift_getMetadataSection(size_t index) {
swift::MetadataSections *result = nullptr;
auto snapshot = swift::registered->snapshot();
if (index < snapshot.count()) {
result = snapshot[index];
}
if (result) {
// Ensure the base address is fixed up before returning it.
swift::fixupMetadataSectionBaseAddress(result);
}
return result;
}
SWIFT_RUNTIME_EXPORT
const char *
swift_getMetadataSectionName(const swift::MetadataSections *section) {
if (auto info = swift::SymbolInfo::lookup(section)) {
if (info->getFilename()) {
return info->getFilename();
}
}
return "";
}
SWIFT_RUNTIME_EXPORT
void swift_getMetadataSectionBaseAddress(const swift::MetadataSections *section,
void const **out_actual,
void const **out_expected) {
if (auto info = swift::SymbolInfo::lookup(section)) {
*out_actual = info->getBaseAddress();
} else {
*out_actual = nullptr;
}
// fixupMetadataSectionBaseAddress() was already called by
// swift_getMetadataSection(), presumably on the same thread, so we don't need
// to call it again here.
*out_expected = section->baseAddress.load(std::memory_order_relaxed);
}
SWIFT_RUNTIME_EXPORT
size_t swift_getMetadataSectionCount() {
auto snapshot = swift::registered->snapshot();
return snapshot.count();
}
#endif // NDEBUG
#endif // !defined(__MACH__)
#endif // SWIFT_RUNTIME_IMAGEINSPECTIONCOMMON_H
|