diff options
author | Tamar Christina <tamar@zhox.com> | 2016-04-11 00:38:42 +0200 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2016-04-11 01:44:41 +0200 |
commit | 90538d86af579595987826cd893828d6f379f35a (patch) | |
tree | 263e787c80664e36ac9dbc895ceff71273b1a03f /rts/RtsSymbols.c | |
parent | 8987ce067d187878f82005293f6b215dec66df48 (diff) | |
download | haskell-90538d86af579595987826cd893828d6f379f35a.tar.gz |
Change runtime linker to perform lazy loading of symbols/sections
The Runtime Linker is currently eagerly loading all object files on all
platforms which do not use the system linker for `GHCi`.
The problem with this approach is that it requires all symbols to be
found. Even those of functions never used/called. This makes the number
of libraries required to link things like `mingwex` quite high.
To work around this the `rts` was relying on a trick. It itself was
compiled with `MingW64-w`'s `GCC`. So it was already linked against
`mingwex`. As such, it re-exported the symbols from itself.
While this worked it made it impossible to link against `mingwex` in
user libraries. And with this means no `C99` code could ever run in
`GHCi` on Windows without having the required symbols re-exported from
the rts.
Consequently this rules out a large number of packages on Windows.
SDL2, HMatrix etc.
After talking with @rwbarton I have taken the approach of loading entire
object files when a symbol is needed instead of doing the dependency
tracking on a per symbol basis. This is a lot less fragile and a lot
less complicated to implement.
The changes come down to the following steps:
1) modify the linker to and introduce a new state for ObjectCode:
`Needed`. A Needed object is one that is required for the linking to
succeed. The initial set consists of all Object files passed as
arguments to the link.
2) Change `ObjectCode`'s to be indexed but not initialized or resolved.
This means we know where we would load the symbols,
but haven't actually done so.
3) Mark any `ObjectCode` belonging to `.o` passed as argument
as required: ObjectState `NEEDED`.
4) During `Resolve` object calls, mark all `ObjectCode`
containing the required symbols as `NEEDED`
5) During `lookupSymbol` lookups, (which is called from `linkExpr`
and `linkDecl` in `GHCI.hs`) is the symbol is in a not-yet-loaded
`ObjectCode` then load the `ObjectCode` on demand and return the
address of the symbol. Otherwise produce an unresolved symbols error
as expected.
6) On `unloadObj` we then change the state of the object and remove
it's symbols from the `reqSymHash` table so it can be reloaded.
This change affects all platforms and OSes which use the runtime linker.
It seems there are no real perf tests for `GHCi`, but performance
shouldn't be impacted much. We gain a lot of time not loading all `obj`
files, and we lose some time in `lookupSymbol` when we're finding
sections that have to be loaded. The actual finding itself is O(1)
(Assuming the hashtnl is perfect)
It also consumes slighly more memory as instead of storing just the
address of a symbol I also store some other information, like if the
symbol is weak or not.
This change will break any packages relying on renamed POSIX functions
that were re-named and re-exported by the rts. Any packages following
the proper naming for functions as found on MSDN will work fine.
Test Plan: ./validate on all platforms which use the Runtime linker.
Reviewers: thomie, rwbarton, simonmar, erikd, bgamari, austin, hvr
Reviewed By: erikd
Subscribers: kgardas, gridaphobe, RyanGlScott, simonmar,
rwbarton, #ghc_windows_task_force
Differential Revision: https://phabricator.haskell.org/D1805
GHC Trac Issues: #11223
Diffstat (limited to 'rts/RtsSymbols.c')
-rw-r--r-- | rts/RtsSymbols.c | 319 |
1 files changed, 2 insertions, 317 deletions
diff --git a/rts/RtsSymbols.c b/rts/RtsSymbols.c index 395a5f10b0..3e82cdffa1 100644 --- a/rts/RtsSymbols.c +++ b/rts/RtsSymbols.c @@ -58,18 +58,6 @@ #if defined(mingw32_HOST_OS) #define RTS_POSIX_ONLY_SYMBOLS /**/ -#if HAVE_GETTIMEOFDAY -#define RTS_MINGW_GETTIMEOFDAY_SYM SymI_NeedsProto(gettimeofday) -#else -#define RTS_MINGW_GETTIMEOFDAY_SYM /**/ -#endif - -#if HAVE___MINGW_VFPRINTF -#define RTS___MINGW_VFPRINTF_SYM SymI_HasProto(__mingw_vfprintf) -#else -#define RTS___MINGW_VFPRINTF_SYM /**/ -#endif - #if defined(i386_HOST_ARCH) #define RTS_WIN32_ONLY(X) X #else @@ -82,324 +70,21 @@ #define RTS_WIN64_ONLY(X) /**/ #endif -/* These are statically linked from the mingw libraries into the ghc - executable, so we have to employ this hack. */ #define RTS_MINGW_ONLY_SYMBOLS \ SymI_HasProto(stg_asyncReadzh) \ SymI_HasProto(stg_asyncWritezh) \ SymI_HasProto(stg_asyncDoProczh) \ SymI_HasProto(getWin32ProgArgv) \ SymI_HasProto(setWin32ProgArgv) \ - SymI_HasProto(memset) \ - SymI_HasProto(inet_ntoa) \ - SymI_HasProto(inet_addr) \ - SymI_HasProto(htonl) \ - SymI_HasProto(recvfrom) \ - SymI_HasProto(listen) \ - SymI_HasProto(bind) \ - SymI_HasProto(shutdown) \ - SymI_HasProto(connect) \ - SymI_HasProto(htons) \ - SymI_HasProto(ntohs) \ - SymI_HasProto(getservbyname) \ - SymI_HasProto(getservbyport) \ - SymI_HasProto(getprotobynumber) \ - SymI_HasProto(getprotobyname) \ - SymI_HasProto(gethostbyname) \ - SymI_HasProto(gethostbyaddr) \ - SymI_HasProto(gethostname) \ - SymI_HasProto(strcpy) \ - SymI_HasProto(strncpy) \ - SymI_HasProto(abort) \ - SymI_HasProto(isxdigit) \ - SymI_HasProto(isupper) \ - SymI_HasProto(ispunct) \ - SymI_HasProto(islower) \ - SymI_HasProto(isspace) \ - SymI_HasProto(isprint) \ - SymI_HasProto(isdigit) \ - SymI_HasProto(iscntrl) \ - SymI_HasProto(isalpha) \ - SymI_HasProto(isalnum) \ - SymI_HasProto(isascii) \ - RTS___MINGW_VFPRINTF_SYM \ - SymI_HasProto(strcmp) \ - SymI_HasProto(memmove) \ - SymI_HasProto(realloc) \ - SymI_HasProto(malloc) \ - SymI_HasProto(pow) \ - SymI_HasProto(tanh) \ - SymI_HasProto(cosh) \ - SymI_HasProto(sinh) \ - SymI_HasProto(atan) \ - SymI_HasProto(acos) \ - SymI_HasProto(asin) \ - SymI_HasProto(tan) \ - SymI_HasProto(cos) \ - SymI_HasProto(sin) \ - SymI_HasProto(exp) \ - SymI_HasProto(log) \ - SymI_HasProto(sqrt) \ - SymI_HasProto(powf) \ - SymI_HasProto(tanhf) \ - SymI_HasProto(coshf) \ - SymI_HasProto(sinhf) \ - SymI_HasProto(atanf) \ - SymI_HasProto(acosf) \ - SymI_HasProto(asinf) \ - SymI_HasProto(tanf) \ - SymI_HasProto(cosf) \ - SymI_HasProto(sinf) \ - SymI_HasProto(expf) \ - SymI_HasProto(logf) \ - SymI_HasProto(sqrtf) \ - SymI_HasProto(erf) \ - SymI_HasProto(erfc) \ - SymI_HasProto(erff) \ - SymI_HasProto(erfcf) \ - SymI_HasProto(expm1) \ - SymI_HasProto(expm1f) \ - SymI_HasProto(log1p) \ - SymI_HasProto(log1pf) \ - SymI_HasProto(memcpy) \ SymI_HasProto(rts_InstallConsoleEvent) \ SymI_HasProto(rts_ConsoleHandlerDone) \ - SymI_NeedsProto(mktime) \ - SymI_NeedsProto(localtime) \ - SymI_NeedsProto(gmtime) \ - SymI_NeedsProto(opendir) \ - SymI_NeedsProto(readdir) \ - SymI_NeedsProto(rewinddir) \ + SymI_HasProto(atexit) \ RTS_WIN32_ONLY(SymI_NeedsProto(__chkstk_ms)) \ RTS_WIN64_ONLY(SymI_NeedsProto(___chkstk_ms)) \ - SymI_NeedsProto(localeconv) \ - SymI_HasProto(close) \ - SymI_HasProto(read) \ - SymI_HasProto(dup) \ - SymI_HasProto(dup2) \ - SymI_HasProto(write) \ - SymI_NeedsProto(getpid) \ - SymI_HasProto(access) \ - SymI_HasProto(chmod) \ - SymI_HasProto(creat) \ - SymI_HasProto(umask) \ - SymI_HasProto(unlink) \ - SymI_HasProto(_errno) \ - SymI_NeedsProto(ftruncate64) \ - SymI_HasProto(setmode) \ - SymI_HasProto(_wstat64) \ - SymI_HasProto(_fstat64) \ - SymI_HasProto(_wsopen) \ RTS_WIN32_ONLY(SymI_HasProto(_imp___environ)) \ RTS_WIN64_ONLY(SymI_HasProto(__imp__environ)) \ RTS_WIN32_ONLY(SymI_HasProto(_imp___iob)) \ - RTS_WIN64_ONLY(SymI_HasProto(__iob_func)) \ - SymI_HasProto(GetFileAttributesA) \ - SymI_HasProto(GetFileInformationByHandle) \ - SymI_HasProto(GetFileType) \ - SymI_HasProto(GetLastError) \ - SymI_HasProto(QueryPerformanceFrequency) \ - SymI_HasProto(QueryPerformanceCounter) \ - SymI_HasProto(GetTickCount) \ - SymI_HasProto(WaitForSingleObject) \ - SymI_HasProto(PeekConsoleInputA) \ - SymI_HasProto(ReadConsoleInputA) \ - SymI_HasProto(PeekNamedPipe) \ - SymI_HasProto(select) \ - SymI_HasProto(isatty) \ - SymI_HasProto(_get_osfhandle) \ - SymI_HasProto(GetConsoleMode) \ - SymI_HasProto(SetConsoleMode) \ - SymI_HasProto(FlushConsoleInputBuffer) \ - SymI_HasProto(free) \ - SymI_NeedsProto(raise) \ - SymI_NeedsProto(_getpid) \ - SymI_HasProto(getc) \ - SymI_HasProto(ungetc) \ - SymI_HasProto(puts) \ - SymI_HasProto(putc) \ - SymI_HasProto(putchar) \ - SymI_HasProto(fputc) \ - SymI_HasProto(fread) \ - SymI_HasProto(fwrite) \ - SymI_HasProto(ferror) \ - SymI_HasProto(printf) \ - SymI_HasProto(fprintf) \ - SymI_HasProto(sprintf) \ - SymI_HasProto(vsprintf) \ - SymI_HasProto(sscanf) \ - SymI_HasProto(ldexp) \ - SymI_HasProto(strlen) \ - SymI_HasProto(strnlen) \ - SymI_HasProto(strchr) \ - SymI_HasProto(strtol) \ - SymI_HasProto(strerror) \ - SymI_HasProto(memchr) \ - SymI_HasProto(memcmp) \ - SymI_HasProto(wcscpy) \ - SymI_HasProto(wcslen) \ - SymI_HasProto(_lseeki64) \ - SymI_HasProto(_wchmod) \ - SymI_HasProto(closesocket) \ - SymI_HasProto(send) \ - SymI_HasProto(recv) \ - SymI_HasProto(bsearch) \ - SymI_HasProto(CommandLineToArgvW) \ - SymI_HasProto(CreateBitmap) \ - SymI_HasProto(CreateBitmapIndirect) \ - SymI_HasProto(CreateCompatibleBitmap) \ - SymI_HasProto(CreateDIBPatternBrushPt) \ - SymI_HasProto(CreateDIBitmap) \ - SymI_HasProto(SetBitmapDimensionEx) \ - SymI_HasProto(GetBitmapDimensionEx) \ - SymI_HasProto(GetStockObject) \ - SymI_HasProto(GetObjectW) \ - SymI_HasProto(DeleteObject) \ - SymI_HasProto(SetDIBits) \ - SymI_HasProto(GetDIBits) \ - SymI_HasProto(CreateSolidBrush) \ - SymI_HasProto(CreateHatchBrush) \ - SymI_HasProto(CreatePatternBrush) \ - SymI_HasProto(CreateFontW) \ - SymI_HasProto(AngleArc) \ - SymI_HasProto(Arc) \ - SymI_HasProto(ArcTo) \ - SymI_HasProto(BeginPath) \ - SymI_HasProto(BitBlt) \ - SymI_HasProto(CancelDC) \ - SymI_HasProto(Chord) \ - SymI_HasProto(CloseFigure) \ - SymI_HasProto(CombineRgn) \ - SymI_HasProto(CreateCompatibleDC) \ - SymI_HasProto(CreateEllipticRgn) \ - SymI_HasProto(CreateEllipticRgnIndirect) \ - SymI_HasProto(CreatePen) \ - SymI_HasProto(CreatePolygonRgn) \ - SymI_HasProto(CreateRectRgn) \ - SymI_HasProto(CreateRectRgnIndirect) \ - SymI_HasProto(CreateRoundRectRgn) \ - SymI_HasProto(DeleteDC) \ - SymI_HasProto(Ellipse) \ - SymI_HasProto(EndPath) \ - SymI_HasProto(EqualRgn) \ - SymI_HasProto(ExtSelectClipRgn) \ - SymI_HasProto(FillPath) \ - SymI_HasProto(FillRgn) \ - SymI_HasProto(FlattenPath) \ - SymI_HasProto(FrameRgn) \ - SymI_HasProto(GetArcDirection) \ - SymI_HasProto(GetBkColor) \ - SymI_HasProto(GetBkMode) \ - SymI_HasProto(GetBrushOrgEx) \ - SymI_HasProto(GetCurrentObject) \ - SymI_HasProto(GetDCOrgEx) \ - SymI_HasProto(GetGraphicsMode) \ - SymI_HasProto(GetMiterLimit) \ - SymI_HasProto(GetPolyFillMode) \ - SymI_HasProto(GetRgnBox) \ - SymI_HasProto(GetStretchBltMode) \ - SymI_HasProto(GetTextAlign) \ - SymI_HasProto(GetTextCharacterExtra) \ - SymI_HasProto(GetTextColor) \ - SymI_HasProto(GetTextExtentPoint32W) \ - SymI_HasProto(InvertRgn) \ - SymI_HasProto(LineTo) \ - SymI_HasProto(MaskBlt) \ - SymI_HasProto(MoveToEx) \ - SymI_HasProto(OffsetRgn) \ - SymI_HasProto(PaintRgn) \ - SymI_HasProto(PathToRegion) \ - SymI_HasProto(Pie) \ - SymI_HasProto(PlgBlt) \ - SymI_HasProto(PolyBezier) \ - SymI_HasProto(PolyBezierTo) \ - SymI_HasProto(Polygon) \ - SymI_HasProto(Polyline) \ - SymI_HasProto(PolylineTo) \ - SymI_HasProto(PtInRegion) \ - SymI_HasProto(Rectangle) \ - SymI_HasProto(RectInRegion) \ - SymI_HasProto(RestoreDC) \ - SymI_HasProto(RoundRect) \ - SymI_HasProto(SaveDC) \ - SymI_HasProto(SelectClipPath) \ - SymI_HasProto(SelectClipRgn) \ - SymI_HasProto(SelectObject) \ - SymI_HasProto(SelectPalette) \ - SymI_HasProto(SetArcDirection) \ - SymI_HasProto(SetBkColor) \ - SymI_HasProto(SetBkMode) \ - SymI_HasProto(SetBrushOrgEx) \ - SymI_HasProto(SetGraphicsMode) \ - SymI_HasProto(SetMiterLimit) \ - SymI_HasProto(SetPolyFillMode) \ - SymI_HasProto(SetStretchBltMode) \ - SymI_HasProto(SetTextAlign) \ - SymI_HasProto(SetTextCharacterExtra) \ - SymI_HasProto(SetTextColor) \ - SymI_HasProto(StretchBlt) \ - SymI_HasProto(StrokeAndFillPath) \ - SymI_HasProto(StrokePath) \ - SymI_HasProto(TextOutW) \ - SymI_HasProto(timeGetTime) \ - SymI_HasProto(WidenPath) \ - SymI_HasProto(GetFileSecurityW) \ - SymI_HasProto(RegCloseKey) \ - SymI_HasProto(RegConnectRegistryW) \ - SymI_HasProto(RegCreateKeyExW) \ - SymI_HasProto(RegCreateKeyW) \ - SymI_HasProto(RegDeleteKeyW) \ - SymI_HasProto(RegDeleteValueW) \ - SymI_HasProto(RegEnumKeyW) \ - SymI_HasProto(RegEnumValueW) \ - SymI_HasProto(RegFlushKey) \ - SymI_HasProto(RegLoadKeyW) \ - SymI_HasProto(RegNotifyChangeKeyValue) \ - SymI_HasProto(RegOpenKeyExW) \ - SymI_HasProto(RegOpenKeyW) \ - SymI_HasProto(RegQueryInfoKeyW) \ - SymI_HasProto(RegQueryValueExW) \ - SymI_HasProto(RegQueryValueW) \ - SymI_HasProto(RegReplaceKeyW) \ - SymI_HasProto(RegRestoreKeyW) \ - SymI_HasProto(RegSaveKeyW) \ - SymI_HasProto(RegSetValueExW) \ - SymI_HasProto(RegSetValueW) \ - SymI_HasProto(RegUnLoadKeyW) \ - SymI_HasProto(SHGetFolderPathW) \ - RTS_WIN32_ONLY(SymI_HasProto(SetWindowLongW)) \ - RTS_WIN32_ONLY(SymI_HasProto(GetWindowLongW)) \ - RTS_WIN64_ONLY(SymI_HasProto(SetWindowLongPtrW)) \ - RTS_WIN64_ONLY(SymI_HasProto(GetWindowLongPtrW)) \ - SymI_HasProto(MenuItemFromPoint) \ - SymI_HasProto(ChildWindowFromPoint) \ - SymI_HasProto(ChildWindowFromPointEx) \ - SymI_HasProto(UnmapViewOfFile) \ - SymI_HasProto(CloseHandle) \ - SymI_HasProto(FreeLibrary) \ - SymI_HasProto(GetMessageW) \ - SymI_HasProto(TranslateMessage) \ - SymI_HasProto(DispatchMessageW) \ - SymI_HasProto(DefWindowProcW) \ - SymI_HasProto(GlobalAlloc) \ - SymI_HasProto(GlobalFree) \ - SymI_HasProto(CreateFileW) \ - SymI_HasProto(WriteFile) \ - SymI_HasProto(FormatMessageW) \ - SymI_NeedsProto(_localtime64) \ - SymI_NeedsProto(_tzname) \ - SymI_NeedsProto(_timezone) \ - SymI_HasProto(CreatePipe) \ - SymI_HasProto(SetHandleInformation) \ - SymI_HasProto(GetStdHandle) \ - SymI_HasProto(GetCurrentProcess) \ - SymI_HasProto(DuplicateHandle) \ - SymI_HasProto(CreateProcessW) \ - SymI_HasProto(TerminateProcess) \ - SymI_HasProto(_open_osfhandle) \ - SymI_HasProto(GetExitCodeProcess) \ - RTS_MINGW_GETTIMEOFDAY_SYM \ - SymI_NeedsProto(closedir) + RTS_WIN64_ONLY(SymI_HasProto(__iob_func)) #else #define RTS_MINGW_ONLY_SYMBOLS /**/ |