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_RDONLY
);
359 return EFI_NOT_FOUND
;
361 FileSize
= lseek (fd
, 0, SEEK_END
);
364 res
= MapMemory (fd
, FileSize
, PROT_READ
| PROT_WRITE
| PROT_EXEC
, MAP_PRIVATE
);
368 if (res
== MAP_FAILED
) {
369 return EFI_DEVICE_ERROR
;
372 *Length
= (UINT64
) FileSize
;
373 *BaseAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) res
;
383 This is the service to load the SEC Core from the Firmware Volume
386 LargestRegion - Memory to use for SEC.
387 LargestRegionSize - Size of Memory to use for PEI
388 BootFirmwareVolumeBase - Start of the Boot FV
389 PeiCorePe32File - SEC PE32
392 Success means control is transfered and thus we should never return
397 IN UINTN LargestRegion
,
398 IN UINTN LargestRegionSize
,
399 IN UINTN BootFirmwareVolumeBase
,
400 IN VOID
*PeiCorePe32File
404 EFI_PHYSICAL_ADDRESS TopOfMemory
;
406 EFI_PHYSICAL_ADDRESS PeiCoreEntryPoint
;
407 EFI_SEC_PEI_HAND_OFF
*SecCoreData
;
411 // Compute Top Of Memory for Stack and PEI Core Allocations
413 TopOfMemory
= LargestRegion
+ LargestRegionSize
;
414 PeiStackSize
= (UINTN
)RShiftU64((UINT64
)STACK_SIZE
,1);
417 // |-----------| <---- TemporaryRamBase + TemporaryRamSize
420 // |-----------| <---- StackBase / PeiTemporaryMemoryBase
423 // |-----------| <---- TemporaryRamBase
425 TopOfStack
= (VOID
*)(LargestRegion
+ PeiStackSize
);
426 TopOfMemory
= LargestRegion
+ PeiStackSize
;
429 // Reservet space for storing PeiCore's parament in stack.
431 TopOfStack
= (VOID
*)((UINTN
)TopOfStack
- sizeof (EFI_SEC_PEI_HAND_OFF
) - CPU_STACK_ALIGNMENT
);
432 TopOfStack
= ALIGN_POINTER (TopOfStack
, CPU_STACK_ALIGNMENT
);
436 // Bind this information into the SEC hand-off state
438 SecCoreData
= (EFI_SEC_PEI_HAND_OFF
*)(UINTN
) TopOfStack
;
439 SecCoreData
->DataSize
= sizeof(EFI_SEC_PEI_HAND_OFF
);
440 SecCoreData
->BootFirmwareVolumeBase
= (VOID
*)BootFirmwareVolumeBase
;
441 SecCoreData
->BootFirmwareVolumeSize
= PcdGet32 (PcdEmuFirmwareFdSize
);
442 SecCoreData
->TemporaryRamBase
= (VOID
*)(UINTN
)LargestRegion
;
443 SecCoreData
->TemporaryRamSize
= STACK_SIZE
;
444 SecCoreData
->StackBase
= SecCoreData
->TemporaryRamBase
;
445 SecCoreData
->StackSize
= PeiStackSize
;
446 SecCoreData
->PeiTemporaryRamBase
= (VOID
*) ((UINTN
) SecCoreData
->TemporaryRamBase
+ PeiStackSize
);
447 SecCoreData
->PeiTemporaryRamSize
= STACK_SIZE
- PeiStackSize
;
450 // Find the SEC Core Entry Point
452 Status
= SecPeCoffGetEntryPoint (PeiCorePe32File
, (VOID
**)&PeiCoreEntryPoint
);
453 if (EFI_ERROR (Status
)) {
458 // Transfer control to the SEC Core
461 (SWITCH_STACK_ENTRY_POINT
) (UINTN
) PeiCoreEntryPoint
,
467 // If we get here, then the SEC Core returned. This is an error
476 This service is called from Index == 0 until it returns EFI_UNSUPPORTED.
477 It allows discontiguous memory regions to be supported by the emulator.
478 It uses gSystemMemory[] and gSystemMemoryCount that were created by
479 parsing the host environment variable EFI_MEMORY_SIZE.
480 The size comes from the varaible and the address comes from the call to
484 Index - Which memory region to use
485 MemoryBase - Return Base address of memory region
486 MemorySize - Return size in bytes of the memory region
489 EFI_SUCCESS - If memory region was mapped
490 EFI_UNSUPPORTED - If Index is not supported
497 OUT EFI_PHYSICAL_ADDRESS
*MemoryBase
,
498 OUT UINT64
*MemorySize
503 if (Index
>= gSystemMemoryCount
) {
504 return EFI_UNSUPPORTED
;
509 0, gSystemMemory
[Index
].Size
,
510 PROT_READ
| PROT_WRITE
| PROT_EXEC
,
511 MAP_PRIVATE
| MAP_ANONYMOUS
513 if (res
== MAP_FAILED
) {
514 return EFI_DEVICE_ERROR
;
516 *MemorySize
= gSystemMemory
[Index
].Size
;
517 *MemoryBase
= (UINTN
)res
;
518 gSystemMemory
[Index
].Memory
= *MemoryBase
;
527 Since the SEC is the only Unix program in stack it must export
528 an interface to do POSIX calls. gUnix is initailized in UnixThunk.c.
531 InterfaceSize - sizeof (EFI_WIN_NT_THUNK_PROTOCOL);
532 InterfaceBase - Address of the gUnix global
535 EFI_SUCCESS - Data returned
544 return &gEmuThunkProtocol
;
551 SecPeCoffGetEntryPoint (
553 IN OUT VOID
**EntryPoint
557 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
559 ZeroMem (&ImageContext
, sizeof (ImageContext
));
560 ImageContext
.Handle
= Pe32Data
;
561 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) SecImageRead
;
563 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
564 if (EFI_ERROR (Status
)) {
569 // Relocate image to match the address where it resides
571 ImageContext
.ImageAddress
= (UINTN
)Pe32Data
;
572 Status
= PeCoffLoaderLoadImage (&ImageContext
);
573 if (EFI_ERROR (Status
)) {
577 Status
= PeCoffLoaderRelocateImage (&ImageContext
);
578 if (EFI_ERROR (Status
)) {
582 // On Unix a dlopen is done that will change the entry point
583 SecPeCoffRelocateImageExtraAction (&ImageContext
);
584 *EntryPoint
= (VOID
*)(UINTN
)ImageContext
.EntryPoint
;
594 Return the FD Size and base address. Since the FD is loaded from a
595 file into host memory only the SEC will know it's address.
598 Index - Which FD, starts at zero.
599 FdSize - Size of the FD in bytes
600 FdBase - Start address of the FD. Assume it points to an FV Header
601 FixUp - Difference between actual FD address and build address
604 EFI_SUCCESS - Return the Base address and size of the FV
605 EFI_UNSUPPORTED - Index does nto map to an FD in the system
612 IN OUT EFI_PHYSICAL_ADDRESS
*FdBase
,
613 IN OUT UINT64
*FdSize
,
614 IN OUT EFI_PHYSICAL_ADDRESS
*FixUp
617 if (Index
>= gFdInfoCount
) {
618 return EFI_UNSUPPORTED
;
621 *FdBase
= gFdInfo
[Index
].Address
;
622 *FdSize
= gFdInfo
[Index
].Size
;
625 if (*FdBase
== 0 && *FdSize
== 0) {
626 return EFI_UNSUPPORTED
;
631 // FD 0 has XIP code and well known PCD values
632 // If the memory buffer could not be allocated at the FD build address
633 // the Fixup is the difference.
635 *FixUp
= *FdBase
- PcdGet64 (PcdEmuFdBaseAddress
);
645 Count the number of seperators in String
648 String - String to process
649 Seperator - Item to count
652 Number of Seperator in String
656 CountSeperatorsInString (
657 IN
const CHAR16
*String
,
663 for (Count
= 0; *String
!= '\0'; String
++) {
664 if (*String
== Seperator
) {
678 IN OUT UINTN
*ReadSize
,
684 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
687 FileHandle - The handle to the PE/COFF file
688 FileOffset - The offset, in bytes, into the file to read
689 ReadSize - The number of bytes to read from the file starting at FileOffset
690 Buffer - A pointer to the buffer to read the data into.
693 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
701 Destination8
= Buffer
;
702 Source8
= (CHAR8
*) ((UINTN
) FileHandle
+ FileOffset
);
705 *(Destination8
++) = *(Source8
++);
715 Store the ModHandle in an array indexed by the Pdb File name.
716 The ModHandle is needed to unload the image.
719 ImageContext - Input data returned from PE Laoder Library. Used to find the
720 .PDB file name of the PE Image.
721 ModHandle - Returned from LoadLibraryEx() and stored for call to
725 EFI_SUCCESS - ModHandle was stored.
730 IN PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
,
735 IMAGE_CONTEXT_TO_MOD_HANDLE
*Array
;
739 Array
= mImageContextModHandleArray
;
740 for (Index
= 0; Index
< mImageContextModHandleArraySize
; Index
++, Array
++) {
741 if (Array
->ImageContext
== NULL
) {
743 // Make a copy of the stirng and store the ModHandle
745 Array
->ImageContext
= ImageContext
;
746 Array
->ModHandle
= ModHandle
;
752 // No free space in mImageContextModHandleArray so grow it by
753 // IMAGE_CONTEXT_TO_MOD_HANDLE entires. realloc will
754 // copy the old values to the new locaiton. But it does
755 // not zero the new memory area.
757 PreviousSize
= mImageContextModHandleArraySize
* sizeof (IMAGE_CONTEXT_TO_MOD_HANDLE
);
758 mImageContextModHandleArraySize
+= MAX_IMAGE_CONTEXT_TO_MOD_HANDLE_ARRAY_SIZE
;
760 mImageContextModHandleArray
= realloc (mImageContextModHandleArray
, mImageContextModHandleArraySize
* sizeof (IMAGE_CONTEXT_TO_MOD_HANDLE
));
761 if (mImageContextModHandleArray
== NULL
) {
763 return EFI_OUT_OF_RESOURCES
;
766 memset (mImageContextModHandleArray
+ PreviousSize
, 0, MAX_IMAGE_CONTEXT_TO_MOD_HANDLE_ARRAY_SIZE
* sizeof (IMAGE_CONTEXT_TO_MOD_HANDLE
));
768 return AddHandle (ImageContext
, ModHandle
);
775 Return the ModHandle and delete the entry in the array.
778 ImageContext - Input data returned from PE Laoder Library. Used to find the
779 .PDB file name of the PE Image.
782 ModHandle - ModHandle assoicated with ImageContext is returned
783 NULL - No ModHandle associated with ImageContext
788 IN PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
792 IMAGE_CONTEXT_TO_MOD_HANDLE
*Array
;
794 if (ImageContext
->PdbPointer
== NULL
) {
796 // If no PDB pointer there is no ModHandle so return NULL
801 Array
= mImageContextModHandleArray
;
802 for (Index
= 0; Index
< mImageContextModHandleArraySize
; Index
++, Array
++) {
803 if (Array
->ImageContext
== ImageContext
) {
805 // If you find a match return it and delete the entry
807 Array
->ImageContext
= NULL
;
808 return Array
->ModHandle
;
818 // Target for gdb breakpoint in a script that uses gGdbWorkingFileName to source a
819 // add-symbol-file command. Hey what can you say scripting in gdb is not that great....
821 // Put .gdbinit in the CWD where you do gdb SecMain.dll for source level debug
824 // b SecGdbScriptBreak
827 // source SecMain.gdb
847 IN CHAR8
*PdbFileName
852 if (PdbFileName
== NULL
) {
856 Len
= strlen (PdbFileName
);
857 if ((Len
< 5)|| (PdbFileName
[Len
- 4] != '.')) {
861 if ((PdbFileName
[Len
- 3] == 'P' || PdbFileName
[Len
- 3] == 'p') &&
862 (PdbFileName
[Len
- 2] == 'D' || PdbFileName
[Len
- 2] == 'd') &&
863 (PdbFileName
[Len
- 1] == 'B' || PdbFileName
[Len
- 1] == 'b')) {
871 #define MAX_SPRINT_BUFFER_SIZE 0x200
875 IN PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
878 if (ImageContext
->PdbPointer
== NULL
) {
880 "0x%08lx Loading NO DEBUG with entry point 0x%08lx\n",
881 (unsigned long)(ImageContext
->ImageAddress
),
882 (unsigned long)ImageContext
->EntryPoint
886 "0x%08lx Loading %s with entry point 0x%08lx\n",
887 (unsigned long)(ImageContext
->ImageAddress
+ ImageContext
->SizeOfHeaders
),
888 ImageContext
->PdbPointer
,
889 (unsigned long)ImageContext
->EntryPoint
892 // Keep output synced up
899 SecPeCoffRelocateImageExtraAction (
900 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
905 BOOLEAN EnabledOnEntry
;
908 // Make sure writting of the file is an atomic operation
910 if (SecInterruptEanbled ()) {
911 SecDisableInterrupt ();
912 EnabledOnEntry
= TRUE
;
914 EnabledOnEntry
= FALSE
;
917 PrintLoadAddress (ImageContext
);
920 // In mach-o (OS X executable) dlopen() can only load files in the MH_DYLIB of MH_BUNDLE format.
921 // To convert to PE/COFF we need to construct a mach-o with the MH_PRELOAD format. We create
922 // .dSYM files for the PE/COFF images that can be used by gdb for source level debugging.
927 // In the Mach-O to PE/COFF conversion the size of the PE/COFF headers is not accounted for.
928 // Thus we need to skip over the PE/COFF header when giving load addresses for our symbol table.
930 if (ImageContext
->PdbPointer
!= NULL
&& !IsPdbFile (ImageContext
->PdbPointer
)) {
932 // Now we have a database of the images that are currently loaded
936 // 'symbol-file' will clear out currnet symbol mappings in gdb.
937 // you can do a 'add-symbol-file filename address' for every image we loaded to get source
938 // level debug in gdb. Note Sec, being a true application will work differently.
940 // We add the PE/COFF header size into the image as the mach-O does not have a header in
941 // loaded into system memory.
943 // This gives us a data base of gdb commands and after something is unloaded that entry will be
944 // removed. We don't yet have the scheme of how to comunicate with gdb, but we have the
945 // data base of info ready to roll.
947 // We could use qXfer:libraries:read, but OS X GDB does not currently support it.
949 // <library name="/lib/libc.so.6"> // ImageContext->PdbPointer
950 // <segment address="0x10000000"/> // ImageContext->ImageAddress + ImageContext->SizeOfHeaders
956 // Write the file we need for the gdb script
958 GdbTempFile
= fopen (gGdbWorkingFileName
, "w");
959 if (GdbTempFile
!= NULL
) {
960 fprintf (GdbTempFile
, "add-symbol-file %s 0x%08lx\n", ImageContext
->PdbPointer
, (long unsigned int)(ImageContext
->ImageAddress
+ ImageContext
->SizeOfHeaders
));
961 fclose (GdbTempFile
);
964 // Target for gdb breakpoint in a script that uses gGdbWorkingFileName to set a breakpoint.
965 // Hey what can you say scripting in gdb is not that great....
967 SecGdbScriptBreak ();
972 AddHandle (ImageContext
, ImageContext
->PdbPointer
);
974 if (EnabledOnEntry
) {
975 SecEnableInterrupt ();
986 if (ImageContext
->PdbPointer
== NULL
) {
990 if (!IsPdbFile (ImageContext
->PdbPointer
)) {
996 "Loading %s 0x%08lx - entry point 0x%08lx\n",
997 ImageContext
->PdbPointer
,
998 (unsigned long)ImageContext
->ImageAddress
,
999 (unsigned long)ImageContext
->EntryPoint
1002 Handle
= dlopen (ImageContext
->PdbPointer
, RTLD_NOW
);
1005 Entry
= dlsym (Handle
, "_ModuleEntryPoint");
1007 printf("%s\n", dlerror());
1010 if (Entry
!= NULL
) {
1011 ImageContext
->EntryPoint
= (UINTN
)Entry
;
1012 printf ("Change %s Entrypoint to :0x%08lx\n", ImageContext
->PdbPointer
, (unsigned long)Entry
);
1015 SecUnixLoaderBreak ();
1025 SecPeCoffUnloadImageExtraAction (
1026 IN PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
1031 Handle
= RemoveHandle (ImageContext
);
1035 BOOLEAN EnabledOnEntry
;
1037 if (Handle
!= NULL
) {
1039 // Need to skip .PDB files created from VC++
1041 if (!IsPdbFile (ImageContext
->PdbPointer
)) {
1042 if (SecInterruptEanbled ()) {
1043 SecDisableInterrupt ();
1044 EnabledOnEntry
= TRUE
;
1046 EnabledOnEntry
= FALSE
;
1050 // Write the file we need for the gdb script
1052 GdbTempFile
= fopen (gGdbWorkingFileName
, "w");
1053 if (GdbTempFile
!= NULL
) {
1054 fprintf (GdbTempFile
, "remove-symbol-file %s\n", ImageContext
->PdbPointer
);
1055 fclose (GdbTempFile
);
1058 // Target for gdb breakpoint in a script that uses gGdbWorkingFileName to set a breakpoint.
1059 // Hey what can you say scripting in gdb is not that great....
1061 SecGdbScriptBreak ();
1066 if (EnabledOnEntry
) {
1067 SecEnableInterrupt ();
1074 // Don't want to confuse gdb with symbols for something that got unloaded
1076 if (Handle
!= NULL
) {