From 2028a9150e06923c02d26423650de665cf4470dc Mon Sep 17 00:00:00 2001 From: Apple Date: Sat, 1 Mar 2008 01:09:11 +0000 Subject: [PATCH] dyld-96.2.tar.gz --- doc/man/man3/dlsym.3 | 16 +- dyld.xcodeproj/kledzik.mode1v3 | 1377 ----------------- dyld.xcodeproj/kledzik.pbxuser | 140 -- launch-cache/MachOBinder.hpp | 9 +- launch-cache/MachOLayout.hpp | 3 + launch-cache/MachORebaser.hpp | 8 +- launch-cache/com.apple.dyld.plist | 2 - launch-cache/update_dyld_shared_cache.cpp | 285 ++-- src/ImageLoader.cpp | 5 +- src/ImageLoader.h | 7 + src/ImageLoaderMachO.cpp | 16 +- src/ImageLoaderMachO.h | 1 + src/dyld.cpp | 39 +- src/dyld.h | 2 + src/dyldAPIs.cpp | 29 +- .../dlopen-init-dlopen-notify/Makefile | 62 + .../dlopen-init-dlopen-notify/bar.c | 1 + .../dlopen-init-dlopen-notify/foo.c | 31 + .../dlopen-init-dlopen-notify/foo1.c | 38 + .../dlopen-init-dlopen-notify/foo2.c | 37 + .../dlopen-init-dlopen-notify/main.cxx | 82 + unit-tests/test-cases/dlopen-leak/Makefile | 68 + unit-tests/test-cases/dlopen-leak/bar.c | 3 + unit-tests/test-cases/dlopen-leak/foo.c | 3 + unit-tests/test-cases/dlopen-leak/main.c | 48 + .../test-cases/dlopen-notify-bind/Makefile | 51 + .../test-cases/dlopen-notify-bind/foo.c | 32 + .../test-cases/dlopen-notify-bind/main.c | 68 + .../test-cases/dlopen_preflight-leak/Makefile | 65 + .../test-cases/dlopen_preflight-leak/bar.c | 3 + .../test-cases/dlopen_preflight-leak/foo.c | 3 + .../test-cases/dlopen_preflight-leak/main.c | 45 + .../test-cases/framework-fallback/main.c | 6 +- .../Makefile | 44 + .../main.c | 14 + .../mymalloc.c | 9 + 36 files changed, 983 insertions(+), 1669 deletions(-) delete mode 100644 dyld.xcodeproj/kledzik.mode1v3 delete mode 100644 dyld.xcodeproj/kledzik.pbxuser create mode 100644 unit-tests/test-cases/dlopen-init-dlopen-notify/Makefile create mode 100644 unit-tests/test-cases/dlopen-init-dlopen-notify/bar.c create mode 100644 unit-tests/test-cases/dlopen-init-dlopen-notify/foo.c create mode 100644 unit-tests/test-cases/dlopen-init-dlopen-notify/foo1.c create mode 100644 unit-tests/test-cases/dlopen-init-dlopen-notify/foo2.c create mode 100644 unit-tests/test-cases/dlopen-init-dlopen-notify/main.cxx create mode 100644 unit-tests/test-cases/dlopen-leak/Makefile create mode 100644 unit-tests/test-cases/dlopen-leak/bar.c create mode 100644 unit-tests/test-cases/dlopen-leak/foo.c create mode 100644 unit-tests/test-cases/dlopen-leak/main.c create mode 100644 unit-tests/test-cases/dlopen-notify-bind/Makefile create mode 100644 unit-tests/test-cases/dlopen-notify-bind/foo.c create mode 100644 unit-tests/test-cases/dlopen-notify-bind/main.c create mode 100644 unit-tests/test-cases/dlopen_preflight-leak/Makefile create mode 100644 unit-tests/test-cases/dlopen_preflight-leak/bar.c create mode 100644 unit-tests/test-cases/dlopen_preflight-leak/foo.c create mode 100644 unit-tests/test-cases/dlopen_preflight-leak/main.c create mode 100644 unit-tests/test-cases/read-only-import-shared-cache-dlopen-override/Makefile create mode 100644 unit-tests/test-cases/read-only-import-shared-cache-dlopen-override/main.c create mode 100644 unit-tests/test-cases/read-only-import-shared-cache-dlopen-override/mymalloc.c diff --git a/doc/man/man3/dlsym.3 b/doc/man/man3/dlsym.3 index d9afeb8..0adbe9a 100644 --- a/doc/man/man3/dlsym.3 +++ b/doc/man/man3/dlsym.3 @@ -1,4 +1,4 @@ -.Dd Sept 25, 2004 +.Dd Jan 16, 2008 .Dt DLSYM 3 .Sh NAME .Nm dlsym @@ -40,8 +40,18 @@ is called with the special .Fa handle .Dv RTLD_NEXT , then the search for the symbol is limited to the images which were loaded -after the one issuing the call to +by the image issuing the call to .Fn dlsym . +In other words, search the dylib symbols that the calling image linked against when it was built. +.Pp +If +.Fn dlsym +is called with the special +.Fa handle +.Dv RTLD_SELF , +then the search for the symbol starts with the image that called +.Fn dlsym . +If it is not found, the search continues as if RTLD_NEXT was used. .Pp .Sh RETURN VALUES The @@ -60,7 +70,5 @@ must NOT be prepended with an underscore. .Xr dlsym 3 .Xr dlerror 3 .Xr dyld 3 -.Xr NSModule 3 -.Xr NSObjectFileImage 3 .Xr ld 1 .Xr cc 1 diff --git a/dyld.xcodeproj/kledzik.mode1v3 b/dyld.xcodeproj/kledzik.mode1v3 deleted file mode 100644 index cbe28df..0000000 --- a/dyld.xcodeproj/kledzik.mode1v3 +++ /dev/null @@ -1,1377 +0,0 @@ - - - - - ActivePerspectiveName - Project - AllowedModules - - - BundleLoadPath - - MaxInstances - n - Module - PBXSmartGroupTreeModule - Name - Groups and Files Outline View - - - BundleLoadPath - - MaxInstances - n - Module - PBXNavigatorGroup - Name - Editor - - - BundleLoadPath - - MaxInstances - n - Module - XCTaskListModule - Name - Task List - - - BundleLoadPath - - MaxInstances - n - Module - XCDetailModule - Name - File and Smart Group Detail Viewer - - - BundleLoadPath - - MaxInstances - 1 - Module - PBXBuildResultsModule - Name - Detailed Build Results Viewer - - - BundleLoadPath - - MaxInstances - 1 - Module - PBXProjectFindModule - Name - Project Batch Find Tool - - - BundleLoadPath - - MaxInstances - n - Module - XCProjectFormatConflictsModule - Name - Project Format Conflicts List - - - BundleLoadPath - - MaxInstances - n - Module - PBXBookmarksModule - Name - Bookmarks Tool - - - BundleLoadPath - - MaxInstances - n - Module - PBXClassBrowserModule - Name - Class Browser - - - BundleLoadPath - - MaxInstances - n - Module - PBXCVSModule - Name - Source Code Control Tool - - - BundleLoadPath - - MaxInstances - n - Module - PBXDebugBreakpointsModule - Name - Debug Breakpoints Tool - - - BundleLoadPath - - MaxInstances - n - Module - XCDockableInspector - Name - Inspector - - - BundleLoadPath - - MaxInstances - n - Module - PBXOpenQuicklyModule - Name - Open Quickly Tool - - - BundleLoadPath - - MaxInstances - 1 - Module - PBXDebugSessionModule - Name - Debugger - - - BundleLoadPath - - MaxInstances - 1 - Module - PBXDebugCLIModule - Name - Debug Console - - - BundleLoadPath - - MaxInstances - n - Module - XCSnapshotModule - Name - Snapshots Tool - - - BundlePath - /Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources - Description - DefaultDescriptionKey - DockingSystemVisible - - Extension - mode1v3 - FavBarConfig - - PBXProjectModuleGUID - F9DBB28F0CD7F5F1009A2B25 - XCBarModuleItemNames - - XCBarModuleItems - - - FirstTimeWindowDisplayed - - Identifier - com.apple.perspectives.project.mode1v3 - MajorVersion - 33 - MinorVersion - 0 - Name - Default - Notifications - - - XCObserverAutoDisconnectKey - - XCObserverDefintionKey - - XCObserverFactoryKey - XCPerspectivesSpecificationIdentifier - XCObserverGUIDKey - XCObserverProjectIdentifier - XCObserverNotificationKey - PBXStatusBuildStateMessageNotification - XCObserverTargetKey - XCMainBuildResultsModuleGUID - XCObserverTriggerKey - awakenModuleWithObserver: - XCObserverValidationKey - - - - OpenEditors - - PerspectiveWidths - - -1 - -1 - - Perspectives - - - ChosenToolbarItems - - active-target-popup - active-buildstyle-popup - active-executable-popup - NSToolbarFlexibleSpaceItem - buildOrClean - build-and-goOrGo - com.apple.ide.PBXToolbarStopButton - get-info - toggle-editor - NSToolbarFlexibleSpaceItem - com.apple.pbx.toolbar.searchfield - - ControllerClassBaseName - - IconName - WindowOfProjectWithEditor - Identifier - perspective.project - IsVertical - - Layout - - - BecomeActive - - ContentConfiguration - - PBXBottomSmartGroupGIDs - - 1C37FBAC04509CD000000102 - 1C37FAAC04509CD000000102 - 1C08E77C0454961000C914BD - 1C37FABC05509CD000000102 - 1C37FABC05539CD112110102 - E2644B35053B69B200211256 - 1C37FABC04509CD000100104 - 1CC0EA4004350EF90044410B - 1CC0EA4004350EF90041110B - - PBXProjectModuleGUID - 1CE0B1FE06471DED0097A5F4 - PBXProjectModuleLabel - Files - PBXProjectStructureProvided - yes - PBXSmartGroupTreeModuleColumnData - - PBXSmartGroupTreeModuleColumnWidthsKey - - 186 - - PBXSmartGroupTreeModuleColumnsKey_v4 - - MainColumn - - - PBXSmartGroupTreeModuleOutlineStateKey_v7 - - PBXSmartGroupTreeModuleOutlineStateExpansionKey - - F9ED4C870630A72200DF4E74 - 1C37FBAC04509CD000000102 - F9DBB28B0CD7F5F1009A2B25 - F9DBB28C0CD7F5F1009A2B25 - 1C37FABC05509CD000000102 - - PBXSmartGroupTreeModuleOutlineStateSelectionKey - - - 14 - 11 - 6 - - - PBXSmartGroupTreeModuleOutlineStateVisibleRectKey - {{0, 102}, {186, 338}} - - PBXTopSmartGroupGIDs - - XCIncludePerspectivesSwitch - - XCSharingToken - com.apple.Xcode.GFSharingToken - - GeometryConfiguration - - Frame - {{0, 0}, {203, 356}} - GroupTreeTableConfiguration - - MainColumn - 186 - - RubberWindowFrame - 128 669 690 397 0 0 1920 1178 - - Module - PBXSmartGroupTreeModule - Proportion - 203pt - - - Dock - - - ContentConfiguration - - PBXProjectModuleGUID - 1CE0B20306471E060097A5F4 - PBXProjectModuleLabel - MyNewFile14.java - PBXSplitModuleInNavigatorKey - - Split0 - - PBXProjectModuleGUID - 1CE0B20406471E060097A5F4 - PBXProjectModuleLabel - MyNewFile14.java - - SplitCount - 1 - - StatusBarVisibility - - - GeometryConfiguration - - Frame - {{0, 0}, {482, 0}} - RubberWindowFrame - 128 669 690 397 0 0 1920 1178 - - Module - PBXNavigatorGroup - Proportion - 0pt - - - ContentConfiguration - - PBXProjectModuleGUID - 1CE0B20506471E060097A5F4 - PBXProjectModuleLabel - Detail - - GeometryConfiguration - - Frame - {{0, 5}, {482, 351}} - RubberWindowFrame - 128 669 690 397 0 0 1920 1178 - - Module - XCDetailModule - Proportion - 351pt - - - Proportion - 482pt - - - Name - Project - ServiceClasses - - XCModuleDock - PBXSmartGroupTreeModule - XCModuleDock - PBXNavigatorGroup - XCDetailModule - - TableOfContents - - F9DBB28D0CD7F5F1009A2B25 - 1CE0B1FE06471DED0097A5F4 - F9DBB28E0CD7F5F1009A2B25 - 1CE0B20306471E060097A5F4 - 1CE0B20506471E060097A5F4 - - ToolbarConfiguration - xcode.toolbar.config.defaultV3 - - - ControllerClassBaseName - - IconName - WindowOfProject - Identifier - perspective.morph - IsVertical - 0 - Layout - - - BecomeActive - 1 - ContentConfiguration - - PBXBottomSmartGroupGIDs - - 1C37FBAC04509CD000000102 - 1C37FAAC04509CD000000102 - 1C08E77C0454961000C914BD - 1C37FABC05509CD000000102 - 1C37FABC05539CD112110102 - E2644B35053B69B200211256 - 1C37FABC04509CD000100104 - 1CC0EA4004350EF90044410B - 1CC0EA4004350EF90041110B - - PBXProjectModuleGUID - 11E0B1FE06471DED0097A5F4 - PBXProjectModuleLabel - Files - PBXProjectStructureProvided - yes - PBXSmartGroupTreeModuleColumnData - - PBXSmartGroupTreeModuleColumnWidthsKey - - 186 - - PBXSmartGroupTreeModuleColumnsKey_v4 - - MainColumn - - - PBXSmartGroupTreeModuleOutlineStateKey_v7 - - PBXSmartGroupTreeModuleOutlineStateExpansionKey - - 29B97314FDCFA39411CA2CEA - 1C37FABC05509CD000000102 - - PBXSmartGroupTreeModuleOutlineStateSelectionKey - - - 0 - - - PBXSmartGroupTreeModuleOutlineStateVisibleRectKey - {{0, 0}, {186, 337}} - - PBXTopSmartGroupGIDs - - XCIncludePerspectivesSwitch - 1 - XCSharingToken - com.apple.Xcode.GFSharingToken - - GeometryConfiguration - - Frame - {{0, 0}, {203, 355}} - GroupTreeTableConfiguration - - MainColumn - 186 - - RubberWindowFrame - 373 269 690 397 0 0 1440 878 - - Module - PBXSmartGroupTreeModule - Proportion - 100% - - - Name - Morph - PreferredWidth - 300 - ServiceClasses - - XCModuleDock - PBXSmartGroupTreeModule - - TableOfContents - - 11E0B1FE06471DED0097A5F4 - - ToolbarConfiguration - xcode.toolbar.config.default.shortV3 - - - PerspectivesBarVisible - - ShelfIsVisible - - SourceDescription - file at '/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources/XCPerspectivesSpecificationMode1.xcperspec' - StatusbarIsVisible - - TimeStamp - 215479759.49117801 - ToolbarDisplayMode - 1 - ToolbarIsVisible - - ToolbarSizeMode - 1 - Type - Perspectives - UpdateMessage - The Default Workspace in this version of Xcode now includes support to hide and show the detail view (what has been referred to as the "Metro-Morph" feature). You must discard your current Default Workspace settings and update to the latest Default Workspace in order to gain this feature. Do you wish to update to the latest Workspace defaults for project '%@'? - WindowJustification - 5 - WindowOrderList - - /tmp/ttt/dyld-95.3/dyld.xcodeproj - - WindowString - 128 669 690 397 0 0 1920 1178 - WindowToolsV3 - - - Identifier - windowTool.build - Layout - - - Dock - - - ContentConfiguration - - PBXProjectModuleGUID - 1CD0528F0623707200166675 - PBXProjectModuleLabel - <No Editor> - PBXSplitModuleInNavigatorKey - - Split0 - - PBXProjectModuleGUID - 1CD052900623707200166675 - - SplitCount - 1 - - StatusBarVisibility - 1 - - GeometryConfiguration - - Frame - {{0, 0}, {500, 215}} - RubberWindowFrame - 192 257 500 500 0 0 1280 1002 - - Module - PBXNavigatorGroup - Proportion - 218pt - - - BecomeActive - 1 - ContentConfiguration - - PBXProjectModuleGUID - XCMainBuildResultsModuleGUID - PBXProjectModuleLabel - Build - - GeometryConfiguration - - Frame - {{0, 222}, {500, 236}} - RubberWindowFrame - 192 257 500 500 0 0 1280 1002 - - Module - PBXBuildResultsModule - Proportion - 236pt - - - Proportion - 458pt - - - Name - Build Results - ServiceClasses - - PBXBuildResultsModule - - StatusbarIsVisible - 1 - TableOfContents - - 1C78EAA5065D492600B07095 - 1C78EAA6065D492600B07095 - 1CD0528F0623707200166675 - XCMainBuildResultsModuleGUID - - ToolbarConfiguration - xcode.toolbar.config.buildV3 - WindowString - 192 257 500 500 0 0 1280 1002 - - - Identifier - windowTool.debugger - Layout - - - Dock - - - ContentConfiguration - - Debugger - - HorizontalSplitView - - _collapsingFrameDimension - 0.0 - _indexOfCollapsedView - 0 - _percentageOfCollapsedView - 0.0 - isCollapsed - yes - sizes - - {{0, 0}, {317, 164}} - {{317, 0}, {377, 164}} - - - VerticalSplitView - - _collapsingFrameDimension - 0.0 - _indexOfCollapsedView - 0 - _percentageOfCollapsedView - 0.0 - isCollapsed - yes - sizes - - {{0, 0}, {694, 164}} - {{0, 164}, {694, 216}} - - - - LauncherConfigVersion - 8 - PBXProjectModuleGUID - 1C162984064C10D400B95A72 - PBXProjectModuleLabel - Debug - GLUTExamples (Underwater) - - GeometryConfiguration - - DebugConsoleDrawerSize - {100, 120} - DebugConsoleVisible - None - DebugConsoleWindowFrame - {{200, 200}, {500, 300}} - DebugSTDIOWindowFrame - {{200, 200}, {500, 300}} - Frame - {{0, 0}, {694, 380}} - RubberWindowFrame - 321 238 694 422 0 0 1440 878 - - Module - PBXDebugSessionModule - Proportion - 100% - - - Proportion - 100% - - - Name - Debugger - ServiceClasses - - PBXDebugSessionModule - - StatusbarIsVisible - 1 - TableOfContents - - 1CD10A99069EF8BA00B06720 - 1C0AD2AB069F1E9B00FABCE6 - 1C162984064C10D400B95A72 - 1C0AD2AC069F1E9B00FABCE6 - - ToolbarConfiguration - xcode.toolbar.config.debugV3 - WindowString - 321 238 694 422 0 0 1440 878 - WindowToolGUID - 1CD10A99069EF8BA00B06720 - WindowToolIsVisible - 0 - - - Identifier - windowTool.find - Layout - - - Dock - - - Dock - - - ContentConfiguration - - PBXProjectModuleGUID - 1CDD528C0622207200134675 - PBXProjectModuleLabel - <No Editor> - PBXSplitModuleInNavigatorKey - - Split0 - - PBXProjectModuleGUID - 1CD0528D0623707200166675 - - SplitCount - 1 - - StatusBarVisibility - 1 - - GeometryConfiguration - - Frame - {{0, 0}, {781, 167}} - RubberWindowFrame - 62 385 781 470 0 0 1440 878 - - Module - PBXNavigatorGroup - Proportion - 781pt - - - Proportion - 50% - - - BecomeActive - 1 - ContentConfiguration - - PBXProjectModuleGUID - 1CD0528E0623707200166675 - PBXProjectModuleLabel - Project Find - - GeometryConfiguration - - Frame - {{8, 0}, {773, 254}} - RubberWindowFrame - 62 385 781 470 0 0 1440 878 - - Module - PBXProjectFindModule - Proportion - 50% - - - Proportion - 428pt - - - Name - Project Find - ServiceClasses - - PBXProjectFindModule - - StatusbarIsVisible - 1 - TableOfContents - - 1C530D57069F1CE1000CFCEE - 1C530D58069F1CE1000CFCEE - 1C530D59069F1CE1000CFCEE - 1CDD528C0622207200134675 - 1C530D5A069F1CE1000CFCEE - 1CE0B1FE06471DED0097A5F4 - 1CD0528E0623707200166675 - - WindowString - 62 385 781 470 0 0 1440 878 - WindowToolGUID - 1C530D57069F1CE1000CFCEE - WindowToolIsVisible - 0 - - - Identifier - MENUSEPARATOR - - - Identifier - windowTool.debuggerConsole - Layout - - - Dock - - - BecomeActive - 1 - ContentConfiguration - - PBXProjectModuleGUID - 1C78EAAC065D492600B07095 - PBXProjectModuleLabel - Debugger Console - - GeometryConfiguration - - Frame - {{0, 0}, {650, 250}} - RubberWindowFrame - 516 632 650 250 0 0 1680 1027 - - Module - PBXDebugCLIModule - Proportion - 209pt - - - Proportion - 209pt - - - Name - Debugger Console - ServiceClasses - - PBXDebugCLIModule - - StatusbarIsVisible - 1 - TableOfContents - - 1C78EAAD065D492600B07095 - 1C78EAAE065D492600B07095 - 1C78EAAC065D492600B07095 - - ToolbarConfiguration - xcode.toolbar.config.consoleV3 - WindowString - 650 41 650 250 0 0 1280 1002 - WindowToolGUID - 1C78EAAD065D492600B07095 - WindowToolIsVisible - 0 - - - Identifier - windowTool.snapshots - Layout - - - Dock - - - Module - XCSnapshotModule - Proportion - 100% - - - Proportion - 100% - - - Name - Snapshots - ServiceClasses - - XCSnapshotModule - - StatusbarIsVisible - Yes - ToolbarConfiguration - xcode.toolbar.config.snapshots - WindowString - 315 824 300 550 0 0 1440 878 - WindowToolIsVisible - Yes - - - Identifier - windowTool.scm - Layout - - - Dock - - - ContentConfiguration - - PBXProjectModuleGUID - 1C78EAB2065D492600B07095 - PBXProjectModuleLabel - <No Editor> - PBXSplitModuleInNavigatorKey - - Split0 - - PBXProjectModuleGUID - 1C78EAB3065D492600B07095 - - SplitCount - 1 - - StatusBarVisibility - 1 - - GeometryConfiguration - - Frame - {{0, 0}, {452, 0}} - RubberWindowFrame - 743 379 452 308 0 0 1280 1002 - - Module - PBXNavigatorGroup - Proportion - 0pt - - - BecomeActive - 1 - ContentConfiguration - - PBXProjectModuleGUID - 1CD052920623707200166675 - PBXProjectModuleLabel - SCM - - GeometryConfiguration - - ConsoleFrame - {{0, 259}, {452, 0}} - Frame - {{0, 7}, {452, 259}} - RubberWindowFrame - 743 379 452 308 0 0 1280 1002 - TableConfiguration - - Status - 30 - FileName - 199 - Path - 197.09500122070312 - - TableFrame - {{0, 0}, {452, 250}} - - Module - PBXCVSModule - Proportion - 262pt - - - Proportion - 266pt - - - Name - SCM - ServiceClasses - - PBXCVSModule - - StatusbarIsVisible - 1 - TableOfContents - - 1C78EAB4065D492600B07095 - 1C78EAB5065D492600B07095 - 1C78EAB2065D492600B07095 - 1CD052920623707200166675 - - ToolbarConfiguration - xcode.toolbar.config.scm - WindowString - 743 379 452 308 0 0 1280 1002 - - - Identifier - windowTool.breakpoints - IsVertical - 0 - Layout - - - Dock - - - BecomeActive - 1 - ContentConfiguration - - PBXBottomSmartGroupGIDs - - 1C77FABC04509CD000000102 - - PBXProjectModuleGUID - 1CE0B1FE06471DED0097A5F4 - PBXProjectModuleLabel - Files - PBXProjectStructureProvided - no - PBXSmartGroupTreeModuleColumnData - - PBXSmartGroupTreeModuleColumnWidthsKey - - 168 - - PBXSmartGroupTreeModuleColumnsKey_v4 - - MainColumn - - - PBXSmartGroupTreeModuleOutlineStateKey_v7 - - PBXSmartGroupTreeModuleOutlineStateExpansionKey - - 1C77FABC04509CD000000102 - - PBXSmartGroupTreeModuleOutlineStateSelectionKey - - - 0 - - - PBXSmartGroupTreeModuleOutlineStateVisibleRectKey - {{0, 0}, {168, 350}} - - PBXTopSmartGroupGIDs - - XCIncludePerspectivesSwitch - 0 - - GeometryConfiguration - - Frame - {{0, 0}, {185, 368}} - GroupTreeTableConfiguration - - MainColumn - 168 - - RubberWindowFrame - 315 424 744 409 0 0 1440 878 - - Module - PBXSmartGroupTreeModule - Proportion - 185pt - - - ContentConfiguration - - PBXProjectModuleGUID - 1CA1AED706398EBD00589147 - PBXProjectModuleLabel - Detail - - GeometryConfiguration - - Frame - {{190, 0}, {554, 368}} - RubberWindowFrame - 315 424 744 409 0 0 1440 878 - - Module - XCDetailModule - Proportion - 554pt - - - Proportion - 368pt - - - MajorVersion - 3 - MinorVersion - 0 - Name - Breakpoints - ServiceClasses - - PBXSmartGroupTreeModule - XCDetailModule - - StatusbarIsVisible - 1 - TableOfContents - - 1CDDB66807F98D9800BB5817 - 1CDDB66907F98D9800BB5817 - 1CE0B1FE06471DED0097A5F4 - 1CA1AED706398EBD00589147 - - ToolbarConfiguration - xcode.toolbar.config.breakpointsV3 - WindowString - 315 424 744 409 0 0 1440 878 - WindowToolGUID - 1CDDB66807F98D9800BB5817 - WindowToolIsVisible - 1 - - - Identifier - windowTool.debugAnimator - Layout - - - Dock - - - Module - PBXNavigatorGroup - Proportion - 100% - - - Proportion - 100% - - - Name - Debug Visualizer - ServiceClasses - - PBXNavigatorGroup - - StatusbarIsVisible - 1 - ToolbarConfiguration - xcode.toolbar.config.debugAnimatorV3 - WindowString - 100 100 700 500 0 0 1280 1002 - - - Identifier - windowTool.bookmarks - Layout - - - Dock - - - Module - PBXBookmarksModule - Proportion - 100% - - - Proportion - 100% - - - Name - Bookmarks - ServiceClasses - - PBXBookmarksModule - - StatusbarIsVisible - 0 - WindowString - 538 42 401 187 0 0 1280 1002 - - - Identifier - windowTool.projectFormatConflicts - Layout - - - Dock - - - Module - XCProjectFormatConflictsModule - Proportion - 100% - - - Proportion - 100% - - - Name - Project Format Conflicts - ServiceClasses - - XCProjectFormatConflictsModule - - StatusbarIsVisible - 0 - WindowContentMinSize - 450 300 - WindowString - 50 850 472 307 0 0 1440 877 - - - Identifier - windowTool.classBrowser - Layout - - - Dock - - - BecomeActive - 1 - ContentConfiguration - - OptionsSetName - Hierarchy, all classes - PBXProjectModuleGUID - 1CA6456E063B45B4001379D8 - PBXProjectModuleLabel - Class Browser - NSObject - - GeometryConfiguration - - ClassesFrame - {{0, 0}, {374, 96}} - ClassesTreeTableConfiguration - - PBXClassNameColumnIdentifier - 208 - PBXClassBookColumnIdentifier - 22 - - Frame - {{0, 0}, {630, 331}} - MembersFrame - {{0, 105}, {374, 395}} - MembersTreeTableConfiguration - - PBXMemberTypeIconColumnIdentifier - 22 - PBXMemberNameColumnIdentifier - 216 - PBXMemberTypeColumnIdentifier - 97 - PBXMemberBookColumnIdentifier - 22 - - PBXModuleWindowStatusBarHidden2 - 1 - RubberWindowFrame - 385 179 630 352 0 0 1440 878 - - Module - PBXClassBrowserModule - Proportion - 332pt - - - Proportion - 332pt - - - Name - Class Browser - ServiceClasses - - PBXClassBrowserModule - - StatusbarIsVisible - 0 - TableOfContents - - 1C0AD2AF069F1E9B00FABCE6 - 1C0AD2B0069F1E9B00FABCE6 - 1CA6456E063B45B4001379D8 - - ToolbarConfiguration - xcode.toolbar.config.classbrowser - WindowString - 385 179 630 352 0 0 1440 878 - WindowToolGUID - 1C0AD2AF069F1E9B00FABCE6 - WindowToolIsVisible - 0 - - - Identifier - windowTool.refactoring - IncludeInToolsMenu - 0 - Layout - - - Dock - - - BecomeActive - 1 - GeometryConfiguration - - Frame - {0, 0}, {500, 335} - RubberWindowFrame - {0, 0}, {500, 335} - - Module - XCRefactoringModule - Proportion - 100% - - - Proportion - 100% - - - Name - Refactoring - ServiceClasses - - XCRefactoringModule - - WindowString - 200 200 500 356 0 0 1920 1200 - - - - diff --git a/dyld.xcodeproj/kledzik.pbxuser b/dyld.xcodeproj/kledzik.pbxuser deleted file mode 100644 index ad6f46d..0000000 --- a/dyld.xcodeproj/kledzik.pbxuser +++ /dev/null @@ -1,140 +0,0 @@ -// !$*UTF8*$! -{ - F93937310A94FAF700070A07 /* update_dyld_shared_cache */ = { - activeExec = 0; - executables = ( - F9DBB2860CD7F5CF009A2B25 /* update_dyld_shared_cache */, - ); - }; - F9DBB2850CD7F5CF009A2B25 /* dyld */ = { - isa = PBXExecutable; - activeArgIndices = ( - ); - argumentStrings = ( - ); - autoAttachOnCrash = 1; - breakpointsEnabled = 1; - configStateDict = { - }; - customDataFormattersEnabled = 1; - debuggerPlugin = GDBDebugging; - disassemblyDisplayState = 0; - enableDebugStr = 1; - environmentEntries = ( - ); - executableSystemSymbolLevel = 0; - executableUserSymbolLevel = 0; - libgmallocEnabled = 0; - name = dyld; - sourceDirectories = ( - ); - }; - F9DBB2860CD7F5CF009A2B25 /* update_dyld_shared_cache */ = { - isa = PBXExecutable; - activeArgIndices = ( - ); - argumentStrings = ( - ); - autoAttachOnCrash = 1; - breakpointsEnabled = 1; - configStateDict = { - }; - customDataFormattersEnabled = 1; - debuggerPlugin = GDBDebugging; - disassemblyDisplayState = 0; - enableDebugStr = 1; - environmentEntries = ( - ); - executableSystemSymbolLevel = 0; - executableUserSymbolLevel = 0; - libgmallocEnabled = 0; - name = update_dyld_shared_cache; - sourceDirectories = ( - ); - }; - F9DBB2890CD7F5D3009A2B25 /* Source Control */ = { - isa = PBXSourceControlManager; - fallbackIsa = XCSourceControlManager; - isSCMEnabled = 0; - scmConfiguration = { - }; - }; - F9DBB28A0CD7F5D3009A2B25 /* Code sense */ = { - isa = PBXCodeSenseManager; - indexTemplatePath = ""; - }; - F9ED4C8B0630A72300DF4E74 /* Project object */ = { - activeArchitecture = i386; - activeBuildConfigurationName = Release; - activeExecutable = F9DBB2850CD7F5CF009A2B25 /* dyld */; - activeTarget = F9ED4C920630A73900DF4E74 /* all */; - codeSenseManager = F9DBB28A0CD7F5D3009A2B25 /* Code sense */; - executables = ( - F9DBB2850CD7F5CF009A2B25 /* dyld */, - F9DBB2860CD7F5CF009A2B25 /* update_dyld_shared_cache */, - ); - perUserDictionary = { - PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = { - PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; - PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; - PBXFileTableDataSourceColumnWidthsKey = ( - 20, - 243, - 20, - 48.16259765625, - 43, - 43, - 20, - ); - PBXFileTableDataSourceColumnsKey = ( - PBXFileDataSource_FiletypeID, - PBXFileDataSource_Filename_ColumnID, - PBXFileDataSource_Built_ColumnID, - PBXFileDataSource_ObjectSize_ColumnID, - PBXFileDataSource_Errors_ColumnID, - PBXFileDataSource_Warnings_ColumnID, - PBXFileDataSource_Target_ColumnID, - ); - }; - PBXConfiguration.PBXTargetDataSource.PBXTargetDataSource = { - PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; - PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; - PBXFileTableDataSourceColumnWidthsKey = ( - 20, - 203, - 60, - 20, - 48.16259765625, - 43, - 43, - ); - PBXFileTableDataSourceColumnsKey = ( - PBXFileDataSource_FiletypeID, - PBXFileDataSource_Filename_ColumnID, - PBXTargetDataSource_PrimaryAttribute, - PBXFileDataSource_Built_ColumnID, - PBXFileDataSource_ObjectSize_ColumnID, - PBXFileDataSource_Errors_ColumnID, - PBXFileDataSource_Warnings_ColumnID, - ); - }; - PBXPerProjectTemplateStateSaveDate = 215479759; - PBXWorkspaceStateSaveDate = 215479759; - }; - sourceControlManager = F9DBB2890CD7F5D3009A2B25 /* Source Control */; - userBuildSettings = { - }; - }; - F9ED4C920630A73900DF4E74 /* all */ = { - activeExec = 0; - }; - F9ED4C970630A76000DF4E74 /* dyld */ = { - activeExec = 0; - executables = ( - F9DBB2850CD7F5CF009A2B25 /* dyld */, - ); - }; - F9ED4C9E0630A76B00DF4E74 /* libdyld */ = { - activeExec = 0; - }; -} diff --git a/launch-cache/MachOBinder.hpp b/launch-cache/MachOBinder.hpp index cb37248..6bde8cd 100644 --- a/launch-cache/MachOBinder.hpp +++ b/launch-cache/MachOBinder.hpp @@ -110,13 +110,14 @@ Binder::Binder(const MachOLayoutAbstraction& layout, uint64_t dyldBaseAddress ((macho_header

