Skip to content

Commit d5ba131

Browse files
authored
Merge pull request #5969 from spevans/pr_dladdr
[runtime] Add platform independent version of dladdr() / Dl_info
2 parents fe1cd74 + c17ca75 commit d5ba131

File tree

6 files changed

+71
-26
lines changed

6 files changed

+71
-26
lines changed

stdlib/public/runtime/Errors.cpp

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <unistd.h>
3131
#endif
3232
#include <stdarg.h>
33+
#include "ImageInspection.h"
3334
#include "swift/Runtime/Debug.h"
3435
#include "swift/Runtime/Mutex.h"
3536
#include "swift/Basic/Demangle.h"
@@ -38,14 +39,11 @@
3839
#if !defined(_MSC_VER)
3940
#include <cxxabi.h>
4041
#endif
41-
#if SWIFT_SUPPORTS_BACKTRACE_REPORTING
4242

43+
#if SWIFT_SUPPORTS_BACKTRACE_REPORTING
4344
// execinfo.h is not available on Android. Checks in this file ensure that
4445
// fatalError behaves as expected, but without stack traces.
4546
#include <execinfo.h>
46-
// We are only using dlfcn.h in code that is invoked on non cygwin/android
47-
// platforms. So I am putting it here.
48-
#include <dlfcn.h>
4947
#endif
5048

5149
#ifdef __APPLE__
@@ -62,26 +60,26 @@ using namespace swift;
6260

6361
#if SWIFT_SUPPORTS_BACKTRACE_REPORTING
6462

