Skip to content

Commit e9ce682

Browse files
authored
Merge pull request #5846 from jckarter/refactor-section-registration
Runtime: Refactor platform-dependent image inspection code.
2 parents 81f9fa2 + 87b27c6 commit e9ce682

File tree

9 files changed

+454
-368
lines changed

9 files changed

+454
-368
lines changed

stdlib/public/runtime/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ set(swift_runtime_sources
4040
ErrorDefaultImpls.cpp
4141
Heap.cpp
4242
HeapObject.cpp
43+
ImageInspectionMachO.cpp
44+
ImageInspectionELF.cpp
45+
ImageInspectionWin32.cpp
4346
KnownMetadata.cpp
4447
Metadata.cpp
4548
MetadataLookup.cpp

stdlib/public/runtime/CygwinPort.cpp

Lines changed: 0 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -32,112 +32,6 @@ using namespace swift;
3232

3333
static std::mutex swiftOnceMutex;
3434

35-
int swift::_swift_dl_iterate_phdr(int (*Callback)(struct dl_phdr_info *info,
36-
size_t size, void *data),
37-
void *data) {
38-
DWORD procId = GetCurrentProcessId();
39-
HANDLE procHandle =
40-
OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, procId);
41-
if (!procHandle) {
42-
swift::fatalError(/* flags = */ 0, "OpenProcess() failed");
43-
return 0;
44-
}
45-
46-
int lastRet = 0;
47-
48-
std::vector<HMODULE> modules(1024);
49-
DWORD neededSize;
50-
51-
BOOL ret = EnumProcessModules(procHandle, modules.data(),
52-
modules.size() * sizeof(HMODULE), &neededSize);
53-
54-
if (!ret) {
55-
swift::fatalError(/* flags = */ 0, "EnumProcessModules() failed");
56-
return 0;
57-
}
58-
59-
if (modules.size() * sizeof(HMODULE) < neededSize) {
60-
modules.resize(neededSize / sizeof(HMODULE));
61-
ret = EnumProcessModules(procHandle, modules.data(),
62-
modules.size() * sizeof(HMODULE), &neededSize);
63-
}
64-
65-
if (!ret) {
66-
swift::fatalError(/* flags = */ 0, "EnumProcessModules() failed");
67-
return 0;
68-
}
69-
70-
for (unsigned i = 0; i < neededSize / sizeof(HMODULE); i++) {
71-
char modName[MAX_PATH];
72-
73-
if (!GetModuleFileNameExA(procHandle, modules[i], modName,
74-
sizeof(modName))) {
75-
swift::fatalError(/* flags = */ 0, "GetModuleFileNameExA() failed");
76-
}
77-
78-
dl_phdr_info hdr;
79-
hdr.dlpi_name = modName;
80-
hdr.dlpi_addr = modules[i];
81-
82-
lastRet = Callback(&hdr, sizeof(hdr), data);
83-
if (lastRet != 0)
84-
break;
85-
}
86-
87-
CloseHandle(procHandle);
88-
89-
return lastRet;
90-
}
91-
92-
uint8_t *swift::_swift_getSectionDataPE(void *handle, const char *sectionName,
93-
unsigned long *sectionSize) {
94-
// In Cygwin, dlopen() returns PE/COFF image pointer.
95-
// This is relying on undocumented feature of Windows API LoadLibrary().
96-
unsigned char *peStart = (unsigned char *)handle;
97-
98-
const int kLocationOfNtHeaderOffset = 0x3C;
99-
int ntHeadersOffset =
100-
*reinterpret_cast<int32_t *>(peStart + kLocationOfNtHeaderOffset);
101-
102-
bool assert1 =
103-
peStart[ntHeadersOffset] == 'P' && peStart[ntHeadersOffset + 1] == 'E';
104-
if (!assert1) {
105-
swift::fatalError(/* flags = */ 0, "_swift_getSectionDataPE()'s finding PE failed");
106-
}
107-
108-
unsigned char *coff = peStart + ntHeadersOffset + 4;
109-
110-
int16_t numberOfSections = *(int16_t *)(coff + 2);
111-
112-
// SizeOfOptionalHeader
113-
int16_t sizeOfOptionalHeader = *(int16_t *)(coff + 16);
114-
115-
const int kCoffFileHeaderSize = 20;
116-
unsigned char *sectionTableBase =
117-
coff + kCoffFileHeaderSize + sizeOfOptionalHeader;
118-
119-
// Section Header Record
120-
const int kSectionRecordSize = 40;
121-
122-
unsigned char *sectionHeader = sectionTableBase;
123-
for (int i = 0; i < numberOfSections; i++) {
124-
uint32_t virtualSize = *(uint32_t *)&sectionHeader[8];
125-
uint32_t virtualAddress = *(uint32_t *)&sectionHeader[12];
126-
127-
char nameOfThisSection[9];
128-
memcpy(nameOfThisSection, sectionHeader, 8);
129-
nameOfThisSection[8] = '\0';
130-
131-
if (strcmp(sectionName, nameOfThisSection) == 0) {
132-
*sectionSize = virtualSize;
133-
return (uint8_t *)handle + virtualAddress;
134-
}
135-
sectionHeader += kSectionRecordSize;
136-
}
137-
138-
return nullptr;
139-
}
140-
14135
#if !defined(_MSC_VER)
14236
void swift::_swift_once_f(uintptr_t *predicate, void *context,
14337
void (*function)(void *)) {
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//===--- ImageInspection.h - Image inspection routines --------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file includes routines that extract metadata from executable and
14+
// dynamic library image files generated by the Swift compiler. The
15+
// concrete implementations vary greatly by platform.
16+
//
17+
//===----------------------------------------------------------------------===//
18+
19+
#ifndef SWIFT_RUNTIME_IMAGE_INSPECTION_H
20+
#define SWIFT_RUNTIME_IMAGE_INSPECTION_H
21+
22+
#include <cstdint>
23+
24+
namespace swift {
25+
26+
/// Load the metadata from the image necessary to find a type's
27+
/// protocol conformance.
28+
void initializeProtocolConformanceLookup();
29+
30+
/// Load the metadata from the image necessary to find a type by name.
31+
void initializeTypeMetadataRecordLookup();
32+
33+
// Callbacks to register metadata from an image to the runtime.
34+
35+
void addImageProtocolConformanceBlockCallback(const void *start,
36+
uintptr_t size);
37+
void addImageTypeMetadataRecordBlockCallback(const void *start,
38+
uintptr_t size);
39+
40+
} // end namespace swift
41+
42+
#endif // SWIFT_RUNTIME_IMAGE_INSPECTION_H
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
//===--- ImageInspectionELFDynamic.cpp - ELF image inspection -------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file includes routines that interact with ld*.so on ELF-based platforms
14+
// to extract runtime metadata embedded in dynamically linked ELF images
15+
// generated by the Swift compiler.
16+
//
17+
//===----------------------------------------------------------------------===//
18+
19+
#if defined(__ELF__) || defined(__ANDROID__)
20+
21+
#include "ImageInspection.h"
22+
#include <elf.h>
23+
#include <link.h>
24+
#include <dlfcn.h>
25+
#include <string.h>
26+
27+
using namespace swift;
28+
29+
/// The symbol name in the image that identifies the beginning of the
30+
/// protocol conformances table.
31+
static const char ProtocolConformancesSymbol[] =
32+
".swift2_protocol_conformances_start";
33+
/// The symbol name in the image that identifies the beginning of the
34+
/// type metadata record table.
35+
static const char TypeMetadataRecordsSymbol[] =
36+
".swift2_type_metadata_start";
37+
38+
/// Context arguments passed down from dl_iterate_phdr to its callback.
39+
struct InspectArgs {
40+
/// Symbol name to look up.
41+
const char *symbolName;
42+
/// Callback function to invoke with the metadata block.
43+
void (*addBlock)(const void *start, uintptr_t size);
44+
};
45+
46+
static int iteratePHDRCallback(struct dl_phdr_info *info,
47+
size_t size, void *data) {
48+
const InspectArgs *inspectArgs = reinterpret_cast<const InspectArgs *>(data);
49+
void *handle;
50+
if (!info->dlpi_name || info->dlpi_name[0] == '\0') {
51+
handle = dlopen(nullptr, RTLD_LAZY);
52+
} else {
53+
handle = dlopen(info->dlpi_name, RTLD_LAZY | RTLD_NOLOAD);
54+
}
55+
56+
if (!handle) {
57+
// Not a shared library.
58+
return 0;
59+
}
60+
61+
const char *conformances =
62+
reinterpret_cast<const char*>(dlsym(handle, inspectArgs->symbolName));
63+
64+
if (!conformances) {
65+
// if there are no conformances, don't hold this handle open.
66+
dlclose(handle);
67+
return 0;
68+
}
69+
70+
// Extract the size of the conformances block from the head of the section.
71+
uint64_t conformancesSize;
72+
memcpy(&conformancesSize, conformances, sizeof(conformancesSize));
73+
conformances += sizeof(conformancesSize);
74+
75+
inspectArgs->addBlock(conformances, conformancesSize);
76+
77+
dlclose(handle);
78+
return 0;
79+
}
80+
81+
void swift::initializeProtocolConformanceLookup() {
82+
// Search the loaded dls. This only searches the already
83+
// loaded ones.
84+
// FIXME: Find a way to have this continue to happen for dlopen-ed images.
85+
// rdar://problem/19045112
86+
InspectArgs ProtocolConformanceArgs = {
87+
ProtocolConformancesSymbol,
88+
addImageProtocolConformanceBlockCallback
89+
};
90+
dl_iterate_phdr(iteratePHDRCallback, &ProtocolConformanceArgs);
91+
}
92+
93+
void swift::initializeTypeMetadataRecordLookup() {
94+
InspectArgs TypeMetadataRecordArgs = {
95+
TypeMetadataRecordsSymbol,
96+
addImageTypeMetadataRecordBlockCallback
97+
};
98+
dl_iterate_phdr(iteratePHDRCallback, &TypeMetadataRecordArgs);
99+
}
100+
101+
#endif // defined(__ELF__) || defined(__ANDROID__)
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
//===--- ImageInspectionMachO.cpp - Mach-O image inspection ---------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file includes routines that interact with dyld on Mach-O-based platforms
14+
// to extract runtime metadata embedded in images generated by the Swift
15+
// compiler.
16+
//
17+
//===----------------------------------------------------------------------===//
18+
19+
#if defined(__APPLE__) && defined(__MACH__)
20+
21+
#include "ImageInspection.h"
22+
#include <mach-o/dyld.h>
23+
#include <mach-o/getsect.h>
24+
#include <assert.h>
25+
26+
using namespace swift;
27+
28+
namespace {
29+
/// The Mach-O section name for the section containing protocol conformances.
30+
/// This lives within SEG_TEXT.
31+
constexpr const char ProtocolConformancesSection[] = "__swift2_proto";
32+
/// The Mach-O section name for the section containing type references.
33+
/// This lives within SEG_TEXT.
34+
constexpr const char TypeMetadataRecordSection[] = "__swift2_types";
35+
36+
template<const char *SECTION_NAME,
37+
void CONSUME_BLOCK(const void *start, uintptr_t size)>
38+
void addImageCallback(const mach_header *mh, intptr_t vmaddr_slide) {
39+
#ifdef __LP64__
40+
using mach_header_platform = mach_header_64;
41+
assert(mh->magic == MH_MAGIC_64 && "loaded non-64-bit image?!");
42+
#else
43+
using mach_header_platform = mach_header;
44+
#endif
45+
46+
// Look for a __swift2_proto section.
47+
unsigned long size;
48+
const uint8_t *section =
49+
getsectiondata(reinterpret_cast<const mach_header_platform *>(mh),
50+
SEG_TEXT, SECTION_NAME,
51+
&size);
52+
53+
if (!section)
54+
return;
55+
56+
CONSUME_BLOCK(section, size);
57+
}
58+
59+
} // end anonymous namespace
60+
61+
void swift::initializeProtocolConformanceLookup() {
62+
_dyld_register_func_for_add_image(
63+
addImageCallback<ProtocolConformancesSection,
64+
addImageProtocolConformanceBlockCallback>);
65+
}
66+
void swift::initializeTypeMetadataRecordLookup() {
67+
_dyld_register_func_for_add_image(
68+
addImageCallback<TypeMetadataRecordSection,
69+
addImageTypeMetadataRecordBlockCallback>);
70+
71+
}
72+
73+
#endif // defined(__APPLE__) && defined(__MACH__)

0 commit comments

Comments
 (0)