3 Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
4 Portions copyright (c) 2008 - 2011, Apple Inc. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #define MAP_ANONYMOUS MAP_ANON
19 char *gGdbWorkingFileName
= NULL
;
27 EMU_THUNK_PPI mSecEmuThunkPpi
= {
28 GasketSecUnixPeiAutoScan
,
29 GasketSecUnixFdAddress
,
30 GasketSecEmuThunkAddress
37 // Default information about where the FD is located.
38 // This array gets filled in with information from EFI_FIRMWARE_VOLUMES
39 // EFI_FIRMWARE_VOLUMES is a host environment variable set by system.cmd.
40 // The number of array elements is allocated base on parsing
41 // EFI_FIRMWARE_VOLUMES and the memory is never freed.
43 UINTN gFdInfoCount
= 0;
47 // Array that supports seperate memory rantes.
48 // The memory ranges are set in system.cmd via the EFI_MEMORY_SIZE variable.
49 // The number of array elements is allocated base on parsing
50 // EFI_MEMORY_SIZE and the memory is never freed.
52 UINTN gSystemMemoryCount
= 0;
53 EMU_SYSTEM_MEMORY
*gSystemMemory
;
57 UINTN mImageContextModHandleArraySize
= 0;
58 IMAGE_CONTEXT_TO_MOD_HANDLE
*mImageContextModHandleArray
= NULL
;
60 EFI_PEI_PPI_DESCRIPTOR
*gPpiList
;
65 Main entry point to SEC for Unix. This is a unix program
68 Argc - Number of command line arguments
69 Argv - Array of command line argument strings
70 Envp - Array of environmemt variable strings
85 EFI_PHYSICAL_ADDRESS InitialStackMemory
;
86 UINT64 InitialStackMemorySize
;
93 EFI_PEI_FILE_HANDLE FileHandle
;
95 CHAR16
*MemorySizeStr
;
96 CHAR16
*FirmwareVolumesStr
;
102 MemorySizeStr
= (CHAR16
*) PcdGetPtr (PcdEmuMemorySize
);
103 FirmwareVolumesStr
= (CHAR16
*) PcdGetPtr (PcdEmuFirmwareVolume
);
105 printf ("\nEDK II UNIX Emulation Environment from edk2.sourceforge.net\n");
108 // PPIs pased into PEI_CORE
110 AddThunkPpi (EFI_PEI_PPI_DESCRIPTOR_PPI
, &gEmuThunkPpiGuid
, &mSecEmuThunkPpi
);
112 SecInitThunkProtocol ();
115 // Emulator Bus Driver Thunks
117 AddThunkProtocol (&gX11ThunkIo
, (CHAR16
*)PcdGetPtr (PcdEmuGop
), TRUE
);
118 AddThunkProtocol (&gPosixFileSystemThunkIo
, (CHAR16
*)PcdGetPtr (PcdEmuFileSystem
), TRUE
);
119 AddThunkProtocol (&gBlockIoThunkIo
, (CHAR16
*)PcdGetPtr (PcdEmuVirtualDisk
), TRUE
);
124 // Emulator other Thunks
126 AddThunkProtocol (&gPthreadThunkIo
, (CHAR16
*)PcdGetPtr (PcdEmuApCount
), FALSE
);
128 // EmuSecLibConstructor ();
130 gPpiList
= GetThunkPpiList ();
135 // We can't use dlopen on OS X, so we need a scheme to get symboles into gdb
136 // We need to create a temp file that contains gdb commands so we can load
137 // symbols when we load every PE/COFF image.
139 Index
= strlen (*Argv
);
140 gGdbWorkingFileName
= malloc (Index
+ strlen(".gdb") + 1);
141 strcpy (gGdbWorkingFileName
, *Argv
);
142 strcat (gGdbWorkingFileName
, ".gdb");
147 // Allocate space for gSystemMemory Array
149 gSystemMemoryCount
= CountSeperatorsInString (MemorySizeStr
, '!') + 1;
150 gSystemMemory
= calloc (gSystemMemoryCount
, sizeof (EMU_SYSTEM_MEMORY
));
151 if (gSystemMemory
== NULL
) {
152 printf ("ERROR : Can not allocate memory for system. Exiting.\n");
156 // Allocate space for gSystemMemory Array
158 gFdInfoCount
= CountSeperatorsInString (FirmwareVolumesStr
, '!') + 1;
159 gFdInfo
= calloc (gFdInfoCount
, sizeof (EMU_FD_INFO
));
160 if (gFdInfo
== NULL
) {
161 printf ("ERROR : Can not allocate memory for fd info. Exiting.\n");
165 printf (" BootMode 0x%02x\n", (unsigned int)PcdGet32 (PcdEmuBootMode
));
168 // Open up a 128K file to emulate temp memory for SEC.
169 // on a real platform this would be SRAM, or using the cache as RAM.
170 // Set InitialStackMemory to zero so UnixOpenFile will allocate a new mapping
172 InitialStackMemorySize
= STACK_SIZE
;
173 InitialStackMemory
= (UINTN
)MapMemory (
174 0, (UINT32
) InitialStackMemorySize
,
175 PROT_READ
| PROT_WRITE
| PROT_EXEC
, MAP_ANONYMOUS
| MAP_PRIVATE
177 if (InitialStackMemory
== 0) {
178 printf ("ERROR : Can not open SecStack Exiting\n");
182 printf (" OS Emulator passing in %u KB of temp RAM at 0x%08lx to SEC\n",
183 (unsigned int)(InitialStackMemorySize
/ 1024),
184 (unsigned long)InitialStackMemory
187 for (StackPointer
= (UINTN
*) (UINTN
) InitialStackMemory
;
188 StackPointer
< (UINTN
*)(UINTN
)((UINTN
) InitialStackMemory
+ (UINT64
) InitialStackMemorySize
);
190 *StackPointer
= 0x5AA55AA5;
194 // Open All the firmware volumes and remember the info in the gFdInfo global
196 FileName
= (CHAR8
*)malloc (StrLen (FirmwareVolumesStr
) + 1);
197 if (FileName
== NULL
) {
198 printf ("ERROR : Can not allocate memory for firmware volume string\n");
203 for (Done
= FALSE
, Index
= 0, PeiIndex
= 0, SecFile
= NULL
;
204 FirmwareVolumesStr
[Index2
] != 0;
206 for (Index1
= 0; (FirmwareVolumesStr
[Index2
] != '!') && (FirmwareVolumesStr
[Index2
] != 0); Index2
++) {
207 FileName
[Index1
++] = FirmwareVolumesStr
[Index2
];
209 if (FirmwareVolumesStr
[Index2
] == '!') {
212 FileName
[Index1
] = '\0';
215 // Map FV Recovery Read Only and other areas Read/Write
223 // Open the FD and remmeber where it got mapped into our processes address space
228 &gFdInfo
[Index
].Address
,
232 if (EFI_ERROR (Status
)) {
233 printf ("ERROR : Can not open Firmware Device File %s (%x). Exiting.\n", FileName
, (unsigned int)Status
);
237 printf (" FD loaded from %s at 0x%08lx",FileName
, (unsigned long)gFdInfo
[Index
].Address
);
239 if (SecFile
== NULL
) {
241 // Assume the beginning of the FD is an FV and look for the SEC Core.
242 // Load the first one we find.
245 Status
= PeiServicesFfsFindNextFile (
246 EFI_FV_FILETYPE_SECURITY_CORE
,
247 (EFI_PEI_FV_HANDLE
)(UINTN
)gFdInfo
[Index
].Address
,
250 if (!EFI_ERROR (Status
)) {
251 Status
= PeiServicesFfsFindSectionData (EFI_SECTION_PE32
, FileHandle
, &SecFile
);
252 if (!EFI_ERROR (Status
)) {
254 printf (" contains SEC Core");
262 // Calculate memory regions and store the information in the gSystemMemory
263 // global for later use. The autosizing code will use this data to
264 // map this memory into the SEC process memory space.
271 // Save the size of the memory.
273 while (MemorySizeStr
[Index1
] >= '0' && MemorySizeStr
[Index1
] <= '9') {
274 val
= val
* 10 + MemorySizeStr
[Index1
] - '0';
277 gSystemMemory
[Index
++].Size
= val
* 0x100000;
278 if (MemorySizeStr
[Index1
] == 0) {
289 SecLoadFromCore ((UINTN
) InitialStackMemory
, (UINTN
) InitialStackMemorySize
, (UINTN
) gFdInfo
[0].Address
, SecFile
);
292 // If we get here, then the SEC Core returned. This is an error as SEC should
293 // always hand off to PEI Core and then on to DXE Core.
295 printf ("ERROR : SEC returned\n");
300 EFI_PHYSICAL_ADDRESS
*
307 STATIC UINTN base
= 0x40000000;
308 CONST UINTN align
= (1 << 24);
310 BOOLEAN isAligned
= 0;
313 // Try to get an aligned block somewhere in the address space of this
316 while((!isAligned
) && (base
!= 0)) {
317 res
= mmap ((void *)base
, length
, prot
, flags
, fd
, 0);
318 if (res
== MAP_FAILED
) {
321 if ((((UINTN
)res
) & ~(align
-1)) == (UINTN
)res
) {
335 Opens and memory maps a file using Unix services. If BaseAddress is non zero
336 the process will try and allocate the memory starting at BaseAddress.
339 FileName - The name of the file to open and map
340 MapSize - The amount of the file to map in bytes
341 CreationDisposition - The flags to pass to CreateFile(). Use to create new files for
342 memory emulation, and exiting files for firmware volume emulation
343 BaseAddress - The base address of the mapped file in the user address space.
344 If passed in as NULL the a new memory region is used.
345 If passed in as non NULL the request memory region is used for
346 the mapping of the file into the process space.
347 Length - The size of the mapped region in bytes
350 EFI_SUCCESS - The file was opened and mapped.
351 EFI_NOT_FOUND - FileName was not found in the current directory
352 EFI_DEVICE_ERROR - An error occured attempting to map the opened file
358 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
366 fd
= open (FileName
, O_RDWR
);
368 return EFI_NOT_FOUND
;
370 FileSize
= lseek (fd
, 0, SEEK_END
);
373 res
= MapMemory (fd
, FileSize
, PROT_READ
| PROT_EXEC
, MAP_PRIVATE
);
378 perror ("MapFile() Failed");
379 return EFI_DEVICE_ERROR
;
382 *Length
= (UINT64
) FileSize
;
383 *BaseAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) res
;
391 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
396 void *res
, *res2
, *res3
;
401 fd
= open (FileName
, O_RDWR
);
403 return EFI_NOT_FOUND
;
405 FileSize
= lseek (fd
, 0, SEEK_END
);
407 FvSize
= FixedPcdGet64 (PcdEmuFlashFvRecoverySize
);
409 // Assume start of FD is Recovery FV, and make it write protected
411 (void *)(UINTN
)FixedPcdGet64 (PcdEmuFlashFvRecoveryBase
),
413 PROT_READ
| PROT_EXEC
,
418 if (res
== MAP_FAILED
) {
419 perror ("MapFd0() Failed res =");
421 return EFI_DEVICE_ERROR
;
422 } else if (res
!= (void *)(UINTN
)FixedPcdGet64 (PcdEmuFlashFvRecoveryBase
)) {
423 // We could not load at the build address, so we need to allow writes
424 munmap (res
, FvSize
);
426 (void *)(UINTN
)FixedPcdGet64 (PcdEmuFlashFvRecoveryBase
),
428 PROT_READ
| PROT_WRITE
| PROT_EXEC
,
433 if (res
== MAP_FAILED
) {
434 perror ("MapFd0() Failed res =");
436 return EFI_DEVICE_ERROR
;
440 // Map the rest of the FD as read/write
442 (void *)(FixedPcdGet64 (PcdEmuFlashFvRecoveryBase
) + FvSize
),
444 PROT_READ
| PROT_WRITE
| PROT_EXEC
,
450 if (res2
== MAP_FAILED
) {
451 perror ("MapFd0() Failed res2 =");
452 return EFI_DEVICE_ERROR
;
456 // If enabled use the magic page to communicate between modules
457 // This replaces the PI PeiServicesTable pointer mechanism that
458 // deos not work in the emulator. It also allows the removal of
459 // writable globals from SEC, PEI_CORE (libraries), PEIMs
461 EmuMagicPage
= (void *)(UINTN
)FixedPcdGet64 (PcdPeiServicesTablePage
);
462 if (EmuMagicPage
!= NULL
) {
464 (void *)EmuMagicPage
,
466 PROT_READ
| PROT_WRITE
,
467 MAP_PRIVATE
| MAP_ANONYMOUS
,
471 if (res3
!= EmuMagicPage
) {
472 printf ("MapFd0(): Could not allocate PeiServicesTablePage @ %lx\n", (long unsigned int)EmuMagicPage
);
473 return EFI_DEVICE_ERROR
;
477 *Length
= (UINT64
) FileSize
;
478 *BaseAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) res
;
487 This is the service to load the SEC Core from the Firmware Volume
490 LargestRegion - Memory to use for SEC.
491 LargestRegionSize - Size of Memory to use for PEI
492 BootFirmwareVolumeBase - Start of the Boot FV
493 PeiCorePe32File - SEC PE32
496 Success means control is transfered and thus we should never return
501 IN UINTN LargestRegion
,
502 IN UINTN LargestRegionSize
,
503 IN UINTN BootFirmwareVolumeBase
,
504 IN VOID
*PeiCorePe32File
508 EFI_PHYSICAL_ADDRESS TopOfMemory
;
510 EFI_PHYSICAL_ADDRESS PeiCoreEntryPoint
;
511 EFI_SEC_PEI_HAND_OFF
*SecCoreData
;
515 // Compute Top Of Memory for Stack and PEI Core Allocations
517 TopOfMemory
= LargestRegion
+ LargestRegionSize
;
518 PeiStackSize
= (UINTN
)RShiftU64((UINT64
)STACK_SIZE
,1);
521 // |-----------| <---- TemporaryRamBase + TemporaryRamSize
524 // |-----------| <---- StackBase / PeiTemporaryMemoryBase
527 // |-----------| <---- TemporaryRamBase
529 TopOfStack
= (VOID
*)(LargestRegion
+ PeiStackSize
);
530 TopOfMemory
= LargestRegion
+ PeiStackSize
;
533 // Reservet space for storing PeiCore's parament in stack.
535 TopOfStack
= (VOID
*)((UINTN
)TopOfStack
- sizeof (EFI_SEC_PEI_HAND_OFF
) - CPU_STACK_ALIGNMENT
);
536 TopOfStack
= ALIGN_POINTER (TopOfStack
, CPU_STACK_ALIGNMENT
);
540 // Bind this information into the SEC hand-off state
542 SecCoreData
= (EFI_SEC_PEI_HAND_OFF
*)(UINTN
) TopOfStack
;
543 SecCoreData
->DataSize
= sizeof(EFI_SEC_PEI_HAND_OFF
);
544 SecCoreData
->BootFirmwareVolumeBase
= (VOID
*)BootFirmwareVolumeBase
;
545 SecCoreData
->BootFirmwareVolumeSize
= PcdGet32 (PcdEmuFirmwareFdSize
);
546 SecCoreData
->TemporaryRamBase
= (VOID
*)(UINTN
)LargestRegion
;
547 SecCoreData
->TemporaryRamSize
= STACK_SIZE
;
548 SecCoreData
->StackBase
= SecCoreData
->TemporaryRamBase
;
549 SecCoreData
->StackSize
= PeiStackSize
;
550 SecCoreData
->PeiTemporaryRamBase
= (VOID
*) ((UINTN
) SecCoreData
->TemporaryRamBase
+ PeiStackSize
);
551 SecCoreData
->PeiTemporaryRamSize
= STACK_SIZE
- PeiStackSize
;
554 // Find the SEC Core Entry Point
556 Status
= SecPeCoffGetEntryPoint (PeiCorePe32File
, (VOID
**)&PeiCoreEntryPoint
);
557 if (EFI_ERROR (Status
)) {
562 // Transfer control to the SEC Core
565 (SWITCH_STACK_ENTRY_POINT
) (UINTN
) PeiCoreEntryPoint
,
571 // If we get here, then the SEC Core returned. This is an error
580 This service is called from Index == 0 until it returns EFI_UNSUPPORTED.
581 It allows discontiguous memory regions to be supported by the emulator.
582 It uses gSystemMemory[] and gSystemMemoryCount that were created by
583 parsing the host environment variable EFI_MEMORY_SIZE.
584 The size comes from the varaible and the address comes from the call to
588 Index - Which memory region to use
589 MemoryBase - Return Base address of memory region
590 MemorySize - Return size in bytes of the memory region
593 EFI_SUCCESS - If memory region was mapped
594 EFI_UNSUPPORTED - If Index is not supported
601 OUT EFI_PHYSICAL_ADDRESS
*MemoryBase
,
602 OUT UINT64
*MemorySize
607 if (Index
>= gSystemMemoryCount
) {
608 return EFI_UNSUPPORTED
;
613 0, gSystemMemory
[Index
].Size
,
614 PROT_READ
| PROT_WRITE
| PROT_EXEC
,
615 MAP_PRIVATE
| MAP_ANONYMOUS
617 if (res
== MAP_FAILED
) {
618 return EFI_DEVICE_ERROR
;
620 *MemorySize
= gSystemMemory
[Index
].Size
;
621 *MemoryBase
= (UINTN
)res
;
622 gSystemMemory
[Index
].Memory
= *MemoryBase
;
631 Since the SEC is the only Unix program in stack it must export
632 an interface to do POSIX calls. gUnix is initailized in UnixThunk.c.
635 InterfaceSize - sizeof (EFI_WIN_NT_THUNK_PROTOCOL);
636 InterfaceBase - Address of the gUnix global
639 EFI_SUCCESS - Data returned
648 return &gEmuThunkProtocol
;
655 SecPeCoffGetEntryPoint (
657 IN OUT VOID
**EntryPoint
661 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
663 ZeroMem (&ImageContext
, sizeof (ImageContext
));
664 ImageContext
.Handle
= Pe32Data
;
665 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) SecImageRead
;
667 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
668 if (EFI_ERROR (Status
)) {
672 if (ImageContext
.ImageAddress
!= (UINTN
)Pe32Data
) {
674 // Relocate image to match the address where it resides
676 ImageContext
.ImageAddress
= (UINTN
)Pe32Data
;
677 Status
= PeCoffLoaderLoadImage (&ImageContext
);
678 if (EFI_ERROR (Status
)) {
682 Status
= PeCoffLoaderRelocateImage (&ImageContext
);
683 if (EFI_ERROR (Status
)) {
688 // Or just return image entry point
690 ImageContext
.PdbPointer
= PeCoffLoaderGetPdbPointer (Pe32Data
);
691 Status
= PeCoffLoaderGetEntryPoint (Pe32Data
, EntryPoint
);
692 if (EFI_ERROR (Status
)) {
695 ImageContext
.EntryPoint
= (UINTN
)*EntryPoint
;
698 // On Unix a dlopen is done that will change the entry point
699 SecPeCoffRelocateImageExtraAction (&ImageContext
);
700 *EntryPoint
= (VOID
*)(UINTN
)ImageContext
.EntryPoint
;
710 Return the FD Size and base address. Since the FD is loaded from a
711 file into host memory only the SEC will know it's address.
714 Index - Which FD, starts at zero.
715 FdSize - Size of the FD in bytes
716 FdBase - Start address of the FD. Assume it points to an FV Header
717 FixUp - Difference between actual FD address and build address
720 EFI_SUCCESS - Return the Base address and size of the FV
721 EFI_UNSUPPORTED - Index does nto map to an FD in the system
728 IN OUT EFI_PHYSICAL_ADDRESS
*FdBase
,
729 IN OUT UINT64
*FdSize
,
730 IN OUT EFI_PHYSICAL_ADDRESS
*FixUp
733 if (Index
>= gFdInfoCount
) {
734 return EFI_UNSUPPORTED
;
737 *FdBase
= gFdInfo
[Index
].Address
;
738 *FdSize
= gFdInfo
[Index
].Size
;
741 if (*FdBase
== 0 && *FdSize
== 0) {
742 return EFI_UNSUPPORTED
;
747 // FD 0 has XIP code and well known PCD values
748 // If the memory buffer could not be allocated at the FD build address
749 // the Fixup is the difference.
751 *FixUp
= *FdBase
- PcdGet64 (PcdEmuFdBaseAddress
);
761 Count the number of seperators in String
764 String - String to process
765 Seperator - Item to count
768 Number of Seperator in String
772 CountSeperatorsInString (
773 IN
const CHAR16
*String
,
779 for (Count
= 0; *String
!= '\0'; String
++) {
780 if (*String
== Seperator
) {
794 IN OUT UINTN
*ReadSize
,
800 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
803 FileHandle - The handle to the PE/COFF file
804 FileOffset - The offset, in bytes, into the file to read
805 ReadSize - The number of bytes to read from the file starting at FileOffset
806 Buffer - A pointer to the buffer to read the data into.
809 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
817 Destination8
= Buffer
;
818 Source8
= (CHAR8
*) ((UINTN
) FileHandle
+ FileOffset
);
821 *(Destination8
++) = *(Source8
++);
831 Store the ModHandle in an array indexed by the Pdb File name.
832 The ModHandle is needed to unload the image.
835 ImageContext - Input data returned from PE Laoder Library. Used to find the
836 .PDB file name of the PE Image.
837 ModHandle - Returned from LoadLibraryEx() and stored for call to
841 EFI_SUCCESS - ModHandle was stored.
846 IN PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
,
851 IMAGE_CONTEXT_TO_MOD_HANDLE
*Array
;
855 Array
= mImageContextModHandleArray
;
856 for (Index
= 0; Index
< mImageContextModHandleArraySize
; Index
++, Array
++) {
857 if (Array
->ImageContext
== NULL
) {
859 // Make a copy of the stirng and store the ModHandle
861 Array
->ImageContext
= ImageContext
;
862 Array
->ModHandle
= ModHandle
;
868 // No free space in mImageContextModHandleArray so grow it by
869 // IMAGE_CONTEXT_TO_MOD_HANDLE entires. realloc will
870 // copy the old values to the new locaiton. But it does
871 // not zero the new memory area.
873 PreviousSize
= mImageContextModHandleArraySize
* sizeof (IMAGE_CONTEXT_TO_MOD_HANDLE
);
874 mImageContextModHandleArraySize
+= MAX_IMAGE_CONTEXT_TO_MOD_HANDLE_ARRAY_SIZE
;
876 mImageContextModHandleArray
= realloc (mImageContextModHandleArray
, mImageContextModHandleArraySize
* sizeof (IMAGE_CONTEXT_TO_MOD_HANDLE
));
877 if (mImageContextModHandleArray
== NULL
) {
879 return EFI_OUT_OF_RESOURCES
;
882 memset (mImageContextModHandleArray
+ PreviousSize
, 0, MAX_IMAGE_CONTEXT_TO_MOD_HANDLE_ARRAY_SIZE
* sizeof (IMAGE_CONTEXT_TO_MOD_HANDLE
));
884 return AddHandle (ImageContext
, ModHandle
);
891 Return the ModHandle and delete the entry in the array.
894 ImageContext - Input data returned from PE Laoder Library. Used to find the
895 .PDB file name of the PE Image.
898 ModHandle - ModHandle assoicated with ImageContext is returned
899 NULL - No ModHandle associated with ImageContext
904 IN PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
908 IMAGE_CONTEXT_TO_MOD_HANDLE
*Array
;
910 if (ImageContext
->PdbPointer
== NULL
) {
912 // If no PDB pointer there is no ModHandle so return NULL
917 Array
= mImageContextModHandleArray
;
918 for (Index
= 0; Index
< mImageContextModHandleArraySize
; Index
++, Array
++) {
919 if (Array
->ImageContext
== ImageContext
) {
921 // If you find a match return it and delete the entry
923 Array
->ImageContext
= NULL
;
924 return Array
->ModHandle
;
934 // Target for gdb breakpoint in a script that uses gGdbWorkingFileName to source a
935 // add-symbol-file command. Hey what can you say scripting in gdb is not that great....
937 // Put .gdbinit in the CWD where you do gdb SecMain.dll for source level debug
940 // b SecGdbScriptBreak
943 // source SecMain.gdb
963 IN CHAR8
*PdbFileName
968 if (PdbFileName
== NULL
) {
972 Len
= strlen (PdbFileName
);
973 if ((Len
< 5)|| (PdbFileName
[Len
- 4] != '.')) {
977 if ((PdbFileName
[Len
- 3] == 'P' || PdbFileName
[Len
- 3] == 'p') &&
978 (PdbFileName
[Len
- 2] == 'D' || PdbFileName
[Len
- 2] == 'd') &&
979 (PdbFileName
[Len
- 1] == 'B' || PdbFileName
[Len
- 1] == 'b')) {
987 #define MAX_SPRINT_BUFFER_SIZE 0x200
991 IN PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
994 if (ImageContext
->PdbPointer
== NULL
) {
996 "0x%08lx Loading NO DEBUG with entry point 0x%08lx\n",
997 (unsigned long)(ImageContext
->ImageAddress
),
998 (unsigned long)ImageContext
->EntryPoint
1002 "0x%08lx Loading %s with entry point 0x%08lx\n",
1003 (unsigned long)(ImageContext
->ImageAddress
+ ImageContext
->SizeOfHeaders
),
1004 ImageContext
->PdbPointer
,
1005 (unsigned long)ImageContext
->EntryPoint
1008 // Keep output synced up
1015 SecPeCoffRelocateImageExtraAction (
1016 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
1021 BOOLEAN EnabledOnEntry
;
1024 // Make sure writting of the file is an atomic operation
1026 if (SecInterruptEanbled ()) {
1027 SecDisableInterrupt ();
1028 EnabledOnEntry
= TRUE
;
1030 EnabledOnEntry
= FALSE
;
1033 PrintLoadAddress (ImageContext
);
1036 // In mach-o (OS X executable) dlopen() can only load files in the MH_DYLIB of MH_BUNDLE format.
1037 // To convert to PE/COFF we need to construct a mach-o with the MH_PRELOAD format. We create
1038 // .dSYM files for the PE/COFF images that can be used by gdb for source level debugging.
1043 // In the Mach-O to PE/COFF conversion the size of the PE/COFF headers is not accounted for.
1044 // Thus we need to skip over the PE/COFF header when giving load addresses for our symbol table.
1046 if (ImageContext
->PdbPointer
!= NULL
&& !IsPdbFile (ImageContext
->PdbPointer
)) {
1048 // Now we have a database of the images that are currently loaded
1052 // 'symbol-file' will clear out currnet symbol mappings in gdb.
1053 // you can do a 'add-symbol-file filename address' for every image we loaded to get source
1054 // level debug in gdb. Note Sec, being a true application will work differently.
1056 // We add the PE/COFF header size into the image as the mach-O does not have a header in
1057 // loaded into system memory.
1059 // This gives us a data base of gdb commands and after something is unloaded that entry will be
1060 // removed. We don't yet have the scheme of how to comunicate with gdb, but we have the
1061 // data base of info ready to roll.
1063 // We could use qXfer:libraries:read, but OS X GDB does not currently support it.
1065 // <library name="/lib/libc.so.6"> // ImageContext->PdbPointer
1066 // <segment address="0x10000000"/> // ImageContext->ImageAddress + ImageContext->SizeOfHeaders
1072 // Write the file we need for the gdb script
1074 GdbTempFile
= fopen (gGdbWorkingFileName
, "w");
1075 if (GdbTempFile
!= NULL
) {
1076 fprintf (GdbTempFile
, "add-symbol-file %s 0x%08lx\n", ImageContext
->PdbPointer
, (long unsigned int)(ImageContext
->ImageAddress
+ ImageContext
->SizeOfHeaders
));
1077 fclose (GdbTempFile
);
1080 // Target for gdb breakpoint in a script that uses gGdbWorkingFileName to set a breakpoint.
1081 // Hey what can you say scripting in gdb is not that great....
1083 SecGdbScriptBreak ();
1088 AddHandle (ImageContext
, ImageContext
->PdbPointer
);
1090 if (EnabledOnEntry
) {
1091 SecEnableInterrupt ();
1099 void *Handle
= NULL
;
1102 if (ImageContext
->PdbPointer
== NULL
) {
1106 if (!IsPdbFile (ImageContext
->PdbPointer
)) {
1112 "Loading %s 0x%08lx - entry point 0x%08lx\n",
1113 ImageContext
->PdbPointer
,
1114 (unsigned long)ImageContext
->ImageAddress
,
1115 (unsigned long)ImageContext
->EntryPoint
1118 Handle
= dlopen (ImageContext
->PdbPointer
, RTLD_NOW
);
1121 Entry
= dlsym (Handle
, "_ModuleEntryPoint");
1123 printf("%s\n", dlerror());
1126 if (Entry
!= NULL
) {
1127 ImageContext
->EntryPoint
= (UINTN
)Entry
;
1128 printf ("Change %s Entrypoint to :0x%08lx\n", ImageContext
->PdbPointer
, (unsigned long)Entry
);
1131 SecUnixLoaderBreak ();
1141 SecPeCoffUnloadImageExtraAction (
1142 IN PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
1147 Handle
= RemoveHandle (ImageContext
);
1151 BOOLEAN EnabledOnEntry
;
1153 if (Handle
!= NULL
) {
1155 // Need to skip .PDB files created from VC++
1157 if (!IsPdbFile (ImageContext
->PdbPointer
)) {
1158 if (SecInterruptEanbled ()) {
1159 SecDisableInterrupt ();
1160 EnabledOnEntry
= TRUE
;
1162 EnabledOnEntry
= FALSE
;
1166 // Write the file we need for the gdb script
1168 GdbTempFile
= fopen (gGdbWorkingFileName
, "w");
1169 if (GdbTempFile
!= NULL
) {
1170 fprintf (GdbTempFile
, "remove-symbol-file %s\n", ImageContext
->PdbPointer
);
1171 fclose (GdbTempFile
);
1174 // Target for gdb breakpoint in a script that uses gGdbWorkingFileName to set a breakpoint.
1175 // Hey what can you say scripting in gdb is not that great....
1177 SecGdbScriptBreak ();
1182 if (EnabledOnEntry
) {
1183 SecEnableInterrupt ();
1190 // Don't want to confuse gdb with symbols for something that got unloaded
1192 if (Handle
!= NULL
) {