osimag.c 59 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644
  1. /*++
  2. Copyright (c) 2012 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. osimag.c
  9. Abstract:
  10. This module implements the underlying support routines for the image
  11. library to be run in user mode.
  12. Author:
  13. Evan Green 17-Oct-2013
  14. Environment:
  15. User
  16. --*/
  17. //
  18. // ------------------------------------------------------------------- Includes
  19. //
  20. #include "osbasep.h"
  21. //
  22. // ---------------------------------------------------------------- Definitions
  23. //
  24. #define OS_IMAGE_ALLOCATION_TAG 0x6D49734F // 'mIsO'
  25. #define OS_IMAGE_LIST_SIZE_GUESS 512
  26. #define OS_IMAGE_LIST_TRY_COUNT 10
  27. #define OS_DYNAMIC_LOADER_USAGE \
  28. "usage: libminocaos.so [options] [program [arguments]]\n" \
  29. "This can be run either indirectly as an interpreter, or it can load and " \
  30. "execute a command line directly.\n"
  31. //
  32. // Define the name of the environment variable to look at to determine whether
  33. // to resolve all PLT symbols at load time or not.
  34. //
  35. #define LD_BIND_NOW "LD_BIND_NOW"
  36. //
  37. // ------------------------------------------------------ Data Type Definitions
  38. //
  39. typedef
  40. VOID
  41. (*PIMAGE_ENTRY_POINT) (
  42. PPROCESS_ENVIRONMENT Environment
  43. );
  44. /*++
  45. Routine Description:
  46. This routine implements the entry point for a loaded image.
  47. Arguments:
  48. Environment - Supplies the process environment.
  49. Return Value:
  50. None, the image does not return.
  51. --*/
  52. //
  53. // ----------------------------------------------- Internal Function Prototypes
  54. //
  55. VOID
  56. OspImArchResolvePltEntry (
  57. VOID
  58. );
  59. PVOID
  60. OspImAllocateMemory (
  61. ULONG Size,
  62. ULONG Tag
  63. );
  64. VOID
  65. OspImFreeMemory (
  66. PVOID Allocation
  67. );
  68. KSTATUS
  69. OspImOpenFile (
  70. PVOID SystemContext,
  71. PCSTR BinaryName,
  72. PIMAGE_FILE_INFORMATION File
  73. );
  74. VOID
  75. OspImCloseFile (
  76. PIMAGE_FILE_INFORMATION File
  77. );
  78. KSTATUS
  79. OspImLoadFile (
  80. PIMAGE_FILE_INFORMATION File,
  81. PIMAGE_BUFFER Buffer
  82. );
  83. VOID
  84. OspImUnloadBuffer (
  85. PIMAGE_FILE_INFORMATION File,
  86. PIMAGE_BUFFER Buffer
  87. );
  88. KSTATUS
  89. OspImAllocateAddressSpace (
  90. PLOADED_IMAGE Image
  91. );
  92. VOID
  93. OspImFreeAddressSpace (
  94. PLOADED_IMAGE Image
  95. );
  96. KSTATUS
  97. OspImMapImageSegment (
  98. HANDLE AddressSpaceHandle,
  99. PVOID AddressSpaceAllocation,
  100. PIMAGE_FILE_INFORMATION File,
  101. ULONGLONG FileOffset,
  102. PIMAGE_SEGMENT Segment,
  103. PIMAGE_SEGMENT PreviousSegment
  104. );
  105. VOID
  106. OspImUnmapImageSegment (
  107. HANDLE AddressSpaceHandle,
  108. PIMAGE_SEGMENT Segment
  109. );
  110. KSTATUS
  111. OspImNotifyImageLoad (
  112. PLOADED_IMAGE Image
  113. );
  114. VOID
  115. OspImNotifyImageUnload (
  116. PLOADED_IMAGE Image
  117. );
  118. VOID
  119. OspImInvalidateInstructionCacheRegion (
  120. PVOID Address,
  121. ULONG Size
  122. );
  123. PSTR
  124. OspImGetEnvironmentVariable (
  125. PSTR Variable
  126. );
  127. KSTATUS
  128. OspImFinalizeSegments (
  129. HANDLE AddressSpaceHandle,
  130. PIMAGE_SEGMENT Segments,
  131. UINTN SegmentCount
  132. );
  133. VOID
  134. OspImInitializeImages (
  135. PLIST_ENTRY ListHead
  136. );
  137. VOID
  138. OspImInitializeImage (
  139. PLOADED_IMAGE Image
  140. );
  141. PVOID
  142. OspImResolvePltEntry (
  143. PLOADED_IMAGE Image,
  144. UINTN RelocationOffset
  145. );
  146. KSTATUS
  147. OspLoadInitialImageList (
  148. BOOL Relocate
  149. );
  150. KSTATUS
  151. OspImAssignModuleNumber (
  152. PLOADED_IMAGE Image
  153. );
  154. VOID
  155. OspImReleaseModuleNumber (
  156. PLOADED_IMAGE Image
  157. );
  158. //
  159. // -------------------------------------------------------------------- Globals
  160. //
  161. //
  162. // Store a pointer to the routine used to get environment variable contents.
  163. //
  164. OS_API PIM_GET_ENVIRONMENT_VARIABLE OsImGetEnvironmentVariable;
  165. //
  166. // Store a pointer to the list head of all loaded images.
  167. //
  168. LIST_ENTRY OsLoadedImagesHead;
  169. OS_RWLOCK OsLoadedImagesLock;
  170. //
  171. // Define the image library function table.
  172. //
  173. IM_IMPORT_TABLE OsImageFunctionTable = {
  174. OspImAllocateMemory,
  175. OspImFreeMemory,
  176. OspImOpenFile,
  177. OspImCloseFile,
  178. OspImLoadFile,
  179. NULL,
  180. OspImUnloadBuffer,
  181. OspImAllocateAddressSpace,
  182. OspImFreeAddressSpace,
  183. OspImMapImageSegment,
  184. OspImUnmapImageSegment,
  185. OspImNotifyImageLoad,
  186. OspImNotifyImageUnload,
  187. OspImInvalidateInstructionCacheRegion,
  188. OspImGetEnvironmentVariable,
  189. OspImFinalizeSegments,
  190. OspImArchResolvePltEntry
  191. };
  192. //
  193. // Store the overridden library path specified by the command arguments to the
  194. // dynamic linker.
  195. //
  196. PSTR OsImLibraryPathOverride;
  197. //
  198. // Store the bitmap for the image module numbers. Index zero is never valid.
  199. //
  200. UINTN OsImStaticModuleNumberBitmap = 0x1;
  201. PUINTN OsImModuleNumberBitmap = &OsImStaticModuleNumberBitmap;
  202. UINTN OsImModuleNumberBitmapSize = 1;
  203. //
  204. // Store the module generation number, which increments whenever a module is
  205. // loaded or unloaded. It is protected under the image list lock.
  206. //
  207. UINTN OsImModuleGeneration;
  208. //
  209. // Store a boolean indicating whether or not the initial image is loaded.
  210. //
  211. BOOL OsImExecutableLoaded = TRUE;
  212. //
  213. // ------------------------------------------------------------------ Functions
  214. //
  215. OS_API
  216. VOID
  217. OsDynamicLoaderMain (
  218. PPROCESS_ENVIRONMENT Environment
  219. )
  220. /*++
  221. Routine Description:
  222. This routine implements the main routine for the Minoca OS loader when
  223. invoked directly (either as a standalone application or an interpreter).
  224. Arguments:
  225. Environment - Supplies the process environment.
  226. Return Value:
  227. None. This routine exits directly and never returns.
  228. --*/
  229. {
  230. PSTR Argument;
  231. UINTN ArgumentIndex;
  232. PLIST_ENTRY CurrentEntry;
  233. PLOADED_IMAGE CurrentImage;
  234. PLOADED_IMAGE Image;
  235. ULONG LoadFlags;
  236. PIMAGE_ENTRY_POINT Start;
  237. KSTATUS Status;
  238. PVOID ThreadData;
  239. //
  240. // Start by relocating this image. Until this is done, no global variables
  241. // can be touched.
  242. //
  243. ImRelocateSelf(Environment->StartData->OsLibraryBase,
  244. OspImArchResolvePltEntry);
  245. OsInitializeLibrary(Environment);
  246. OsImExecutableLoaded = FALSE;
  247. Status = OspLoadInitialImageList(TRUE);
  248. if (!KSUCCESS(Status)) {
  249. RtlDebugPrint("Failed to populate initial image list: %d.\n", Status);
  250. goto DynamicLoaderMainEnd;
  251. }
  252. //
  253. // If the executable is this library, then the dynamic loader is being
  254. // invoked directly.
  255. //
  256. if (Environment->StartData->ExecutableBase ==
  257. Environment->StartData->OsLibraryBase) {
  258. LoadFlags = IMAGE_LOAD_FLAG_IGNORE_INTERPRETER |
  259. IMAGE_LOAD_FLAG_PRIMARY_EXECUTABLE |
  260. IMAGE_LOAD_FLAG_NO_RELOCATIONS;
  261. if (OspImGetEnvironmentVariable(LD_BIND_NOW) != NULL) {
  262. LoadFlags |= IMAGE_LOAD_FLAG_BIND_NOW;
  263. }
  264. ArgumentIndex = 1;
  265. while (ArgumentIndex < Environment->ArgumentCount) {
  266. Argument = Environment->Arguments[ArgumentIndex];
  267. if (RtlAreStringsEqual(Argument, "--library-path", -1) != FALSE) {
  268. ArgumentIndex += 1;
  269. if (ArgumentIndex == Environment->ArgumentCount) {
  270. RtlDebugPrint("--library-path Argument missing.\n");
  271. Status = STATUS_INVALID_PARAMETER;
  272. goto DynamicLoaderMainEnd;
  273. }
  274. OsImLibraryPathOverride = Environment->Arguments[ArgumentIndex];
  275. ArgumentIndex += 1;
  276. } else {
  277. break;
  278. }
  279. }
  280. if (ArgumentIndex >= Environment->ArgumentCount) {
  281. RtlDebugPrint(OS_DYNAMIC_LOADER_USAGE);
  282. Status = STATUS_UNSUCCESSFUL;
  283. goto DynamicLoaderMainEnd;
  284. }
  285. //
  286. // Munge the environment to make it look like the program was
  287. // invoked directly.
  288. //
  289. Environment->Arguments = &(Environment->Arguments[ArgumentIndex]);
  290. Environment->ArgumentCount -= ArgumentIndex;
  291. Environment->ImageName = Environment->Arguments[0];
  292. Environment->ImageNameLength =
  293. RtlStringLength(Environment->Arguments[0]) + 1;
  294. Status = ImLoad(&OsLoadedImagesHead,
  295. Environment->ImageName,
  296. NULL,
  297. NULL,
  298. NULL,
  299. LoadFlags,
  300. &Image,
  301. NULL);
  302. }
  303. if (!KSUCCESS(Status)) {
  304. RtlDebugPrint("Failed to load %s: %d\n",
  305. Environment->ImageName,
  306. Status);
  307. goto DynamicLoaderMainEnd;
  308. }
  309. //
  310. // Assign module numbers to any modules that do not have them yet. This is
  311. // done after the executable is loaded so the executable gets the first
  312. // slot.
  313. //
  314. CurrentEntry = OsLoadedImagesHead.Next;
  315. while (CurrentEntry != &OsLoadedImagesHead) {
  316. CurrentImage = LIST_VALUE(CurrentEntry, LOADED_IMAGE, ListEntry);
  317. CurrentEntry = CurrentEntry->Next;
  318. if (CurrentImage->ModuleNumber == 0) {
  319. OspImAssignModuleNumber(CurrentImage);
  320. }
  321. if ((Image == NULL) &&
  322. ((CurrentImage->LoadFlags &
  323. IMAGE_LOAD_FLAG_PRIMARY_EXECUTABLE) != 0)) {
  324. Image = CurrentImage;
  325. }
  326. }
  327. OsImExecutableLoaded = TRUE;
  328. //
  329. // Initialize TLS support.
  330. //
  331. OspTlsAllocate(&OsLoadedImagesHead, &ThreadData);
  332. OsSetThreadPointer(ThreadData);
  333. //
  334. // Now that TLS offsets are settled, relocate the images.
  335. //
  336. Status = ImRelocateImages(&OsLoadedImagesHead);
  337. if (!KSUCCESS(Status)) {
  338. RtlDebugPrint("Failed to relocate: %d\n", Status);
  339. goto DynamicLoaderMainEnd;
  340. }
  341. //
  342. // Call static constructors, without acquiring and releasing the lock
  343. // constantly.
  344. //
  345. CurrentEntry = OsLoadedImagesHead.Previous;
  346. while (CurrentEntry != &OsLoadedImagesHead) {
  347. CurrentImage = LIST_VALUE(CurrentEntry, LOADED_IMAGE, ListEntry);
  348. ASSERT((CurrentImage->Flags & IMAGE_FLAG_INITIALIZED) == 0);
  349. OspImInitializeImage(CurrentImage);
  350. CurrentImage->Flags |= IMAGE_FLAG_INITIALIZED;
  351. CurrentEntry = CurrentEntry->Previous;
  352. }
  353. //
  354. // Jump off to the image entry point.
  355. //
  356. Start = Image->EntryPoint;
  357. Start(Environment);
  358. RtlDebugPrint("Warning: Image returned to interpreter!\n");
  359. Status = STATUS_UNSUCCESSFUL;
  360. DynamicLoaderMainEnd:
  361. OsExitProcess(Status);
  362. return;
  363. }
  364. OS_API
  365. KSTATUS
  366. OsLoadLibrary (
  367. PSTR LibraryName,
  368. ULONG Flags,
  369. PHANDLE Handle
  370. )
  371. /*++
  372. Routine Description:
  373. This routine loads a dynamic library.
  374. Arguments:
  375. LibraryName - Supplies a pointer to the library name to load.
  376. Flags - Supplies a bitfield of flags associated with the request.
  377. Handle - Supplies a pointer where a handle to the dynamic library will be
  378. returned on success. INVALID_HANDLE will be returned on failure.
  379. Return Value:
  380. Status code.
  381. --*/
  382. {
  383. PLOADED_IMAGE LoadedImage;
  384. ULONG LoadFlags;
  385. KSTATUS Status;
  386. //
  387. // Prime the get environment variable function to ensure it does not
  388. // have to resolve a PLT entry (and reacquire the lock) during load.
  389. //
  390. OspImGetEnvironmentVariable(LD_BIND_NOW);
  391. OspAcquireImageLock(TRUE);
  392. if (OsLoadedImagesHead.Next == NULL) {
  393. Status = OspLoadInitialImageList(FALSE);
  394. if (!KSUCCESS(Status)) {
  395. OspReleaseImageLock();
  396. goto LoadLibraryEnd;
  397. }
  398. }
  399. *Handle = INVALID_HANDLE;
  400. LoadedImage = NULL;
  401. LoadFlags = 0;
  402. Status = ImLoad(&OsLoadedImagesHead,
  403. LibraryName,
  404. NULL,
  405. NULL,
  406. NULL,
  407. LoadFlags,
  408. &LoadedImage,
  409. NULL);
  410. OspReleaseImageLock();
  411. if (!KSUCCESS(Status)) {
  412. goto LoadLibraryEnd;
  413. }
  414. OspImInitializeImages(&OsLoadedImagesHead);
  415. *Handle = LoadedImage;
  416. LoadLibraryEnd:
  417. return Status;
  418. }
  419. OS_API
  420. VOID
  421. OsFreeLibrary (
  422. HANDLE Library
  423. )
  424. /*++
  425. Routine Description:
  426. This routine indicates a release of the resources associated with a
  427. previously loaded library. This may or may not actually unload the library
  428. depending on whether or not there are other references to it.
  429. Arguments:
  430. Library - Supplies the library to release.
  431. Return Value:
  432. None.
  433. --*/
  434. {
  435. if (Library == INVALID_HANDLE) {
  436. return;
  437. }
  438. OspAcquireImageLock(TRUE);
  439. ImImageReleaseReference(Library);
  440. OspReleaseImageLock();
  441. return;
  442. }
  443. OS_API
  444. KSTATUS
  445. OsGetLibrarySymbolAddress (
  446. HANDLE Library,
  447. PSTR SymbolName,
  448. PVOID *Address
  449. )
  450. /*++
  451. Routine Description:
  452. This routine returns the address of the given symbol in the given library.
  453. Both the library and all of its imports will be searched.
  454. Arguments:
  455. Library - Supplies the library to look up. Use OS_LIBRARY_DEFAULT to search
  456. the current executable or OS_LIBRARY_NEXT to start the search after the
  457. current executable.
  458. SymbolName - Supplies a pointer to a null terminated string containing the
  459. name of the symbol to look up.
  460. Address - Supplies a pointer that on success receives the address of the
  461. symbol, or NULL on failure.
  462. Return Value:
  463. STATUS_SUCCESS on success.
  464. STATUS_INVALID_HANDLE if the library handle is not valid.
  465. STATUS_NOT_FOUND if the symbol could not be found.
  466. --*/
  467. {
  468. PLIST_ENTRY CurrentEntry;
  469. BOOL ExecutableFound;
  470. PLOADED_IMAGE Image;
  471. KSTATUS Status;
  472. IMAGE_SYMBOL Symbol;
  473. TLS_INDEX TlsIndex;
  474. *Address = NULL;
  475. RtlZeroMemory(&Symbol, sizeof(IMAGE_SYMBOL));
  476. Symbol.Image = INVALID_HANDLE;
  477. OspAcquireImageLock(FALSE);
  478. if (OsLoadedImagesHead.Next == NULL) {
  479. Status = OspLoadInitialImageList(FALSE);
  480. if (!KSUCCESS(Status)) {
  481. goto GetLibrarySymbolAddressEnd;
  482. }
  483. }
  484. //
  485. // The default and next libraries are special cases that search the global
  486. // scope starting with the primary executable and the next library after
  487. // the primary executable. These must iterate in order to include any
  488. // libraries added via OsLoadLibrary.
  489. //
  490. if ((Library == OS_LIBRARY_DEFAULT) || (Library == OS_LIBRARY_NEXT)) {
  491. ExecutableFound = FALSE;
  492. CurrentEntry = OsLoadedImagesHead.Next;
  493. while (CurrentEntry != &OsLoadedImagesHead) {
  494. Image = LIST_VALUE(CurrentEntry, LOADED_IMAGE, ListEntry);
  495. CurrentEntry = CurrentEntry->Next;
  496. //
  497. // Do not start searching until the primary executable is found. If
  498. // the next library is actually the start, loop one more time and
  499. // then start.
  500. //
  501. if (ExecutableFound == FALSE) {
  502. if ((Image->LoadFlags &
  503. IMAGE_LOAD_FLAG_PRIMARY_EXECUTABLE) == 0) {
  504. continue;
  505. }
  506. ExecutableFound = TRUE;
  507. if (Library == OS_LIBRARY_NEXT) {
  508. continue;
  509. }
  510. }
  511. Status = ImGetSymbolByName(Image, SymbolName, TRUE, &Symbol);
  512. if (KSUCCESS(Status)) {
  513. break;
  514. }
  515. }
  516. //
  517. // Otherwise only search the supplied library and its imports.
  518. //
  519. } else {
  520. Status = ImGetSymbolByName(Library, SymbolName, TRUE, &Symbol);
  521. }
  522. if (KSUCCESS(Status)) {
  523. if (Symbol.TlsAddress != FALSE) {
  524. Image = Symbol.Image;
  525. if (Image == INVALID_HANDLE) {
  526. Status = STATUS_INVALID_HANDLE;
  527. goto GetLibrarySymbolAddressEnd;
  528. }
  529. TlsIndex.Module = Image->ModuleNumber;
  530. TlsIndex.Offset = (UINTN)Symbol.Address;
  531. Symbol.Address = OsGetTlsAddress(&TlsIndex);
  532. }
  533. *Address = Symbol.Address;
  534. }
  535. GetLibrarySymbolAddressEnd:
  536. OspReleaseImageLock();
  537. return Status;
  538. }
  539. OS_API
  540. KSTATUS
  541. OsGetLibrarySymbolForAddress (
  542. HANDLE Library,
  543. PVOID Address,
  544. POS_LIBRARY_SYMBOL Symbol
  545. )
  546. /*++
  547. Routine Description:
  548. This routine resolves the given address into a symbol by searching the
  549. given library. Both the library and all its imports will be searched.
  550. Arguments:
  551. Library - Supplies the library to look up. Use OS_LIBRARY_DEFAULT to search
  552. the current executable or OS_LIBRARY_NEXT to start the search after the
  553. current executable.
  554. Address - Supplies the address to look up.
  555. Symbol - Supplies a pointer to a structure that receives the resolved
  556. symbol information.
  557. Return Value:
  558. STATUS_SUCCESS on success.
  559. STATUS_INVALID_HANDLE if the library handle is not valid.
  560. STATUS_NOT_FOUND if the address could not be found.
  561. --*/
  562. {
  563. PLIST_ENTRY CurrentEntry;
  564. BOOL ExecutableFound;
  565. PLOADED_IMAGE Image;
  566. IMAGE_SYMBOL ImageSymbol;
  567. KSTATUS Status;
  568. RtlZeroMemory(Symbol, sizeof(OS_LIBRARY_SYMBOL));
  569. RtlZeroMemory(&ImageSymbol, sizeof(IMAGE_SYMBOL));
  570. ImageSymbol.Image = INVALID_HANDLE;
  571. OspAcquireImageLock(FALSE);
  572. if (OsLoadedImagesHead.Next == NULL) {
  573. Status = OspLoadInitialImageList(FALSE);
  574. if (!KSUCCESS(Status)) {
  575. goto GetLibrarySymbolForAddress;
  576. }
  577. }
  578. //
  579. // The default and next libraries are special cases that search the global
  580. // scope starting with the primary executable and the next library after
  581. // the primary executable. These must iterate in order to include any
  582. // libraries added via OsLoadLibrary.
  583. //
  584. if ((Library == OS_LIBRARY_DEFAULT) || (Library == OS_LIBRARY_NEXT)) {
  585. ExecutableFound = FALSE;
  586. CurrentEntry = OsLoadedImagesHead.Next;
  587. while (CurrentEntry != &OsLoadedImagesHead) {
  588. Image = LIST_VALUE(CurrentEntry, LOADED_IMAGE, ListEntry);
  589. CurrentEntry = CurrentEntry->Next;
  590. //
  591. // Do not start searching until the primary executable is found. If
  592. // the next library is actually the start, loop one more time and
  593. // then start.
  594. //
  595. if (ExecutableFound == FALSE) {
  596. if ((Image->LoadFlags &
  597. IMAGE_LOAD_FLAG_PRIMARY_EXECUTABLE) == 0) {
  598. continue;
  599. }
  600. ExecutableFound = TRUE;
  601. if (Library == OS_LIBRARY_NEXT) {
  602. continue;
  603. }
  604. }
  605. Status = ImGetSymbolByAddress(Image, Address, TRUE, &ImageSymbol);
  606. if (KSUCCESS(Status)) {
  607. break;
  608. }
  609. }
  610. //
  611. // Otherwise only search through the supplied library.
  612. //
  613. } else {
  614. Status = ImGetSymbolByAddress(Library, Address, TRUE, &ImageSymbol);
  615. }
  616. if (KSUCCESS(Status)) {
  617. //
  618. // If the image has no name and it's the primary executable, then fill
  619. // in the name from the OS environment.
  620. //
  621. Image = ImageSymbol.Image;
  622. Symbol->LibraryName = Image->FileName;
  623. if ((Symbol->LibraryName == NULL) &&
  624. ((Image->LoadFlags & IMAGE_LOAD_FLAG_PRIMARY_EXECUTABLE) != 0)) {
  625. Symbol->LibraryName = OsEnvironment->ImageName;
  626. }
  627. Symbol->LibraryBaseAddress = Image->LoadedImageBuffer;
  628. Symbol->SymbolName = ImageSymbol.Name;
  629. Symbol->SymbolAddress = ImageSymbol.Address;
  630. }
  631. GetLibrarySymbolForAddress:
  632. OspReleaseImageLock();
  633. return Status;
  634. }
  635. OS_API
  636. KSTATUS
  637. OsFlushCache (
  638. PVOID Address,
  639. UINTN Size
  640. )
  641. /*++
  642. Routine Description:
  643. This routine flushes the caches for a region of memory after executable
  644. code has been modified.
  645. Arguments:
  646. Address - Supplies the address of the region to flush.
  647. Size - Supplies the number of bytes in the region.
  648. Return Value:
  649. STATUS_SUCCESS on success.
  650. STATUS_ACCESS_VIOLATION if the given address was not valid.
  651. --*/
  652. {
  653. SYSTEM_CALL_FLUSH_CACHE Parameters;
  654. Parameters.Address = Address;
  655. Parameters.Size = Size;
  656. return OsSystemCall(SystemCallFlushCache, &Parameters);
  657. }
  658. OS_API
  659. KSTATUS
  660. OsCreateThreadData (
  661. PVOID *ThreadData
  662. )
  663. /*++
  664. Routine Description:
  665. This routine creates the OS library data necessary to manage a new thread.
  666. This function is usually called by the C library.
  667. Arguments:
  668. ThreadData - Supplies a pointer where a pointer to the thread data will be
  669. returned on success. It is the callers responsibility to destroy this
  670. thread data. The contents of this data are opaque and should not be
  671. interpreted. The caller should set this returned pointer as the
  672. thread pointer.
  673. Return Value:
  674. Status code.
  675. --*/
  676. {
  677. KSTATUS Status;
  678. //
  679. // Allocate the initial TLS image and control block for the thread.
  680. //
  681. OspAcquireImageLock(FALSE);
  682. Status = OspTlsAllocate(&OsLoadedImagesHead, ThreadData);
  683. OspReleaseImageLock();
  684. return Status;
  685. }
  686. OS_API
  687. VOID
  688. OsDestroyThreadData (
  689. PVOID ThreadData
  690. )
  691. /*++
  692. Routine Description:
  693. This routine destroys the previously created OS library thread data.
  694. Arguments:
  695. ThreadData - Supplies the previously returned thread data.
  696. Return Value:
  697. Status code.
  698. --*/
  699. {
  700. OspAcquireImageLock(FALSE);
  701. OspTlsDestroy(ThreadData);
  702. OspReleaseImageLock();
  703. return;
  704. }
  705. OS_API
  706. VOID
  707. OsIterateImages (
  708. PIMAGE_ITERATOR_ROUTINE IteratorRoutine,
  709. PVOID Context
  710. )
  711. /*++
  712. Routine Description:
  713. This routine iterates over all images currently loaded in the process.
  714. Arguments:
  715. IteratorRoutine - Supplies a pointer to the routine to call for each image.
  716. Context - Supplies an opaque context pointer that is passed directly into
  717. the iterator routine.
  718. Return Value:
  719. None.
  720. --*/
  721. {
  722. PLIST_ENTRY CurrentEntry;
  723. PLOADED_IMAGE Image;
  724. OspAcquireImageLock(FALSE);
  725. CurrentEntry = OsLoadedImagesHead.Next;
  726. if (CurrentEntry != NULL) {
  727. while (CurrentEntry != &OsLoadedImagesHead) {
  728. Image = LIST_VALUE(CurrentEntry, LOADED_IMAGE, ListEntry);
  729. CurrentEntry = CurrentEntry->Next;
  730. IteratorRoutine(Image, Context);
  731. }
  732. }
  733. OspReleaseImageLock();
  734. return;
  735. }
  736. VOID
  737. OspInitializeImageSupport (
  738. VOID
  739. )
  740. /*++
  741. Routine Description:
  742. This routine initializes the image library for use in the image creation
  743. tool.
  744. Arguments:
  745. None.
  746. Return Value:
  747. None.
  748. --*/
  749. {
  750. OsRwLockInitialize(&OsLoadedImagesLock, 0);
  751. ImInitialize(&OsImageFunctionTable);
  752. return;
  753. }
  754. VOID
  755. OspAcquireImageLock (
  756. BOOL Exclusive
  757. )
  758. /*++
  759. Routine Description:
  760. This routine acquires the global image lock.
  761. Arguments:
  762. Exclusive - Supplies a boolean indicating whether the lock should be
  763. held shared (FALSE) or exclusive (TRUE).
  764. Return Value:
  765. None.
  766. --*/
  767. {
  768. if (Exclusive != FALSE) {
  769. OsRwLockWrite(&OsLoadedImagesLock);
  770. } else {
  771. OsRwLockRead(&OsLoadedImagesLock);
  772. }
  773. return;
  774. }
  775. VOID
  776. OspReleaseImageLock (
  777. VOID
  778. )
  779. /*++
  780. Routine Description:
  781. This routine releases the global image lock.
  782. Arguments:
  783. None.
  784. Return Value:
  785. None.
  786. --*/
  787. {
  788. OsRwLockUnlock(&OsLoadedImagesLock);
  789. return;
  790. }
  791. //
  792. // --------------------------------------------------------- Internal Functions
  793. //
  794. PVOID
  795. OspImAllocateMemory (
  796. ULONG Size,
  797. ULONG Tag
  798. )
  799. /*++
  800. Routine Description:
  801. This routine allocates memory for the image library.
  802. Arguments:
  803. Size - Supplies the number of bytes required for the memory allocation.
  804. Tag - Supplies a 32-bit ASCII identifier used to tag the memroy allocation.
  805. Return Value:
  806. Returns a pointer to the memory allocation on success.
  807. NULL on failure.
  808. --*/
  809. {
  810. return OsHeapAllocate(Size, Tag);
  811. }
  812. VOID
  813. OspImFreeMemory (
  814. PVOID Allocation
  815. )
  816. /*++
  817. Routine Description:
  818. This routine frees memory allocated by the image library.
  819. Arguments:
  820. Allocation - Supplies a pointer the allocation to free.
  821. Return Value:
  822. None.
  823. --*/
  824. {
  825. OsHeapFree(Allocation);
  826. return;
  827. }
  828. KSTATUS
  829. OspImOpenFile (
  830. PVOID SystemContext,
  831. PCSTR BinaryName,
  832. PIMAGE_FILE_INFORMATION File
  833. )
  834. /*++
  835. Routine Description:
  836. This routine opens a file.
  837. Arguments:
  838. SystemContext - Supplies the context pointer passed to the load executable
  839. function.
  840. BinaryName - Supplies the name of the executable image to open.
  841. File - Supplies a pointer where the information for the file including its
  842. open handle will be returned.
  843. Return Value:
  844. Status code.
  845. --*/
  846. {
  847. ULONG BinaryNameSize;
  848. FILE_CONTROL_PARAMETERS_UNION FileControlParameters;
  849. PFILE_PROPERTIES FileProperties;
  850. ULONGLONG LocalFileSize;
  851. KSTATUS Status;
  852. File->Handle = INVALID_HANDLE;
  853. BinaryNameSize = RtlStringLength(BinaryName) + 1;
  854. Status = OsOpen(INVALID_HANDLE,
  855. BinaryName,
  856. BinaryNameSize,
  857. SYS_OPEN_FLAG_READ,
  858. FILE_PERMISSION_NONE,
  859. &(File->Handle));
  860. if (!KSUCCESS(Status)) {
  861. goto OpenFileEnd;
  862. }
  863. Status = OsFileControl(File->Handle,
  864. FileControlCommandGetFileInformation,
  865. &FileControlParameters);
  866. if (!KSUCCESS(Status)) {
  867. goto OpenFileEnd;
  868. }
  869. FileProperties = &(FileControlParameters.SetFileInformation.FileProperties);
  870. if (FileProperties->Type != IoObjectRegularFile) {
  871. Status = STATUS_UNEXPECTED_TYPE;
  872. goto OpenFileEnd;
  873. }
  874. READ_INT64_SYNC(&(FileProperties->FileSize), &LocalFileSize);
  875. File->Size = LocalFileSize;
  876. File->ModificationDate = FileProperties->ModifiedTime.Seconds;
  877. File->DeviceId = FileProperties->DeviceId;
  878. File->FileId = FileProperties->FileId;
  879. Status = STATUS_SUCCESS;
  880. OpenFileEnd:
  881. if (!KSUCCESS(Status)) {
  882. if (File->Handle != INVALID_HANDLE) {
  883. OsClose(File->Handle);
  884. }
  885. }
  886. return Status;
  887. }
  888. VOID
  889. OspImCloseFile (
  890. PIMAGE_FILE_INFORMATION File
  891. )
  892. /*++
  893. Routine Description:
  894. This routine closes an open file, invalidating any memory mappings to it.
  895. Arguments:
  896. File - Supplies a pointer to the file information.
  897. Return Value:
  898. None.
  899. --*/
  900. {
  901. KSTATUS Status;
  902. if (File->Handle != INVALID_HANDLE) {
  903. Status = OsClose(File->Handle);
  904. ASSERT(KSUCCESS(Status));
  905. File->Handle = INVALID_HANDLE;
  906. }
  907. return;
  908. }
  909. KSTATUS
  910. OspImLoadFile (
  911. PIMAGE_FILE_INFORMATION File,
  912. PIMAGE_BUFFER Buffer
  913. )
  914. /*++
  915. Routine Description:
  916. This routine loads an entire file into memory so the image library can
  917. access it.
  918. Arguments:
  919. File - Supplies a pointer to the file information.
  920. Buffer - Supplies a pointer where the buffer will be returned on success.
  921. Return Value:
  922. Status code.
  923. --*/
  924. {
  925. ULONGLONG AlignedSize;
  926. KSTATUS Status;
  927. AlignedSize = ALIGN_RANGE_UP(File->Size, OsPageSize);
  928. if (AlignedSize > MAX_UINTN) {
  929. return STATUS_NOT_SUPPORTED;
  930. }
  931. Status = OsMemoryMap(File->Handle,
  932. 0,
  933. (UINTN)AlignedSize,
  934. SYS_MAP_FLAG_READ,
  935. &(Buffer->Data));
  936. if (!KSUCCESS(Status)) {
  937. return Status;
  938. }
  939. Buffer->Size = File->Size;
  940. return Status;
  941. }
  942. VOID
  943. OspImUnloadBuffer (
  944. PIMAGE_FILE_INFORMATION File,
  945. PIMAGE_BUFFER Buffer
  946. )
  947. /*++
  948. Routine Description:
  949. This routine unloads a file buffer created from either the load file or
  950. read file function, and frees the buffer.
  951. Arguments:
  952. File - Supplies a pointer to the file information.
  953. Buffer - Supplies the buffer returned by the load file function.
  954. Return Value:
  955. None.
  956. --*/
  957. {
  958. UINTN AlignedSize;
  959. KSTATUS Status;
  960. ASSERT(Buffer->Data != NULL);
  961. AlignedSize = ALIGN_RANGE_UP(File->Size, OsPageSize);
  962. Status = OsMemoryUnmap(Buffer->Data, AlignedSize);
  963. ASSERT(KSUCCESS(Status));
  964. Buffer->Data = NULL;
  965. return;
  966. }
  967. KSTATUS
  968. OspImAllocateAddressSpace (
  969. PLOADED_IMAGE Image
  970. )
  971. /*++
  972. Routine Description:
  973. This routine allocates a section of virtual address space that an image
  974. can be mapped in to.
  975. Arguments:
  976. Image - Supplies a pointer to the image being loaded. The system context,
  977. size, file information, load flags, and preferred virtual address will
  978. be initialized. This routine should set up the loaded image buffer,
  979. loaded lowest address, and allocator handle if needed.
  980. Return Value:
  981. Status code.
  982. --*/
  983. {
  984. PVOID Address;
  985. UINTN AlignedSize;
  986. ULONG MapFlags;
  987. KSTATUS Status;
  988. //
  989. // Memory map a region to use.
  990. //
  991. Address = Image->PreferredLowestAddress;
  992. AlignedSize = ALIGN_RANGE_UP(Image->Size, OsPageSize);
  993. MapFlags = SYS_MAP_FLAG_READ | SYS_MAP_FLAG_WRITE | SYS_MAP_FLAG_EXECUTE;
  994. Status = OsMemoryMap(Image->File.Handle,
  995. 0,
  996. AlignedSize,
  997. MapFlags,
  998. &Address);
  999. Image->BaseDifference = Address - Image->PreferredLowestAddress;
  1000. Image->LoadedImageBuffer = Address;
  1001. Image->AllocatorHandle = Address;
  1002. return Status;
  1003. }
  1004. VOID
  1005. OspImFreeAddressSpace (
  1006. PLOADED_IMAGE Image
  1007. )
  1008. /*++
  1009. Routine Description:
  1010. This routine frees a section of virtual address space that was previously
  1011. allocated.
  1012. Arguments:
  1013. Image - Supplies a pointer to the loaded (or partially loaded) image.
  1014. Return Value:
  1015. None.
  1016. --*/
  1017. {
  1018. KSTATUS Status;
  1019. Status = OsMemoryUnmap(Image->LoadedImageBuffer, Image->Size);
  1020. ASSERT(KSUCCESS(Status));
  1021. return;
  1022. }
  1023. KSTATUS
  1024. OspImMapImageSegment (
  1025. HANDLE AddressSpaceHandle,
  1026. PVOID AddressSpaceAllocation,
  1027. PIMAGE_FILE_INFORMATION File,
  1028. ULONGLONG FileOffset,
  1029. PIMAGE_SEGMENT Segment,
  1030. PIMAGE_SEGMENT PreviousSegment
  1031. )
  1032. /*++
  1033. Routine Description:
  1034. This routine maps a section of the image to the given virtual address.
  1035. Arguments:
  1036. AddressSpaceHandle - Supplies the handle used to claim the overall region
  1037. of address space.
  1038. AddressSpaceAllocation - Supplies the original lowest virtual address for
  1039. this image.
  1040. File - Supplies an optional pointer to the file being mapped. If this
  1041. parameter is NULL, then a zeroed memory section is being mapped.
  1042. FileOffset - Supplies the offset from the beginning of the file to the
  1043. beginning of the mapping, in bytes.
  1044. Segment - Supplies a pointer to the segment information to map. On output,
  1045. the virtual address will contain the actual mapped address, and the
  1046. mapping handle may be set.
  1047. PreviousSegment - Supplies an optional pointer to the previous segment
  1048. that was mapped, so this routine can handle overlap appropriately. This
  1049. routine can assume that segments are always mapped in increasing order.
  1050. Return Value:
  1051. Status code.
  1052. --*/
  1053. {
  1054. PVOID Address;
  1055. UINTN BytesCompleted;
  1056. HANDLE FileHandle;
  1057. PVOID FileRegion;
  1058. UINTN FileRegionSize;
  1059. UINTN FileSize;
  1060. UINTN IoSize;
  1061. ULONG MapFlags;
  1062. UINTN MemoryRegionSize;
  1063. UINTN MemorySize;
  1064. UINTN NextPage;
  1065. UINTN PageMask;
  1066. UINTN PageOffset;
  1067. UINTN PageSize;
  1068. UINTN PreviousEnd;
  1069. UINTN RegionEnd;
  1070. UINTN RegionSize;
  1071. UINTN SegmentAddress;
  1072. KSTATUS Status;
  1073. ASSERT((PreviousSegment == NULL) ||
  1074. (Segment->VirtualAddress > PreviousSegment->VirtualAddress));
  1075. FileRegion = NULL;
  1076. FileRegionSize = 0;
  1077. FileHandle = INVALID_HANDLE;
  1078. if (File != NULL) {
  1079. FileHandle = File->Handle;
  1080. }
  1081. FileSize = Segment->FileSize;
  1082. MemorySize = Segment->MemorySize;
  1083. ASSERT((FileSize == Segment->FileSize) &&
  1084. (MemorySize == Segment->MemorySize));
  1085. //
  1086. // Map everything readable and writable for now, it will get fixed up
  1087. // during finalization.
  1088. //
  1089. MapFlags = SYS_MAP_FLAG_READ | SYS_MAP_FLAG_WRITE;
  1090. if ((Segment->Flags & IMAGE_MAP_FLAG_EXECUTE) != 0) {
  1091. MapFlags |= SYS_MAP_FLAG_EXECUTE;
  1092. }
  1093. if ((Segment->Flags & IMAGE_MAP_FLAG_FIXED) != 0) {
  1094. MapFlags |= SYS_MAP_FLAG_FIXED;
  1095. }
  1096. //
  1097. // Handle the first part, which may overlap with the previous segment.
  1098. //
  1099. PageSize = OsPageSize;
  1100. PageMask = PageSize - 1;
  1101. SegmentAddress = (UINTN)(Segment->VirtualAddress);
  1102. if (PreviousSegment != NULL) {
  1103. PreviousEnd = (UINTN)(PreviousSegment->VirtualAddress) +
  1104. PreviousSegment->MemorySize;
  1105. RegionEnd = ALIGN_RANGE_UP(PreviousEnd, PageSize);
  1106. if (RegionEnd > SegmentAddress) {
  1107. //
  1108. // Compute the portion of this section that needs to be read or
  1109. // zeroed into it.
  1110. //
  1111. if (SegmentAddress + MemorySize < RegionEnd) {
  1112. RegionEnd = SegmentAddress + MemorySize;
  1113. }
  1114. RegionSize = RegionEnd - SegmentAddress;
  1115. IoSize = FileSize;
  1116. if (IoSize > RegionSize) {
  1117. IoSize = RegionSize;
  1118. }
  1119. Status = OsPerformIo(FileHandle,
  1120. FileOffset,
  1121. IoSize,
  1122. 0,
  1123. SYS_WAIT_TIME_INDEFINITE,
  1124. (PVOID)SegmentAddress,
  1125. &BytesCompleted);
  1126. if (!KSUCCESS(Status)) {
  1127. goto MapImageSegmentEnd;
  1128. }
  1129. if (BytesCompleted != IoSize) {
  1130. Status = STATUS_END_OF_FILE;
  1131. goto MapImageSegmentEnd;
  1132. }
  1133. if (IoSize < RegionSize) {
  1134. RtlZeroMemory((PVOID)SegmentAddress + IoSize,
  1135. RegionSize - IoSize);
  1136. }
  1137. if (((Segment->Flags | PreviousSegment->Flags) &
  1138. IMAGE_MAP_FLAG_EXECUTE) != 0) {
  1139. Status = OsFlushCache((PVOID)SegmentAddress, RegionSize);
  1140. ASSERT(KSUCCESS(Status));
  1141. }
  1142. FileOffset += IoSize;
  1143. FileSize -= IoSize;
  1144. MemorySize -= RegionSize;
  1145. SegmentAddress = RegionEnd;
  1146. //
  1147. // If there is a hole in between the previous segment and this one,
  1148. // change the protection to none for the hole.
  1149. //
  1150. } else {
  1151. RegionSize = SegmentAddress - RegionEnd;
  1152. RegionSize = ALIGN_RANGE_DOWN(RegionSize, PageSize);
  1153. if (RegionSize != 0) {
  1154. Status = OsSetMemoryProtection((PVOID)RegionEnd, RegionSize, 0);
  1155. if (!KSUCCESS(Status)) {
  1156. ASSERT(FALSE);
  1157. goto MapImageSegmentEnd;
  1158. }
  1159. }
  1160. }
  1161. }
  1162. //
  1163. // This is the main portion. If the file offset and address have the same
  1164. // page alignment, then it can be mapped directly. Otherwise, it must be
  1165. // read in.
  1166. //
  1167. if (FileSize != 0) {
  1168. PageOffset = FileOffset & PageMask;
  1169. FileRegion = (PVOID)(SegmentAddress - PageOffset);
  1170. FileRegionSize = ALIGN_RANGE_UP(FileSize + PageOffset, PageSize);
  1171. //
  1172. // Try to memory map the file directly.
  1173. //
  1174. if (PageOffset == (SegmentAddress & PageMask)) {
  1175. //
  1176. // Memory map the file to the desired address. The address space
  1177. // allocation was created by memory mapping the beginning of the
  1178. // file, so skip the mapping if it's trying to do exactly that.
  1179. // This saves a redundant system call.
  1180. //
  1181. if ((FileOffset != PageOffset) ||
  1182. (FileRegion != AddressSpaceAllocation)) {
  1183. Status = OsMemoryMap(FileHandle,
  1184. FileOffset - PageOffset,
  1185. FileRegionSize,
  1186. MapFlags,
  1187. &FileRegion);
  1188. if (!KSUCCESS(Status)) {
  1189. RtlDebugPrint("Failed to map 0x%x bytes at 0x%x: %d\n",
  1190. FileRegionSize,
  1191. FileRegion,
  1192. Status);
  1193. FileRegionSize = 0;
  1194. goto MapImageSegmentEnd;
  1195. }
  1196. }
  1197. IoSize = 0;
  1198. //
  1199. // The file offsets don't agree. Allocate a region for reading.
  1200. //
  1201. } else {
  1202. Status = OsMemoryMap(INVALID_HANDLE,
  1203. 0,
  1204. FileRegionSize,
  1205. MapFlags | SYS_MAP_FLAG_ANONYMOUS,
  1206. &FileRegion);
  1207. if (!KSUCCESS(Status)) {
  1208. RtlDebugPrint("Failed to map 0x%x bytes at 0x%x: %d\n",
  1209. FileRegionSize,
  1210. FileRegion,
  1211. Status);
  1212. FileRegionSize = 0;
  1213. goto MapImageSegmentEnd;
  1214. }
  1215. IoSize = FileSize;
  1216. }
  1217. //
  1218. // If the mapping wasn't at the expected location, adjust.
  1219. //
  1220. if ((UINTN)FileRegion != SegmentAddress - PageOffset) {
  1221. ASSERT((PreviousSegment == NULL) &&
  1222. ((Segment->Flags & IMAGE_MAP_FLAG_FIXED) == 0));
  1223. SegmentAddress = (UINTN)FileRegion + PageOffset;
  1224. Segment->VirtualAddress = (PVOID)SegmentAddress;
  1225. }
  1226. Segment->MappingStart = FileRegion;
  1227. //
  1228. // Read from the file if the file wasn't mapped directly.
  1229. //
  1230. if (IoSize != 0) {
  1231. Status = OsPerformIo(FileHandle,
  1232. FileOffset,
  1233. IoSize,
  1234. 0,
  1235. SYS_WAIT_TIME_INDEFINITE,
  1236. (PVOID)SegmentAddress,
  1237. &BytesCompleted);
  1238. if (!KSUCCESS(Status)) {
  1239. goto MapImageSegmentEnd;
  1240. }
  1241. if (BytesCompleted != IoSize) {
  1242. Status = STATUS_END_OF_FILE;
  1243. goto MapImageSegmentEnd;
  1244. }
  1245. if ((Segment->Flags & IMAGE_MAP_FLAG_EXECUTE) != 0) {
  1246. Status = OsFlushCache((PVOID)SegmentAddress, IoSize);
  1247. ASSERT(KSUCCESS(Status));
  1248. }
  1249. }
  1250. SegmentAddress += FileSize;
  1251. MemorySize -= FileSize;
  1252. //
  1253. // Zero out any region between the end of the file portion and the next
  1254. // page.
  1255. //
  1256. NextPage = ALIGN_RANGE_UP(SegmentAddress, PageSize);
  1257. if (NextPage - SegmentAddress != 0) {
  1258. RtlZeroMemory((PVOID)SegmentAddress, NextPage - SegmentAddress);
  1259. if ((Segment->Flags & IMAGE_MAP_FLAG_EXECUTE) != 0) {
  1260. Status = OsFlushCache((PVOID)SegmentAddress,
  1261. NextPage - SegmentAddress);
  1262. ASSERT(KSUCCESS(Status));
  1263. }
  1264. }
  1265. if (NextPage >= SegmentAddress + MemorySize) {
  1266. Status = STATUS_SUCCESS;
  1267. goto MapImageSegmentEnd;
  1268. }
  1269. MemorySize -= NextPage - SegmentAddress;
  1270. SegmentAddress = NextPage;
  1271. //
  1272. // If the file region was decided, any remaining memory region is now
  1273. // fixed.
  1274. //
  1275. MapFlags |= SYS_MAP_FLAG_FIXED;
  1276. }
  1277. //
  1278. // Memory map the remaining region.
  1279. //
  1280. PageOffset = SegmentAddress & PageMask;
  1281. Address = (PVOID)(SegmentAddress - PageOffset);
  1282. MemoryRegionSize = MemorySize + PageOffset;
  1283. MemoryRegionSize = ALIGN_RANGE_UP(MemoryRegionSize, PageSize);
  1284. Status = OsMemoryMap(INVALID_HANDLE,
  1285. 0,
  1286. MemoryRegionSize,
  1287. MapFlags | SYS_MAP_FLAG_ANONYMOUS,
  1288. &Address);
  1289. if (!KSUCCESS(Status)) {
  1290. RtlDebugPrint("Failed to map 0x%x bytes at 0x%x: %d\n",
  1291. MemorySize + PageOffset,
  1292. Address,
  1293. Status);
  1294. goto MapImageSegmentEnd;
  1295. }
  1296. if (Segment->MappingStart == NULL) {
  1297. Segment->MappingStart = Address;
  1298. }
  1299. MapImageSegmentEnd:
  1300. if (!KSUCCESS(Status)) {
  1301. if (FileRegionSize != 0) {
  1302. OsMemoryUnmap(FileRegion, FileRegionSize);
  1303. }
  1304. }
  1305. return Status;
  1306. }
  1307. VOID
  1308. OspImUnmapImageSegment (
  1309. HANDLE AddressSpaceHandle,
  1310. PIMAGE_SEGMENT Segment
  1311. )
  1312. /*++
  1313. Routine Description:
  1314. This routine maps unmaps an image segment.
  1315. Arguments:
  1316. AddressSpaceHandle - Supplies the handle used to claim the overall region
  1317. of address space.
  1318. Segment - Supplies a pointer to the segment information to unmap.
  1319. Return Value:
  1320. None.
  1321. --*/
  1322. {
  1323. //
  1324. // There's no need to unmap each segment individually, the free address
  1325. // space function does it all at the end.
  1326. //
  1327. return;
  1328. }
  1329. KSTATUS
  1330. OspImNotifyImageLoad (
  1331. PLOADED_IMAGE Image
  1332. )
  1333. /*++
  1334. Routine Description:
  1335. This routine notifies the primary consumer of the image library that an
  1336. image has been loaded.
  1337. Arguments:
  1338. Image - Supplies the image that has just been loaded. This image should
  1339. be subsequently returned to the image library upon requests for loaded
  1340. images with the given name.
  1341. Return Value:
  1342. Status code. Failing status codes veto the image load.
  1343. --*/
  1344. {
  1345. PROCESS_DEBUG_MODULE_CHANGE Notification;
  1346. KSTATUS Status;
  1347. ASSERT(OsLoadedImagesHead.Next != NULL);
  1348. Image->Debug.DynamicLinkerBase = OsEnvironment->StartData->InterpreterBase;
  1349. Notification.Version = PROCESS_DEBUG_MODULE_CHANGE_VERSION;
  1350. Notification.Load = TRUE;
  1351. Notification.Image = Image;
  1352. Notification.BinaryNameSize = RtlStringLength(Image->FileName) + 1;
  1353. Status = OsDebug(DebugCommandReportModuleChange,
  1354. 0,
  1355. NULL,
  1356. &Notification,
  1357. sizeof(PROCESS_DEBUG_MODULE_CHANGE),
  1358. 0);
  1359. if (!KSUCCESS(Status)) {
  1360. RtlDebugPrint("Warning: Failed to notify kernel of module %s: %d\n",
  1361. Image->FileName,
  1362. Status);
  1363. }
  1364. Status = OspImAssignModuleNumber(Image);
  1365. if (!KSUCCESS(Status)) {
  1366. return Status;
  1367. }
  1368. return STATUS_SUCCESS;
  1369. }
  1370. VOID
  1371. OspImNotifyImageUnload (
  1372. PLOADED_IMAGE Image
  1373. )
  1374. /*++
  1375. Routine Description:
  1376. This routine notifies the primary consumer of the image library that an
  1377. image is about to be unloaded from memory. Once this routine returns, the
  1378. image should not be referenced again as it will be freed.
  1379. Arguments:
  1380. Image - Supplies the image that is about to be unloaded.
  1381. Return Value:
  1382. None.
  1383. --*/
  1384. {
  1385. PIMAGE_STATIC_FUNCTION *Begin;
  1386. PIMAGE_STATIC_FUNCTION *DestructorPointer;
  1387. PROCESS_DEBUG_MODULE_CHANGE Notification;
  1388. PIMAGE_STATIC_FUNCTIONS StaticFunctions;
  1389. KSTATUS Status;
  1390. //
  1391. // Release the image lock while calling out to destructors.
  1392. //
  1393. if (OsImExecutableLoaded != FALSE) {
  1394. OspReleaseImageLock();
  1395. }
  1396. //
  1397. // Call the static destructor functions. These are only filled in for
  1398. // dynamic objects. For executables, this is all handled internally in the
  1399. // static portion of the C library.
  1400. //
  1401. StaticFunctions = Image->StaticFunctions;
  1402. if ((StaticFunctions != NULL) &&
  1403. ((Image->LoadFlags & IMAGE_LOAD_FLAG_PRIMARY_EXECUTABLE) == 0)) {
  1404. //
  1405. // Call the .fini_array functions in reverse order.
  1406. //
  1407. if (StaticFunctions->FiniArraySize > sizeof(PIMAGE_STATIC_FUNCTION)) {
  1408. Begin = StaticFunctions->FiniArray;
  1409. DestructorPointer = (PVOID)(Begin) + StaticFunctions->FiniArraySize;
  1410. DestructorPointer -= 1;
  1411. while (DestructorPointer >= Begin) {
  1412. //
  1413. // Call the destructor.
  1414. //
  1415. (*DestructorPointer)();
  1416. DestructorPointer -= 1;
  1417. }
  1418. }
  1419. //
  1420. // Also call the old school _fini destructor if present.
  1421. //
  1422. if (StaticFunctions->FiniFunction != NULL) {
  1423. StaticFunctions->FiniFunction();
  1424. }
  1425. }
  1426. ASSERT(OsLoadedImagesHead.Next != NULL);
  1427. if (OsImExecutableLoaded != FALSE) {
  1428. OspAcquireImageLock(TRUE);
  1429. }
  1430. //
  1431. // Tear down all the TLS segments for this module.
  1432. //
  1433. OspTlsTearDownModule(Image);
  1434. //
  1435. // Notify the kernel the module is being unloaded.
  1436. //
  1437. Notification.Version = PROCESS_DEBUG_MODULE_CHANGE_VERSION;
  1438. Notification.Load = FALSE;
  1439. Notification.Image = Image;
  1440. Notification.BinaryNameSize = RtlStringLength(Image->FileName) + 1;
  1441. Status = OsDebug(DebugCommandReportModuleChange,
  1442. 0,
  1443. NULL,
  1444. &Notification,
  1445. sizeof(PROCESS_DEBUG_MODULE_CHANGE),
  1446. 0);
  1447. if (!KSUCCESS(Status)) {
  1448. RtlDebugPrint("Warning: Failed to unload module %s: %d\n",
  1449. Image->FileName,
  1450. Status);
  1451. }
  1452. OspImReleaseModuleNumber(Image);
  1453. return;
  1454. }
  1455. VOID
  1456. OspImInvalidateInstructionCacheRegion (
  1457. PVOID Address,
  1458. ULONG Size
  1459. )
  1460. /*++
  1461. Routine Description:
  1462. This routine invalidates an instruction cache region after code has been
  1463. modified.
  1464. Arguments:
  1465. Address - Supplies the virtual address of the revion to invalidate.
  1466. Size - Supplies the number of bytes to invalidate.
  1467. Return Value:
  1468. None.
  1469. --*/
  1470. {
  1471. KSTATUS Status;
  1472. Status = OsFlushCache(Address, Size);
  1473. ASSERT(KSUCCESS(Status));
  1474. return;
  1475. }
  1476. PSTR
  1477. OspImGetEnvironmentVariable (
  1478. PSTR Variable
  1479. )
  1480. /*++
  1481. Routine Description:
  1482. This routine gets an environment variable value for the image library.
  1483. Arguments:
  1484. Variable - Supplies a pointer to a null terminated string containing the
  1485. name of the variable to get.
  1486. Return Value:
  1487. Returns a pointer to the value of the environment variable. The image
  1488. library will not free or modify this value.
  1489. NULL if the given environment variable is not set.
  1490. --*/
  1491. {
  1492. PPROCESS_ENVIRONMENT Environment;
  1493. UINTN Index;
  1494. BOOL Match;
  1495. UINTN VariableLength;
  1496. PSTR VariableString;
  1497. VariableLength = RtlStringLength(Variable);
  1498. Match = RtlAreStringsEqual(Variable,
  1499. IMAGE_LOAD_LIBRARY_PATH_VARIABLE,
  1500. VariableLength + 1);
  1501. if (Match != FALSE) {
  1502. if (OsImLibraryPathOverride != NULL) {
  1503. return OsImLibraryPathOverride;
  1504. }
  1505. }
  1506. if (OsImGetEnvironmentVariable != NULL) {
  1507. return OsImGetEnvironmentVariable(Variable);
  1508. }
  1509. //
  1510. // Search through the initial environment.
  1511. //
  1512. Environment = OsGetCurrentEnvironment();
  1513. for (Index = 0; Index < Environment->EnvironmentCount; Index += 1) {
  1514. VariableString = Environment->Environment[Index];
  1515. Match = RtlAreStringsEqual(Variable,
  1516. VariableString,
  1517. VariableLength);
  1518. if ((Match != FALSE) && (VariableString[VariableLength] == '=')) {
  1519. return VariableString + VariableLength + 1;
  1520. }
  1521. }
  1522. return NULL;
  1523. }
  1524. KSTATUS
  1525. OspImFinalizeSegments (
  1526. HANDLE AddressSpaceHandle,
  1527. PIMAGE_SEGMENT Segments,
  1528. UINTN SegmentCount
  1529. )
  1530. /*++
  1531. Routine Description:
  1532. This routine applies the final memory protection attributes to the given
  1533. segments. Read and execute bits can be applied at the time of mapping, but
  1534. write protection may be applied here.
  1535. Arguments:
  1536. AddressSpaceHandle - Supplies the handle used to claim the overall region
  1537. of address space.
  1538. Segments - Supplies the final array of segments.
  1539. SegmentCount - Supplies the number of segments.
  1540. Return Value:
  1541. Status code.
  1542. --*/
  1543. {
  1544. UINTN End;
  1545. ULONG MapFlags;
  1546. UINTN PageSize;
  1547. PIMAGE_SEGMENT Segment;
  1548. UINTN SegmentIndex;
  1549. UINTN Size;
  1550. KSTATUS Status;
  1551. PageSize = OsPageSize;
  1552. for (SegmentIndex = 0; SegmentIndex < SegmentCount; SegmentIndex += 1) {
  1553. Segment = &(Segments[SegmentIndex]);
  1554. if (Segment->Type == ImageSegmentInvalid) {
  1555. continue;
  1556. }
  1557. //
  1558. // If the segment has no protection features, then there's nothing to
  1559. // tighten up.
  1560. //
  1561. if ((Segment->Flags & IMAGE_MAP_FLAG_WRITE) != 0) {
  1562. continue;
  1563. }
  1564. //
  1565. // If the image was so small it fit entirely in some other segment's
  1566. // remainder, skip it.
  1567. //
  1568. if (Segment->MappingStart == NULL) {
  1569. continue;
  1570. }
  1571. //
  1572. // Compute the region whose protection should actually be changed.
  1573. //
  1574. End = (UINTN)(Segment->VirtualAddress) + Segment->MemorySize;
  1575. End = ALIGN_RANGE_UP(End, PageSize);
  1576. //
  1577. // If the region has a real size, change it's protection to read-only.
  1578. //
  1579. if ((PVOID)End > Segment->MappingStart) {
  1580. Size = End - (UINTN)(Segment->MappingStart);
  1581. MapFlags = SYS_MAP_FLAG_READ;
  1582. if ((Segment->Flags & IMAGE_MAP_FLAG_EXECUTE) != 0) {
  1583. MapFlags |= SYS_MAP_FLAG_EXECUTE;
  1584. }
  1585. Status = OsSetMemoryProtection(Segment->MappingStart,
  1586. Size,
  1587. MapFlags);
  1588. if (!KSUCCESS(Status)) {
  1589. goto FinalizeSegmentsEnd;
  1590. }
  1591. }
  1592. }
  1593. Status = STATUS_SUCCESS;
  1594. FinalizeSegmentsEnd:
  1595. return Status;
  1596. }
  1597. VOID
  1598. OspImInitializeImages (
  1599. PLIST_ENTRY ListHead
  1600. )
  1601. /*++
  1602. Routine Description:
  1603. This routine initializes any new images and calls their static constructors.
  1604. This routine assumes the list lock is already held.
  1605. Arguments:
  1606. ListHead - Supplies a pointer to the head of the list of images to
  1607. initialize.
  1608. Return Value:
  1609. None.
  1610. --*/
  1611. {
  1612. PLIST_ENTRY CurrentEntry;
  1613. PLOADED_IMAGE Image;
  1614. //
  1615. // Iterate over list backwards to initialize dependencies before the
  1616. // libraries that depend on them.
  1617. //
  1618. OspAcquireImageLock(FALSE);
  1619. CurrentEntry = ListHead->Previous;
  1620. while (CurrentEntry != ListHead) {
  1621. Image = LIST_VALUE(CurrentEntry, LOADED_IMAGE, ListEntry);
  1622. if ((Image->Flags & IMAGE_FLAG_INITIALIZED) == 0) {
  1623. //
  1624. // Release the lock around initializing the image.
  1625. //
  1626. OspReleaseImageLock();
  1627. OspImInitializeImage(Image);
  1628. OspAcquireImageLock(FALSE);
  1629. Image->Flags |= IMAGE_FLAG_INITIALIZED;
  1630. }
  1631. CurrentEntry = CurrentEntry->Previous;
  1632. }
  1633. OspReleaseImageLock();
  1634. return;
  1635. }
  1636. VOID
  1637. OspImInitializeImage (
  1638. PLOADED_IMAGE Image
  1639. )
  1640. /*++
  1641. Routine Description:
  1642. This routine is called when the image is fully loaded. It flushes the cache
  1643. region and calls the entry point.
  1644. Arguments:
  1645. Image - Supplies the image that has just been completely loaded.
  1646. Return Value:
  1647. None.
  1648. --*/
  1649. {
  1650. PIMAGE_STATIC_FUNCTION *ConstructorPointer;
  1651. PIMAGE_STATIC_FUNCTION *End;
  1652. PIMAGE_STATIC_FUNCTIONS StaticFunctions;
  1653. StaticFunctions = Image->StaticFunctions;
  1654. if (StaticFunctions == NULL) {
  1655. return;
  1656. }
  1657. //
  1658. // The executable is responsible for its own initialization.
  1659. //
  1660. if ((Image->LoadFlags & IMAGE_LOAD_FLAG_PRIMARY_EXECUTABLE) != 0) {
  1661. return;
  1662. }
  1663. //
  1664. // Call the .preinit_array functions.
  1665. //
  1666. ConstructorPointer = StaticFunctions->PreinitArray;
  1667. End = ((PVOID)ConstructorPointer) + StaticFunctions->PreinitArraySize;
  1668. while (ConstructorPointer < End) {
  1669. //
  1670. // Call the constructor function. Remember it's an array pointer, hence
  1671. // the extra dereference.
  1672. //
  1673. (*ConstructorPointer)();
  1674. ConstructorPointer += 1;
  1675. }
  1676. //
  1677. // Call the old school init function if it exists.
  1678. //
  1679. if (StaticFunctions->InitFunction != NULL) {
  1680. StaticFunctions->InitFunction();
  1681. }
  1682. //
  1683. // Call the .init_array functions.
  1684. //
  1685. ConstructorPointer = StaticFunctions->InitArray;
  1686. End = ((PVOID)ConstructorPointer) + StaticFunctions->InitArraySize;
  1687. while (ConstructorPointer < End) {
  1688. //
  1689. // Call the constructor function. Remember it's an array pointer, hence
  1690. // the extra dereference.
  1691. //
  1692. (*ConstructorPointer)();
  1693. ConstructorPointer += 1;
  1694. }
  1695. return;
  1696. }
  1697. PVOID
  1698. OspImResolvePltEntry (
  1699. PLOADED_IMAGE Image,
  1700. UINTN RelocationOffset
  1701. )
  1702. /*++
  1703. Routine Description:
  1704. This routine implements the slow path for a Procedure Linkable Table entry
  1705. that has not yet been resolved to its target function address. This routine
  1706. is only called once for each PLT entry, as subsequent calls jump directly
  1707. to the destination function address. This routine is called directly by
  1708. assembly, which takes care of the volatile register save/restore and
  1709. non C style return jump at the end.
  1710. Arguments:
  1711. Image - Supplies a pointer to the loaded image whose PLT needs resolution.
  1712. This is really whatever pointer is in GOT + 4.
  1713. RelocationOffset - Supplies the byte offset from the start of the
  1714. relocation section where the relocation for this PLT entry resides, or
  1715. the PLT index, depending on the architecture.
  1716. Return Value:
  1717. Returns a pointer to the function to jump to (in addition to writing that
  1718. address in the GOT at the appropriate spot).
  1719. --*/
  1720. {
  1721. PVOID FunctionAddress;
  1722. OspAcquireImageLock(FALSE);
  1723. FunctionAddress = ImResolvePltEntry(&OsLoadedImagesHead,
  1724. Image,
  1725. RelocationOffset);
  1726. OspReleaseImageLock();
  1727. return FunctionAddress;
  1728. }
  1729. KSTATUS
  1730. OspLoadInitialImageList (
  1731. BOOL Relocate
  1732. )
  1733. /*++
  1734. Routine Description:
  1735. This routine attempts to populate the initial image list with data
  1736. from the kernel.
  1737. Arguments:
  1738. Relocate - Supplies a boolean indicating whether or not the loaded images
  1739. should be relocated.
  1740. Return Value:
  1741. Status code.
  1742. --*/
  1743. {
  1744. PLOADED_IMAGE Executable;
  1745. ULONG Flags;
  1746. IMAGE_BUFFER ImageBuffer;
  1747. PLOADED_IMAGE Interpreter;
  1748. PLOADED_IMAGE OsLibrary;
  1749. PPROCESS_START_DATA StartData;
  1750. KSTATUS Status;
  1751. Interpreter = NULL;
  1752. ASSERT(OsLoadedImagesHead.Next == NULL);
  1753. INITIALIZE_LIST_HEAD(&OsLoadedImagesHead);
  1754. RtlZeroMemory(&ImageBuffer, sizeof(IMAGE_BUFFER));
  1755. StartData = OsEnvironment->StartData;
  1756. ImageBuffer.Size = MAX_UINTN;
  1757. ImageBuffer.Data = StartData->OsLibraryBase;
  1758. Status = ImAddImage(&ImageBuffer, &OsLibrary);
  1759. if (!KSUCCESS(Status)) {
  1760. goto LoadInitialImageListEnd;
  1761. }
  1762. OsLibrary->Flags |= IMAGE_FLAG_RELOCATED | IMAGE_FLAG_IMPORTS_LOADED;
  1763. INSERT_BEFORE(&(OsLibrary->ListEntry), &OsLoadedImagesHead);
  1764. OsLibrary->LoadFlags |= IMAGE_LOAD_FLAG_PRIMARY_LOAD;
  1765. OsLibrary->Debug.DynamicLinkerBase = StartData->InterpreterBase;
  1766. if ((StartData->InterpreterBase != NULL) &&
  1767. (StartData->InterpreterBase != StartData->OsLibraryBase)) {
  1768. ImageBuffer.Data = StartData->InterpreterBase;
  1769. Status = ImAddImage(&ImageBuffer, &Interpreter);
  1770. if (!KSUCCESS(Status)) {
  1771. goto LoadInitialImageListEnd;
  1772. }
  1773. INSERT_BEFORE(&(Interpreter->ListEntry), &OsLoadedImagesHead);
  1774. Interpreter->LoadFlags |= IMAGE_LOAD_FLAG_PRIMARY_LOAD;
  1775. }
  1776. ASSERT(StartData->ExecutableBase != StartData->InterpreterBase);
  1777. if (StartData->ExecutableBase != StartData->OsLibraryBase) {
  1778. ImageBuffer.Data = StartData->ExecutableBase;
  1779. Status = ImAddImage(&ImageBuffer, &Executable);
  1780. if (!KSUCCESS(Status)) {
  1781. goto LoadInitialImageListEnd;
  1782. }
  1783. INSERT_BEFORE(&(Executable->ListEntry), &OsLoadedImagesHead);
  1784. Executable->Debug.DynamicLinkerBase = StartData->InterpreterBase;
  1785. } else {
  1786. Executable = OsLibrary;
  1787. }
  1788. Executable->LoadFlags |= IMAGE_LOAD_FLAG_PRIMARY_LOAD |
  1789. IMAGE_LOAD_FLAG_PRIMARY_EXECUTABLE;
  1790. if (OspImGetEnvironmentVariable(LD_BIND_NOW) != NULL) {
  1791. Executable->LoadFlags |= IMAGE_LOAD_FLAG_BIND_NOW;
  1792. }
  1793. //
  1794. // If no relocations should be performed, another binary is taking care of
  1795. // the binary linking. If this library ever requires relocations to work
  1796. // properly, then relocate just the OS library image here.
  1797. //
  1798. if (Relocate != FALSE) {
  1799. Status = ImLoadImports(&OsLoadedImagesHead);
  1800. if (!KSUCCESS(Status)) {
  1801. RtlDebugPrint("Failed to load initial imports: %d\n", Status);
  1802. goto LoadInitialImageListEnd;
  1803. }
  1804. } else {
  1805. Flags = IMAGE_FLAG_IMPORTS_LOADED | IMAGE_FLAG_RELOCATED |
  1806. IMAGE_FLAG_INITIALIZED;
  1807. OsLibrary->Flags |= Flags;
  1808. if (Interpreter != NULL) {
  1809. Interpreter->Flags |= Flags;
  1810. }
  1811. if (Executable != NULL) {
  1812. Executable->Flags |= Flags;
  1813. }
  1814. }
  1815. Status = STATUS_SUCCESS;
  1816. LoadInitialImageListEnd:
  1817. return Status;
  1818. }
  1819. KSTATUS
  1820. OspImAssignModuleNumber (
  1821. PLOADED_IMAGE Image
  1822. )
  1823. /*++
  1824. Routine Description:
  1825. This routine attempts to assign the newly loaded module an image number.
  1826. Arguments:
  1827. Image - Supplies a pointer to the image to assign.
  1828. Return Value:
  1829. STATUS_SUCCESS on success.
  1830. STATUS_INSUFFICIENT_RESOURCES if an allocation failed.
  1831. --*/
  1832. {
  1833. UINTN Bitmap;
  1834. UINTN BlockIndex;
  1835. UINTN Index;
  1836. PUINTN NewBuffer;
  1837. UINTN NewCapacity;
  1838. ASSERT(Image->ModuleNumber == 0);
  1839. for (BlockIndex = 0;
  1840. BlockIndex < OsImModuleNumberBitmapSize;
  1841. BlockIndex += 1) {
  1842. Bitmap = OsImModuleNumberBitmap[BlockIndex];
  1843. for (Index = 0; Index < sizeof(UINTN) * BITS_PER_BYTE; Index += 1) {
  1844. if ((Bitmap & (1 << Index)) == 0) {
  1845. OsImModuleNumberBitmap[BlockIndex] |= 1 << Index;
  1846. Image->ModuleNumber =
  1847. (BlockIndex * (sizeof(UINTN) * BITS_PER_BYTE)) + Index;
  1848. if (Image->ModuleNumber > OsImModuleGeneration) {
  1849. OsImModuleGeneration += 1;
  1850. }
  1851. return STATUS_SUCCESS;
  1852. }
  1853. }
  1854. }
  1855. //
  1856. // Allocate more space.
  1857. //
  1858. NewCapacity = OsImModuleNumberBitmapSize * 2;
  1859. if (OsImModuleNumberBitmap == &OsImStaticModuleNumberBitmap) {
  1860. NewBuffer = OsHeapAllocate(NewCapacity * sizeof(UINTN),
  1861. OS_IMAGE_ALLOCATION_TAG);
  1862. } else {
  1863. NewBuffer = OsHeapReallocate(OsImModuleNumberBitmap,
  1864. NewCapacity * sizeof(UINTN),
  1865. OS_IMAGE_ALLOCATION_TAG);
  1866. }
  1867. if (NewBuffer == NULL) {
  1868. return STATUS_INSUFFICIENT_RESOURCES;
  1869. }
  1870. if (OsImModuleNumberBitmap == &OsImStaticModuleNumberBitmap) {
  1871. NewBuffer[0] = OsImModuleNumberBitmap[0];
  1872. }
  1873. RtlZeroMemory(NewBuffer + OsImModuleNumberBitmapSize,
  1874. (NewCapacity - OsImModuleNumberBitmapSize) * sizeof(UINTN));
  1875. Image->ModuleNumber = OsImModuleNumberBitmapSize * sizeof(UINTN) *
  1876. BITS_PER_BYTE;
  1877. OsImModuleNumberBitmap[OsImModuleNumberBitmapSize] = 1;
  1878. if (Image->ModuleNumber > OsImModuleGeneration) {
  1879. OsImModuleGeneration += 1;
  1880. }
  1881. OsImModuleNumberBitmap = NewBuffer;
  1882. OsImModuleNumberBitmapSize = NewCapacity;
  1883. return STATUS_SUCCESS;
  1884. }
  1885. VOID
  1886. OspImReleaseModuleNumber (
  1887. PLOADED_IMAGE Image
  1888. )
  1889. /*++
  1890. Routine Description:
  1891. This routine releases the module number assigned to the loaded image.
  1892. Arguments:
  1893. Image - Supplies a pointer to the image to release.
  1894. Return Value:
  1895. None.
  1896. --*/
  1897. {
  1898. UINTN BlockIndex;
  1899. UINTN BlockOffset;
  1900. ASSERT((Image->ModuleNumber != 0) &&
  1901. (Image->ModuleNumber <
  1902. OsImModuleNumberBitmapSize * sizeof(UINTN) * BITS_PER_BYTE));
  1903. BlockIndex = Image->ModuleNumber / (sizeof(UINTN) * BITS_PER_BYTE);
  1904. BlockOffset = Image->ModuleNumber % (sizeof(UINTN) * BITS_PER_BYTE);
  1905. OsImModuleNumberBitmap[BlockIndex] &= ~(1 << BlockOffset);
  1906. Image->ModuleNumber = 0;
  1907. return;
  1908. }