*)this->fHeader)->set_flags(this->fHeader->flags() | MH_PREBOUND | MH_SPLIT_SEGS | 0x80000000); // calculate fDynamicInfo, fStrings, fSymbolTable + const macho_symtab_command

* symtab; const macho_load_command

* const cmds = (macho_load_command

*)((uint8_t*)this->fHeader + sizeof(macho_header

)); const uint32_t cmd_count = this->fHeader->ncmds(); const macho_load_command

* cmd = cmds; for (uint32_t i = 0; i < cmd_count; ++i) { switch (cmd->cmd()) { case LC_SYMTAB: - const macho_symtab_command

* symtab = (macho_symtab_command

*)cmd; + symtab = (macho_symtab_command

*)cmd; fSymbolTable = (macho_nlist

*)(&this->fLinkEditBase[symtab->symoff()]); fStrings = (const char*)&this->fLinkEditBase[symtab->stroff()]; break; @@ -256,10 +257,12 @@ void Binder::setDependentBinders(const Map& map) if ( (this->fHeader->flags() & MH_NO_REEXPORTED_DYLIBS) == 0 ) { cmd = cmds; // LC_SUB_LIBRARY means re-export one with matching leaf name + const char* dylibBaseName; + const char* frameworkLeafName; for (uint32_t i = 0; i < cmd_count; ++i) { switch ( cmd->cmd() ) { case LC_SUB_LIBRARY: - const char* dylibBaseName = ((macho_sub_library_command

*)cmd)->sub_library(); + dylibBaseName = ((macho_sub_library_command

*)cmd)->sub_library(); for (typename std::vector::iterator it = fDependentDylibs.begin(); it != fDependentDylibs.end(); ++it) { const char* dylibName = it->binder->getDylibID(); const char* lastSlash = strrchr(dylibName, '/'); @@ -275,7 +278,7 @@ void Binder::setDependentBinders(const Map& map) } break; case LC_SUB_UMBRELLA: - const char* frameworkLeafName = ((macho_sub_umbrella_command

*)cmd)->sub_umbrella(); + frameworkLeafName = ((macho_sub_umbrella_command

*)cmd)->sub_umbrella(); for (typename std::vector::iterator it = fDependentDylibs.begin(); it != fDependentDylibs.end(); ++it) { const char* dylibName = it->binder->getDylibID(); const char* lastSlash = strrchr(dylibName, '/'); diff --git a/launch-cache/MachOLayout.hpp b/launch-cache/MachOLayout.hpp index 1a3017f..f49210d 100644 --- a/launch-cache/MachOLayout.hpp +++ b/launch-cache/MachOLayout.hpp @@ -40,6 +40,7 @@ #include #include +#include #include "MachOFileAbstraction.hpp" #include "Architectures.hpp" @@ -274,6 +275,8 @@ UniversalMachOLayout::UniversalMachOLayout(const char* path, const std::setnfat_arch); ++i) { uint32_t fileOffset = OSSwapBigToHostInt32(archs[i].offset); cpu_type_t curArch = OSSwapBigToHostInt32(archs[i].cputype); + if ( fileOffset > stat_buf.st_size ) + throwf("malformed universal file, slice for architecture 0x%08X is beyond end of file: %s", curArch, path); try { if ( (onlyArchs == NULL) || (onlyArchs->count(curArch) != 0) ) { switch ( curArch ) { diff --git a/launch-cache/MachORebaser.hpp b/launch-cache/MachORebaser.hpp index 4cf81f3..e3c187f 100644 --- a/launch-cache/MachORebaser.hpp +++ b/launch-cache/MachORebaser.hpp @@ -389,9 +389,11 @@ void Rebaser::doCodeUpdate(uint8_t kind, uint64_t address, int64_t codeToData throwf("codeToDataDelta=0x%0llX is not a multiple of 64K", codeToDataDelta); p = (uint32_t*)mappedAddressForVMAddress(address); instruction = BigEndian::get32(*p); - uint16_t originalLo16 = instruction & 0x0000FFFF; - uint16_t delta64Ks = codeToDataDelta >> 16; - instruction = (instruction & 0xFFFF0000) | ((originalLo16+delta64Ks) & 0x0000FFFF); + { + uint16_t originalLo16 = instruction & 0x0000FFFF; + uint16_t delta64Ks = codeToDataDelta >> 16; + instruction = (instruction & 0xFFFF0000) | ((originalLo16+delta64Ks) & 0x0000FFFF); + } BigEndian::set32(*p, instruction); break; case 4: // only used for i386, a reference to something in the IMPORT segment diff --git a/launch-cache/com.apple.dyld.plist b/launch-cache/com.apple.dyld.plist index 7481c33..c059670 100644 --- a/launch-cache/com.apple.dyld.plist +++ b/launch-cache/com.apple.dyld.plist @@ -20,7 +20,5 @@ DYLD_NO_FIX_PREBINDING 1 - ThrottleInterval - 60 diff --git a/launch-cache/update_dyld_shared_cache.cpp b/launch-cache/update_dyld_shared_cache.cpp index 4ec8cf8..f437330 100644 --- a/launch-cache/update_dyld_shared_cache.cpp +++ b/launch-cache/update_dyld_shared_cache.cpp @@ -31,9 +31,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -390,7 +392,7 @@ class SharedCache { public: SharedCache(ArchGraph* graph, bool alphaSort, uint64_t dyldBaseAddress); - bool update(const char* rootPath, const char* cacheDir, bool force, bool optimize, int archIndex, int archCount); + bool update(const char* rootPath, const char* cacheDir, bool force, bool optimize, bool deleteExistingFirst, int archIndex, int archCount); static const char* filename(bool optimized); private: @@ -440,7 +442,6 @@ private: std::vector fDylibs; std::vector fMappings; uint32_t fHeaderSize; - uint8_t* fMappedCacheFile; uint64_t fDyldBaseAddress; uint64_t fLinkEditsTotalUnoptimizedSize; uint64_t fLinkEditsStartAddress; @@ -1195,8 +1196,21 @@ uint8_t* SharedCache::optimizeLINKEDIT() } +static const char* sCleanupFile = NULL; +static void cleanup(int sig) +{ + ::signal(sig, SIG_DFL); + if ( sCleanupFile != NULL ) + ::unlink(sCleanupFile); + //if ( verbose ) + // fprintf(stderr, "update_dyld_shared_cache: deleting temp file in response to a signal\n"); + if ( sig == SIGINT ) + ::exit(1); +} + + template -bool SharedCache::update(const char* rootPath, const char* cacheDir, bool force, bool optimize, int archIndex, int archCount) +bool SharedCache::update(const char* rootPath, const char* cacheDir, bool force, bool optimize, bool deleteExistingFirst, int archIndex, int archCount) { bool didUpdate = false; char cachePath[1024]; @@ -1213,29 +1227,28 @@ bool SharedCache::update(const char* rootPath, const char* cacheDir, bool for fprintf(stderr, "update_dyld_shared_cache: warning, empty cache not generated for arch %s\n", archName()); return false; } + // delete existing cache while building the new one + // this is a flag to dyld to stop pinging update_dyld_shared_cache + if ( deleteExistingFirst ) + ::unlink(cachePath); + uint8_t* inMemoryCache = NULL; + uint32_t allocatedCacheSize = 0; char tempCachePath[strlen(cachePath)+16]; sprintf(tempCachePath, "%s.tmp%u", cachePath, getpid()); try { - int fd = ::open(tempCachePath, O_CREAT | O_RDWR | O_TRUNC, 0644); - if ( fd == -1 ) - throwf("can't create temp file %s, errnor=%d", tempCachePath, errno); - - // try to allocate whole cache file contiguously + // allocate a memory block to hold cache uint32_t cacheFileSize = 0; for(std::vector::iterator it = fMappings.begin(); it != fMappings.end(); ++it) { uint32_t end = it->sfm_file_offset + it->sfm_size; if ( end > cacheFileSize ) cacheFileSize = end; } - fstore_t fcntlSpec = { F_ALLOCATECONTIG|F_ALLOCATEALL, F_PEOFPOSMODE, 0, cacheFileSize, 0 }; - fcntl(fd, F_PREALLOCATE, &fcntlSpec); - - // fill in cache header memory buffer - uint8_t buffer[pageAlign(fHeaderSize)]; - bzero(buffer, sizeof(buffer)); + if ( vm_allocate(mach_task_self(), (vm_address_t*)(&inMemoryCache), cacheFileSize, VM_FLAGS_ANYWHERE) != KERN_SUCCESS ) + throwf("can't vm_allocate cache of size %u", cacheFileSize); + allocatedCacheSize = cacheFileSize; // fill in header - dyldCacheHeader* header = (dyldCacheHeader*)buffer; + dyldCacheHeader* header = (dyldCacheHeader*)inMemoryCache; char temp[16]; strcpy(temp, "dyld_v1 "); strcpy(&temp[15-strlen(archName())], archName()); @@ -1250,7 +1263,7 @@ bool SharedCache::update(const char* rootPath, const char* cacheDir, bool for //header->set_dependenciesCount(fDependencyPool.size()); // fill in mappings - dyldCacheFileMapping* mapping = (dyldCacheFileMapping*)&buffer[sizeof(dyldCacheHeader)]; + dyldCacheFileMapping* mapping = (dyldCacheFileMapping*)&inMemoryCache[sizeof(dyldCacheHeader)]; for(std::vector::iterator it = fMappings.begin(); it != fMappings.end(); ++it) { if ( verbose ) fprintf(stderr, "update_dyld_shared_cache: cache mappings: address=0x%0llX, size=0x%0llX, fileOffset=0x%0llX, prot=0x%X\n", @@ -1274,23 +1287,7 @@ bool SharedCache::update(const char* rootPath, const char* cacheDir, bool for ++image; } - // write whole header to disk - pwrite(fd, buffer, sizeof(buffer), 0); - - // allocate copy buffer - const uint64_t kCopyBufferSize = 256*1024; - uint8_t* copyBuffer; - vm_address_t addr = 0; - if ( vm_allocate(mach_task_self(), &addr, kCopyBufferSize, VM_FLAGS_ANYWHERE) == KERN_SUCCESS ) - copyBuffer = (uint8_t*)addr; - else - throw "can't allcoate copy buffer"; - - // make zero-fill buffer - uint8_t zerofill[4096]; - bzero(zerofill, sizeof(zerofill)); - - // write each segment to cache file + // copy each segment to cache buffer int dylibIndex = 0; for(typename std::vector::const_iterator it = fDylibs.begin(); it != fDylibs.end(); ++it, ++dylibIndex) { const char* path = it->layout->getFilePath(); @@ -1301,7 +1298,7 @@ bool SharedCache::update(const char* rootPath, const char* cacheDir, bool for (void)fcntl(src, F_NOCACHE, 1); if ( verbose ) - fprintf(stderr, "update_prebinding: copying %s to cache\n", it->layout->getID().name); + fprintf(stderr, "update_dyld_shared_cache: copying %s to cache\n", it->layout->getID().name); try { const std::vector& segs = it->layout->getSegments(); for (int i=0; i < segs.size(); ++i) { @@ -1312,23 +1309,8 @@ bool SharedCache::update(const char* rootPath, const char* cacheDir, bool for const uint64_t segmentSrcStartOffset = it->layout->getOffsetInUniversalFile()+seg.fileOffset(); const uint64_t segmentSize = seg.fileSize(); const uint64_t segmentDstStartOffset = cacheFileOffsetForAddress(seg.newAddress()); - for(uint64_t copiedAmount=0; copiedAmount < segmentSize; copiedAmount += kCopyBufferSize) { - uint64_t amount = std::min(segmentSize-copiedAmount, kCopyBufferSize); - //fprintf(stderr, "copy 0x%08llX bytes at offset 0x%08llX for segment %s in %s to cache offset 0x%08llX\n", - // amount, segmentSrcStartOffset+copiedAmount, seg.name(), it->layout->getID().name, segmentDstStartOffset+copiedAmount); - if ( ::pread(src, copyBuffer, amount, segmentSrcStartOffset+copiedAmount) != amount ) - throwf("read failure copying dylib errno=%d for %s", errno, it->layout->getID().name); - if ( ::pwrite(fd, copyBuffer, amount, segmentDstStartOffset+copiedAmount) != amount ) - throwf("write failure copying dylib errno=%d for %s", errno, it->layout->getID().name); - } - if ( seg.size() > seg.fileSize() ) { - // write zero-filled area - for(uint64_t copiedAmount=seg.fileSize(); copiedAmount < seg.size(); copiedAmount += sizeof(zerofill)) { - uint64_t amount = std::min(seg.size()-copiedAmount, (uint64_t)(sizeof(zerofill))); - if ( ::pwrite(fd, zerofill, amount, segmentDstStartOffset+copiedAmount) != amount ) - throwf("write failure copying dylib errno=%d for %s", errno, it->layout->getID().name); - } - } + if ( ::pread(src, &inMemoryCache[segmentDstStartOffset], segmentSize, segmentSrcStartOffset) != segmentSize ) + throwf("read failure copying dylib errno=%d for %s", errno, it->layout->getID().name); } } } @@ -1337,26 +1319,14 @@ bool SharedCache::update(const char* rootPath, const char* cacheDir, bool for } ::close(src); } - - // free copy buffer - vm_deallocate(mach_task_self(), addr, kCopyBufferSize); - - // map cache file - fMappedCacheFile = (uint8_t*)mmap(NULL, cacheFileSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if ( fMappedCacheFile == (uint8_t*)(-1) ) - throw "can't mmap cache file"; - - // close cache file - ::fsync(fd); - ::close(fd); - + // set mapped address for each segment for(typename std::vector::const_iterator it = fDylibs.begin(); it != fDylibs.end(); ++it) { std::vector& segs = ((MachOLayoutAbstraction*)(it->layout))->getSegments(); for (int i=0; i < segs.size(); ++i) { MachOLayoutAbstraction::Segment& seg = segs[i]; if ( seg.size() > 0 ) - seg.setMappedAddress(fMappedCacheFile + cacheFileOffsetForAddress(seg.newAddress())); + seg.setMappedAddress(inMemoryCache + cacheFileOffsetForAddress(seg.newAddress())); //fprintf(stderr, "%s at %p to %p for %s\n", seg.name(), seg.mappedAddress(), (char*)seg.mappedAddress()+ seg.size(), it->layout->getID().name); } } @@ -1377,11 +1347,11 @@ bool SharedCache::update(const char* rootPath, const char* cacheDir, bool for // merge/optimize all LINKEDIT segments if ( optimize ) { //fprintf(stderr, "update_dyld_shared_cache: original cache file size %uMB\n", cacheFileSize/(1024*1024)); - cacheFileSize = (this->optimizeLINKEDIT() - fMappedCacheFile); + cacheFileSize = (this->optimizeLINKEDIT() - inMemoryCache); //fprintf(stderr, "update_dyld_shared_cache: optimized cache file size %uMB\n", cacheFileSize/(1024*1024)); // update header to reduce mapping size - dyldCacheHeader* cacheHeader = (dyldCacheHeader*)fMappedCacheFile; - dyldCacheFileMapping* mappings = (dyldCacheFileMapping*)&fMappedCacheFile[sizeof(dyldCacheHeader)]; + dyldCacheHeader* cacheHeader = (dyldCacheHeader*)inMemoryCache; + dyldCacheFileMapping* mappings = (dyldCacheFileMapping*)&inMemoryCache[sizeof(dyldCacheHeader)]; dyldCacheFileMapping* lastMapping = &mappings[cacheHeader->mappingCount()-1]; lastMapping->set_size(cacheFileSize-lastMapping->file_offset()); // update fMappings so .map file will print correctly @@ -1420,33 +1390,53 @@ bool SharedCache::update(const char* rootPath, const char* cacheDir, bool for for(typename std::vector*>::iterator it = binders.begin(); it != binders.end(); ++it) { delete *it; } - - // close mapping - int result = ::msync(fMappedCacheFile, cacheFileSize, MS_SYNC); - if ( result != 0 ) - throw "error syncing cache file"; - result = ::munmap(fMappedCacheFile, cacheFileSize); - if ( result != 0 ) - throw "error unmapping cache file"; + + // install signal handlers to delete temp file if program is killed + sCleanupFile = tempCachePath; + ::signal(SIGINT, cleanup); + ::signal(SIGBUS, cleanup); + ::signal(SIGSEGV, cleanup); - // cut back cache file to match optmized size - if ( optimize ) { - if ( ::truncate(tempCachePath, cacheFileSize) != 0 ) - throw "error truncating cache file"; - } + // create temp file for cache + int fd = ::open(tempCachePath, O_CREAT | O_RDWR | O_TRUNC, 0644); + if ( fd == -1 ) + throwf("can't create temp file %s, errnor=%d", tempCachePath, errno); + + // try to allocate whole cache file contiguously + fstore_t fcntlSpec = { F_ALLOCATECONTIG|F_ALLOCATEALL, F_PEOFPOSMODE, 0, cacheFileSize, 0 }; + ::fcntl(fd, F_PREALLOCATE, &fcntlSpec); + + // write out cache file + if ( verbose ) + fprintf(stderr, "update_dyld_shared_cache: writing cache to disk\n"); + if ( ::pwrite(fd, inMemoryCache, cacheFileSize, 0) != cacheFileSize ) + throwf("write() failure creating cache file, errno=%d", errno); - // commit - ::sync(); - // flush everything to disk, otherwise if kernel panics before the cache file is completely written to disk - // then next reboot will use a corrupted cache and die + // flush to disk and close + int result = ::fcntl(fd, F_FULLFSYNC, NULL); + if ( result == -1 ) + fprintf(stderr, "update_dyld_shared_cache: warning, fcntl(F_FULLFSYNC) failed with errno=%d for %s\n", errno, tempCachePath); + result = ::close(fd); + if ( result != 0 ) + fprintf(stderr, "update_dyld_shared_cache: warning, close() failed with errno=%d for %s\n", errno, tempCachePath); + + // atomically swap in new cache file, do this after F_FULLFSYNC result = ::rename(tempCachePath, cachePath); if ( result != 0 ) throwf("can't swap newly create dyld shared cache file: rename(%s,%s) returned errno=%d", tempCachePath, cachePath, errno); + // flush everything to disk to assure rename() gets recorded ::sync(); didUpdate = true; + + // restore default signal handlers + ::signal(SIGINT, SIG_DFL); + ::signal(SIGBUS, SIG_DFL); + ::signal(SIGSEGV, SIG_DFL); // generate human readable "map" file that shows the layout of the cache file + if ( verbose ) + fprintf(stderr, "update_dyld_shared_cache: writing .map file to disk\n"); sprintf(tempCachePath, "%s.map", cachePath);// re-use path buffer FILE* fmap = ::fopen(tempCachePath, "w"); if ( fmap == NULL ) { @@ -1484,10 +1474,17 @@ bool SharedCache::update(const char* rootPath, const char* cacheDir, bool for } fclose(fmap); } + + // free in memory cache + vm_deallocate(mach_task_self(), (vm_address_t)inMemoryCache, allocatedCacheSize); + inMemoryCache = NULL; } catch (...){ - // remove temp cache + // remove temp cache file ::unlink(tempCachePath); + // remove in memory cache + if ( inMemoryCache != NULL ) + vm_deallocate(mach_task_self(), (vm_address_t)inMemoryCache, allocatedCacheSize); throw; } } @@ -1617,9 +1614,51 @@ static void scanForSharedDylibs(const char* rootPath, const char* dirOfPathFiles } +// If the 10.5.0 version of update_dyld_shared_cache was killed or crashed, it +// could leave large half written cache files laying around. The function deletes +// those files. To prevent the deletion of tmp files being created by another +// copy of update_dyld_shared_cache, it only deletes the temp cache file if its +// creation time was before the last restart of this machine. +static void deleteOrphanTempCacheFiles() +{ + DIR* dir = ::opendir(DYLD_SHARED_CACHE_DIR); + if ( dir != NULL ) { + std::vector filesToDelete; + for (dirent* entry = ::readdir(dir); entry != NULL; entry = ::readdir(dir)) { + if ( entry->d_type == DT_REG ) { + // only look at files with .tmp in name + if ( strstr(entry->d_name, ".tmp") != NULL ) { + char fullPath[strlen(DYLD_SHARED_CACHE_DIR)+entry->d_namlen+2]; + strcpy(fullPath, DYLD_SHARED_CACHE_DIR); + strcat(fullPath, "/"); + strcat(fullPath, entry->d_name); + struct stat tmpFileStatInfo; + if ( stat(fullPath, &tmpFileStatInfo) != -1 ) { + int mib[2] = {CTL_KERN, KERN_BOOTTIME}; + struct timeval boottime; + size_t size = sizeof(boottime); + if ( (sysctl(mib, 2, &boottime, &size, NULL, 0) != -1) && (boottime.tv_sec != 0) ) { + // make sure this file is older than the boot time of this machine + if ( tmpFileStatInfo.st_mtime < boottime.tv_sec ) { + filesToDelete.push_back(strdup(fullPath)); + } + } + } + } + } + } + ::closedir(dir); + for(std::vector::iterator it = filesToDelete.begin(); it != filesToDelete.end(); ++it) { + fprintf(stderr, "update_dyld_shared_cache: deleting old temp cache file: %s\n", *it); + ::unlink(*it); + } + } +} + + static bool updateSharedeCacheFile(const char* rootPath, const char* cacheDir, const std::set& onlyArchs, - bool force, bool alphaSort, bool optimize) + bool force, bool alphaSort, bool optimize, bool deleteExistingFirst) { bool didUpdate = false; // get dyld load address info @@ -1638,32 +1677,35 @@ static bool updateSharedeCacheFile(const char* rootPath, const char* cacheDir, c SharedCache cache(ArchGraph::getArch(*a), alphaSort, dyldBaseAddress); #if __i386__ // Rosetta does not work with optimized dyld shared cache - didUpdate |= cache.update(rootPath, cacheDir, force, false, index, archCount); + didUpdate |= cache.update(rootPath, cacheDir, force, false, deleteExistingFirst, index, archCount); #else - didUpdate |= cache.update(rootPath, cacheDir, force, optimize, index, archCount); + didUpdate |= cache.update(rootPath, cacheDir, force, optimize, deleteExistingFirst, index, archCount); #endif } break; case CPU_TYPE_POWERPC64: { SharedCache cache(ArchGraph::getArch(*a), alphaSort, dyldBaseAddress); - didUpdate |= cache.update(rootPath, cacheDir, force, optimize, index, archCount); + didUpdate |= cache.update(rootPath, cacheDir, force, optimize, deleteExistingFirst, index, archCount); } break; case CPU_TYPE_I386: { SharedCache cache(ArchGraph::getArch(*a), alphaSort, dyldBaseAddress); - didUpdate |= cache.update(rootPath, cacheDir, force, optimize, index, archCount); + didUpdate |= cache.update(rootPath, cacheDir, force, optimize, deleteExistingFirst, index, archCount); } break; case CPU_TYPE_X86_64: { SharedCache cache(ArchGraph::getArch(*a), alphaSort, dyldBaseAddress); - didUpdate |= cache.update(rootPath, cacheDir, force, optimize, index, archCount); + didUpdate |= cache.update(rootPath, cacheDir, force, optimize, deleteExistingFirst, index, archCount); } break; } } + + deleteOrphanTempCacheFiles(); + return didUpdate; } @@ -1673,31 +1715,40 @@ static void usage() fprintf(stderr, "update_dyld_shared_cache [-force] [-root dir] [-arch arch] [-debug]\n"); } +// flag so that we only update cache once per invocation +static bool doNothingAndDrainQueue = false; -kern_return_t do_dyld_shared_cache_missing(mach_port_t dyld_port, cpu_type_t arch) +static kern_return_t do_update_cache(cpu_type_t arch, bool deleteExistingCacheFileFirst) { - std::set onlyArchs; - onlyArchs.insert(arch); - try { - scanForSharedDylibs("", "/var/db/dyld/shared_region_roots/", onlyArchs); - if ( updateSharedeCacheFile("", DYLD_SHARED_CACHE_DIR, onlyArchs, false, false, true) ) - fprintf(stderr, "update_dyld_shared_cache[%u] regenerated cache for arch=%s\n", getpid(), ArchGraph::archName(arch)); - } - catch (const char* msg) { - fprintf(stderr, "update_dyld_shared_cache[%u] for arch=%s failed: %s\n", getpid(), ArchGraph::archName(arch), msg); - return KERN_FAILURE; + if ( !doNothingAndDrainQueue ) { + std::set onlyArchs; + onlyArchs.insert(arch); + try { + scanForSharedDylibs("", "/var/db/dyld/shared_region_roots/", onlyArchs); + if ( updateSharedeCacheFile("", DYLD_SHARED_CACHE_DIR, onlyArchs, false, false, true, deleteExistingCacheFileFirst) ) + fprintf(stderr, "update_dyld_shared_cache[%u] regenerated cache for arch=%s\n", getpid(), ArchGraph::archName(arch)); + } + catch (const char* msg) { + fprintf(stderr, "update_dyld_shared_cache[%u] for arch=%s failed: %s\n", getpid(), ArchGraph::archName(arch), msg); + return KERN_FAILURE; + } } return KERN_SUCCESS; } + +kern_return_t do_dyld_shared_cache_missing(mach_port_t dyld_port, cpu_type_t arch) +{ + return do_update_cache(arch, false); +} + + kern_return_t do_dyld_shared_cache_out_of_date(mach_port_t dyld_port, cpu_type_t arch) { - // reduce priority of this process so it only runs at the lowest priority - setpriority(PRIO_PROCESS, 0, PRIO_MAX); - - // and then rebuild cache - return do_dyld_shared_cache_missing(dyld_port, arch); + // If cache exists but is out of date, delete the file while building the new one. + // This will stop dyld from pinging update_dyld_share_cache while the cache is being built. + return do_update_cache(arch, true); } @@ -1706,12 +1757,18 @@ int main(int argc, const char* argv[]) mach_port_t mp; if ( bootstrap_check_in(bootstrap_port, "com.apple.dyld", &mp) == KERN_SUCCESS ) { // started by launchd - // Just process one message and quit mach_msg_size_t mxmsgsz = sizeof(union __RequestUnion__do_dyld_server_subsystem) + MAX_TRAILER_SIZE; - mach_msg_server_once(dyld_server_server, mxmsgsz, mp, MACH_RCV_TIMEOUT); - // The problem with staying alive and processing messages is that the rest of this - // tool leaks mapped memory and file descriptors. Quiting will clean that up. - // 9A516 - Keep getting disk full errors + doNothingAndDrainQueue = false; + while ( mach_msg_server(dyld_server_server, mxmsgsz, mp, MACH_RCV_TIMEOUT) == KERN_SUCCESS ) { + // keep processing messages + doNothingAndDrainQueue = true; + // but set flag so work is no longer done. + // This is because the rest of the tool leaks and processing more than once + // can hog system resources: 9A516 - Keep getting disk full errors + // We drain the queue of messages because there is usually are a couple of duplicate messages. + // It is ok to miss some messages. If the cache is out of date or missing, some new process + // will discover it and send another message. + } return 0; } else { @@ -1811,7 +1868,7 @@ int main(int argc, const char* argv[]) // build list of shared dylibs scanForSharedDylibs(rootPath, "/var/db/dyld/shared_region_roots/", onlyArchs); - updateSharedeCacheFile(rootPath, DYLD_SHARED_CACHE_DIR, onlyArchs, force, alphaSort, optimize); + updateSharedeCacheFile(rootPath, DYLD_SHARED_CACHE_DIR, onlyArchs, force, alphaSort, optimize, false); // To make a universal bootable image with dyld caches, // build the rosetta cache and symlink ppc to point to it. diff --git a/src/ImageLoader.cpp b/src/ImageLoader.cpp index 7a84b13..1274a7f 100644 --- a/src/ImageLoader.cpp +++ b/src/ImageLoader.cpp @@ -91,6 +91,7 @@ void ImageLoader::init(const char* path, uint64_t offsetInFat, dev_t device, ino #endif fAllLazyPointersBound = false; fBeingRemoved = false; + fAddFuncNotified = false; fPathOwnedByImage = false; #if RECURSIVE_INITIALIZER_LOCK fInitializerRecursiveLock = NULL; @@ -472,8 +473,8 @@ void ImageLoader::bindAllLazyPointers(const LinkContext& context, bool recursive libInfo.image->bindAllLazyPointers(context, recursive); } } - // bind lazys in this image - this->doBind(context, true); + // bind lazies in this image + this->doBindJustLazies(context); } } diff --git a/src/ImageLoader.h b/src/ImageLoader.h index e7795d0..e6c2480 100644 --- a/src/ImageLoader.h +++ b/src/ImageLoader.h @@ -153,6 +153,7 @@ public: bool prebinding; bool bindFlat; bool linkingMainExecutable; + bool startedInitializingMainExecutable; bool verboseOpts; bool verboseEnv; bool verboseMapping; @@ -360,6 +361,8 @@ public: void setBeingRemoved() { fBeingRemoved = true; } bool isBeingRemoved() const { return fBeingRemoved; } + void setAddFuncNotified() { fAddFuncNotified = true; } + bool addFuncNotified() const { return fAddFuncNotified; } protected: struct DependentLibrary; @@ -457,6 +460,9 @@ protected: // do any symbolic fix ups in this image virtual void doBind(const LinkContext& context, bool forceLazysBound) = 0; + // called later via API to force all lazy pointer to be bound + virtual void doBindJustLazies(const LinkContext& context) = 0; + // update any segment permissions virtual void doUpdateMappingPermissions(const LinkContext& context) = 0; @@ -569,6 +575,7 @@ private: #endif fAllLazyPointersBound : 1, fBeingRemoved : 1, + fAddFuncNotified : 1, fPathOwnedByImage : 1; #if RECURSIVE_INITIALIZER_LOCK diff --git a/src/ImageLoaderMachO.cpp b/src/ImageLoaderMachO.cpp index fcf7cd7..1a8bfdf 100644 --- a/src/ImageLoaderMachO.cpp +++ b/src/ImageLoaderMachO.cpp @@ -2459,7 +2459,7 @@ void ImageLoaderMachO::makeImportSegmentWritable(const LinkContext& context) { if ( fReadOnlyImportSegment != NULL ) { if ( fInSharedCache ) { - if ( !context.linkingMainExecutable ) { + if ( context.startedInitializingMainExecutable ) { _spin_lock(&fgReadOnlyImportSpinLock); context.makeSharedCacheImportSegmentsWritable(true); } @@ -2475,7 +2475,7 @@ void ImageLoaderMachO::makeImportSegmentReadOnly(const LinkContext& context) { if ( fReadOnlyImportSegment != NULL ) { if ( fInSharedCache ) { - if ( !context.linkingMainExecutable ) { + if ( context.startedInitializingMainExecutable ) { context.makeSharedCacheImportSegmentsWritable(false); _spin_unlock(&fgReadOnlyImportSpinLock); } @@ -2806,14 +2806,14 @@ bool ImageLoaderMachO::usablePrebinding(const LinkContext& context) const return false; } -void ImageLoaderMachO::doBind(const LinkContext& context, bool forceLazysBound) +void ImageLoaderMachO::doBindJustLazies(const LinkContext& context) { - // check for runtime forcing of lazy pointers to be bound - if ( forceLazysBound && (this->getState() > dyld_image_state_bound) ) { - this->doBindIndirectSymbolPointers(context, false, forceLazysBound, false); - return; - } + // some API called requested that all lazy pointers in this image be force bound + this->doBindIndirectSymbolPointers(context, false, true, false); +} +void ImageLoaderMachO::doBind(const LinkContext& context, bool forceLazysBound) +{ // set dyld entry points in image this->setupLazyPointerHandler(context); diff --git a/src/ImageLoaderMachO.h b/src/ImageLoaderMachO.h index a7f2c41..e28f672 100644 --- a/src/ImageLoaderMachO.h +++ b/src/ImageLoaderMachO.h @@ -94,6 +94,7 @@ protected: virtual void getRPaths(const LinkContext& context, std::vector&) const; virtual void doRebase(const LinkContext& context); virtual void doBind(const LinkContext& context, bool forceLazysBound); + virtual void doBindJustLazies(const LinkContext& context); virtual void doUpdateMappingPermissions(const LinkContext& context); virtual void doInitialization(const LinkContext& context); virtual void doGetDOFSections(const LinkContext& context, std::vector& dofs); diff --git a/src/dyld.cpp b/src/dyld.cpp index 8d340ad..33a4a03 100644 --- a/src/dyld.cpp +++ b/src/dyld.cpp @@ -328,8 +328,12 @@ static void unregisterDOF(int registrationID) // static void notifyAddImageCallbacks(ImageLoader* image) { - for (std::vector::iterator it=sAddImageCallbacks.begin(); it != sAddImageCallbacks.end(); it++) - (*it)(image->machHeader(), image->getSlide()); + // use guard so that we cannot notify about the same image twice + if ( ! image->addFuncNotified() ) { + for (std::vector::iterator it=sAddImageCallbacks.begin(); it != sAddImageCallbacks.end(); it++) + (*it)(image->machHeader(), image->getSlide()); + image->setAddFuncNotified(); + } } @@ -676,6 +680,9 @@ const char* getExecutablePath() void initializeMainExecutable() { + // record that we've reached this step + gLinkContext.startedInitializingMainExecutable = true; + #if __i386__ // make all __IMPORT segments in the shared cache read-only // before executing any code @@ -2076,6 +2083,21 @@ static int __attribute__((noinline)) _shared_region_map_np(int fd, uint32_t coun #define ARCH_CACHE_MAGIC "dyld_v1 x86_64" #endif +const void* imMemorySharedCacheHeader() +{ + return sSharedCache; +} + +int openSharedCacheFile() +{ +#if __ppc__ + // rosetta cannot handle optimized _ppc cache, so it use _rosetta cache instead, rdar://problem/5495438 + if ( isRosetta() ) + return ::open(DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME ARCH_NAME_ROSETTA, O_RDONLY); + else +#endif + return ::open(DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME ARCH_NAME, O_RDONLY); +} static void mapSharedCache() { @@ -2092,14 +2114,7 @@ static void mapSharedCache() } else { // map in shared cache to shared region - int fd; -#if __ppc__ - // rosetta cannot handle optimized _ppc cache, so it use _rosetta cache instead, rdar://problem/5495438 - if ( isRosetta() ) - fd = open(DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME ARCH_NAME_ROSETTA, O_RDONLY); - else -#endif - fd = open(DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME ARCH_NAME, O_RDONLY); + int fd = openSharedCacheFile(); if ( fd != -1 ) { uint8_t firstPage[4096]; if ( ::read(fd, firstPage, 4096) == 4096 ) { @@ -2113,7 +2128,9 @@ static void mapSharedCache() if ( fstat(fd, &stat_buf) == 0 ) { goodCache = true; for (const shared_file_mapping_np* p = mappings; p < end; ++p) { - if ( p->sfm_file_offset+p->sfm_size > (uint64_t)stat_buf.st_size ) + // rdar://problem/5694507 old update_dyld_shared_cache tool could make a cache file + // that is not page aligned, but otherwise ok. + if ( p->sfm_file_offset+p->sfm_size > (uint64_t)(stat_buf.st_size+4095 & (-4096)) ) goodCache = false; } } diff --git a/src/dyld.h b/src/dyld.h index 4ccbdd7..5ae4796 100644 --- a/src/dyld.h +++ b/src/dyld.h @@ -102,6 +102,8 @@ namespace dyld { extern void registerImageStateSingleChangeHandler(dyld_image_states state, dyld_image_state_change_handler handler); extern void registerImageStateBatchChangeHandler(dyld_image_states state, dyld_image_state_change_handler handler); extern void garbageCollectImages(); + extern int openSharedCacheFile(); + extern const void* imMemorySharedCacheHeader(); }; diff --git a/src/dyldAPIs.cpp b/src/dyldAPIs.cpp index 6daf5f1..c9f0e97 100644 --- a/src/dyldAPIs.cpp +++ b/src/dyldAPIs.cpp @@ -454,7 +454,7 @@ const struct mach_header* addImage(void* callerAddress, const char* path, bool s } // not halting, so set error state for NSLinkEditError to find setLastError(NSLinkEditOtherError, 0, path, msg); - free((void*)msg); + free((void*)msg); // our free() will do nothing if msg is a string literal image = NULL; } // free rpaths (getRPaths() malloc'ed each string) @@ -1245,8 +1245,31 @@ static void registerThreadHelpers(const dyld::LibSystemHelpers* helpers) if ( ! readOnlyBootVolume() ) { if ( dyld::gSharedCacheNotFound ) (*helpers->dyld_shared_cache_missing)(); - else if ( dyld::gSharedCacheNeedsUpdating ) + else if ( dyld::imMemorySharedCacheHeader() == NULL ) { + // since shared cache is not mapped and not missing, it must be + // corrupt. Don't need to test contents, just + // ping launchd to start update_dyld_shared_cache + // rdar://problem/5694507 (*helpers->dyld_shared_cache_out_of_date)(); + } + else if ( dyld::gSharedCacheNeedsUpdating ) { + // To reduce the storm of messages to update_dyld_shared_cache + // don't message if the cache file is missing (which means the cache is in + // the process of being regenerated) or if the contents of the cache file + // don't match what is already in memory (which means the cache has + // already be regenerated). + int fd = dyld::openSharedCacheFile(); + if ( fd != -1 ) { + uint8_t onDiskCache[4096]; + if ( ::read(fd, onDiskCache, 4096) == 4096 ) { + if ( ::memcmp(onDiskCache, dyld::imMemorySharedCacheHeader(), 4096) == 0 ) { + // ping launchd to start update_dyld_shared_cache + (*helpers->dyld_shared_cache_out_of_date)(); + } + } + ::close(fd); + } + } } } } @@ -1318,6 +1341,7 @@ bool dlopen_preflight(const char* path) const char* str = dyld::mkstringf("dlopen_preflight(%s): %s", path, msg); dlerrorSet(str); free((void*)str); + free((void*)msg); // our free() will do nothing if msg is a string literal } // free rpaths (getRPaths() malloc'ed each string) for(std::vector::iterator it=rpathsFromCallerImage.begin(); it != rpathsFromCallerImage.end(); ++it) { @@ -1436,6 +1460,7 @@ void* dlopen(const char* path, int mode) const char* str = dyld::mkstringf("dlopen(%s, %d): %s", path, mode, msg); dlerrorSet(str); free((void*)str); + free((void*)msg); // our free() will do nothing if msg is a string literal result = NULL; } // free rpaths (getRPaths() malloc'ed each string) diff --git a/unit-tests/test-cases/dlopen-init-dlopen-notify/Makefile b/unit-tests/test-cases/dlopen-init-dlopen-notify/Makefile new file mode 100644 index 0000000..b24fa5f --- /dev/null +++ b/unit-tests/test-cases/dlopen-init-dlopen-notify/Makefile @@ -0,0 +1,62 @@ +all-check: all check + +check:## +# Copyright (c) 2007 Apple Inc. All rights reserved. +# +# @APPLE_LICENSE_HEADER_START@ +# +# This file contains Original Code and/or Modifications of Original Code +# as defined in and that are subject to the Apple Public Source License +# Version 2.0 (the 'License'). You may not use this file except in +# compliance with the License. Please obtain a copy of the License at +# http://www.opensource.apple.com/apsl/ and read it before using this +# file. +# +# The Original Code and all software distributed under the License are +# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER +# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. +# Please see the License for the specific language governing rights and +# limitations under the License. +# +# @APPLE_LICENSE_HEADER_END@ +## +TESTROOT = ../.. +include ${TESTROOT}/include/common.makefile + + +### ADOBE: Premiere Pro crashes on quit +### +### libfoo depends on libfoo1 and libfoo2. main dlopens(libfoo). +### libfoo1 has an initializer that calls dlopen(libbar). +### libbar depends on libfoo2 +### + +all-check: all check + +check: + ./main + +all: main + +main : main.cxx libfoo.dylib + ${CXX} ${CCXXFLAGS} -I${TESTROOT}/include -o main main.cxx + + +libfoo.dylib : foo.c libfoo1.dylib libfoo2.dylib + ${CC} ${CCFLAGS} -dynamiclib foo.c -o libfoo.dylib libfoo1.dylib libfoo2.dylib + +libfoo1.dylib : foo1.c libbar.dylib + ${CC} ${CCFLAGS} -dynamiclib foo1.c -o libfoo1.dylib + +libfoo2.dylib : foo2.c + ${CC} ${CCFLAGS} -dynamiclib foo2.c -o libfoo2.dylib + +libbar.dylib : bar.c libfoo2.dylib + ${CC} ${CCFLAGS} -dynamiclib bar.c -o libbar.dylib libfoo2.dylib + + +clean: + ${RM} ${RMFLAGS} *~ main libbar.dylib libfoo.dylib libfoo1.dylib libfoo2.dylib + diff --git a/unit-tests/test-cases/dlopen-init-dlopen-notify/bar.c b/unit-tests/test-cases/dlopen-init-dlopen-notify/bar.c new file mode 100644 index 0000000..e425999 --- /dev/null +++ b/unit-tests/test-cases/dlopen-init-dlopen-notify/bar.c @@ -0,0 +1 @@ +void bar() {} diff --git a/unit-tests/test-cases/dlopen-init-dlopen-notify/foo.c b/unit-tests/test-cases/dlopen-init-dlopen-notify/foo.c new file mode 100644 index 0000000..edbdbc4 --- /dev/null +++ b/unit-tests/test-cases/dlopen-init-dlopen-notify/foo.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include + + + +int foo() +{ + return 10; +} diff --git a/unit-tests/test-cases/dlopen-init-dlopen-notify/foo1.c b/unit-tests/test-cases/dlopen-init-dlopen-notify/foo1.c new file mode 100644 index 0000000..c24996b --- /dev/null +++ b/unit-tests/test-cases/dlopen-init-dlopen-notify/foo1.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include + +static void myInit() __attribute__((constructor)); + +static void myInit() +{ + // call dlopen to verify that initializer lock can be held recursively + dlopen("libbar.dylib", RTLD_LAZY); +} + + +int foo1() +{ + return 10; +} diff --git a/unit-tests/test-cases/dlopen-init-dlopen-notify/foo2.c b/unit-tests/test-cases/dlopen-init-dlopen-notify/foo2.c new file mode 100644 index 0000000..5dd0a2a --- /dev/null +++ b/unit-tests/test-cases/dlopen-init-dlopen-notify/foo2.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include + +static void myInit() __attribute__((constructor)); + +static void myInit() +{ + +} + + +int foo2() +{ + return 10; +} diff --git a/unit-tests/test-cases/dlopen-init-dlopen-notify/main.cxx b/unit-tests/test-cases/dlopen-init-dlopen-notify/main.cxx new file mode 100644 index 0000000..cb916f2 --- /dev/null +++ b/unit-tests/test-cases/dlopen-init-dlopen-notify/main.cxx @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2005 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +#include // fprintf(), NULL +#include // exit(), EXIT_SUCCESS +#include +#include +#include + +#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL() + + +static void trySO(const char* path) +{ + void* handle = dlopen(path, RTLD_LAZY); + if ( handle == NULL ) { + FAIL("dlopen(\"%s\") failed with: %s", path, dlerror()); + exit(0); + } + + void* sym = dlsym(handle, "foo"); + if ( sym == NULL ) { + FAIL("dlsym(handle, \"foo\") failed"); + exit(0); + } + + int result = dlclose(handle); + if ( result != 0 ) { + if ( result == 1 ) { + // panther dyld returns 1 if you try to dlclose() a dylib + XFAIL("dlclose(handle) returned %d", result); + } + else { + FAIL("dlclose(handle) returned %d", result); + exit(0); + } + } + +} + +static std::set sCurrentImages; + +static void notify(const struct mach_header *mh, intptr_t vmaddr_slide) +{ + //fprintf(stderr, "mh=%p\n", mh); + if ( sCurrentImages.count(mh) != 0 ) { + FAIL("notified twice about %p", mh); + exit(0); + } + sCurrentImages.insert(mh); +} + + + +int main() +{ + _dyld_register_func_for_add_image(¬ify); + + trySO("libfoo.dylib"); + + PASS("dlopen-init-dlopen-notify"); + return EXIT_SUCCESS; +} diff --git a/unit-tests/test-cases/dlopen-leak/Makefile b/unit-tests/test-cases/dlopen-leak/Makefile new file mode 100644 index 0000000..b3a47a3 --- /dev/null +++ b/unit-tests/test-cases/dlopen-leak/Makefile @@ -0,0 +1,68 @@ +## +# Copyright (c) 2007 Apple Inc. All rights reserved. +# +# @APPLE_LICENSE_HEADER_START@ +# +# This file contains Original Code and/or Modifications of Original Code +# as defined in and that are subject to the Apple Public Source License +# Version 2.0 (the 'License'). You may not use this file except in +# compliance with the License. Please obtain a copy of the License at +# http://www.opensource.apple.com/apsl/ and read it before using this +# file. +# +# The Original Code and all software distributed under the License are +# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER +# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. +# Please see the License for the specific language governing rights and +# limitations under the License. +# +# @APPLE_LICENSE_HEADER_END@ +## +TESTROOT = ../.. +include ${TESTROOT}/include/common.makefile + + +# +# verify there are no leaks with dlopen/close on success and failure +# + +# leaks does not work on rosetta processes +CHECK = check-real +ifeq "ppc" "$(ARCH)" + MACHINE = $(shell arch) + ifeq "i386" "$(MACHINE)" + CHECK = check-xfail + endif +endif + +all-check: all check + +check: ${CHECK} + +check-real: + ${TESTROOT}/bin/exit-zero-pass.pl "dlopen-leak" "dlopen-leak" "DYLD_LIBRARY_PATH=hide && ./main | grep '0 leaks for 0 total leaked bytes' > /dev/null" + ${TESTROOT}/bin/exit-zero-pass.pl "dlopen-leak" "dlopen-leak" "./main | grep '0 leaks for 0 total leaked bytes' > /dev/null" + +check-xfail: + echo "XFAIL dlopen-leak"; + + +all: main + + +hide/libbar.dylib : bar.c + mkdir -p hide + ${CC} bar.c -dynamiclib -o hide/libbar.dylib -install_name libbar.dylib + +libfoo.dylib : foo.c hide/libbar.dylib + ${CC} foo.c hide/libbar.dylib -dynamiclib -o libfoo.dylib + +main : main.c libfoo.dylib + ${CC} ${CCFLAGS} -I${TESTROOT}/include main.c -o main + + + +clean: + ${RM} ${RMFLAGS} *~ main libfoo.dylib hide diff --git a/unit-tests/test-cases/dlopen-leak/bar.c b/unit-tests/test-cases/dlopen-leak/bar.c new file mode 100644 index 0000000..b72a1a5 --- /dev/null +++ b/unit-tests/test-cases/dlopen-leak/bar.c @@ -0,0 +1,3 @@ +void bar() +{ +} diff --git a/unit-tests/test-cases/dlopen-leak/foo.c b/unit-tests/test-cases/dlopen-leak/foo.c new file mode 100644 index 0000000..3695dc9 --- /dev/null +++ b/unit-tests/test-cases/dlopen-leak/foo.c @@ -0,0 +1,3 @@ +void foo() +{ +} diff --git a/unit-tests/test-cases/dlopen-leak/main.c b/unit-tests/test-cases/dlopen-leak/main.c new file mode 100644 index 0000000..511a140 --- /dev/null +++ b/unit-tests/test-cases/dlopen-leak/main.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2007 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +#include +#include +#include +#include +#include + + +#include "test.h" + + +int main() +{ + for (int i=0; i < 100; ++i) { + void* handle = dlopen("libfoo.dylib", RTLD_LAZY); + if ( handle != NULL ) + dlclose(handle); + dlopen("libnotthere.dylib", RTLD_LAZY); + } + + // execute leaks command on myself + char cmd[512]; + sprintf(cmd, "leaks %u\n", getpid()); + system(cmd); + + return EXIT_SUCCESS; +} diff --git a/unit-tests/test-cases/dlopen-notify-bind/Makefile b/unit-tests/test-cases/dlopen-notify-bind/Makefile new file mode 100644 index 0000000..5844be2 --- /dev/null +++ b/unit-tests/test-cases/dlopen-notify-bind/Makefile @@ -0,0 +1,51 @@ +## +# Copyright (c) 2007 Apple Inc. All rights reserved. +# +# @APPLE_LICENSE_HEADER_START@ +# +# This file contains Original Code and/or Modifications of Original Code +# as defined in and that are subject to the Apple Public Source License +# Version 2.0 (the 'License'). You may not use this file except in +# compliance with the License. Please obtain a copy of the License at +# http://www.opensource.apple.com/apsl/ and read it before using this +# file. +# +# The Original Code and all software distributed under the License are +# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER +# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. +# Please see the License for the specific language governing rights and +# limitations under the License. +# +# @APPLE_LICENSE_HEADER_END@ +## +TESTROOT = ../.. +include ${TESTROOT}/include/common.makefile + + +### CFSTRs cause crashes in Leopard +### +### main registers for notification and then dlopens(libfoo). +### In the notification callback, main calls NSLookupSymbolInImage(BIND) +### which double bound libfoo +### + +all-check: all check + +check: + ./main + +all: main + +main : main.c libfoo.dylib + ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c -mmacosx-version-min=10.4 + + +libfoo.dylib : foo.c + ${CC} ${CCFLAGS} -dynamiclib foo.c -o libfoo.dylib + + +clean: + ${RM} ${RMFLAGS} *~ main libfoo.dylib + diff --git a/unit-tests/test-cases/dlopen-notify-bind/foo.c b/unit-tests/test-cases/dlopen-notify-bind/foo.c new file mode 100644 index 0000000..8dab6be --- /dev/null +++ b/unit-tests/test-cases/dlopen-notify-bind/foo.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include + + +void* externalRlocToMalloc = &malloc; + +void* foo() +{ + return externalRlocToMalloc; +} diff --git a/unit-tests/test-cases/dlopen-notify-bind/main.c b/unit-tests/test-cases/dlopen-notify-bind/main.c new file mode 100644 index 0000000..d99436a --- /dev/null +++ b/unit-tests/test-cases/dlopen-notify-bind/main.c @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2005 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +#include // fprintf(), NULL +#include // exit(), EXIT_SUCCESS +#include +#include + +#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL() + + +typedef void* (*fooProc)(); + + +static void notify(const struct mach_header *mh, intptr_t vmaddr_slide) +{ + //fprintf(stderr, "mh=%p\n", mh); + NSLookupSymbolInImage(mh, "_bar", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); +} + + +int main() +{ + _dyld_register_func_for_add_image(¬ify); + + void* handle = dlopen("libfoo.dylib", RTLD_LAZY); + if ( handle == NULL ) { + FAIL("dlopen(\"%s\") failed with: %s", "libfoo.dylib", dlerror()); + exit(0); + } + + fooProc fooPtr = (fooProc)dlsym(handle, "foo"); + if ( fooPtr == NULL ) { + FAIL("dlsym(handle, \"foo\") failed"); + exit(0); + } + + void* foosMalloc = (*fooPtr)(); + //fprintf(stderr, "foo says &malloc=%p\n", foosMalloc); + //fprintf(stderr, "&malloc=%p\n", &malloc); + + dlclose(handle); + + if ( foosMalloc == &malloc ) + PASS("dlopen-notify-bind"); + else + FAIL("dlopen-notify-bind libfoo.dylib double bound"); + return EXIT_SUCCESS; +} diff --git a/unit-tests/test-cases/dlopen_preflight-leak/Makefile b/unit-tests/test-cases/dlopen_preflight-leak/Makefile new file mode 100644 index 0000000..eff03d8 --- /dev/null +++ b/unit-tests/test-cases/dlopen_preflight-leak/Makefile @@ -0,0 +1,65 @@ +## +# Copyright (c) 2007 Apple Inc. All rights reserved. +# +# @APPLE_LICENSE_HEADER_START@ +# +# This file contains Original Code and/or Modifications of Original Code +# as defined in and that are subject to the Apple Public Source License +# Version 2.0 (the 'License'). You may not use this file except in +# compliance with the License. Please obtain a copy of the License at +# http://www.opensource.apple.com/apsl/ and read it before using this +# file. +# +# The Original Code and all software distributed under the License are +# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER +# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. +# Please see the License for the specific language governing rights and +# limitations under the License. +# +# @APPLE_LICENSE_HEADER_END@ +## +TESTROOT = ../.. +include ${TESTROOT}/include/common.makefile + + +# +# verify there are no leaks with dlopen/close on success and failure +# + +# leaks does not work on rosetta processes +CHECK = check-real +ifeq "ppc" "$(ARCH)" + MACHINE = $(shell arch) + ifeq "i386" "$(MACHINE)" + CHECK = check-xfail + endif +endif + +all-check: all check + +check: ${CHECK} + +check-real: + ${TESTROOT}/bin/exit-zero-pass.pl "dlopen_preflight-leak" "dlopen_preflight-leak" "DYLD_LIBRARY_PATH=hide && ./main | grep '0 leaks for 0 total leaked bytes' > /dev/null" + ${TESTROOT}/bin/exit-zero-pass.pl "dlopen_preflight-leak" "dlopen_preflight-leak" "./main | grep '0 leaks for 0 total leaked bytes' > /dev/null" + +check-xfail: + echo "XFAIL dlopen-leak"; + +all: main + +hide/libbar.dylib : bar.c + mkdir -p hide + ${CC} bar.c -dynamiclib -o hide/libbar.dylib -install_name libbar.dylib + +libfoo.dylib : foo.c hide/libbar.dylib + ${CC} foo.c hide/libbar.dylib -dynamiclib -o libfoo.dylib + +main : main.c libfoo.dylib + ${CC} ${CCFLAGS} -I${TESTROOT}/include main.c -o main + + +clean: + ${RM} ${RMFLAGS} *~ main libfoo.dylib hide diff --git a/unit-tests/test-cases/dlopen_preflight-leak/bar.c b/unit-tests/test-cases/dlopen_preflight-leak/bar.c new file mode 100644 index 0000000..b72a1a5 --- /dev/null +++ b/unit-tests/test-cases/dlopen_preflight-leak/bar.c @@ -0,0 +1,3 @@ +void bar() +{ +} diff --git a/unit-tests/test-cases/dlopen_preflight-leak/foo.c b/unit-tests/test-cases/dlopen_preflight-leak/foo.c new file mode 100644 index 0000000..3695dc9 --- /dev/null +++ b/unit-tests/test-cases/dlopen_preflight-leak/foo.c @@ -0,0 +1,3 @@ +void foo() +{ +} diff --git a/unit-tests/test-cases/dlopen_preflight-leak/main.c b/unit-tests/test-cases/dlopen_preflight-leak/main.c new file mode 100644 index 0000000..612e141 --- /dev/null +++ b/unit-tests/test-cases/dlopen_preflight-leak/main.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2007 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +#include +#include +#include +#include +#include + + +#include "test.h" + + +int main() +{ + for (int i=0; i < 100; ++i) { + dlopen_preflight("libfoo.dylib"); + } + + // execute leaks command on myself + char cmd[512]; + sprintf(cmd, "leaks %u\n", getpid()); + system(cmd); + + return EXIT_SUCCESS; +} diff --git a/unit-tests/test-cases/framework-fallback/main.c b/unit-tests/test-cases/framework-fallback/main.c index 13f8146..904aeb3 100644 --- a/unit-tests/test-cases/framework-fallback/main.c +++ b/unit-tests/test-cases/framework-fallback/main.c @@ -39,12 +39,12 @@ main(int argc, const char* argv[]) { const struct mach_header *image; - image = NSAddImage("Carbon.framework/Carbon", + image = NSAddImage("AppKit.framework/AppKit", NSADDIMAGE_OPTION_RETURN_ON_ERROR | NSADDIMAGE_OPTION_WITH_SEARCHING); if ( image != NULL ) - PASS("Carbon loaded"); + PASS("AppKit loaded"); else - FAIL("Could not load Carbon"); + FAIL("Could not load AppKit"); return 0; } diff --git a/unit-tests/test-cases/read-only-import-shared-cache-dlopen-override/Makefile b/unit-tests/test-cases/read-only-import-shared-cache-dlopen-override/Makefile new file mode 100644 index 0000000..26eb706 --- /dev/null +++ b/unit-tests/test-cases/read-only-import-shared-cache-dlopen-override/Makefile @@ -0,0 +1,44 @@ +## +# Copyright (c) 2007 Apple Inc. All rights reserved. +# +# @APPLE_LICENSE_HEADER_START@ +# +# This file contains Original Code and/or Modifications of Original Code +# as defined in and that are subject to the Apple Public Source License +# Version 2.0 (the 'License'). You may not use this file except in +# compliance with the License. Please obtain a copy of the License at +# http://www.opensource.apple.com/apsl/ and read it before using this +# file. +# +# The Original Code and all software distributed under the License are +# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER +# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. +# Please see the License for the specific language governing rights and +# limitations under the License. +# +# @APPLE_LICENSE_HEADER_END@ +## +TESTROOT = ../.. +include ${TESTROOT}/include/common.makefile + + +run: all + export DYLD_INSERT_LIBRARIES="libmymalloc.dylib" && ./main + +all: main libmymalloc.dylib + +main: main.c + ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c + + +libmymalloc.dylib : mymalloc.c + ${CC} ${CCFLAGS} -dynamiclib mymalloc.c -o libmymalloc.dylib + + + +clean: + ${RM} ${RMFLAGS} *~ main libmymalloc.dylib + + diff --git a/unit-tests/test-cases/read-only-import-shared-cache-dlopen-override/main.c b/unit-tests/test-cases/read-only-import-shared-cache-dlopen-override/main.c new file mode 100644 index 0000000..b3c927d --- /dev/null +++ b/unit-tests/test-cases/read-only-import-shared-cache-dlopen-override/main.c @@ -0,0 +1,14 @@ +#include + +#include "test.h" + +int main() +{ + // dynamically load libz.dylib which imports _malloc from libSystem + dlopen("/usr/lib/libz.dylib", RTLD_LAZY); + + + PASS("read-only-import-shared-cache-dlopen-override"); + return 0; +} + diff --git a/unit-tests/test-cases/read-only-import-shared-cache-dlopen-override/mymalloc.c b/unit-tests/test-cases/read-only-import-shared-cache-dlopen-override/mymalloc.c new file mode 100644 index 0000000..b0dd819 --- /dev/null +++ b/unit-tests/test-cases/read-only-import-shared-cache-dlopen-override/mymalloc.c @@ -0,0 +1,9 @@ +#include +#include + +void* mymalloc(size_t s) +{ + return malloc(s); +} + +DYLD_INTERPOSE(mymalloc, malloc) -- 2.45.2