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
,
31 GasketSecUnixPeiLoadFile
34 EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mSecTemporaryRamSupportPpi
= {
35 GasketSecTemporaryRamSupport
41 // Default information about where the FD is located.
42 // This array gets filled in with information from EFI_FIRMWARE_VOLUMES
43 // EFI_FIRMWARE_VOLUMES is a host environment variable set by system.cmd.
44 // The number of array elements is allocated base on parsing
45 // EFI_FIRMWARE_VOLUMES and the memory is never freed.
47 UINTN gFdInfoCount
= 0;
51 // Array that supports seperate memory rantes.
52 // The memory ranges are set in system.cmd via the EFI_MEMORY_SIZE variable.
53 // The number of array elements is allocated base on parsing
54 // EFI_MEMORY_SIZE and the memory is never freed.
56 UINTN gSystemMemoryCount
= 0;
57 EMU_SYSTEM_MEMORY
*gSystemMemory
;
61 UINTN mImageContextModHandleArraySize
= 0;
62 IMAGE_CONTEXT_TO_MOD_HANDLE
*mImageContextModHandleArray
= NULL
;
66 EFI_PHYSICAL_ADDRESS
*
76 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
82 SecNt32PeCoffRelocateImage (
83 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
96 Main entry point to SEC for Unix. This is a unix program
99 Argc - Number of command line arguments
100 Argv - Array of command line argument strings
101 Envp - Array of environmemt variable strings
110 EFI_PHYSICAL_ADDRESS InitialStackMemory
;
111 UINT64 InitialStackMemorySize
;
119 CHAR16
*MemorySizeStr
;
120 CHAR16
*FirmwareVolumesStr
;
126 MemorySizeStr
= (CHAR16
*) PcdGetPtr (PcdEmuMemorySize
);
127 FirmwareVolumesStr
= (CHAR16
*) PcdGetPtr (PcdEmuFirmwareVolume
);
129 printf ("\nEDK SEC Main UNIX Emulation Environment from edk2.sourceforge.net\n");
132 // PPIs pased into PEI_CORE
134 AddThunkPpi (EFI_PEI_PPI_DESCRIPTOR_PPI
, &gEfiTemporaryRamSupportPpiGuid
, &mSecTemporaryRamSupportPpi
);
135 AddThunkPpi (EFI_PEI_PPI_DESCRIPTOR_PPI
, &gEmuThunkPpiGuid
, &mSecEmuThunkPpi
);
136 AddThunkPpi (EFI_PEI_PPI_DESCRIPTOR_PPI
, &gEmuPeiServicesTableUpdatePpiGuid
, NULL
);
138 SecInitThunkProtocol ();
141 // Emulator Bus Driver Thunks
143 AddThunkProtocol (&gX11ThunkIo
, (CHAR16
*)PcdGetPtr (PcdEmuGop
), TRUE
);
144 AddThunkProtocol (&gPosixFileSystemThunkIo
, (CHAR16
*)PcdGetPtr (PcdEmuFileSystem
), TRUE
);
147 // Emulator other Thunks
149 AddThunkProtocol (&gPthreadThunkIo
, (CHAR16
*)PcdGetPtr (PcdEmuApCount
), FALSE
);
151 // EmuSecLibConstructor ();
155 // We can't use dlopen on OS X, so we need a scheme to get symboles into gdb
156 // We need to create a temp file that contains gdb commands so we can load
157 // symbols when we load every PE/COFF image.
159 Index
= strlen (*Argv
);
160 gGdbWorkingFileName
= malloc (Index
+ strlen(".gdb") + 1);
161 strcpy (gGdbWorkingFileName
, *Argv
);
162 strcat (gGdbWorkingFileName
, ".gdb");
167 // Allocate space for gSystemMemory Array
169 gSystemMemoryCount
= CountSeperatorsInString (MemorySizeStr
, '!') + 1;
170 gSystemMemory
= calloc (gSystemMemoryCount
, sizeof (EMU_SYSTEM_MEMORY
));
171 if (gSystemMemory
== NULL
) {
172 printf ("ERROR : Can not allocate memory for system. Exiting.\n");
176 // Allocate space for gSystemMemory Array
178 gFdInfoCount
= CountSeperatorsInString (FirmwareVolumesStr
, '!') + 1;
179 gFdInfo
= calloc (gFdInfoCount
, sizeof (EMU_FD_INFO
));
180 if (gFdInfo
== NULL
) {
181 printf ("ERROR : Can not allocate memory for fd info. Exiting.\n");
185 printf (" BootMode 0x%02x\n", (unsigned int)PcdGet32 (PcdEmuBootMode
));
188 // Open up a 128K file to emulate temp memory for PEI.
189 // on a real platform this would be SRAM, or using the cache as RAM.
190 // Set InitialStackMemory to zero so UnixOpenFile will allocate a new mapping
192 InitialStackMemorySize
= STACK_SIZE
;
193 InitialStackMemory
= (UINTN
)MapMemory(0,
194 (UINT32
) InitialStackMemorySize
,
195 PROT_READ
| PROT_WRITE
| PROT_EXEC
,
196 MAP_ANONYMOUS
| MAP_PRIVATE
);
197 if (InitialStackMemory
== 0) {
198 printf ("ERROR : Can not open SecStack Exiting\n");
202 printf (" SEC passing in %u KB of temp RAM at 0x%08lx to PEI\n",
203 (unsigned int)(InitialStackMemorySize
/ 1024),
204 (unsigned long)InitialStackMemory
);
206 for (StackPointer
= (UINTN
*) (UINTN
) InitialStackMemory
;
207 StackPointer
< (UINTN
*)(UINTN
)((UINTN
) InitialStackMemory
+ (UINT64
) InitialStackMemorySize
);
209 *StackPointer
= 0x5AA55AA5;
213 // Open All the firmware volumes and remember the info in the gFdInfo global
215 FileName
= (CHAR8
*)malloc (StrLen (FirmwareVolumesStr
) + 1);
216 if (FileName
== NULL
) {
217 printf ("ERROR : Can not allocate memory for firmware volume string\n");
222 for (Done
= FALSE
, Index
= 0, PeiIndex
= 0, PeiCoreFile
= NULL
;
223 FirmwareVolumesStr
[Index2
] != 0;
225 for (Index1
= 0; (FirmwareVolumesStr
[Index2
] != '!') && (FirmwareVolumesStr
[Index2
] != 0); Index2
++)
226 FileName
[Index1
++] = FirmwareVolumesStr
[Index2
];
227 if (FirmwareVolumesStr
[Index2
] == '!')
229 FileName
[Index1
] = '\0';
232 // Open the FD and remmeber where it got mapped into our processes address space
236 &gFdInfo
[Index
].Address
,
239 if (EFI_ERROR (Status
)) {
240 printf ("ERROR : Can not open Firmware Device File %s (%x). Exiting.\n", FileName
, (unsigned int)Status
);
244 printf (" FD loaded from %s at 0x%08lx",
245 FileName
, (unsigned long)gFdInfo
[Index
].Address
);
247 if (PeiCoreFile
== NULL
) {
249 // Assume the beginning of the FD is an FV and look for the PEI Core.
250 // Load the first one we find.
252 Status
= SecFfsFindPeiCore ((EFI_FIRMWARE_VOLUME_HEADER
*) (UINTN
) gFdInfo
[Index
].Address
, &PeiCoreFile
);
253 if (!EFI_ERROR (Status
)) {
255 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)
286 // Hand off to PEI Core
288 SecLoadFromCore ((UINTN
) InitialStackMemory
, (UINTN
) InitialStackMemorySize
, (UINTN
) gFdInfo
[0].Address
, PeiCoreFile
);
291 // If we get here, then the PEI Core returned. This is an error as PEI should
292 // always hand off to DXE.
294 printf ("ERROR : PEI Core returned\n");
298 EFI_PHYSICAL_ADDRESS
*
305 STATIC UINTN base
= 0x40000000;
306 CONST UINTN align
= (1 << 24);
308 BOOLEAN isAligned
= 0;
311 // Try to get an aligned block somewhere in the address space of this
314 while((!isAligned
) && (base
!= 0)) {
315 res
= mmap ((void *)base
, length
, prot
, flags
, fd
, 0);
316 if (res
== MAP_FAILED
) {
319 if ((((UINTN
)res
) & ~(align
-1)) == (UINTN
)res
) {
333 IN OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
,
339 Opens and memory maps a file using Unix services. If BaseAddress is non zero
340 the process will try and allocate the memory starting at BaseAddress.
343 FileName - The name of the file to open and map
344 MapSize - The amount of the file to map in bytes
345 CreationDisposition - The flags to pass to CreateFile(). Use to create new files for
346 memory emulation, and exiting files for firmware volume emulation
347 BaseAddress - The base address of the mapped file in the user address space.
348 If passed in as NULL the a new memory region is used.
349 If passed in as non NULL the request memory region is used for
350 the mapping of the file into the process space.
351 Length - The size of the mapped region in bytes
354 EFI_SUCCESS - The file was opened and mapped.
355 EFI_NOT_FOUND - FileName was not found in the current directory
356 EFI_DEVICE_ERROR - An error occured attempting to map the opened file
364 fd
= open (FileName
, O_RDONLY
);
366 return EFI_NOT_FOUND
;
367 FileSize
= lseek (fd
, 0, SEEK_END
);
370 res
= MapMemory(fd
, FileSize
, PROT_READ
| PROT_WRITE
| PROT_EXEC
, MAP_PRIVATE
);
374 if (res
== MAP_FAILED
)
375 return EFI_DEVICE_ERROR
;
377 *Length
= (UINT64
) FileSize
;
378 *BaseAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) res
;
387 IN UINTN LargestRegion
,
388 IN UINTN LargestRegionSize
,
389 IN UINTN BootFirmwareVolumeBase
,
390 IN VOID
*PeiCorePe32File
395 This is the service to load the PEI Core from the Firmware Volume
398 LargestRegion - Memory to use for PEI.
399 LargestRegionSize - Size of Memory to use for PEI
400 BootFirmwareVolumeBase - Start of the Boot FV
401 PeiCorePe32File - PEI Core PE32
404 Success means control is transfered and thus we should never return
409 EFI_PHYSICAL_ADDRESS TopOfMemory
;
412 EFI_PHYSICAL_ADDRESS PeiCoreEntryPoint
;
413 EFI_PHYSICAL_ADDRESS PeiImageAddress
;
414 EFI_SEC_PEI_HAND_OFF
*SecCoreData
;
418 // Compute Top Of Memory for Stack and PEI Core Allocations
420 TopOfMemory
= LargestRegion
+ LargestRegionSize
;
421 PeiStackSize
= (UINTN
)RShiftU64((UINT64
)STACK_SIZE
,1);
424 // |-----------| <---- TemporaryRamBase + TemporaryRamSize
427 // |-----------| <---- StackBase / PeiTemporaryMemoryBase
430 // |-----------| <---- TemporaryRamBase
432 TopOfStack
= (VOID
*)(LargestRegion
+ PeiStackSize
);
433 TopOfMemory
= LargestRegion
+ PeiStackSize
;
436 // Reservet space for storing PeiCore's parament in stack.
438 TopOfStack
= (VOID
*)((UINTN
)TopOfStack
- sizeof (EFI_SEC_PEI_HAND_OFF
) - CPU_STACK_ALIGNMENT
);
439 TopOfStack
= ALIGN_POINTER (TopOfStack
, CPU_STACK_ALIGNMENT
);
443 // Bind this information into the SEC hand-off state
445 SecCoreData
= (EFI_SEC_PEI_HAND_OFF
*)(UINTN
) TopOfStack
;
446 SecCoreData
->DataSize
= sizeof(EFI_SEC_PEI_HAND_OFF
);
447 SecCoreData
->BootFirmwareVolumeBase
= (VOID
*)BootFirmwareVolumeBase
;
448 SecCoreData
->BootFirmwareVolumeSize
= PcdGet32 (PcdEmuFirmwareFdSize
);
449 SecCoreData
->TemporaryRamBase
= (VOID
*)(UINTN
)LargestRegion
;
450 SecCoreData
->TemporaryRamSize
= STACK_SIZE
;
451 SecCoreData
->StackBase
= SecCoreData
->TemporaryRamBase
;
452 SecCoreData
->StackSize
= PeiStackSize
;
453 SecCoreData
->PeiTemporaryRamBase
= (VOID
*) ((UINTN
) SecCoreData
->TemporaryRamBase
+ PeiStackSize
);
454 SecCoreData
->PeiTemporaryRamSize
= STACK_SIZE
- PeiStackSize
;
457 // Load the PEI Core from a Firmware Volume
459 Status
= SecUnixPeiLoadFile (
465 if (EFI_ERROR (Status
)) {
470 // Transfer control to the PEI Core
473 (SWITCH_STACK_ENTRY_POINT
) (UINTN
) PeiCoreEntryPoint
,
475 (VOID
*)GetThunkPpiList (),
480 // If we get here, then the PEI Core returned. This is an error
489 OUT EFI_PHYSICAL_ADDRESS
*MemoryBase
,
490 OUT UINT64
*MemorySize
495 This service is called from Index == 0 until it returns EFI_UNSUPPORTED.
496 It allows discontiguous memory regions to be supported by the emulator.
497 It uses gSystemMemory[] and gSystemMemoryCount that were created by
498 parsing the host environment variable EFI_MEMORY_SIZE.
499 The size comes from the varaible and the address comes from the call to
503 Index - Which memory region to use
504 MemoryBase - Return Base address of memory region
505 MemorySize - Return size in bytes of the memory region
508 EFI_SUCCESS - If memory region was mapped
509 EFI_UNSUPPORTED - If Index is not supported
515 if (Index
>= gSystemMemoryCount
) {
516 return EFI_UNSUPPORTED
;
520 res
= MapMemory(0, gSystemMemory
[Index
].Size
,
521 PROT_READ
| PROT_WRITE
| PROT_EXEC
,
522 MAP_PRIVATE
| MAP_ANONYMOUS
);
523 if (res
== MAP_FAILED
)
524 return EFI_DEVICE_ERROR
;
525 *MemorySize
= gSystemMemory
[Index
].Size
;
526 *MemoryBase
= (UINTN
)res
;
527 gSystemMemory
[Index
].Memory
= *MemoryBase
;
540 Since the SEC is the only Unix program in stack it must export
541 an interface to do POSIX calls. gUnix is initailized in UnixThunk.c.
544 InterfaceSize - sizeof (EFI_WIN_NT_THUNK_PROTOCOL);
545 InterfaceBase - Address of the gUnix global
548 EFI_SUCCESS - Data returned
552 return &gEmuThunkProtocol
;
559 OUT EFI_PHYSICAL_ADDRESS
*ImageAddress
,
560 OUT UINT64
*ImageSize
,
561 OUT EFI_PHYSICAL_ADDRESS
*EntryPoint
566 Loads and relocates a PE/COFF image into memory.
569 Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated
570 ImageAddress - The base address of the relocated PE/COFF image
571 ImageSize - The size of the relocated PE/COFF image
572 EntryPoint - The entry point of the relocated PE/COFF image
575 EFI_SUCCESS - The file was loaded and relocated
576 EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file
581 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
583 ZeroMem (&ImageContext
, sizeof (ImageContext
));
584 ImageContext
.Handle
= Pe32Data
;
586 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) SecImageRead
;
588 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
589 if (EFI_ERROR (Status
)) {
595 // Allocate space in UNIX (not emulator) memory. Extra space is for alignment
597 ImageContext
.ImageAddress
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) MapMemory (
599 (UINT32
) (ImageContext
.ImageSize
+ (ImageContext
.SectionAlignment
* 2)),
600 PROT_READ
| PROT_WRITE
| PROT_EXEC
,
601 MAP_ANONYMOUS
| MAP_PRIVATE
603 if (ImageContext
.ImageAddress
== 0) {
604 return EFI_OUT_OF_RESOURCES
;
608 // Align buffer on section boundry
610 ImageContext
.ImageAddress
+= ImageContext
.SectionAlignment
- 1;
611 ImageContext
.ImageAddress
&= ~((EFI_PHYSICAL_ADDRESS
)(ImageContext
.SectionAlignment
- 1));
614 Status
= PeCoffLoaderLoadImage (&ImageContext
);
615 if (EFI_ERROR (Status
)) {
619 Status
= PeCoffLoaderRelocateImage (&ImageContext
);
620 if (EFI_ERROR (Status
)) {
625 SecPeCoffRelocateImageExtraAction (&ImageContext
);
628 // BugBug: Flush Instruction Cache Here when CPU Lib is ready
631 *ImageAddress
= ImageContext
.ImageAddress
;
632 *ImageSize
= ImageContext
.ImageSize
;
633 *EntryPoint
= ImageContext
.EntryPoint
;
641 SecPeCoffGetEntryPoint (
643 IN OUT VOID
**EntryPoint
647 EFI_PHYSICAL_ADDRESS ImageAddress
;
649 EFI_PHYSICAL_ADDRESS PhysEntryPoint
;
651 Status
= SecUnixPeiLoadFile (Pe32Data
, &ImageAddress
, &ImageSize
, &PhysEntryPoint
);
653 *EntryPoint
= (VOID
*)(UINTN
)PhysEntryPoint
;
663 IN OUT EFI_PHYSICAL_ADDRESS
*FdBase
,
664 IN OUT UINT64
*FdSize
,
665 IN OUT EFI_PHYSICAL_ADDRESS
*FixUp
670 Return the FD Size and base address. Since the FD is loaded from a
671 file into host memory only the SEC will know it's address.
674 Index - Which FD, starts at zero.
675 FdSize - Size of the FD in bytes
676 FdBase - Start address of the FD. Assume it points to an FV Header
677 FixUp - Difference between actual FD address and build address
680 EFI_SUCCESS - Return the Base address and size of the FV
681 EFI_UNSUPPORTED - Index does nto map to an FD in the system
685 if (Index
>= gFdInfoCount
) {
686 return EFI_UNSUPPORTED
;
689 *FdBase
= gFdInfo
[Index
].Address
;
690 *FdSize
= gFdInfo
[Index
].Size
;
693 if (*FdBase
== 0 && *FdSize
== 0) {
694 return EFI_UNSUPPORTED
;
699 // FD 0 has XIP code and well known PCD values
700 // If the memory buffer could not be allocated at the FD build address
701 // the Fixup is the difference.
703 *FixUp
= *FdBase
- PcdGet64 (PcdEmuFdBaseAddress
);
714 IN OUT UINTN
*ReadSize
,
720 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
723 FileHandle - The handle to the PE/COFF file
724 FileOffset - The offset, in bytes, into the file to read
725 ReadSize - The number of bytes to read from the file starting at FileOffset
726 Buffer - A pointer to the buffer to read the data into.
729 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
737 Destination8
= Buffer
;
738 Source8
= (CHAR8
*) ((UINTN
) FileHandle
+ FileOffset
);
741 *(Destination8
++) = *(Source8
++);
748 CountSeperatorsInString (
749 IN
const CHAR16
*String
,
755 Count the number of seperators in String
758 String - String to process
759 Seperator - Item to count
762 Number of Seperator in String
768 for (Count
= 0; *String
!= '\0'; String
++) {
769 if (*String
== Seperator
) {
780 IN PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
,
786 Store the ModHandle in an array indexed by the Pdb File name.
787 The ModHandle is needed to unload the image.
790 ImageContext - Input data returned from PE Laoder Library. Used to find the
791 .PDB file name of the PE Image.
792 ModHandle - Returned from LoadLibraryEx() and stored for call to
796 EFI_SUCCESS - ModHandle was stored.
801 IMAGE_CONTEXT_TO_MOD_HANDLE
*Array
;
805 Array
= mImageContextModHandleArray
;
806 for (Index
= 0; Index
< mImageContextModHandleArraySize
; Index
++, Array
++) {
807 if (Array
->ImageContext
== NULL
) {
809 // Make a copy of the stirng and store the ModHandle
811 Array
->ImageContext
= ImageContext
;
812 Array
->ModHandle
= ModHandle
;
818 // No free space in mImageContextModHandleArray so grow it by
819 // IMAGE_CONTEXT_TO_MOD_HANDLE entires. realloc will
820 // copy the old values to the new locaiton. But it does
821 // not zero the new memory area.
823 PreviousSize
= mImageContextModHandleArraySize
* sizeof (IMAGE_CONTEXT_TO_MOD_HANDLE
);
824 mImageContextModHandleArraySize
+= MAX_IMAGE_CONTEXT_TO_MOD_HANDLE_ARRAY_SIZE
;
826 mImageContextModHandleArray
= realloc (mImageContextModHandleArray
, mImageContextModHandleArraySize
* sizeof (IMAGE_CONTEXT_TO_MOD_HANDLE
));
827 if (mImageContextModHandleArray
== NULL
) {
829 return EFI_OUT_OF_RESOURCES
;
832 memset (mImageContextModHandleArray
+ PreviousSize
, 0, MAX_IMAGE_CONTEXT_TO_MOD_HANDLE_ARRAY_SIZE
* sizeof (IMAGE_CONTEXT_TO_MOD_HANDLE
));
834 return AddHandle (ImageContext
, ModHandle
);
840 IN PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
845 Return the ModHandle and delete the entry in the array.
848 ImageContext - Input data returned from PE Laoder Library. Used to find the
849 .PDB file name of the PE Image.
852 ModHandle - ModHandle assoicated with ImageContext is returned
853 NULL - No ModHandle associated with ImageContext
858 IMAGE_CONTEXT_TO_MOD_HANDLE
*Array
;
860 if (ImageContext
->PdbPointer
== NULL
) {
862 // If no PDB pointer there is no ModHandle so return NULL
867 Array
= mImageContextModHandleArray
;
868 for (Index
= 0; Index
< mImageContextModHandleArraySize
; Index
++, Array
++) {
869 if (Array
->ImageContext
== ImageContext
) {
871 // If you find a match return it and delete the entry
873 Array
->ImageContext
= NULL
;
874 return Array
->ModHandle
;
884 // Target for gdb breakpoint in a script that uses gGdbWorkingFileName to source a
885 // add-symbol-file command. Hey what can you say scripting in gdb is not that great....
887 // Put .gdbinit in the CWD where you do gdb SecMain.dll for source level debug
890 // b SecGdbScriptBreak
893 // source SecMain.dll.gdb
913 IN CHAR8
*PdbFileName
918 if (PdbFileName
== NULL
) {
922 Len
= strlen (PdbFileName
);
923 if ((Len
< 5)|| (PdbFileName
[Len
- 4] != '.')) {
927 if ((PdbFileName
[Len
- 3] == 'P' || PdbFileName
[Len
- 3] == 'p') &&
928 (PdbFileName
[Len
- 2] == 'D' || PdbFileName
[Len
- 2] == 'd') &&
929 (PdbFileName
[Len
- 1] == 'B' || PdbFileName
[Len
- 1] == 'b')) {
937 #define MAX_SPRINT_BUFFER_SIZE 0x200
941 IN PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
944 if (ImageContext
->PdbPointer
== NULL
) {
946 "0x%08lx Loading NO DEBUG with entry point 0x%08lx\n",
947 (unsigned long)(ImageContext
->ImageAddress
),
948 (unsigned long)ImageContext
->EntryPoint
952 "0x%08lx Loading %s with entry point 0x%08lx\n",
953 (unsigned long)(ImageContext
->ImageAddress
+ ImageContext
->SizeOfHeaders
),
954 ImageContext
->PdbPointer
,
955 (unsigned long)ImageContext
->EntryPoint
958 // Keep output synced up
965 SecPeCoffRelocateImageExtraAction (
966 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
971 BOOLEAN EnabledOnEntry
;
974 // Make sure writting of the file is an atomic operation
976 if (SecInterruptEanbled ()) {
977 SecDisableInterrupt ();
978 EnabledOnEntry
= TRUE
;
980 EnabledOnEntry
= FALSE
;
983 PrintLoadAddress (ImageContext
);
986 // In mach-o (OS X executable) dlopen() can only load files in the MH_DYLIB of MH_BUNDLE format.
987 // To convert to PE/COFF we need to construct a mach-o with the MH_PRELOAD format. We create
988 // .dSYM files for the PE/COFF images that can be used by gdb for source level debugging.
993 // In the Mach-O to PE/COFF conversion the size of the PE/COFF headers is not accounted for.
994 // Thus we need to skip over the PE/COFF header when giving load addresses for our symbol table.
996 if (ImageContext
->PdbPointer
!= NULL
&& !IsPdbFile (ImageContext
->PdbPointer
)) {
998 // Now we have a database of the images that are currently loaded
1002 // 'symbol-file' will clear out currnet symbol mappings in gdb.
1003 // you can do a 'add-symbol-file filename address' for every image we loaded to get source
1004 // level debug in gdb. Note Sec, being a true application will work differently.
1006 // We add the PE/COFF header size into the image as the mach-O does not have a header in
1007 // loaded into system memory.
1009 // This gives us a data base of gdb commands and after something is unloaded that entry will be
1010 // removed. We don't yet have the scheme of how to comunicate with gdb, but we have the
1011 // data base of info ready to roll.
1013 // We could use qXfer:libraries:read, but OS X GDB does not currently support it.
1015 // <library name="/lib/libc.so.6"> // ImageContext->PdbPointer
1016 // <segment address="0x10000000"/> // ImageContext->ImageAddress + ImageContext->SizeOfHeaders
1022 // Write the file we need for the gdb script
1024 GdbTempFile
= fopen (gGdbWorkingFileName
, "w");
1025 if (GdbTempFile
!= NULL
) {
1026 fprintf (GdbTempFile
, "add-symbol-file %s 0x%08lx\n", ImageContext
->PdbPointer
, (long unsigned int)(ImageContext
->ImageAddress
+ ImageContext
->SizeOfHeaders
));
1027 fclose (GdbTempFile
);
1030 // Target for gdb breakpoint in a script that uses gGdbWorkingFileName to set a breakpoint.
1031 // Hey what can you say scripting in gdb is not that great....
1033 SecGdbScriptBreak ();
1038 AddHandle (ImageContext
, ImageContext
->PdbPointer
);
1040 if (EnabledOnEntry
) {
1041 SecEnableInterrupt ();
1049 void *Handle
= NULL
;
1052 if (ImageContext
->PdbPointer
== NULL
) {
1056 if (!IsPdbFile (ImageContext
->PdbPointer
)) {
1061 "Loading %s 0x%08lx - entry point 0x%08lx\n",
1062 ImageContext
->PdbPointer
,
1063 (unsigned long)ImageContext
->ImageAddress
,
1064 (unsigned long)ImageContext
->EntryPoint
);
1066 Handle
= dlopen (ImageContext
->PdbPointer
, RTLD_NOW
);
1069 Entry
= dlsym (Handle
, "_ModuleEntryPoint");
1071 printf("%s\n", dlerror());
1074 if (Entry
!= NULL
) {
1075 ImageContext
->EntryPoint
= (UINTN
)Entry
;
1076 printf("Change %s Entrypoint to :0x%08lx\n", ImageContext
->PdbPointer
, (unsigned long)Entry
);
1079 SecUnixLoaderBreak ();
1089 SecPeCoffUnloadImageExtraAction (
1090 IN PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
1095 Handle
= RemoveHandle (ImageContext
);
1099 BOOLEAN EnabledOnEntry
;
1101 if (Handle
!= NULL
) {
1103 // Need to skip .PDB files created from VC++
1105 if (!IsPdbFile (ImageContext
->PdbPointer
)) {
1106 if (SecInterruptEanbled ()) {
1107 SecDisableInterrupt ();
1108 EnabledOnEntry
= TRUE
;
1110 EnabledOnEntry
= FALSE
;
1114 // Write the file we need for the gdb script
1116 GdbTempFile
= fopen (gGdbWorkingFileName
, "w");
1117 if (GdbTempFile
!= NULL
) {
1118 fprintf (GdbTempFile
, "remove-symbol-file %s\n", ImageContext
->PdbPointer
);
1119 fclose (GdbTempFile
);
1122 // Target for gdb breakpoint in a script that uses gGdbWorkingFileName to set a breakpoint.
1123 // Hey what can you say scripting in gdb is not that great....
1125 SecGdbScriptBreak ();
1130 if (EnabledOnEntry
) {
1131 SecEnableInterrupt ();
1138 // Don't want to confuse gdb with symbols for something that got unloaded
1140 if (Handle
!= NULL
) {