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
;
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 ();
131 gPpiList
= GetThunkPpiList ();
136 // We can't use dlopen on OS X, so we need a scheme to get symboles into gdb
137 // We need to create a temp file that contains gdb commands so we can load
138 // symbols when we load every PE/COFF image.
140 Index
= strlen (*Argv
);
141 gGdbWorkingFileName
= malloc (Index
+ strlen(".gdb") + 1);
142 strcpy (gGdbWorkingFileName
, *Argv
);
143 strcat (gGdbWorkingFileName
, ".gdb");
148 // Allocate space for gSystemMemory Array
150 gSystemMemoryCount
= CountSeperatorsInString (MemorySizeStr
, '!') + 1;
151 gSystemMemory
= calloc (gSystemMemoryCount
, sizeof (EMU_SYSTEM_MEMORY
));
152 if (gSystemMemory
== NULL
) {
153 printf ("ERROR : Can not allocate memory for system. Exiting.\n");
157 // Allocate space for gSystemMemory Array
159 gFdInfoCount
= CountSeperatorsInString (FirmwareVolumesStr
, '!') + 1;
160 gFdInfo
= calloc (gFdInfoCount
, sizeof (EMU_FD_INFO
));
161 if (gFdInfo
== NULL
) {
162 printf ("ERROR : Can not allocate memory for fd info. Exiting.\n");
166 printf (" BootMode 0x%02x\n", (unsigned int)PcdGet32 (PcdEmuBootMode
));
169 // Open up a 128K file to emulate temp memory for SEC.
170 // on a real platform this would be SRAM, or using the cache as RAM.
171 // Set InitialStackMemory to zero so UnixOpenFile will allocate a new mapping
173 InitialStackMemorySize
= STACK_SIZE
;
174 InitialStackMemory
= (UINTN
)MapMemory (
175 0, (UINT32
) InitialStackMemorySize
,
176 PROT_READ
| PROT_WRITE
| PROT_EXEC
, MAP_ANONYMOUS
| MAP_PRIVATE
178 if (InitialStackMemory
== 0) {
179 printf ("ERROR : Can not open SecStack Exiting\n");
183 printf (" OS Emulator passing in %u KB of temp RAM at 0x%08lx to SEC\n",
184 (unsigned int)(InitialStackMemorySize
/ 1024),
185 (unsigned long)InitialStackMemory
188 for (StackPointer
= (UINTN
*) (UINTN
) InitialStackMemory
;
189 StackPointer
< (UINTN
*)(UINTN
)((UINTN
) InitialStackMemory
+ (UINT64
) InitialStackMemorySize
);
191 *StackPointer
= 0x5AA55AA5;
195 // Open All the firmware volumes and remember the info in the gFdInfo global
197 FileName
= (CHAR8
*)malloc (StrLen (FirmwareVolumesStr
) + 1);
198 if (FileName
== NULL
) {
199 printf ("ERROR : Can not allocate memory for firmware volume string\n");
204 for (Done
= FALSE
, Index
= 0, PeiIndex
= 0, SecFile
= NULL
;
205 FirmwareVolumesStr
[Index2
] != 0;
207 for (Index1
= 0; (FirmwareVolumesStr
[Index2
] != '!') && (FirmwareVolumesStr
[Index2
] != 0); Index2
++) {
208 FileName
[Index1
++] = FirmwareVolumesStr
[Index2
];
210 if (FirmwareVolumesStr
[Index2
] == '!') {
213 FileName
[Index1
] = '\0';
216 // Open the FD and remmeber where it got mapped into our processes address space
220 &gFdInfo
[Index
].Address
,
223 if (EFI_ERROR (Status
)) {
224 printf ("ERROR : Can not open Firmware Device File %s (%x). Exiting.\n", FileName
, (unsigned int)Status
);
228 printf (" FD loaded from %s at 0x%08lx",FileName
, (unsigned long)gFdInfo
[Index
].Address
);
230 if (SecFile
== NULL
) {
232 // Assume the beginning of the FD is an FV and look for the SEC Core.
233 // Load the first one we find.
236 Status
= PeiServicesFfsFindNextFile (
237 EFI_FV_FILETYPE_SECURITY_CORE
,
238 (EFI_PEI_FV_HANDLE
)(UINTN
)gFdInfo
[Index
].Address
,
241 if (!EFI_ERROR (Status
)) {
242 Status
= PeiServicesFfsFindSectionData (EFI_SECTION_PE32
, FileHandle
, &SecFile
);
243 if (!EFI_ERROR (Status
)) {
245 printf (" contains SEC Core");
253 // Calculate memory regions and store the information in the gSystemMemory
254 // global for later use. The autosizing code will use this data to
255 // map this memory into the SEC process memory space.
262 // Save the size of the memory.
264 while (MemorySizeStr
[Index1
] >= '0' && MemorySizeStr
[Index1
] <= '9') {
265 val
= val
* 10 + MemorySizeStr
[Index1
] - '0';
268 gSystemMemory
[Index
++].Size
= val
* 0x100000;
269 if (MemorySizeStr
[Index1
] == 0) {
280 SecLoadFromCore ((UINTN
) InitialStackMemory
, (UINTN
) InitialStackMemorySize
, (UINTN
) gFdInfo
[0].Address
, SecFile
);
283 // If we get here, then the SEC Core returned. This is an error as SEC should
284 // always hand off to PEI Core and then on to DXE Core.
286 printf ("ERROR : SEC returned\n");
291 EFI_PHYSICAL_ADDRESS
*
298 STATIC UINTN base
= 0x40000000;
299 CONST UINTN align
= (1 << 24);
301 BOOLEAN isAligned
= 0;
304 // Try to get an aligned block somewhere in the address space of this
307 while((!isAligned
) && (base
!= 0)) {
308 res
= mmap ((void *)base
, length
, prot
, flags
, fd
, 0);
309 if (res
== MAP_FAILED
) {
312 if ((((UINTN
)res
) & ~(align
-1)) == (UINTN
)res
) {
326 Opens and memory maps a file using Unix services. If BaseAddress is non zero
327 the process will try and allocate the memory starting at BaseAddress.
330 FileName - The name of the file to open and map
331 MapSize - The amount of the file to map in bytes
332 CreationDisposition - The flags to pass to CreateFile(). Use to create new files for
333 memory emulation, and exiting files for firmware volume emulation
334 BaseAddress - The base address of the mapped file in the user address space.
335 If passed in as NULL the a new memory region is used.
336 If passed in as non NULL the request memory region is used for
337 the mapping of the file into the process space.
338 Length - The size of the mapped region in bytes
341 EFI_SUCCESS - The file was opened and mapped.
342 EFI_NOT_FOUND - FileName was not found in the current directory
343 EFI_DEVICE_ERROR - An error occured attempting to map the opened file
349 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
357 fd
= open (FileName
, O_RDWR
);
359 return EFI_NOT_FOUND
;
361 FileSize
= lseek (fd
, 0, SEEK_END
);
364 res
= MapMemory (fd
, FileSize
, PROT_READ
| PROT_WRITE
| PROT_EXEC
, MAP_SHARED
);
369 perror ("MapFile() Failed");
370 return EFI_DEVICE_ERROR
;
373 *Length
= (UINT64
) FileSize
;
374 *BaseAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) res
;
384 This is the service to load the SEC Core from the Firmware Volume
387 LargestRegion - Memory to use for SEC.
388 LargestRegionSize - Size of Memory to use for PEI
389 BootFirmwareVolumeBase - Start of the Boot FV
390 PeiCorePe32File - SEC PE32
393 Success means control is transfered and thus we should never return
398 IN UINTN LargestRegion
,
399 IN UINTN LargestRegionSize
,
400 IN UINTN BootFirmwareVolumeBase
,
401 IN VOID
*PeiCorePe32File
405 EFI_PHYSICAL_ADDRESS TopOfMemory
;
407 EFI_PHYSICAL_ADDRESS PeiCoreEntryPoint
;
408 EFI_SEC_PEI_HAND_OFF
*SecCoreData
;
412 // Compute Top Of Memory for Stack and PEI Core Allocations
414 TopOfMemory
= LargestRegion
+ LargestRegionSize
;
415 PeiStackSize
= (UINTN
)RShiftU64((UINT64
)STACK_SIZE
,1);
418 // |-----------| <---- TemporaryRamBase + TemporaryRamSize
421 // |-----------| <---- StackBase / PeiTemporaryMemoryBase
424 // |-----------| <---- TemporaryRamBase
426 TopOfStack
= (VOID
*)(LargestRegion
+ PeiStackSize
);
427 TopOfMemory
= LargestRegion
+ PeiStackSize
;
430 // Reservet space for storing PeiCore's parament in stack.
432 TopOfStack
= (VOID
*)((UINTN
)TopOfStack
- sizeof (EFI_SEC_PEI_HAND_OFF
) - CPU_STACK_ALIGNMENT
);
433 TopOfStack
= ALIGN_POINTER (TopOfStack
, CPU_STACK_ALIGNMENT
);
437 // Bind this information into the SEC hand-off state
439 SecCoreData
= (EFI_SEC_PEI_HAND_OFF
*)(UINTN
) TopOfStack
;
440 SecCoreData
->DataSize
= sizeof(EFI_SEC_PEI_HAND_OFF
);
441 SecCoreData
->BootFirmwareVolumeBase
= (VOID
*)BootFirmwareVolumeBase
;
442 SecCoreData
->BootFirmwareVolumeSize
= PcdGet32 (PcdEmuFirmwareFdSize
);
443 SecCoreData
->TemporaryRamBase
= (VOID
*)(UINTN
)LargestRegion
;
444 SecCoreData
->TemporaryRamSize
= STACK_SIZE
;
445 SecCoreData
->StackBase
= SecCoreData
->TemporaryRamBase
;
446 SecCoreData
->StackSize
= PeiStackSize
;
447 SecCoreData
->PeiTemporaryRamBase
= (VOID
*) ((UINTN
) SecCoreData
->TemporaryRamBase
+ PeiStackSize
);
448 SecCoreData
->PeiTemporaryRamSize
= STACK_SIZE
- PeiStackSize
;
451 // Find the SEC Core Entry Point
453 Status
= SecPeCoffGetEntryPoint (PeiCorePe32File
, (VOID
**)&PeiCoreEntryPoint
);
454 if (EFI_ERROR (Status
)) {
459 // Transfer control to the SEC Core
462 (SWITCH_STACK_ENTRY_POINT
) (UINTN
) PeiCoreEntryPoint
,
468 // If we get here, then the SEC Core returned. This is an error
477 This service is called from Index == 0 until it returns EFI_UNSUPPORTED.
478 It allows discontiguous memory regions to be supported by the emulator.
479 It uses gSystemMemory[] and gSystemMemoryCount that were created by
480 parsing the host environment variable EFI_MEMORY_SIZE.
481 The size comes from the varaible and the address comes from the call to
485 Index - Which memory region to use
486 MemoryBase - Return Base address of memory region
487 MemorySize - Return size in bytes of the memory region
490 EFI_SUCCESS - If memory region was mapped
491 EFI_UNSUPPORTED - If Index is not supported
498 OUT EFI_PHYSICAL_ADDRESS
*MemoryBase
,
499 OUT UINT64
*MemorySize
504 if (Index
>= gSystemMemoryCount
) {
505 return EFI_UNSUPPORTED
;
510 0, gSystemMemory
[Index
].Size
,
511 PROT_READ
| PROT_WRITE
| PROT_EXEC
,
512 MAP_PRIVATE
| MAP_ANONYMOUS
514 if (res
== MAP_FAILED
) {
515 return EFI_DEVICE_ERROR
;
517 *MemorySize
= gSystemMemory
[Index
].Size
;
518 *MemoryBase
= (UINTN
)res
;
519 gSystemMemory
[Index
].Memory
= *MemoryBase
;
528 Since the SEC is the only Unix program in stack it must export
529 an interface to do POSIX calls. gUnix is initailized in UnixThunk.c.
532 InterfaceSize - sizeof (EFI_WIN_NT_THUNK_PROTOCOL);
533 InterfaceBase - Address of the gUnix global
536 EFI_SUCCESS - Data returned
545 return &gEmuThunkProtocol
;
552 SecPeCoffGetEntryPoint (
554 IN OUT VOID
**EntryPoint
558 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
560 ZeroMem (&ImageContext
, sizeof (ImageContext
));
561 ImageContext
.Handle
= Pe32Data
;
562 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) SecImageRead
;
564 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
565 if (EFI_ERROR (Status
)) {
570 // Relocate image to match the address where it resides
572 ImageContext
.ImageAddress
= (UINTN
)Pe32Data
;
573 Status
= PeCoffLoaderLoadImage (&ImageContext
);
574 if (EFI_ERROR (Status
)) {
578 Status
= PeCoffLoaderRelocateImage (&ImageContext
);
579 if (EFI_ERROR (Status
)) {
583 // On Unix a dlopen is done that will change the entry point
584 SecPeCoffRelocateImageExtraAction (&ImageContext
);
585 *EntryPoint
= (VOID
*)(UINTN
)ImageContext
.EntryPoint
;
595 Return the FD Size and base address. Since the FD is loaded from a
596 file into host memory only the SEC will know it's address.
599 Index - Which FD, starts at zero.
600 FdSize - Size of the FD in bytes
601 FdBase - Start address of the FD. Assume it points to an FV Header
602 FixUp - Difference between actual FD address and build address
605 EFI_SUCCESS - Return the Base address and size of the FV
606 EFI_UNSUPPORTED - Index does nto map to an FD in the system
613 IN OUT EFI_PHYSICAL_ADDRESS
*FdBase
,
614 IN OUT UINT64
*FdSize
,
615 IN OUT EFI_PHYSICAL_ADDRESS
*FixUp
618 if (Index
>= gFdInfoCount
) {
619 return EFI_UNSUPPORTED
;
622 *FdBase
= gFdInfo
[Index
].Address
;
623 *FdSize
= gFdInfo
[Index
].Size
;
626 if (*FdBase
== 0 && *FdSize
== 0) {
627 return EFI_UNSUPPORTED
;
632 // FD 0 has XIP code and well known PCD values
633 // If the memory buffer could not be allocated at the FD build address
634 // the Fixup is the difference.
636 *FixUp
= *FdBase
- PcdGet64 (PcdEmuFdBaseAddress
);
646 Count the number of seperators in String
649 String - String to process
650 Seperator - Item to count
653 Number of Seperator in String
657 CountSeperatorsInString (
658 IN
const CHAR16
*String
,
664 for (Count
= 0; *String
!= '\0'; String
++) {
665 if (*String
== Seperator
) {
679 IN OUT UINTN
*ReadSize
,
685 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
688 FileHandle - The handle to the PE/COFF file
689 FileOffset - The offset, in bytes, into the file to read
690 ReadSize - The number of bytes to read from the file starting at FileOffset
691 Buffer - A pointer to the buffer to read the data into.
694 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
702 Destination8
= Buffer
;
703 Source8
= (CHAR8
*) ((UINTN
) FileHandle
+ FileOffset
);
706 *(Destination8
++) = *(Source8
++);
716 Store the ModHandle in an array indexed by the Pdb File name.
717 The ModHandle is needed to unload the image.
720 ImageContext - Input data returned from PE Laoder Library. Used to find the
721 .PDB file name of the PE Image.
722 ModHandle - Returned from LoadLibraryEx() and stored for call to
726 EFI_SUCCESS - ModHandle was stored.
731 IN PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
,
736 IMAGE_CONTEXT_TO_MOD_HANDLE
*Array
;
740 Array
= mImageContextModHandleArray
;
741 for (Index
= 0; Index
< mImageContextModHandleArraySize
; Index
++, Array
++) {
742 if (Array
->ImageContext
== NULL
) {
744 // Make a copy of the stirng and store the ModHandle
746 Array
->ImageContext
= ImageContext
;
747 Array
->ModHandle
= ModHandle
;
753 // No free space in mImageContextModHandleArray so grow it by
754 // IMAGE_CONTEXT_TO_MOD_HANDLE entires. realloc will
755 // copy the old values to the new locaiton. But it does
756 // not zero the new memory area.
758 PreviousSize
= mImageContextModHandleArraySize
* sizeof (IMAGE_CONTEXT_TO_MOD_HANDLE
);
759 mImageContextModHandleArraySize
+= MAX_IMAGE_CONTEXT_TO_MOD_HANDLE_ARRAY_SIZE
;
761 mImageContextModHandleArray
= realloc (mImageContextModHandleArray
, mImageContextModHandleArraySize
* sizeof (IMAGE_CONTEXT_TO_MOD_HANDLE
));
762 if (mImageContextModHandleArray
== NULL
) {
764 return EFI_OUT_OF_RESOURCES
;
767 memset (mImageContextModHandleArray
+ PreviousSize
, 0, MAX_IMAGE_CONTEXT_TO_MOD_HANDLE_ARRAY_SIZE
* sizeof (IMAGE_CONTEXT_TO_MOD_HANDLE
));
769 return AddHandle (ImageContext
, ModHandle
);
776 Return the ModHandle and delete the entry in the array.
779 ImageContext - Input data returned from PE Laoder Library. Used to find the
780 .PDB file name of the PE Image.
783 ModHandle - ModHandle assoicated with ImageContext is returned
784 NULL - No ModHandle associated with ImageContext
789 IN PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
793 IMAGE_CONTEXT_TO_MOD_HANDLE
*Array
;
795 if (ImageContext
->PdbPointer
== NULL
) {
797 // If no PDB pointer there is no ModHandle so return NULL
802 Array
= mImageContextModHandleArray
;
803 for (Index
= 0; Index
< mImageContextModHandleArraySize
; Index
++, Array
++) {
804 if (Array
->ImageContext
== ImageContext
) {
806 // If you find a match return it and delete the entry
808 Array
->ImageContext
= NULL
;
809 return Array
->ModHandle
;
819 // Target for gdb breakpoint in a script that uses gGdbWorkingFileName to source a
820 // add-symbol-file command. Hey what can you say scripting in gdb is not that great....
822 // Put .gdbinit in the CWD where you do gdb SecMain.dll for source level debug
825 // b SecGdbScriptBreak
828 // source SecMain.gdb
848 IN CHAR8
*PdbFileName
853 if (PdbFileName
== NULL
) {
857 Len
= strlen (PdbFileName
);
858 if ((Len
< 5)|| (PdbFileName
[Len
- 4] != '.')) {
862 if ((PdbFileName
[Len
- 3] == 'P' || PdbFileName
[Len
- 3] == 'p') &&
863 (PdbFileName
[Len
- 2] == 'D' || PdbFileName
[Len
- 2] == 'd') &&
864 (PdbFileName
[Len
- 1] == 'B' || PdbFileName
[Len
- 1] == 'b')) {
872 #define MAX_SPRINT_BUFFER_SIZE 0x200
876 IN PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
879 if (ImageContext
->PdbPointer
== NULL
) {
881 "0x%08lx Loading NO DEBUG with entry point 0x%08lx\n",
882 (unsigned long)(ImageContext
->ImageAddress
),
883 (unsigned long)ImageContext
->EntryPoint
887 "0x%08lx Loading %s with entry point 0x%08lx\n",
888 (unsigned long)(ImageContext
->ImageAddress
+ ImageContext
->SizeOfHeaders
),
889 ImageContext
->PdbPointer
,
890 (unsigned long)ImageContext
->EntryPoint
893 // Keep output synced up
900 SecPeCoffRelocateImageExtraAction (
901 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
906 BOOLEAN EnabledOnEntry
;
909 // Make sure writting of the file is an atomic operation
911 if (SecInterruptEanbled ()) {
912 SecDisableInterrupt ();
913 EnabledOnEntry
= TRUE
;
915 EnabledOnEntry
= FALSE
;
918 PrintLoadAddress (ImageContext
);
921 // In mach-o (OS X executable) dlopen() can only load files in the MH_DYLIB of MH_BUNDLE format.
922 // To convert to PE/COFF we need to construct a mach-o with the MH_PRELOAD format. We create
923 // .dSYM files for the PE/COFF images that can be used by gdb for source level debugging.
928 // In the Mach-O to PE/COFF conversion the size of the PE/COFF headers is not accounted for.
929 // Thus we need to skip over the PE/COFF header when giving load addresses for our symbol table.
931 if (ImageContext
->PdbPointer
!= NULL
&& !IsPdbFile (ImageContext
->PdbPointer
)) {
933 // Now we have a database of the images that are currently loaded
937 // 'symbol-file' will clear out currnet symbol mappings in gdb.
938 // you can do a 'add-symbol-file filename address' for every image we loaded to get source
939 // level debug in gdb. Note Sec, being a true application will work differently.
941 // We add the PE/COFF header size into the image as the mach-O does not have a header in
942 // loaded into system memory.
944 // This gives us a data base of gdb commands and after something is unloaded that entry will be
945 // removed. We don't yet have the scheme of how to comunicate with gdb, but we have the
946 // data base of info ready to roll.
948 // We could use qXfer:libraries:read, but OS X GDB does not currently support it.
950 // <library name="/lib/libc.so.6"> // ImageContext->PdbPointer
951 // <segment address="0x10000000"/> // ImageContext->ImageAddress + ImageContext->SizeOfHeaders
957 // Write the file we need for the gdb script
959 GdbTempFile
= fopen (gGdbWorkingFileName
, "w");
960 if (GdbTempFile
!= NULL
) {
961 fprintf (GdbTempFile
, "add-symbol-file %s 0x%08lx\n", ImageContext
->PdbPointer
, (long unsigned int)(ImageContext
->ImageAddress
+ ImageContext
->SizeOfHeaders
));
962 fclose (GdbTempFile
);
965 // Target for gdb breakpoint in a script that uses gGdbWorkingFileName to set a breakpoint.
966 // Hey what can you say scripting in gdb is not that great....
968 SecGdbScriptBreak ();
973 AddHandle (ImageContext
, ImageContext
->PdbPointer
);
975 if (EnabledOnEntry
) {
976 SecEnableInterrupt ();
987 if (ImageContext
->PdbPointer
== NULL
) {
991 if (!IsPdbFile (ImageContext
->PdbPointer
)) {
997 "Loading %s 0x%08lx - entry point 0x%08lx\n",
998 ImageContext
->PdbPointer
,
999 (unsigned long)ImageContext
->ImageAddress
,
1000 (unsigned long)ImageContext
->EntryPoint
1003 Handle
= dlopen (ImageContext
->PdbPointer
, RTLD_NOW
);
1006 Entry
= dlsym (Handle
, "_ModuleEntryPoint");
1008 printf("%s\n", dlerror());
1011 if (Entry
!= NULL
) {
1012 ImageContext
->EntryPoint
= (UINTN
)Entry
;
1013 printf ("Change %s Entrypoint to :0x%08lx\n", ImageContext
->PdbPointer
, (unsigned long)Entry
);
1016 SecUnixLoaderBreak ();
1026 SecPeCoffUnloadImageExtraAction (
1027 IN PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
1032 Handle
= RemoveHandle (ImageContext
);
1036 BOOLEAN EnabledOnEntry
;
1038 if (Handle
!= NULL
) {
1040 // Need to skip .PDB files created from VC++
1042 if (!IsPdbFile (ImageContext
->PdbPointer
)) {
1043 if (SecInterruptEanbled ()) {
1044 SecDisableInterrupt ();
1045 EnabledOnEntry
= TRUE
;
1047 EnabledOnEntry
= FALSE
;
1051 // Write the file we need for the gdb script
1053 GdbTempFile
= fopen (gGdbWorkingFileName
, "w");
1054 if (GdbTempFile
!= NULL
) {
1055 fprintf (GdbTempFile
, "remove-symbol-file %s\n", ImageContext
->PdbPointer
);
1056 fclose (GdbTempFile
);
1059 // Target for gdb breakpoint in a script that uses gGdbWorkingFileName to set a breakpoint.
1060 // Hey what can you say scripting in gdb is not that great....
1062 SecGdbScriptBreak ();
1067 if (EnabledOnEntry
) {
1068 SecEnableInterrupt ();
1075 // Don't want to confuse gdb with symbols for something that got unloaded
1077 if (Handle
!= NULL
) {