diff options
Diffstat (limited to 'SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLib.c')
| -rw-r--r-- | SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLib.c | 462 |
1 files changed, 231 insertions, 231 deletions
diff --git a/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLib.c b/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLib.c index 2c80f7e22d..755de384d3 100644 --- a/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLib.c +++ b/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLib.c @@ -1,231 +1,231 @@ -/** @file
- PE/Coff Extra Action library instances.
-
- Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include <PeCoffExtraActionLib.h>
-
-/**
- Check if the hardware breakpoint in Drx is enabled by checking the Lx and Gx bit in Dr7.
-
- It assumes that DebugAgent will set both Lx and Gx bit when setting up the hardware breakpoint.
-
-
- @param RegisterIndex Index of Dr register. The value range is from 0 to 3.
- @param Dr7 Value of Dr7 register.
-
- @return TRUE The hardware breakpoint specified in the Drx is enabled.
- @return FALSE The hardware breakpoint specified in the Drx is disabled.
-
-**/
-BOOLEAN
-IsDrxEnabled (
- IN UINT8 RegisterIndex,
- IN UINTN Dr7
- )
-{
- return (BOOLEAN)(((Dr7 >> (RegisterIndex * 2)) & (BIT0 | BIT1)) == (BIT0 | BIT1));
-}
-
-/**
- Common routine to report the PE/COFF image loading/relocating or unloading event.
-
- If ImageContext is NULL, then ASSERT().
-
- @param ImageContext Pointer to the image context structure that describes the
- PE/COFF image.
- @param Signature IMAGE_LOAD_SIGNATURE or IMAGE_UNLOAD_SIGNATURE.
-
-**/
-VOID
-PeCoffLoaderExtraActionCommon (
- IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
- IN UINTN Signature
- )
-{
- BOOLEAN InterruptState;
- UINTN Dr0;
- UINTN Dr1;
- UINTN Dr2;
- UINTN Dr3;
- UINTN Dr7;
- UINTN Cr4;
- UINTN NewDr7;
- UINT8 LoadImageMethod;
- UINT8 DebugAgentStatus;
- IA32_DESCRIPTOR IdtDescriptor;
- IA32_IDT_GATE_DESCRIPTOR OriginalIdtEntry;
- BOOLEAN IdtEntryHooked;
- UINT32 RegEdx;
-
- ASSERT (ImageContext != NULL);
-
- if (ImageContext->PdbPointer != NULL) {
- DEBUG ((DEBUG_ERROR, " PDB = %a\n", ImageContext->PdbPointer));
- }
-
- //
- // Disable interrupts and save the current interrupt state
- //
- InterruptState = SaveAndDisableInterrupts ();
-
- IdtEntryHooked = FALSE;
- LoadImageMethod = PcdGet8 (PcdDebugLoadImageMethod);
- if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_IO_HW_BREAKPOINT) {
- //
- // If the CPU does not support Debug Extensions(CPUID:01 EDX:BIT2)
- // then force use of DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3
- //
- AsmCpuid (1, NULL, NULL, NULL, &RegEdx);
- if ((RegEdx & BIT2) == 0) {
- LoadImageMethod = DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3;
- }
- }
-
- AsmReadIdtr (&IdtDescriptor);
- if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3) {
- if (!CheckDebugAgentHandler (&IdtDescriptor, SOFT_INT_VECTOR_NUM)) {
- //
- // Do not trigger INT3 if Debug Agent did not setup IDT entries.
- //
- return;
- }
- } else {
- if (!CheckDebugAgentHandler (&IdtDescriptor, IO_HW_BREAKPOINT_VECTOR_NUM)) {
- //
- // Save and update IDT entry for INT1
- //
- SaveAndUpdateIdtEntry1 (&IdtDescriptor, &OriginalIdtEntry);
- IdtEntryHooked = TRUE;
- }
- }
-
- //
- // Save Debug Register State
- //
- Dr0 = AsmReadDr0 ();
- Dr1 = AsmReadDr1 ();
- Dr2 = AsmReadDr2 ();
- Dr3 = AsmReadDr3 ();
- Dr7 = AsmReadDr7 () | BIT10; // H/w sets bit 10, some simulators don't
- Cr4 = AsmReadCr4 ();
-
- //
- // DR0 = Signature
- // DR1 = The address of the Null-terminated ASCII string for the PE/COFF image's PDB file name
- // DR2 = The pointer to the ImageContext structure
- // DR3 = IO_PORT_BREAKPOINT_ADDRESS
- // DR7 = Disables all HW breakpoints except for DR3 I/O port access of length 1 byte
- // CR4 = Make sure DE(BIT3) is set
- //
- AsmWriteDr7 (BIT10);
- AsmWriteDr0 (Signature);
- AsmWriteDr1 ((UINTN)ImageContext->PdbPointer);
- AsmWriteDr2 ((UINTN)ImageContext);
- AsmWriteDr3 (IO_PORT_BREAKPOINT_ADDRESS);
-
- if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_IO_HW_BREAKPOINT) {
- AsmWriteDr7 (0x20000480);
- AsmWriteCr4 (Cr4 | BIT3);
- //
- // Do an IN from IO_PORT_BREAKPOINT_ADDRESS to generate a HW breakpoint until the port
- // returns a read value other than DEBUG_AGENT_IMAGE_WAIT
- //
- do {
- DebugAgentStatus = IoRead8 (IO_PORT_BREAKPOINT_ADDRESS);
- } while (DebugAgentStatus == DEBUG_AGENT_IMAGE_WAIT);
- } else if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3) {
- //
- // Generate a software break point.
- //
- CpuBreakpoint ();
- }
-
- //
- // Restore Debug Register State only when Host didn't change it inside exception handler.
- // E.g.: User halts the target and sets the HW breakpoint while target is
- // in the above exception handler
- //
- NewDr7 = AsmReadDr7 () | BIT10; // H/w sets bit 10, some simulators don't
- if (!IsDrxEnabled (0, NewDr7) && ((AsmReadDr0 () == 0) || (AsmReadDr0 () == Signature))) {
- //
- // If user changed Dr3 (by setting HW bp in the above exception handler,
- // we will not set Dr0 to 0 in GO/STEP handler because the break cause is not IMAGE_LOAD/_UNLOAD.
- //
- AsmWriteDr0 (Dr0);
- }
-
- if (!IsDrxEnabled (1, NewDr7) && (AsmReadDr1 () == (UINTN)ImageContext->PdbPointer)) {
- AsmWriteDr1 (Dr1);
- }
-
- if (!IsDrxEnabled (2, NewDr7) && (AsmReadDr2 () == (UINTN)ImageContext)) {
- AsmWriteDr2 (Dr2);
- }
-
- if (!IsDrxEnabled (3, NewDr7) && (AsmReadDr3 () == IO_PORT_BREAKPOINT_ADDRESS)) {
- AsmWriteDr3 (Dr3);
- }
-
- if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_IO_HW_BREAKPOINT) {
- if (AsmReadCr4 () == (Cr4 | BIT3)) {
- AsmWriteCr4 (Cr4);
- }
-
- if (NewDr7 == 0x20000480) {
- AsmWriteDr7 (Dr7);
- }
- } else if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3) {
- if (NewDr7 == BIT10) {
- AsmWriteDr7 (Dr7);
- }
- }
-
- //
- // Restore original IDT entry for INT1 if it was hooked.
- //
- if (IdtEntryHooked) {
- RestoreIdtEntry1 (&IdtDescriptor, &OriginalIdtEntry);
- }
-
- //
- // Restore the interrupt state
- //
- SetInterruptState (InterruptState);
-}
-
-/**
- Performs additional actions after a PE/COFF image has been loaded and relocated.
-
- @param ImageContext Pointer to the image context structure that describes the
- PE/COFF image that has already been loaded and relocated.
-
-**/
-VOID
-EFIAPI
-PeCoffLoaderRelocateImageExtraAction (
- IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
- )
-{
- PeCoffLoaderExtraActionCommon (ImageContext, IMAGE_LOAD_SIGNATURE);
-}
-
-/**
- Performs additional actions just before a PE/COFF image is unloaded. Any resources
- that were allocated by PeCoffLoaderRelocateImageExtraAction() must be freed.
-
- @param ImageContext Pointer to the image context structure that describes the
- PE/COFF image that is being unloaded.
-
-**/
-VOID
-EFIAPI
-PeCoffLoaderUnloadImageExtraAction (
- IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
- )
-{
- PeCoffLoaderExtraActionCommon (ImageContext, IMAGE_UNLOAD_SIGNATURE);
-}
+/** @file + PE/Coff Extra Action library instances. + + Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <PeCoffExtraActionLib.h> + +/** + Check if the hardware breakpoint in Drx is enabled by checking the Lx and Gx bit in Dr7. + + It assumes that DebugAgent will set both Lx and Gx bit when setting up the hardware breakpoint. + + + @param RegisterIndex Index of Dr register. The value range is from 0 to 3. + @param Dr7 Value of Dr7 register. + + @return TRUE The hardware breakpoint specified in the Drx is enabled. + @return FALSE The hardware breakpoint specified in the Drx is disabled. + +**/ +BOOLEAN +IsDrxEnabled ( + IN UINT8 RegisterIndex, + IN UINTN Dr7 + ) +{ + return (BOOLEAN)(((Dr7 >> (RegisterIndex * 2)) & (BIT0 | BIT1)) == (BIT0 | BIT1)); +} + +/** + Common routine to report the PE/COFF image loading/relocating or unloading event. + + If ImageContext is NULL, then ASSERT(). + + @param ImageContext Pointer to the image context structure that describes the + PE/COFF image. + @param Signature IMAGE_LOAD_SIGNATURE or IMAGE_UNLOAD_SIGNATURE. + +**/ +VOID +PeCoffLoaderExtraActionCommon ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + IN UINTN Signature + ) +{ + BOOLEAN InterruptState; + UINTN Dr0; + UINTN Dr1; + UINTN Dr2; + UINTN Dr3; + UINTN Dr7; + UINTN Cr4; + UINTN NewDr7; + UINT8 LoadImageMethod; + UINT8 DebugAgentStatus; + IA32_DESCRIPTOR IdtDescriptor; + IA32_IDT_GATE_DESCRIPTOR OriginalIdtEntry; + BOOLEAN IdtEntryHooked; + UINT32 RegEdx; + + ASSERT (ImageContext != NULL); + + if (ImageContext->PdbPointer != NULL) { + DEBUG ((DEBUG_ERROR, " PDB = %a\n", ImageContext->PdbPointer)); + } + + // + // Disable interrupts and save the current interrupt state + // + InterruptState = SaveAndDisableInterrupts (); + + IdtEntryHooked = FALSE; + LoadImageMethod = PcdGet8 (PcdDebugLoadImageMethod); + if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_IO_HW_BREAKPOINT) { + // + // If the CPU does not support Debug Extensions(CPUID:01 EDX:BIT2) + // then force use of DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3 + // + AsmCpuid (1, NULL, NULL, NULL, &RegEdx); + if ((RegEdx & BIT2) == 0) { + LoadImageMethod = DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3; + } + } + + AsmReadIdtr (&IdtDescriptor); + if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3) { + if (!CheckDebugAgentHandler (&IdtDescriptor, SOFT_INT_VECTOR_NUM)) { + // + // Do not trigger INT3 if Debug Agent did not setup IDT entries. + // + return; + } + } else { + if (!CheckDebugAgentHandler (&IdtDescriptor, IO_HW_BREAKPOINT_VECTOR_NUM)) { + // + // Save and update IDT entry for INT1 + // + SaveAndUpdateIdtEntry1 (&IdtDescriptor, &OriginalIdtEntry); + IdtEntryHooked = TRUE; + } + } + + // + // Save Debug Register State + // + Dr0 = AsmReadDr0 (); + Dr1 = AsmReadDr1 (); + Dr2 = AsmReadDr2 (); + Dr3 = AsmReadDr3 (); + Dr7 = AsmReadDr7 () | BIT10; // H/w sets bit 10, some simulators don't + Cr4 = AsmReadCr4 (); + + // + // DR0 = Signature + // DR1 = The address of the Null-terminated ASCII string for the PE/COFF image's PDB file name + // DR2 = The pointer to the ImageContext structure + // DR3 = IO_PORT_BREAKPOINT_ADDRESS + // DR7 = Disables all HW breakpoints except for DR3 I/O port access of length 1 byte + // CR4 = Make sure DE(BIT3) is set + // + AsmWriteDr7 (BIT10); + AsmWriteDr0 (Signature); + AsmWriteDr1 ((UINTN)ImageContext->PdbPointer); + AsmWriteDr2 ((UINTN)ImageContext); + AsmWriteDr3 (IO_PORT_BREAKPOINT_ADDRESS); + + if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_IO_HW_BREAKPOINT) { + AsmWriteDr7 (0x20000480); + AsmWriteCr4 (Cr4 | BIT3); + // + // Do an IN from IO_PORT_BREAKPOINT_ADDRESS to generate a HW breakpoint until the port + // returns a read value other than DEBUG_AGENT_IMAGE_WAIT + // + do { + DebugAgentStatus = IoRead8 (IO_PORT_BREAKPOINT_ADDRESS); + } while (DebugAgentStatus == DEBUG_AGENT_IMAGE_WAIT); + } else if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3) { + // + // Generate a software break point. + // + CpuBreakpoint (); + } + + // + // Restore Debug Register State only when Host didn't change it inside exception handler. + // E.g.: User halts the target and sets the HW breakpoint while target is + // in the above exception handler + // + NewDr7 = AsmReadDr7 () | BIT10; // H/w sets bit 10, some simulators don't + if (!IsDrxEnabled (0, NewDr7) && ((AsmReadDr0 () == 0) || (AsmReadDr0 () == Signature))) { + // + // If user changed Dr3 (by setting HW bp in the above exception handler, + // we will not set Dr0 to 0 in GO/STEP handler because the break cause is not IMAGE_LOAD/_UNLOAD. + // + AsmWriteDr0 (Dr0); + } + + if (!IsDrxEnabled (1, NewDr7) && (AsmReadDr1 () == (UINTN)ImageContext->PdbPointer)) { + AsmWriteDr1 (Dr1); + } + + if (!IsDrxEnabled (2, NewDr7) && (AsmReadDr2 () == (UINTN)ImageContext)) { + AsmWriteDr2 (Dr2); + } + + if (!IsDrxEnabled (3, NewDr7) && (AsmReadDr3 () == IO_PORT_BREAKPOINT_ADDRESS)) { + AsmWriteDr3 (Dr3); + } + + if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_IO_HW_BREAKPOINT) { + if (AsmReadCr4 () == (Cr4 | BIT3)) { + AsmWriteCr4 (Cr4); + } + + if (NewDr7 == 0x20000480) { + AsmWriteDr7 (Dr7); + } + } else if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3) { + if (NewDr7 == BIT10) { + AsmWriteDr7 (Dr7); + } + } + + // + // Restore original IDT entry for INT1 if it was hooked. + // + if (IdtEntryHooked) { + RestoreIdtEntry1 (&IdtDescriptor, &OriginalIdtEntry); + } + + // + // Restore the interrupt state + // + SetInterruptState (InterruptState); +} + +/** + Performs additional actions after a PE/COFF image has been loaded and relocated. + + @param ImageContext Pointer to the image context structure that describes the + PE/COFF image that has already been loaded and relocated. + +**/ +VOID +EFIAPI +PeCoffLoaderRelocateImageExtraAction ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +{ + PeCoffLoaderExtraActionCommon (ImageContext, IMAGE_LOAD_SIGNATURE); +} + +/** + Performs additional actions just before a PE/COFF image is unloaded. Any resources + that were allocated by PeCoffLoaderRelocateImageExtraAction() must be freed. + + @param ImageContext Pointer to the image context structure that describes the + PE/COFF image that is being unloaded. + +**/ +VOID +EFIAPI +PeCoffLoaderUnloadImageExtraAction ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +{ + PeCoffLoaderExtraActionCommon (ImageContext, IMAGE_UNLOAD_SIGNATURE); +} |