65-
static bool getSymbolNameAddr(llvm::StringRef libraryName, Dl_info dlinfo,
63+
static bool getSymbolNameAddr(llvm::StringRef libraryName, SymbolInfo syminfo,
6664
std::string &symbolName, uintptr_t &addrOut) {
6765

6866
// If we failed to find a symbol and thus dlinfo->dli_sname is nullptr, we
6967
// need to use the hex address.
70-
bool hasUnavailableAddress = dlinfo.dli_sname == nullptr;
68+
bool hasUnavailableAddress = syminfo.symbolName == nullptr;
7169

7270
if (hasUnavailableAddress) {
7371
return false;
7472
}
7573

7674
// Ok, now we know that we have some sort of "real" name. Set the outAddr.
77-
addrOut = uintptr_t(dlinfo.dli_saddr);
75+
addrOut = uintptr_t(syminfo.symbolAddress);
7876

7977
// First lets try to demangle using cxxabi. If this fails, we will try to
8078
// demangle with swift. We are taking advantage of __cxa_demangle actually
8179
// providing failure status instead of just returning the original string like
8280
// swift demangle.
8381
int status;
84-
char *demangled = abi::__cxa_demangle(dlinfo.dli_sname, 0, 0, &status);
82+
char *demangled = abi::__cxa_demangle(syminfo.symbolName, 0, 0, &status);
8583
if (status == 0) {
8684
assert(demangled != nullptr && "If __cxa_demangle succeeds, demangled "
8785
"should never be nullptr");
@@ -95,27 +93,24 @@ static bool getSymbolNameAddr(llvm::StringRef libraryName, Dl_info dlinfo,
9593
// Otherwise, try to demangle with swift. If swift fails to demangle, it will
9694
// just pass through the original output.
9795
symbolName = demangleSymbolAsString(
98-
dlinfo.dli_sname, strlen(dlinfo.dli_sname),
96+
syminfo.symbolName, strlen(syminfo.symbolName),
9997
Demangle::DemangleOptions::SimplifiedUIDemangleOptions());
10098
return true;
10199
}
102100

103101
/// This function dumps one line of a stack trace. It is assumed that \p address
104102
/// is the address of the stack frame at index \p index.
105103
static void dumpStackTraceEntry(unsigned index, void *framePC) {
106-
Dl_info dlinfo;
104+
SymbolInfo syminfo;
107105

108-
// 0 is failure for dladdr. We do not use nullptr since it is an int
109-
// argument. This violates normal unix patterns. See man page for dladdr on OS
110-
// X.
111-
if (0 == dladdr(framePC, &dlinfo)) {
106+
// 0 is failure for lookupSymbol
107+
if (0 == lookupSymbol(framePC, &syminfo)) {
112108
return;
113109
}
114110

115-
// According to the man page of dladdr, if dladdr returns non-zero, then we
116-
// know that it must have fname, fbase set. Thus, we find the library name
117-
// here.
118-
StringRef libraryName = StringRef(dlinfo.dli_fname).rsplit('/').second;
111+
// If lookupSymbol succeeded then fileName is non-null. Thus, we find the
112+
// library name here.
113+
StringRef libraryName = StringRef(syminfo.fileName).rsplit('/').second;
119114

120115
// Next we get the symbol name that we are going to use in our backtrace.
121116
std::string symbolName;
@@ -124,7 +119,7 @@ static void dumpStackTraceEntry(unsigned index, void *framePC) {
124119
// we just get HexAddr + 0.
125120
uintptr_t symbolAddr = uintptr_t(framePC);
126121
bool foundSymbol =
127-
getSymbolNameAddr(libraryName, dlinfo, symbolName, symbolAddr);
122+
getSymbolNameAddr(libraryName, syminfo, symbolName, symbolAddr);
128123

129124
// We do not use %p here for our pointers since the format is implementation
130125
// defined. This makes it logically impossible to check the output. Forcing
@@ -142,7 +137,7 @@ static void dumpStackTraceEntry(unsigned index, void *framePC) {
142137
"<unavailable> + %td\n";
143138
fprintf(stderr, backtraceEntryFormat, index, libraryName.data(),
144139
uintptr_t(framePC),
145-
ptrdiff_t(uintptr_t(framePC) - uintptr_t(dlinfo.dli_fbase)));
140+
ptrdiff_t(uintptr_t(framePC) - uintptr_t(syminfo.baseAddress)));
146141
}
147142
}
148143

stdlib/public/runtime/ImageInspection.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@
2222
#include <cstdint>
2323

2424
namespace swift {
25+
// This is a platform independent version of Dl_info from dlfcn.h
26+
struct SymbolInfo {
27+
const char *fileName;
28+
void *baseAddress;
29+
const char *symbolName;
30+
void *symbolAddress;
31+
};
2532

2633
/// Load the metadata from the image necessary to find a type's
2734
/// protocol conformance.
@@ -37,6 +44,7 @@ void addImageProtocolConformanceBlockCallback(const void *start,
3744
void addImageTypeMetadataRecordBlockCallback(const void *start,
3845
uintptr_t size);
3946

47+
int lookupSymbol(const void *address, SymbolInfo *info);
4048
} // end namespace swift
4149

4250
#endif // SWIFT_RUNTIME_IMAGE_INSPECTION_H

stdlib/public/runtime/ImageInspectionELF.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,4 +98,17 @@ void swift::initializeTypeMetadataRecordLookup() {
9898
dl_iterate_phdr(iteratePHDRCallback, &TypeMetadataRecordArgs);
9999
}
100100

101+
int swift::lookupSymbol(const void *address, SymbolInfo *info) {
102+
Dl_info dlinfo;
103+
if (dladdr(address, &dlinfo) == 0) {
104+
return 0;
105+
}
106+
107+
info->fileName = dlinfo.dli_fname;
108+
info->baseAddress = dlinfo.dli_fbase;
109+
info->symbolName = dlinfo.dli_sname;
110+
info->symbolAddress = dlinfo.dli_saddr;
111+
return 1;
112+
}
113+
101114
#endif // defined(__ELF__) || defined(__ANDROID__)

stdlib/public/runtime/ImageInspectionMachO.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <mach-o/dyld.h>
2323
#include <mach-o/getsect.h>
2424
#include <assert.h>
25+
#include <dlfcn.h>
2526

2627
using namespace swift;
2728

@@ -70,4 +71,17 @@ void swift::initializeTypeMetadataRecordLookup() {
7071

7172
}
7273

74+
int swift::lookupSymbol(const void *address, SymbolInfo *info) {
75+
Dl_info dlinfo;
76+
if (dladdr(address, &dlinfo) == 0) {
77+
return 0;
78+
}
79+
80+
info->fileName = dlinfo.dli_fname;
81+
info->baseAddress = dlinfo.dli_fbase;
82+
info->symbolName = dlinfo.dli_sname;
83+
info->symbolAddress = dlinfo.dli_saddr;
84+
return 1;
85+
}
86+
7387
#endif // defined(__APPLE__) && defined(__MACH__)

stdlib/public/runtime/ImageInspectionWin32.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,4 +217,22 @@ void swift::initializeTypeMetadataRecordLookup() {
217217
_swift_dl_iterate_phdr(_addImageCallback, &TypeMetadataRecordsArgs);
218218
}
219219

220+
221+
int swift::lookupSymbol(const void *address, SymbolInfo *info) {
222+
#if defined(__CYGWIN__)
223+
Dl_info dlinfo;
224+
if (dladdr(address, &dlinfo) == 0) {
225+
return 0;
226+
}
227+
228+
info->fileName = dlinfo.dli_fname;
229+
info->baseAddress = dlinfo.dli_fbase;
230+
info->symbolName = dli_info.dli_sname;
231+
info->symbolAddress = dli_saddr;
232+
return 1;
233+
#else
234+
return 0;
235+
#endif // __CYGWIN__
236+
}
237+
220238
#endif // defined(_MSC_VER) || defined(__CYGWIN__)

stdlib/public/runtime/ProtocolConformance.cpp

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,6 @@
2121
#include "swift/Runtime/Mutex.h"
2222
#include "ImageInspection.h"
2323
#include "Private.h"
24-
#if !defined(_WIN32)
25-
#include <dlfcn.h>
26-
#endif
2724

2825
using namespace swift;
2926

@@ -37,11 +34,11 @@ static const char *class_getName(const ClassMetadata* type) {
3734

3835
template<> void ProtocolConformanceRecord::dump() const {
3936
auto symbolName = [&](const void *addr) -> const char * {
40-
Dl_info info;
41-
int ok = dladdr(addr, &info);
37+
SymbolInfo info;
38+
int ok = lookupSymbol(addr, &info);
4239
if (!ok)
4340
return "<unknown addr>";
44-
return info.dli_sname;
41+
return info.symbolName;
4542
};
4643

4744
switch (auto kind = getTypeKind()) {

0 commit comments

Comments
 (0)