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