image.c 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287
  1. /*++
  2. Copyright (c) 2012 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. image.c
  5. Abstract:
  6. This module implements image loading functionality, forking off most of the
  7. work to the individual file format functions.
  8. Author:
  9. Evan Green 13-Oct-2012
  10. Environment:
  11. Kernel/Boot/Build
  12. --*/
  13. //
  14. // ------------------------------------------------------------------- Includes
  15. //
  16. #include "imp.h"
  17. #include "pe.h"
  18. #include "elf.h"
  19. //
  20. // --------------------------------------------------------------------- Macros
  21. //
  22. //
  23. // This macro subtracts a value from a pointer.
  24. //
  25. #define POINTER_SUBTRACT(_Pointer, _Value) (PVOID)((UINTN)(_Pointer) - (_Value))
  26. //
  27. // This macro adds a value to a pointer.
  28. //
  29. #define POINTER_ADD(_Pointer, _Value) (PVOID)((UINTN)(_Pointer) + (_Value))
  30. //
  31. // ---------------------------------------------------------------- Definitions
  32. //
  33. //
  34. // ----------------------------------------------- Internal Function Prototypes
  35. //
  36. KSTATUS
  37. ImpOpenLibrary (
  38. PLIST_ENTRY ListHead,
  39. PLOADED_IMAGE Parent,
  40. PVOID SystemContext,
  41. PSTR BinaryName,
  42. PIMAGE_FILE_INFORMATION File,
  43. PSTR *Path
  44. );
  45. KSTATUS
  46. ImpGetImageSize (
  47. PLIST_ENTRY ListHead,
  48. PLOADED_IMAGE Image,
  49. PIMAGE_BUFFER Buffer,
  50. PSTR *InterpreterPath
  51. );
  52. KSTATUS
  53. ImpLoadImage (
  54. PLIST_ENTRY ListHead,
  55. PLOADED_IMAGE Image,
  56. PIMAGE_BUFFER Buffer
  57. );
  58. KSTATUS
  59. ImpAddImage (
  60. PIMAGE_BUFFER ImageBuffer,
  61. PLOADED_IMAGE Image
  62. );
  63. KSTATUS
  64. ImpOpenImport (
  65. PLIST_ENTRY ListHead,
  66. PLOADED_IMAGE Parent,
  67. PVOID SystemContext,
  68. PSTR BinaryName,
  69. PIMAGE_FILE_INFORMATION File,
  70. PSTR *Path
  71. );
  72. VOID
  73. ImpUnloadImage (
  74. PLOADED_IMAGE Image
  75. );
  76. KSTATUS
  77. ImpGetSymbolByName (
  78. PLOADED_IMAGE Image,
  79. PSTR SymbolName,
  80. ULONG RecursionLevel,
  81. ULONG VisitMarker,
  82. PIMAGE_SYMBOL Symbol
  83. );
  84. KSTATUS
  85. ImpGetSymbolByAddress (
  86. PLOADED_IMAGE Image,
  87. PVOID Address,
  88. ULONG RecursionLevel,
  89. ULONG VisitMarker,
  90. PIMAGE_SYMBOL Symbol
  91. );
  92. VOID
  93. ImpRelocateSelf (
  94. PIMAGE_BUFFER Buffer,
  95. PLOADED_IMAGE Image
  96. );
  97. PLOADED_IMAGE
  98. ImpFindImageByLibraryName (
  99. PLIST_ENTRY ListHead,
  100. PSTR Name
  101. );
  102. PLOADED_IMAGE
  103. ImpFindImageByFile (
  104. PLIST_ENTRY ListHead,
  105. PIMAGE_FILE_INFORMATION File
  106. );
  107. PLOADED_IMAGE
  108. ImpAllocateImage (
  109. VOID
  110. );
  111. //
  112. // ------------------------------------------------------ Data Type Definitions
  113. //
  114. //
  115. // -------------------------------------------------------------------- Globals
  116. //
  117. //
  118. // Define the table of functions called by the image library.
  119. //
  120. PIM_IMPORT_TABLE ImImportTable = NULL;
  121. //
  122. // Store the last visit marker.
  123. //
  124. UCHAR ImLastVisitMarker;
  125. //
  126. // ------------------------------------------------------------------ Functions
  127. //
  128. KSTATUS
  129. ImInitialize (
  130. PIM_IMPORT_TABLE ImportTable
  131. )
  132. /*++
  133. Routine Description:
  134. This routine initializes the image library. It must be called before any
  135. other image library routines are called.
  136. Arguments:
  137. ImportTable - Supplies a pointer to a table of functions that will be used
  138. by the image library to provide basic memory allocation and loading
  139. support. This memory must stick around, the given pointer is cached.
  140. Return Value:
  141. STATUS_SUCCESS on success.
  142. STATUS_TOO_LATE if the image library has already been initialized.
  143. STATUS_INVALID_PARAMETER if one of the required functions is not
  144. implemented.
  145. --*/
  146. {
  147. if (ImImportTable != NULL) {
  148. return STATUS_TOO_LATE;
  149. }
  150. ImImportTable = ImportTable;
  151. return STATUS_SUCCESS;
  152. }
  153. KSTATUS
  154. ImGetExecutableFormat (
  155. PSTR BinaryName,
  156. PVOID SystemContext,
  157. PIMAGE_FILE_INFORMATION ImageFile,
  158. PIMAGE_BUFFER ImageBuffer,
  159. PIMAGE_FORMAT Format
  160. )
  161. /*++
  162. Routine Description:
  163. This routine determines the executable format of a given image path.
  164. Arguments:
  165. BinaryName - Supplies the name of the binary executable image to examine.
  166. SystemContext - Supplies the context pointer passed to the load executable
  167. function.
  168. ImageFile - Supplies an optional pointer where the file handle and other
  169. information will be returned on success.
  170. ImageBuffer - Supplies an optional pointer where the image buffer
  171. information will be returned.
  172. Format - Supplies a pointer where the format will be returned on success.
  173. Return Value:
  174. Status code.
  175. --*/
  176. {
  177. ULONG BinaryNameLength;
  178. IMAGE_BUFFER Buffer;
  179. IMAGE_FILE_INFORMATION File;
  180. KSTATUS Status;
  181. File.Handle = INVALID_HANDLE;
  182. RtlZeroMemory(&Buffer, sizeof(IMAGE_BUFFER));
  183. BinaryNameLength = RtlStringLength(BinaryName);
  184. if (BinaryNameLength == 0) {
  185. Status = STATUS_INVALID_PARAMETER;
  186. goto GetExecutableFormatEnd;
  187. }
  188. //
  189. // Load the file contents into memory.
  190. //
  191. Status = ImpOpenLibrary(NULL, NULL, SystemContext, BinaryName, &File, NULL);
  192. if (!KSUCCESS(Status)) {
  193. goto GetExecutableFormatEnd;
  194. }
  195. Status = ImReadFile(&File,
  196. 0,
  197. IMAGE_INITIAL_READ_SIZE,
  198. &Buffer);
  199. if (!KSUCCESS(Status)) {
  200. goto GetExecutableFormatEnd;
  201. }
  202. //
  203. // Determine the file format.
  204. //
  205. *Format = ImGetImageFormat(&Buffer);
  206. if ((*Format == ImageInvalidFormat) || (*Format == ImageUnknownFormat)) {
  207. Status = STATUS_UNKNOWN_IMAGE_FORMAT;
  208. goto GetExecutableFormatEnd;
  209. }
  210. Status = STATUS_SUCCESS;
  211. GetExecutableFormatEnd:
  212. if (((!KSUCCESS(Status)) || (ImageBuffer == NULL)) &&
  213. (Buffer.Data != NULL)) {
  214. ImUnloadBuffer(&File, &Buffer);
  215. Buffer.Data = NULL;
  216. }
  217. if (((!KSUCCESS(Status)) || (ImageFile == NULL)) &&
  218. (File.Handle != INVALID_HANDLE)) {
  219. ImCloseFile(&File);
  220. File.Handle = INVALID_HANDLE;
  221. }
  222. if (ImageFile != NULL) {
  223. RtlCopyMemory(ImageFile, &File, sizeof(IMAGE_FILE_INFORMATION));
  224. }
  225. if (ImageBuffer != NULL) {
  226. RtlCopyMemory(ImageBuffer, &Buffer, sizeof(IMAGE_BUFFER));
  227. }
  228. return Status;
  229. }
  230. KSTATUS
  231. ImLoad (
  232. PLIST_ENTRY ListHead,
  233. PSTR BinaryName,
  234. PIMAGE_FILE_INFORMATION BinaryFile,
  235. PIMAGE_BUFFER ImageBuffer,
  236. PVOID SystemContext,
  237. ULONG Flags,
  238. PLOADED_IMAGE *LoadedImage,
  239. PLOADED_IMAGE *Interpreter
  240. )
  241. /*++
  242. Routine Description:
  243. This routine loads an executable image into memory.
  244. Arguments:
  245. ListHead - Supplies a pointer to the head of the list of loaded images.
  246. BinaryName - Supplies the name of the binary executable image to load. If
  247. this is NULL, then a pointer to the first (primary) image loaded, with
  248. a reference added.
  249. BinaryFile - Supplies an optional handle to the file information. The
  250. handle should be positioned to the beginning of the file. Supply NULL
  251. if the caller does not already have an open handle to the binary. On
  252. success, the image library takes ownership of the handle.
  253. ImageBuffer - Supplies an optional pointer to the image buffer. This can
  254. be a complete image file buffer, or just a partial load of the file.
  255. SystemContext - Supplies an opaque token that will be passed to the
  256. support functions called by the image support library.
  257. Flags - Supplies a bitfield of flags governing the load. See
  258. IMAGE_LOAD_FLAG_* flags.
  259. LoadedImage - Supplies an optional pointer where a pointer to the loaded
  260. image structure will be returned on success.
  261. Interpreter - Supplies an optional pointer where a pointer to the loaded
  262. interpreter structure will be returned on success.
  263. Return Value:
  264. Status code.
  265. --*/
  266. {
  267. KSTATUS Status;
  268. Status = ImpLoad(ListHead,
  269. BinaryName,
  270. BinaryFile,
  271. ImageBuffer,
  272. SystemContext,
  273. Flags,
  274. NULL,
  275. LoadedImage,
  276. Interpreter);
  277. return Status;
  278. }
  279. KSTATUS
  280. ImAddImage (
  281. PIMAGE_BUFFER Buffer,
  282. PLOADED_IMAGE *LoadedImage
  283. )
  284. /*++
  285. Routine Description:
  286. This routine adds the accounting structures for an image that has already
  287. been loaded into memory.
  288. Arguments:
  289. Buffer - Supplies the image buffer containing the loaded image.
  290. LoadedImage - Supplies an optional pointer where a pointer to the loaded
  291. image structure will be returned on success.
  292. Return Value:
  293. Status code.
  294. --*/
  295. {
  296. PLOADED_IMAGE Image;
  297. KSTATUS Status;
  298. Image = ImpAllocateImage();
  299. if (Image == NULL) {
  300. Status = STATUS_INSUFFICIENT_RESOURCES;
  301. goto AddImageEnd;
  302. }
  303. Image->Format = ImGetImageFormat(Buffer);
  304. Image->LoadedImageBuffer = Buffer->Data;
  305. Image->File.Size = Buffer->Size;
  306. Status = ImpAddImage(Buffer, Image);
  307. //
  308. // Set the file name equal to the library name so there's at least
  309. // something to go off of.
  310. //
  311. Image->FileName = Image->LibraryName;
  312. AddImageEnd:
  313. if (!KSUCCESS(Status)) {
  314. if (Image != NULL) {
  315. ImFreeMemory(Image);
  316. Image = NULL;
  317. }
  318. }
  319. if (LoadedImage != NULL) {
  320. *LoadedImage = Image;
  321. }
  322. return Status;
  323. }
  324. KSTATUS
  325. ImLoadImports (
  326. PLIST_ENTRY ListHead
  327. )
  328. /*++
  329. Routine Description:
  330. This routine loads all import libraries for a given image list.
  331. Arguments:
  332. ListHead - Supplies a pointer to the head of the list of loaded images to
  333. load import libraries for.
  334. Return Value:
  335. Status code.
  336. --*/
  337. {
  338. PLOADED_IMAGE FirstImage;
  339. KSTATUS Status;
  340. if (LIST_EMPTY(ListHead)) {
  341. return STATUS_SUCCESS;
  342. }
  343. FirstImage = LIST_VALUE(ListHead->Next, LOADED_IMAGE, ListEntry);
  344. switch (FirstImage->Format) {
  345. case ImagePe32:
  346. Status = STATUS_SUCCESS;
  347. break;
  348. case ImageElf32:
  349. Status = ImpElf32LoadAllImports(ListHead);
  350. break;
  351. default:
  352. ASSERT(FALSE);
  353. Status = STATUS_FILE_CORRUPT;
  354. break;
  355. }
  356. return Status;
  357. }
  358. KSTATUS
  359. ImRelocateImages (
  360. PLIST_ENTRY ListHead
  361. )
  362. /*++
  363. Routine Description:
  364. This routine relocates all images that have not yet been relocated on the
  365. given list.
  366. Arguments:
  367. ListHead - Supplies a pointer to the head of the list of loaded images to
  368. apply relocations for.
  369. Return Value:
  370. Status code.
  371. --*/
  372. {
  373. PLOADED_IMAGE FirstImage;
  374. KSTATUS Status;
  375. if (LIST_EMPTY(ListHead)) {
  376. return STATUS_SUCCESS;
  377. }
  378. FirstImage = LIST_VALUE(ListHead->Next, LOADED_IMAGE, ListEntry);
  379. switch (FirstImage->Format) {
  380. case ImagePe32:
  381. Status = STATUS_SUCCESS;
  382. break;
  383. case ImageElf32:
  384. Status = ImpElf32RelocateImages(ListHead);
  385. break;
  386. default:
  387. ASSERT(FALSE);
  388. Status = STATUS_FILE_CORRUPT;
  389. break;
  390. }
  391. return Status;
  392. }
  393. VOID
  394. ImImageAddReference (
  395. PLOADED_IMAGE Image
  396. )
  397. /*++
  398. Routine Description:
  399. This routine increments the reference count on an image.
  400. Arguments:
  401. Image - Supplies a pointer to the loaded image.
  402. Return Value:
  403. None.
  404. --*/
  405. {
  406. ASSERT((Image->ReferenceCount != 0) &&
  407. (Image->ReferenceCount <= 0x10000000));
  408. RtlAtomicAdd32(&(Image->ReferenceCount), 1);
  409. return;
  410. }
  411. VOID
  412. ImImageReleaseReference (
  413. PLOADED_IMAGE Image
  414. )
  415. /*++
  416. Routine Description:
  417. This routine releases a reference on a loaded executable image from memory.
  418. If this is the last reference, the image will be unloaded.
  419. Arguments:
  420. Image - Supplies a pointer to the loaded image.
  421. Return Value:
  422. None.
  423. --*/
  424. {
  425. ASSERT((Image->ReferenceCount != 0) &&
  426. (Image->ReferenceCount <= 0x10000000));
  427. if (RtlAtomicAdd32(&(Image->ReferenceCount), -1) != 1) {
  428. return;
  429. }
  430. ImNotifyImageUnload(Image);
  431. ImpUnloadImage(Image);
  432. LIST_REMOVE(&(Image->ListEntry));
  433. if (Image->AllocatorHandle != INVALID_HANDLE) {
  434. ImFreeAddressSpace(Image);
  435. }
  436. if (Image->File.Handle != INVALID_HANDLE) {
  437. ImCloseFile(&(Image->File));
  438. }
  439. if (Image->FileName != NULL) {
  440. ImFreeMemory(Image->FileName);
  441. }
  442. ImFreeMemory(Image);
  443. return;
  444. }
  445. KSTATUS
  446. ImGetImageInformation (
  447. PIMAGE_BUFFER Buffer,
  448. PIMAGE_INFORMATION Information
  449. )
  450. /*++
  451. Routine Description:
  452. This routine gets various pieces of information about an image. This is the
  453. generic form that can get information from any supported image type.
  454. Arguments:
  455. Buffer - Supplies a pointer to the image buffer.
  456. Information - Supplies a pointer to the information structure that will be
  457. filled out by this function. It is assumed the memory pointed to here
  458. is valid.
  459. Return Value:
  460. STATUS_SUCCESS on success.
  461. STATUS_UNKNOWN_IMAGE_FORMAT if the image is unknown or corrupt.
  462. --*/
  463. {
  464. LOADED_IMAGE Image;
  465. BOOL IsPeImage;
  466. PIMAGE_NT_HEADERS PeHeaders;
  467. KSTATUS Status;
  468. Status = STATUS_UNKNOWN_IMAGE_FORMAT;
  469. RtlZeroMemory(Information, sizeof(IMAGE_INFORMATION));
  470. //
  471. // Attempt to get image information for a PE image.
  472. //
  473. IsPeImage = ImpPeGetHeaders(Buffer, &PeHeaders);
  474. if (IsPeImage != FALSE) {
  475. Information->Format = ImagePe32;
  476. Information->ImageBase = PeHeaders->OptionalHeader.ImageBase;
  477. if (PeHeaders->FileHeader.Machine == IMAGE_FILE_MACHINE_I386) {
  478. Information->Machine = ImageMachineTypeX86;
  479. } else if (PeHeaders->FileHeader.Machine == IMAGE_FILE_MACHINE_ARMT) {
  480. Information->Machine = ImageMachineTypeArm32;
  481. } else {
  482. Information->Machine = ImageMachineTypeUnknown;
  483. }
  484. Information->EntryPoint = PeHeaders->OptionalHeader.AddressOfEntryPoint;
  485. Status = STATUS_SUCCESS;
  486. goto GetImageInformationEnd;
  487. }
  488. RtlZeroMemory(&Image, sizeof(LOADED_IMAGE));
  489. Status = ImpElf32GetImageSize(NULL, &Image, Buffer, NULL);
  490. if (KSUCCESS(Status)) {
  491. Information->Format = Image.Format;
  492. Information->Machine = Image.Machine;
  493. Information->EntryPoint = (ULONG)(Image.EntryPoint);
  494. Information->ImageBase = (UINTN)(Image.PreferredLowestAddress);
  495. goto GetImageInformationEnd;
  496. }
  497. GetImageInformationEnd:
  498. return Status;
  499. }
  500. BOOL
  501. ImGetImageSection (
  502. PIMAGE_BUFFER Buffer,
  503. PSTR SectionName,
  504. PVOID *Section,
  505. PULONGLONG VirtualAddress,
  506. PULONG SectionSizeInFile,
  507. PULONG SectionSizeInMemory
  508. )
  509. /*++
  510. Routine Description:
  511. This routine gets a pointer to the given section in a PE image given a
  512. memory mapped file.
  513. Arguments:
  514. Buffer - Supplies a pointer to the image buffer.
  515. SectionName - Supplies the name of the desired section.
  516. Section - Supplies a pointer where the pointer to the section will be
  517. returned.
  518. VirtualAddress - Supplies a pointer where the virtual address of the section
  519. will be returned, if applicable.
  520. SectionSizeInFile - Supplies a pointer where the size of the section as it
  521. appears in the file will be returned.
  522. SectionSizeInMemory - Supplies a pointer where the size of the section as it
  523. appears after being loaded in memory will be returned.
  524. Return Value:
  525. TRUE on success.
  526. FALSE otherwise.
  527. --*/
  528. {
  529. IMAGE_FORMAT Format;
  530. Format = ImGetImageFormat(Buffer);
  531. switch (Format) {
  532. case ImagePe32:
  533. return ImpPeGetSection(Buffer,
  534. SectionName,
  535. Section,
  536. VirtualAddress,
  537. SectionSizeInFile,
  538. SectionSizeInMemory);
  539. case ImageElf32:
  540. return ImpElf32GetSection(Buffer,
  541. SectionName,
  542. Section,
  543. VirtualAddress,
  544. SectionSizeInFile,
  545. SectionSizeInMemory);
  546. default:
  547. break;
  548. }
  549. //
  550. // The image format is unknown or invalid.
  551. //
  552. return FALSE;
  553. }
  554. IMAGE_FORMAT
  555. ImGetImageFormat (
  556. PIMAGE_BUFFER Buffer
  557. )
  558. /*++
  559. Routine Description:
  560. This routine determines the file format for an image mapped in memory.
  561. Arguments:
  562. Buffer - Supplies a pointer to the image buffer to determine the type of.
  563. Return Value:
  564. Returns the file format of the image.
  565. --*/
  566. {
  567. PELF32_HEADER ElfHeader;
  568. BOOL IsElfImage;
  569. BOOL IsPeImage;
  570. PIMAGE_NT_HEADERS PeHeaders;
  571. //
  572. // Attempt to get the ELF image header.
  573. //
  574. IsElfImage = ImpElf32GetHeader(Buffer, &ElfHeader);
  575. if (IsElfImage != FALSE) {
  576. return ImageElf32;
  577. }
  578. //
  579. // Attempt to get the PE image headers.
  580. //
  581. IsPeImage = ImpPeGetHeaders(Buffer, &PeHeaders);
  582. if (IsPeImage != FALSE) {
  583. return ImagePe32;
  584. }
  585. //
  586. // Unknown image format.
  587. //
  588. return ImageUnknownFormat;
  589. }
  590. KSTATUS
  591. ImGetSymbolByName (
  592. PLOADED_IMAGE Image,
  593. PSTR SymbolName,
  594. BOOL Recursive,
  595. PIMAGE_SYMBOL Symbol
  596. )
  597. /*++
  598. Routine Description:
  599. This routine attempts to find an exported symbol with the given name in the
  600. given binary. This routine also looks through the image imports if the
  601. recursive flag is specified.
  602. Arguments:
  603. Image - Supplies a pointer to the image to query.
  604. SymbolName - Supplies a pointer to the string containing the name of the
  605. symbol to search for.
  606. Recursive - Supplies a boolean indicating if the routine should recurse
  607. into imports or just query this binary.
  608. Symbol - Supplies a pointer to a structure that receives the symbol's
  609. information on success.
  610. Return Value:
  611. Status code.
  612. --*/
  613. {
  614. ULONG RecursionLevel;
  615. KSTATUS Status;
  616. UCHAR VisitMarker;
  617. //
  618. // Get a new visitor generation number. This means only one thread can be
  619. // in here at a time.
  620. //
  621. ImLastVisitMarker += 1;
  622. VisitMarker = ImLastVisitMarker;
  623. RecursionLevel = 0;
  624. if (Recursive == FALSE) {
  625. RecursionLevel = MAX_IMPORT_RECURSION_DEPTH;
  626. }
  627. Status = ImpGetSymbolByName(Image,
  628. SymbolName,
  629. RecursionLevel,
  630. VisitMarker,
  631. Symbol);
  632. return Status;
  633. }
  634. KSTATUS
  635. ImGetSymbolByAddress (
  636. PLOADED_IMAGE Image,
  637. PVOID Address,
  638. BOOL Recursive,
  639. PIMAGE_SYMBOL Symbol
  640. )
  641. /*++
  642. Routine Description:
  643. This routine attempts to resolve the given address into a symbol. This
  644. routine also looks through the image imports if the recursive flag is
  645. specified.
  646. Arguments:
  647. Image - Supplies a pointer to the image to query.
  648. Address - Supplies the address to search for.
  649. Recursive - Supplies a boolean indicating if the routine should recurse
  650. into imports or just query this binary.
  651. Symbol - Supplies a pointer to a structure that receives the address's
  652. symbol information on success.
  653. Return Value:
  654. Status code.
  655. --*/
  656. {
  657. ULONG RecursionLevel;
  658. KSTATUS Status;
  659. UCHAR VisitMarker;
  660. //
  661. // Toggle between two values that are not the default. This means only one
  662. // thread can be in here at a time.
  663. //
  664. ImLastVisitMarker += 1;
  665. VisitMarker = ImLastVisitMarker;
  666. RecursionLevel = 0;
  667. if (Recursive == FALSE) {
  668. RecursionLevel = MAX_IMPORT_RECURSION_DEPTH;
  669. }
  670. Status = ImpGetSymbolByAddress(Image,
  671. Address,
  672. RecursionLevel,
  673. VisitMarker,
  674. Symbol);
  675. return Status;
  676. }
  677. VOID
  678. ImRelocateSelf (
  679. PVOID Base
  680. )
  681. /*++
  682. Routine Description:
  683. This routine relocates the currently running image.
  684. Arguments:
  685. Base - Supplies a pointer to the base of the loaded image.
  686. Return Value:
  687. None.
  688. --*/
  689. {
  690. IMAGE_BUFFER Buffer;
  691. LOADED_IMAGE FakeImage;
  692. Buffer.Context = NULL;
  693. Buffer.Data = Base;
  694. Buffer.Size = -1;
  695. RtlZeroMemory(&FakeImage, sizeof(LOADED_IMAGE));
  696. FakeImage.Format = ImGetImageFormat(&Buffer);
  697. ImpRelocateSelf(&Buffer, &FakeImage);
  698. return;
  699. }
  700. PVOID
  701. ImResolvePltEntry (
  702. PLIST_ENTRY ListHead,
  703. PLOADED_IMAGE Image,
  704. UINTN RelocationOffset
  705. )
  706. /*++
  707. Routine Description:
  708. This routine implements the slow path for a Procedure Linkable Table entry
  709. that has not yet been resolved to its target function address. This routine
  710. is only called once for each PLT entry, as subsequent calls jump directly
  711. to the destination function address. It resolves the appropriate GOT
  712. relocation and returns a pointer to the function to jump to.
  713. Arguments:
  714. ListHead - Supplies a pointer to the head of the list of images to use for
  715. symbol resolution.
  716. Image - Supplies a pointer to the loaded image whose PLT needs resolution.
  717. This is really whatever pointer is in GOT + 4.
  718. RelocationOffset - Supplies the byte offset from the start of the
  719. relocation section where the relocation for this PLT entry resides, or
  720. the PLT index, depending on the architecture.
  721. Return Value:
  722. Returns a pointer to the function to jump to (in addition to writing that
  723. address in the GOT at the appropriate spot).
  724. --*/
  725. {
  726. PVOID FunctionAddress;
  727. switch (Image->Format) {
  728. case ImageElf32:
  729. FunctionAddress = ImpElf32ResolvePltEntry(ListHead,
  730. Image,
  731. RelocationOffset);
  732. break;
  733. default:
  734. ASSERT(FALSE);
  735. FunctionAddress = NULL;
  736. break;
  737. }
  738. return FunctionAddress;
  739. }
  740. PVOID
  741. ImpReadBuffer (
  742. PIMAGE_FILE_INFORMATION File,
  743. PIMAGE_BUFFER Buffer,
  744. UINTN Offset,
  745. UINTN Size
  746. )
  747. /*++
  748. Routine Description:
  749. This routine handles access to an image buffer.
  750. Arguments:
  751. File - Supplies an optional pointer to the file information, if the buffer
  752. may need to be resized.
  753. Buffer - Supplies a pointer to the buffer to read from.
  754. Offset - Supplies the offset from the start of the file to read.
  755. Size - Supplies the required size.
  756. Return Value:
  757. Returns a pointer to the image file at the requested offset on success.
  758. NULL if the range is invalid or the file could not be fully loaded.
  759. --*/
  760. {
  761. UINTN End;
  762. KSTATUS Status;
  763. End = Offset + Size;
  764. if (Offset > End) {
  765. return NULL;
  766. }
  767. //
  768. // In most cases, the buffer can satisfy the request.
  769. //
  770. if ((Buffer->Data != NULL) &&
  771. (Offset < Buffer->Size) &&
  772. (End <= Buffer->Size)) {
  773. return Buffer->Data + Offset;
  774. }
  775. //
  776. // If there's no file, buffer is already the entire file, or the entire
  777. // file wouldn't satisfy the request, fail.
  778. //
  779. if ((File == NULL) || (Buffer->Size == File->Size) || (End > File->Size)) {
  780. return NULL;
  781. }
  782. //
  783. // Unload the current buffer.
  784. //
  785. ImUnloadBuffer(File, Buffer);
  786. RtlZeroMemory(Buffer, sizeof(IMAGE_BUFFER));
  787. //
  788. // Load up the whole file.
  789. //
  790. Status = ImLoadFile(File, Buffer);
  791. if (!KSUCCESS(Status)) {
  792. RtlDebugPrint("Failed to load file: %d\n", Status);
  793. return NULL;
  794. }
  795. ASSERT(End <= Buffer->Size);
  796. return Buffer->Data + Offset;
  797. }
  798. KSTATUS
  799. ImpLoad (
  800. PLIST_ENTRY ListHead,
  801. PSTR BinaryName,
  802. PIMAGE_FILE_INFORMATION BinaryFile,
  803. PIMAGE_BUFFER ImageBuffer,
  804. PVOID SystemContext,
  805. ULONG Flags,
  806. PLOADED_IMAGE Parent,
  807. PLOADED_IMAGE *LoadedImage,
  808. PLOADED_IMAGE *Interpreter
  809. )
  810. /*++
  811. Routine Description:
  812. This routine loads an executable image into memory.
  813. Arguments:
  814. ListHead - Supplies a pointer to the head of the list of loaded images.
  815. BinaryName - Supplies the name of the binary executable image to load. If
  816. this is NULL, then a pointer to the first (primary) image loaded, with
  817. a reference added.
  818. BinaryFile - Supplies an optional handle to the file information. The
  819. handle should be positioned to the beginning of the file. Supply NULL
  820. if the caller does not already have an open handle to the binary. On
  821. success, the image library takes ownership of the handle.
  822. ImageBuffer - Supplies an optional pointer to the image buffer. This can
  823. be a complete image file buffer, or just a partial load of the file.
  824. SystemContext - Supplies an opaque token that will be passed to the
  825. support functions called by the image support library.
  826. Flags - Supplies a bitfield of flags governing the load. See
  827. IMAGE_LOAD_FLAG_* flags.
  828. Parent - Supplies an optional pointer to the parent image that imports this
  829. image.
  830. LoadedImage - Supplies an optional pointer where a pointer to the loaded
  831. image structure will be returned on success.
  832. Interpreter - Supplies an optional pointer where a pointer to the loaded
  833. interpreter structure will be returned on success.
  834. Return Value:
  835. Status code.
  836. --*/
  837. {
  838. ULONG BinaryNameLength;
  839. PLOADED_IMAGE ExistingImage;
  840. PLOADED_IMAGE Image;
  841. PLOADED_IMAGE InterpreterImage;
  842. PSTR InterpreterPath;
  843. IMAGE_BUFFER LocalImageBuffer;
  844. KSTATUS Status;
  845. Image = NULL;
  846. InterpreterImage = NULL;
  847. RtlZeroMemory(&LocalImageBuffer, sizeof(IMAGE_BUFFER));
  848. //
  849. // If the primary executable flag is set, also set the primary load flag.
  850. // The difference is that the primary executable flag is set only on the
  851. // executable itself, whereas the primary load flag is set on the primary
  852. // executable and any dynamic libraries loaded to satisfy dependencies
  853. // during this process.
  854. //
  855. if ((Flags & IMAGE_LOAD_FLAG_PRIMARY_EXECUTABLE) != 0) {
  856. Flags |= IMAGE_LOAD_FLAG_PRIMARY_LOAD;
  857. }
  858. //
  859. // If the name is NULL, return the primary executable.
  860. //
  861. if (BinaryName == NULL) {
  862. ASSERT((Flags & IMAGE_LOAD_FLAG_PRIMARY_EXECUTABLE) == 0);
  863. Image = ImpGetPrimaryExecutable(ListHead);
  864. if (Image == NULL) {
  865. Status = STATUS_NOT_READY;
  866. goto LoadEnd;
  867. }
  868. ImImageAddReference(Image);
  869. Status = STATUS_SUCCESS;
  870. goto LoadEnd;
  871. }
  872. BinaryNameLength = RtlStringLength(BinaryName);
  873. if (BinaryNameLength == 0) {
  874. Status = STATUS_INVALID_PARAMETER;
  875. goto LoadEnd;
  876. }
  877. //
  878. // See if the image is already loaded, and return if so.
  879. //
  880. Image = ImpFindImageByLibraryName(ListHead, BinaryName);
  881. if (Image != NULL) {
  882. ImImageAddReference(Image);
  883. Status = STATUS_SUCCESS;
  884. goto LoadEnd;
  885. }
  886. //
  887. // Allocate space for the loaded image structure.
  888. //
  889. Image = ImpAllocateImage();
  890. if (Image == NULL) {
  891. Status = STATUS_INSUFFICIENT_RESOURCES;
  892. goto LoadEnd;
  893. }
  894. Image->SystemContext = SystemContext;
  895. if (Parent != NULL) {
  896. ASSERT((Flags & IMAGE_LOAD_FLAG_IGNORE_INTERPRETER) != 0);
  897. Image->Parent = Parent;
  898. Image->ImportDepth = Parent->ImportDepth + 1;
  899. }
  900. Image->LoadFlags = Flags;
  901. //
  902. // Open up the file.
  903. //
  904. if (BinaryFile != NULL) {
  905. RtlCopyMemory(&(Image->File),
  906. BinaryFile,
  907. sizeof(IMAGE_FILE_INFORMATION));
  908. Image->FileName = ImAllocateMemory(BinaryNameLength + 1,
  909. IM_ALLOCATION_TAG);
  910. if (Image->FileName == NULL) {
  911. Status = STATUS_INSUFFICIENT_RESOURCES;
  912. goto LoadEnd;
  913. }
  914. RtlCopyMemory(Image->FileName, BinaryName, BinaryNameLength + 1);
  915. } else {
  916. Status = ImpOpenLibrary(ListHead,
  917. Parent,
  918. SystemContext,
  919. BinaryName,
  920. &(Image->File),
  921. &(Image->FileName));
  922. if (!KSUCCESS(Status)) {
  923. goto LoadEnd;
  924. }
  925. //
  926. // The library is open, and the real path has been found. Search
  927. // for an already loaded library with the same absolute path.
  928. //
  929. ExistingImage = ImpFindImageByFile(ListHead, &(Image->File));
  930. if (ExistingImage != NULL) {
  931. ImCloseFile(&(Image->File));
  932. ImFreeMemory(Image->FileName);
  933. ImFreeMemory(Image);
  934. Image = ExistingImage;
  935. ImImageAddReference(Image);
  936. Status = STATUS_SUCCESS;
  937. goto LoadEnd;
  938. }
  939. }
  940. if (ImageBuffer == NULL) {
  941. //
  942. // In a load-only scenario, just try to do a small read of the file
  943. // contents. Otherwise, just map the whole file.
  944. //
  945. if ((Flags & IMAGE_LOAD_FLAG_LOAD_ONLY) != 0) {
  946. Status = ImReadFile(&(Image->File),
  947. 0,
  948. IMAGE_INITIAL_READ_SIZE,
  949. &LocalImageBuffer);
  950. } else {
  951. Status = ImLoadFile(&(Image->File), &LocalImageBuffer);
  952. }
  953. if (!KSUCCESS(Status)) {
  954. goto LoadEnd;
  955. }
  956. ImageBuffer = &LocalImageBuffer;
  957. }
  958. //
  959. // Determine the file format.
  960. //
  961. Image->Format = ImGetImageFormat(ImageBuffer);
  962. if ((Image->Format == ImageInvalidFormat) ||
  963. (Image->Format == ImageUnknownFormat)) {
  964. Status = STATUS_UNKNOWN_IMAGE_FORMAT;
  965. goto LoadEnd;
  966. }
  967. //
  968. // Determine the image size and preferred VA.
  969. //
  970. Status = ImpGetImageSize(ListHead, Image, ImageBuffer, &InterpreterPath);
  971. if (!KSUCCESS(Status)) {
  972. goto LoadEnd;
  973. }
  974. //
  975. // Load the interpreter if there is one.
  976. //
  977. if (InterpreterPath != NULL) {
  978. ASSERT(((Flags & IMAGE_LOAD_FLAG_IGNORE_INTERPRETER) == 0) &&
  979. (Parent == NULL));
  980. Status = ImpLoad(ListHead,
  981. InterpreterPath,
  982. NULL,
  983. NULL,
  984. SystemContext,
  985. Flags | IMAGE_LOAD_FLAG_IGNORE_INTERPRETER,
  986. NULL,
  987. &InterpreterImage,
  988. NULL);
  989. if (!KSUCCESS(Status)) {
  990. goto LoadEnd;
  991. }
  992. }
  993. if (ImAllocateAddressSpace != NULL) {
  994. //
  995. // Call out to the allocator to get space for the image.
  996. //
  997. Image->BaseDifference = 0;
  998. Status = ImAllocateAddressSpace(Image);
  999. if (!KSUCCESS(Status)) {
  1000. goto LoadEnd;
  1001. }
  1002. //
  1003. // If the image is not relocatable and the preferred address could not
  1004. // be allocated, then this image cannot be loaded.
  1005. //
  1006. if ((Image->BaseDifference != 0) &&
  1007. ((Image->Flags & IMAGE_FLAG_RELOCATABLE) == 0)) {
  1008. Status = STATUS_MEMORY_CONFLICT;
  1009. goto LoadEnd;
  1010. }
  1011. //
  1012. // Just pretend for now it got put at the right spot. This will be adjusted
  1013. // later.
  1014. //
  1015. } else {
  1016. Image->BaseDifference = 0;
  1017. }
  1018. //
  1019. // Call the image-specific routine to actually load/map the image into its
  1020. // allocated space.
  1021. //
  1022. Status = ImpLoadImage(ListHead, Image, ImageBuffer);
  1023. if (!KSUCCESS(Status)) {
  1024. goto LoadEnd;
  1025. }
  1026. LoadEnd:
  1027. //
  1028. // Tear down the portion of the image loaded so far on failure.
  1029. //
  1030. if (!KSUCCESS(Status)) {
  1031. if (InterpreterImage != NULL) {
  1032. ImImageReleaseReference(InterpreterImage);
  1033. }
  1034. if (Image != NULL) {
  1035. if (Image->AllocatorHandle != INVALID_HANDLE) {
  1036. ImFreeAddressSpace(Image);
  1037. }
  1038. if (Image->File.Handle != INVALID_HANDLE) {
  1039. if (LocalImageBuffer.Data != NULL) {
  1040. ImUnloadBuffer(&(Image->File), &LocalImageBuffer);
  1041. }
  1042. if (BinaryFile == NULL) {
  1043. ImCloseFile(&(Image->File));
  1044. }
  1045. }
  1046. if (Image->FileName != NULL) {
  1047. ImFreeMemory(Image->FileName);
  1048. }
  1049. ImFreeMemory(Image);
  1050. Image = NULL;
  1051. }
  1052. }
  1053. if (LoadedImage != NULL) {
  1054. *LoadedImage = Image;
  1055. }
  1056. if (Interpreter != NULL) {
  1057. *Interpreter = InterpreterImage;
  1058. }
  1059. return Status;
  1060. }
  1061. PLOADED_IMAGE
  1062. ImpGetPrimaryExecutable (
  1063. PLIST_ENTRY ListHead
  1064. )
  1065. /*++
  1066. Routine Description:
  1067. This routine returns the primary executable in the list, if there is one.
  1068. Arguments:
  1069. ListHead - Supplies a pointer to the head of the list of loaded images.
  1070. Return Value:
  1071. Returns a pointer to the primary executable if it exists. This routine does
  1072. not add a reference on the image.
  1073. NULL if no primary executable is currently loaded in the list.
  1074. --*/
  1075. {
  1076. PLIST_ENTRY CurrentEntry;
  1077. PLOADED_IMAGE Image;
  1078. if (ListHead == NULL) {
  1079. return NULL;
  1080. }
  1081. CurrentEntry = ListHead->Next;
  1082. while (CurrentEntry != ListHead) {
  1083. Image = LIST_VALUE(CurrentEntry, LOADED_IMAGE, ListEntry);
  1084. if ((Image->LoadFlags & IMAGE_LOAD_FLAG_PRIMARY_EXECUTABLE) != 0) {
  1085. return Image;
  1086. }
  1087. CurrentEntry = CurrentEntry->Next;
  1088. }
  1089. return NULL;
  1090. }
  1091. //
  1092. // --------------------------------------------------------- Internal Functions
  1093. //
  1094. KSTATUS
  1095. ImpOpenLibrary (
  1096. PLIST_ENTRY ListHead,
  1097. PLOADED_IMAGE Parent,
  1098. PVOID SystemContext,
  1099. PSTR BinaryName,
  1100. PIMAGE_FILE_INFORMATION File,
  1101. PSTR *Path
  1102. )
  1103. /*++
  1104. Routine Description:
  1105. This routine attempts to open a file.
  1106. Arguments:
  1107. ListHead - Supplies an optional pointer to the head of the list of loaded
  1108. images.
  1109. Parent - Supplies an optional pointer to the parent image requiring this
  1110. image for load.
  1111. SystemContext - Supplies the context pointer passed to the load executable
  1112. function.
  1113. BinaryName - Supplies the name of the executable image to open.
  1114. File - Supplies a pointer where the information for the file including its
  1115. open handle will be returned.
  1116. Image - Supplies a pointer where an existing image may be returned.
  1117. Path - Supplies a pointer where the real path to the opened file will be
  1118. returned. The caller is responsible for freeing this memory.
  1119. Return Value:
  1120. Status code.
  1121. --*/
  1122. {
  1123. ULONG NameLength;
  1124. KSTATUS Status;
  1125. if (Parent == NULL) {
  1126. Parent = ImpGetPrimaryExecutable(ListHead);
  1127. }
  1128. //
  1129. // If this is an executable being loaded for the first time, just try to
  1130. // open the file directly. No extra paths are searched.
  1131. //
  1132. if (Parent == NULL) {
  1133. Status = ImOpenFile(SystemContext, BinaryName, File);
  1134. if (KSUCCESS(Status)) {
  1135. if (Path == NULL) {
  1136. Status = STATUS_SUCCESS;
  1137. } else {
  1138. NameLength = RtlStringLength(BinaryName);
  1139. *Path = ImAllocateMemory(NameLength + 1, IM_ALLOCATION_TAG);
  1140. if (*Path != NULL) {
  1141. RtlCopyMemory(*Path, BinaryName, NameLength + 1);
  1142. } else {
  1143. Status = STATUS_INSUFFICIENT_RESOURCES;
  1144. }
  1145. }
  1146. if (!KSUCCESS(Status)) {
  1147. ImCloseFile(File);
  1148. File->Handle = INVALID_HANDLE;
  1149. }
  1150. }
  1151. } else {
  1152. Status = ImpOpenImport(ListHead,
  1153. Parent,
  1154. SystemContext,
  1155. BinaryName,
  1156. File,
  1157. Path);
  1158. }
  1159. return Status;
  1160. }
  1161. KSTATUS
  1162. ImpGetImageSize (
  1163. PLIST_ENTRY ListHead,
  1164. PLOADED_IMAGE Image,
  1165. PIMAGE_BUFFER Buffer,
  1166. PSTR *InterpreterPath
  1167. )
  1168. /*++
  1169. Routine Description:
  1170. This routine determines the expanded image size and preferred image
  1171. virtual address and stores that in the loaded image structure.
  1172. Arguments:
  1173. ListHead - Supplies a pointer to the head of the list of loaded images.
  1174. Image - Supplies a pointer to the loaded image structure. The format
  1175. memeber is the only member that is required to be initialized.
  1176. Buffer - Supplies a pointer to the loaded image buffer.
  1177. InterpreterPath - Supplies a pointer where the interpreter name will be
  1178. returned if the program is requesting an interpreter.
  1179. Return Value:
  1180. Status code.
  1181. --*/
  1182. {
  1183. KSTATUS Status;
  1184. switch (Image->Format) {
  1185. case ImagePe32:
  1186. Status = STATUS_NOT_SUPPORTED;
  1187. break;
  1188. case ImageElf32:
  1189. Status = ImpElf32GetImageSize(ListHead, Image, Buffer, InterpreterPath);
  1190. break;
  1191. default:
  1192. ASSERT(FALSE);
  1193. Status = STATUS_INVALID_CONFIGURATION;
  1194. break;
  1195. }
  1196. return Status;
  1197. }
  1198. KSTATUS
  1199. ImpLoadImage (
  1200. PLIST_ENTRY ListHead,
  1201. PLOADED_IMAGE Image,
  1202. PIMAGE_BUFFER Buffer
  1203. )
  1204. /*++
  1205. Routine Description:
  1206. This routine loads an executable image into virtual memory.
  1207. Arguments:
  1208. ListHead - Supplies a pointer to the head of the list of loaded images.
  1209. Image - Supplies a pointer to the loaded image. This must be partially
  1210. filled out. Notable fields that must be filled out by the caller
  1211. include the loaded virtual address and image size. This routine will
  1212. fill out many other fields.
  1213. Buffer - Supplies a pointer to the image file buffer.
  1214. Return Value:
  1215. STATUS_SUCCESS on success.
  1216. STATUS_FILE_CORRUPT if the file headers were corrupt or unexpected.
  1217. Other errors on failure.
  1218. --*/
  1219. {
  1220. KSTATUS Status;
  1221. switch (Image->Format) {
  1222. case ImagePe32:
  1223. Status = STATUS_NOT_SUPPORTED;
  1224. break;
  1225. case ImageElf32:
  1226. Status = ImpElf32LoadImage(ListHead, Image, Buffer);
  1227. break;
  1228. default:
  1229. Status = STATUS_UNKNOWN_IMAGE_FORMAT;
  1230. break;
  1231. }
  1232. return Status;
  1233. }
  1234. KSTATUS
  1235. ImpAddImage (
  1236. PIMAGE_BUFFER ImageBuffer,
  1237. PLOADED_IMAGE Image
  1238. )
  1239. /*++
  1240. Routine Description:
  1241. This routine adds the accounting structures for an image that has already
  1242. been loaded into memory.
  1243. Arguments:
  1244. ImageBuffer - Supplies a pointer to the loaded image buffer.
  1245. Image - Supplies a pointer to the image to initialize.
  1246. Return Value:
  1247. Status code.
  1248. --*/
  1249. {
  1250. KSTATUS Status;
  1251. switch (Image->Format) {
  1252. case ImageElf32:
  1253. Status = ImpElf32AddImage(ImageBuffer, Image);
  1254. break;
  1255. default:
  1256. Status = STATUS_UNKNOWN_IMAGE_FORMAT;
  1257. break;
  1258. }
  1259. return Status;
  1260. }
  1261. KSTATUS
  1262. ImpOpenImport (
  1263. PLIST_ENTRY ListHead,
  1264. PLOADED_IMAGE Parent,
  1265. PVOID SystemContext,
  1266. PSTR BinaryName,
  1267. PIMAGE_FILE_INFORMATION File,
  1268. PSTR *Path
  1269. )
  1270. /*++
  1271. Routine Description:
  1272. This routine attempts to open a file.
  1273. Arguments:
  1274. ListHead - Supplies an optional pointer to the head of the list of loaded
  1275. images.
  1276. Parent - Supplies an optional pointer to the parent image requiring this
  1277. image for load.
  1278. SystemContext - Supplies the context pointer passed to the load executable
  1279. function.
  1280. BinaryName - Supplies the name of the executable image to open.
  1281. File - Supplies a pointer where the information for the file including its
  1282. open handle will be returned.
  1283. Image - Supplies a pointer where an existing image may be returned.
  1284. Path - Supplies a pointer where the real path to the opened file will be
  1285. returned. The caller is responsible for freeing this memory.
  1286. Return Value:
  1287. Status code.
  1288. --*/
  1289. {
  1290. KSTATUS Status;
  1291. ASSERT(Parent->SystemContext == SystemContext);
  1292. switch (Parent->Format) {
  1293. case ImageElf32:
  1294. Status = ImpElf32OpenLibrary(ListHead, Parent, BinaryName, File, Path);
  1295. break;
  1296. default:
  1297. ASSERT(FALSE);
  1298. Status = STATUS_INVALID_CONFIGURATION;
  1299. break;
  1300. }
  1301. return Status;
  1302. }
  1303. VOID
  1304. ImpUnloadImage (
  1305. PLOADED_IMAGE Image
  1306. )
  1307. /*++
  1308. Routine Description:
  1309. This routine unloads an executable image from virtual memory.
  1310. Arguments:
  1311. Image - Supplies a pointer to the loaded image.
  1312. Return Value:
  1313. None.
  1314. --*/
  1315. {
  1316. switch (Image->Format) {
  1317. case ImageElf32:
  1318. ImpElf32UnloadImage(Image);
  1319. break;
  1320. default:
  1321. ASSERT(FALSE);
  1322. break;
  1323. }
  1324. return;
  1325. }
  1326. KSTATUS
  1327. ImpGetSymbolByName (
  1328. PLOADED_IMAGE Image,
  1329. PSTR SymbolName,
  1330. ULONG RecursionLevel,
  1331. ULONG VisitMarker,
  1332. PIMAGE_SYMBOL Symbol
  1333. )
  1334. /*++
  1335. Routine Description:
  1336. This routine attempts to find an exported symbol with the given name in the
  1337. given binary. This routine also looks through the image imports if the
  1338. recursive level is not greater than or equal to the maximum import
  1339. recursion depth.
  1340. Arguments:
  1341. Image - Supplies a pointer to the image to query.
  1342. SymbolName - Supplies a pointer to the string containing the name of the
  1343. symbol to search for.
  1344. RecursionLevel - Supplies the current level of recursion.
  1345. VisitMarker - Supplies the value that images are marked with to indicate
  1346. they've been visited in this trip already.
  1347. Symbol - Supplies a pointer to a structure that receives the symbol's
  1348. information on success.
  1349. Return Value:
  1350. Status code.
  1351. --*/
  1352. {
  1353. PLOADED_IMAGE Import;
  1354. ULONG ImportIndex;
  1355. KSTATUS Status;
  1356. if (Image == NULL) {
  1357. return STATUS_INVALID_PARAMETER;
  1358. }
  1359. switch (Image->Format) {
  1360. case ImageElf32:
  1361. Status = ImpElf32GetSymbolByName(Image, SymbolName, Symbol);
  1362. break;
  1363. default:
  1364. Status = STATUS_UNKNOWN_IMAGE_FORMAT;
  1365. break;
  1366. }
  1367. if ((Status != STATUS_NOT_FOUND) ||
  1368. (RecursionLevel >= MAX_IMPORT_RECURSION_DEPTH)) {
  1369. return Status;
  1370. }
  1371. Image->VisitMarker = VisitMarker;
  1372. for (ImportIndex = 0; ImportIndex < Image->ImportCount; ImportIndex += 1) {
  1373. Import = Image->Imports[ImportIndex];
  1374. if ((Import != NULL) && (Import->VisitMarker != VisitMarker)) {
  1375. Status = ImpGetSymbolByName(Import,
  1376. SymbolName,
  1377. RecursionLevel + 1,
  1378. VisitMarker,
  1379. Symbol);
  1380. if (Status != STATUS_NOT_FOUND) {
  1381. return Status;
  1382. }
  1383. }
  1384. }
  1385. //
  1386. // The image format is unknown or invalid.
  1387. //
  1388. return Status;
  1389. }
  1390. KSTATUS
  1391. ImpGetSymbolByAddress (
  1392. PLOADED_IMAGE Image,
  1393. PVOID Address,
  1394. ULONG RecursionLevel,
  1395. ULONG VisitMarker,
  1396. PIMAGE_SYMBOL Symbol
  1397. )
  1398. /*++
  1399. Routine Description:
  1400. This routine attempts to resolve the given address into a symbol. This
  1401. routine also looks through the image imports if the recursive level is not
  1402. greater than or equal to the maximum import recursion depth.
  1403. Arguments:
  1404. Image - Supplies a pointer to the image to query.
  1405. Address - Supplies the address to search for.
  1406. RecursionLevel - Supplies the current level of recursion.
  1407. VisitMarker - Supplies the value that images are marked with to indicate
  1408. they've been visited in this trip already.
  1409. Symbol - Supplies a pointer to a structure that receives the address's
  1410. symbol information on success.
  1411. Return Value:
  1412. Status code.
  1413. --*/
  1414. {
  1415. PLOADED_IMAGE Import;
  1416. ULONG ImportIndex;
  1417. KSTATUS Status;
  1418. if (Image == NULL) {
  1419. return STATUS_INVALID_PARAMETER;
  1420. }
  1421. switch (Image->Format) {
  1422. case ImageElf32:
  1423. Status = ImpElf32GetSymbolByAddress(Image, Address, Symbol);
  1424. break;
  1425. default:
  1426. Status = STATUS_UNKNOWN_IMAGE_FORMAT;
  1427. break;
  1428. }
  1429. if ((Status != STATUS_NOT_FOUND) ||
  1430. (RecursionLevel >= MAX_IMPORT_RECURSION_DEPTH)) {
  1431. return Status;
  1432. }
  1433. Image->VisitMarker = VisitMarker;
  1434. for (ImportIndex = 0; ImportIndex < Image->ImportCount; ImportIndex += 1) {
  1435. Import = Image->Imports[ImportIndex];
  1436. if ((Import != NULL) && (Import->VisitMarker != VisitMarker)) {
  1437. Status = ImpGetSymbolByAddress(Import,
  1438. Address,
  1439. RecursionLevel + 1,
  1440. VisitMarker,
  1441. Symbol);
  1442. if (Status != STATUS_NOT_FOUND) {
  1443. return Status;
  1444. }
  1445. }
  1446. }
  1447. //
  1448. // The image format is unknown or invalid.
  1449. //
  1450. return Status;
  1451. }
  1452. VOID
  1453. ImpRelocateSelf (
  1454. PIMAGE_BUFFER Buffer,
  1455. PLOADED_IMAGE Image
  1456. )
  1457. /*++
  1458. Routine Description:
  1459. This routine relocates the currently running image.
  1460. Arguments:
  1461. Buffer - Supplies a pointer to an initialized buffer pointing at the base
  1462. of the loaded image.
  1463. Image - Supplies a pointer to a zeroed out image structure. The image
  1464. format should be initialized. This can be stack allocated.
  1465. Return Value:
  1466. None.
  1467. --*/
  1468. {
  1469. switch (Image->Format) {
  1470. case ImageElf32:
  1471. ImpElf32RelocateSelf(Buffer, Image);
  1472. break;
  1473. default:
  1474. ASSERT(FALSE);
  1475. break;
  1476. }
  1477. return;
  1478. }
  1479. PLOADED_IMAGE
  1480. ImpFindImageByLibraryName (
  1481. PLIST_ENTRY ListHead,
  1482. PSTR Name
  1483. )
  1484. /*++
  1485. Routine Description:
  1486. This routine attempts to find an image with the given library name in the
  1487. given list.
  1488. Arguments:
  1489. ListHead - Supplies a pointer to the head of the list of images to
  1490. search through.
  1491. Name - Supplies a pointer to a string containing the name of the image.
  1492. Return Value:
  1493. Returns a pointer to the image within the list on success.
  1494. NULL on failure.
  1495. --*/
  1496. {
  1497. PLIST_ENTRY CurrentEntry;
  1498. PLOADED_IMAGE Image;
  1499. ULONG NameLength;
  1500. PSTR Potential;
  1501. NameLength = RtlStringLength(Name) + 1;
  1502. CurrentEntry = ListHead->Next;
  1503. while (CurrentEntry != ListHead) {
  1504. Image = LIST_VALUE(CurrentEntry, LOADED_IMAGE, ListEntry);
  1505. CurrentEntry = CurrentEntry->Next;
  1506. Potential = Image->LibraryName;
  1507. if ((Potential != NULL) &&
  1508. (RtlAreStringsEqual(Potential, Name, NameLength) != FALSE)) {
  1509. //
  1510. // This routine is used to load real images, so it would be bad to
  1511. // return a placeholder image here.
  1512. //
  1513. ASSERT((Image->LoadFlags & IMAGE_LOAD_FLAG_PLACEHOLDER) == 0);
  1514. //
  1515. // Finding the image indicates that an image further along in the
  1516. // list depends on said images. Move it to be back of the list.
  1517. //
  1518. LIST_REMOVE(&(Image->ListEntry));
  1519. INSERT_BEFORE(&(Image->ListEntry), ListHead);
  1520. return Image;
  1521. }
  1522. }
  1523. return NULL;
  1524. }
  1525. PLOADED_IMAGE
  1526. ImpFindImageByFile (
  1527. PLIST_ENTRY ListHead,
  1528. PIMAGE_FILE_INFORMATION File
  1529. )
  1530. /*++
  1531. Routine Description:
  1532. This routine attempts to find an image matching the given file and device
  1533. ID.
  1534. Arguments:
  1535. ListHead - Supplies a pointer to the head of the list of images to
  1536. search through.
  1537. File - Supplies a pointer to the file information.
  1538. Return Value:
  1539. Returns a pointer to the image within the list on success.
  1540. NULL on failure.
  1541. --*/
  1542. {
  1543. PLIST_ENTRY CurrentEntry;
  1544. PLOADED_IMAGE Image;
  1545. //
  1546. // If this image doesn't have the file/device ID supported, then don't
  1547. // match anything.
  1548. //
  1549. if ((File->DeviceId == 0) && (File->FileId == 0)) {
  1550. return NULL;
  1551. }
  1552. CurrentEntry = ListHead->Next;
  1553. while (CurrentEntry != ListHead) {
  1554. Image = LIST_VALUE(CurrentEntry, LOADED_IMAGE, ListEntry);
  1555. CurrentEntry = CurrentEntry->Next;
  1556. if ((Image->File.DeviceId == File->DeviceId) &&
  1557. (Image->File.FileId == File->FileId)) {
  1558. //
  1559. // This routine is used to load real images, so it would be bad to
  1560. // return a placeholder image here.
  1561. //
  1562. ASSERT((Image->LoadFlags & IMAGE_LOAD_FLAG_PLACEHOLDER) == 0);
  1563. //
  1564. // Finding the image indicates that an image further along in the
  1565. // list depends on said images. Move it to be back of the list.
  1566. //
  1567. LIST_REMOVE(&(Image->ListEntry));
  1568. INSERT_BEFORE(&(Image->ListEntry), ListHead);
  1569. return Image;
  1570. }
  1571. }
  1572. return NULL;
  1573. }
  1574. PLOADED_IMAGE
  1575. ImpAllocateImage (
  1576. VOID
  1577. )
  1578. /*++
  1579. Routine Description:
  1580. This routine allocates a new loaded image structure, and initializes some
  1581. basic fields and the name.
  1582. Arguments:
  1583. None.
  1584. Return Value:
  1585. Returns a pointer to the newly allocated image structure on success.
  1586. NULL on failure.
  1587. --*/
  1588. {
  1589. PLOADED_IMAGE Image;
  1590. //
  1591. // Allocate space for the loaded image structure.
  1592. //
  1593. Image = ImAllocateMemory(sizeof(LOADED_IMAGE), IM_ALLOCATION_TAG);
  1594. if (Image == NULL) {
  1595. return NULL;
  1596. }
  1597. RtlZeroMemory(Image, sizeof(LOADED_IMAGE));
  1598. Image->ReferenceCount = 1;
  1599. Image->AllocatorHandle = INVALID_HANDLE;
  1600. Image->File.Handle = INVALID_HANDLE;
  1601. Image->TlsOffset = -1;
  1602. Image->Debug.Version = IMAGE_DEBUG_VERSION;
  1603. Image->Debug.Image = Image;
  1604. //
  1605. // Consider consolidating ImNotifyImageLoad and ImNotifyImageUnload
  1606. // so this mechanism works fully.
  1607. //
  1608. Image->Debug.ImageChangeFunction = ImNotifyImageLoad;
  1609. return Image;
  1610. }