]> git.proxmox.com Git - mirror_edk2.git/blame - SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLib.c
SourceLevelDebugPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / SourceLevelDebugPkg / Library / PeCoffExtraActionLibDebug / PeCoffExtraActionLib.c
CommitLineData
18b144ea 1/** @file\r
2 PE/Coff Extra Action library instances.\r
3\r
77695f4d 4 Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>\r
85f7e110 5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
18b144ea 6\r
7**/\r
8\r
b422b62c 9#include <PeCoffExtraActionLib.h>\r
18b144ea 10\r
11/**\r
12 Check if the hardware breakpoint in Drx is enabled by checking the Lx and Gx bit in Dr7.\r
77695f4d 13\r
18b144ea 14 It assumes that DebugAgent will set both Lx and Gx bit when setting up the hardware breakpoint.\r
15\r
16\r
17 @param RegisterIndex Index of Dr register. The value range is from 0 to 3.\r
18 @param Dr7 Value of Dr7 register.\r
19\r
20 @return TRUE The hardware breakpoint specified in the Drx is enabled.\r
21 @return FALSE The hardware breakpoint specified in the Drx is disabled.\r
22\r
23**/\r
24BOOLEAN\r
25IsDrxEnabled (\r
26 IN UINT8 RegisterIndex,\r
27 IN UINTN Dr7\r
28 )\r
29{\r
30 return (BOOLEAN) (((Dr7 >> (RegisterIndex * 2)) & (BIT0 | BIT1)) == (BIT0 | BIT1));\r
31}\r
32\r
33/**\r
93c0bdec 34 Common routine to report the PE/COFF image loading/relocating or unloading event.\r
18b144ea 35\r
36 If ImageContext is NULL, then ASSERT().\r
77695f4d 37\r
18b144ea 38 @param ImageContext Pointer to the image context structure that describes the\r
93c0bdec 39 PE/COFF image.\r
40 @param Signature IMAGE_LOAD_SIGNATURE or IMAGE_UNLOAD_SIGNATURE.\r
18b144ea 41\r
42**/\r
43VOID\r
93c0bdec 44PeCoffLoaderExtraActionCommon (\r
45 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,\r
46 IN UINTN Signature\r
18b144ea 47 )\r
48{\r
b422b62c 49 BOOLEAN InterruptState;\r
50 UINTN Dr0;\r
51 UINTN Dr1;\r
52 UINTN Dr2;\r
53 UINTN Dr3;\r
54 UINTN Dr7;\r
55 UINTN Cr4;\r
56 UINTN NewDr7;\r
57 UINT8 LoadImageMethod;\r
58 UINT8 DebugAgentStatus;\r
59 IA32_DESCRIPTOR IdtDescriptor;\r
60 IA32_IDT_GATE_DESCRIPTOR OriginalIdtEntry;\r
61 BOOLEAN IdtEntryHooked;\r
ef530fe7 62 UINT32 RegEdx;\r
18b144ea 63\r
64 ASSERT (ImageContext != NULL);\r
65\r
66 if (ImageContext->PdbPointer != NULL) {\r
67 DEBUG((EFI_D_ERROR, " PDB = %a\n", ImageContext->PdbPointer));\r
68 }\r
69\r
70 //\r
71 // Disable interrupts and save the current interrupt state\r
72 //\r
73 InterruptState = SaveAndDisableInterrupts ();\r
74\r
b422b62c 75 IdtEntryHooked = FALSE;\r
76 LoadImageMethod = PcdGet8 (PcdDebugLoadImageMethod);\r
ef530fe7
MK
77 if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_IO_HW_BREAKPOINT) {\r
78 //\r
79 // If the CPU does not support Debug Extensions(CPUID:01 EDX:BIT2)\r
77695f4d 80 // then force use of DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3\r
ef530fe7
MK
81 //\r
82 AsmCpuid (1, NULL, NULL, NULL, &RegEdx);\r
83 if ((RegEdx & BIT2) == 0) {\r
84 LoadImageMethod = DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3;\r
85 }\r
86 }\r
b422b62c 87 AsmReadIdtr (&IdtDescriptor);\r
8cc26df4
JF
88 if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3) {\r
89 if (!CheckDebugAgentHandler (&IdtDescriptor, SOFT_INT_VECTOR_NUM)) {\r
b422b62c 90 //\r
91 // Do not trigger INT3 if Debug Agent did not setup IDT entries.\r
92 //\r
93 return;\r
94 }\r
8cc26df4
JF
95 } else {\r
96 if (!CheckDebugAgentHandler (&IdtDescriptor, IO_HW_BREAKPOINT_VECTOR_NUM)) {\r
97 //\r
98 // Save and update IDT entry for INT1\r
99 //\r
100 SaveAndUpdateIdtEntry1 (&IdtDescriptor, &OriginalIdtEntry);\r
101 IdtEntryHooked = TRUE;\r
102 }\r
b422b62c 103 }\r
77695f4d 104\r
18b144ea 105 //\r
106 // Save Debug Register State\r
107 //\r
108 Dr0 = AsmReadDr0 ();\r
109 Dr1 = AsmReadDr1 ();\r
110 Dr2 = AsmReadDr2 ();\r
111 Dr3 = AsmReadDr3 ();\r
602adebb 112 Dr7 = AsmReadDr7 () | BIT10; // H/w sets bit 10, some simulators don't\r
18b144ea 113 Cr4 = AsmReadCr4 ();\r
114\r
115 //\r
93c0bdec 116 // DR0 = Signature\r
18b144ea 117 // DR1 = The address of the Null-terminated ASCII string for the PE/COFF image's PDB file name\r
118 // DR2 = The pointer to the ImageContext structure\r
119 // DR3 = IO_PORT_BREAKPOINT_ADDRESS\r
120 // DR7 = Disables all HW breakpoints except for DR3 I/O port access of length 1 byte\r
121 // CR4 = Make sure DE(BIT3) is set\r
122 //\r
602adebb 123 AsmWriteDr7 (BIT10);\r
93c0bdec 124 AsmWriteDr0 (Signature);\r
125 AsmWriteDr1 ((UINTN) ImageContext->PdbPointer);\r
126 AsmWriteDr2 ((UINTN) ImageContext);\r
18b144ea 127 AsmWriteDr3 (IO_PORT_BREAKPOINT_ADDRESS);\r
128\r
18b144ea 129 if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_IO_HW_BREAKPOINT) {\r
130 AsmWriteDr7 (0x20000480);\r
131 AsmWriteCr4 (Cr4 | BIT3);\r
132 //\r
133 // Do an IN from IO_PORT_BREAKPOINT_ADDRESS to generate a HW breakpoint until the port\r
134 // returns a read value other than DEBUG_AGENT_IMAGE_WAIT\r
135 //\r
136 do {\r
137 DebugAgentStatus = IoRead8 (IO_PORT_BREAKPOINT_ADDRESS);\r
138 } while (DebugAgentStatus == DEBUG_AGENT_IMAGE_WAIT);\r
139\r
140 } else if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3) {\r
141 //\r
142 // Generate a software break point.\r
143 //\r
144 CpuBreakpoint ();\r
145 }\r
146\r
147 //\r
148 // Restore Debug Register State only when Host didn't change it inside exception handler.\r
77695f4d 149 // E.g.: User halts the target and sets the HW breakpoint while target is\r
18b144ea 150 // in the above exception handler\r
151 //\r
602adebb 152 NewDr7 = AsmReadDr7 () | BIT10; // H/w sets bit 10, some simulators don't\r
93c0bdec 153 if (!IsDrxEnabled (0, NewDr7) && (AsmReadDr0 () == 0 || AsmReadDr0 () == Signature)) {\r
154 //\r
155 // If user changed Dr3 (by setting HW bp in the above exception handler,\r
156 // we will not set Dr0 to 0 in GO/STEP handler because the break cause is not IMAGE_LOAD/_UNLOAD.\r
157 //\r
18b144ea 158 AsmWriteDr0 (Dr0);\r
159 }\r
93c0bdec 160 if (!IsDrxEnabled (1, NewDr7) && (AsmReadDr1 () == (UINTN) ImageContext->PdbPointer)) {\r
18b144ea 161 AsmWriteDr1 (Dr1);\r
162 }\r
93c0bdec 163 if (!IsDrxEnabled (2, NewDr7) && (AsmReadDr2 () == (UINTN) ImageContext)) {\r
18b144ea 164 AsmWriteDr2 (Dr2);\r
165 }\r
93c0bdec 166 if (!IsDrxEnabled (3, NewDr7) && (AsmReadDr3 () == IO_PORT_BREAKPOINT_ADDRESS)) {\r
18b144ea 167 AsmWriteDr3 (Dr3);\r
168 }\r
602adebb
BJ
169 if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_IO_HW_BREAKPOINT) {\r
170 if (AsmReadCr4 () == (Cr4 | BIT3)) {\r
171 AsmWriteCr4 (Cr4);\r
172 }\r
173 if (NewDr7 == 0x20000480) {\r
174 AsmWriteDr7 (Dr7);\r
175 }\r
176 } else if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3) {\r
177 if (NewDr7 == BIT10) {\r
178 AsmWriteDr7 (Dr7);\r
179 }\r
18b144ea 180 }\r
181 //\r
b422b62c 182 // Restore original IDT entry for INT1 if it was hooked.\r
183 //\r
184 if (IdtEntryHooked) {\r
185 RestoreIdtEntry1 (&IdtDescriptor, &OriginalIdtEntry);\r
186 }\r
187 //\r
18b144ea 188 // Restore the interrupt state\r
189 //\r
190 SetInterruptState (InterruptState);\r
191}\r
192\r
93c0bdec 193/**\r
194 Performs additional actions after a PE/COFF image has been loaded and relocated.\r
195\r
196 @param ImageContext Pointer to the image context structure that describes the\r
197 PE/COFF image that has already been loaded and relocated.\r
198\r
199**/\r
200VOID\r
201EFIAPI\r
202PeCoffLoaderRelocateImageExtraAction (\r
203 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext\r
204 )\r
205{\r
206 PeCoffLoaderExtraActionCommon (ImageContext, IMAGE_LOAD_SIGNATURE);\r
207}\r
208\r
18b144ea 209/**\r
210 Performs additional actions just before a PE/COFF image is unloaded. Any resources\r
211 that were allocated by PeCoffLoaderRelocateImageExtraAction() must be freed.\r
212\r
18b144ea 213 @param ImageContext Pointer to the image context structure that describes the\r
214 PE/COFF image that is being unloaded.\r
215\r
216**/\r
217VOID\r
218EFIAPI\r
219PeCoffLoaderUnloadImageExtraAction (\r
220 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext\r
221 )\r
222{\r
93c0bdec 223 PeCoffLoaderExtraActionCommon (ImageContext, IMAGE_UNLOAD_SIGNATURE);\r
18b144ea 224}\r