VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLib.c@ 99396

最後變更 在這個檔案從99396是 81010,由 vboxsync 提交於 5 年 前

EFI/Firmware/PeCoffExtraActionLibDebug: Merge code from VBoxPeCoffExtraActionLib into here so we get the load addresses in VBox.log and support for the UDK debugger at the same time

  • 屬性 svn:eol-style 設為 native
檔案大小: 9.0 KB
 
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#ifdef VBOX
12#include "VBoxPkg.h"
13#include "../../../../DevEFI.h"
14
15
16
17static void vboxImageEvtU64(uint32_t uCmd, uint64_t uValue)
18{
19 RTUINT64U u; /* 64-bit shift builtins. */
20 u.u = uValue;
21 ASMOutU32(EFI_PORT_IMAGE_EVENT, EFI_IMAGE_EVT_MAKE(uCmd, u.au16[3]));
22 ASMOutU32(EFI_PORT_IMAGE_EVENT, EFI_IMAGE_EVT_MAKE(uCmd, u.au16[2]));
23 ASMOutU32(EFI_PORT_IMAGE_EVENT, EFI_IMAGE_EVT_MAKE(uCmd, u.au16[1]));
24 ASMOutU32(EFI_PORT_IMAGE_EVENT, EFI_IMAGE_EVT_MAKE(uCmd, u.au16[0]));
25}
26
27static void vboxImageEvtString(uint32_t uCmd, const char *pszName)
28{
29 unsigned char uch;
30 while ((uch = *pszName++) != '\0')
31 ASMOutU32(EFI_PORT_IMAGE_EVENT, EFI_IMAGE_EVT_MAKE(uCmd, uch));
32}
33
34static void vboxImageEvtEmitOne(PE_COFF_LOADER_IMAGE_CONTEXT const *pImageCtx, uint32_t uEvt)
35{
36 ASMOutU32(EFI_PORT_IMAGE_EVENT, uEvt);
37 if (pImageCtx->DestinationAddress)
38 vboxImageEvtU64(EFI_IMAGE_EVT_CMD_ADDR0, pImageCtx->DestinationAddress);
39 else
40 vboxImageEvtU64(EFI_IMAGE_EVT_CMD_ADDR0, pImageCtx->ImageAddress);
41 vboxImageEvtU64(EFI_IMAGE_EVT_CMD_SIZE0, pImageCtx->ImageSize);
42 if (pImageCtx->PdbPointer)
43 vboxImageEvtString(EFI_IMAGE_EVT_CMD_NAME, pImageCtx->PdbPointer);
44 ASMOutU32(EFI_PORT_IMAGE_EVENT, EFI_IMAGE_EVT_CMD_COMPLETE);
45}
46#endif
47
48
49#ifdef VBOX_SOURCE_DEBUG_ENABLE
50/**
51 Check if the hardware breakpoint in Drx is enabled by checking the Lx and Gx bit in Dr7.
52
53 It assumes that DebugAgent will set both Lx and Gx bit when setting up the hardware breakpoint.
54
55
56 @param RegisterIndex Index of Dr register. The value range is from 0 to 3.
57 @param Dr7 Value of Dr7 register.
58
59 @return TRUE The hardware breakpoint specified in the Drx is enabled.
60 @return FALSE The hardware breakpoint specified in the Drx is disabled.
61
62**/
63BOOLEAN
64IsDrxEnabled (
65 IN UINT8 RegisterIndex,
66 IN UINTN Dr7
67 )
68{
69 return (BOOLEAN) (((Dr7 >> (RegisterIndex * 2)) & (BIT0 | BIT1)) == (BIT0 | BIT1));
70}
71
72/**
73 Common routine to report the PE/COFF image loading/relocating or unloading event.
74
75 If ImageContext is NULL, then ASSERT().
76
77 @param ImageContext Pointer to the image context structure that describes the
78 PE/COFF image.
79 @param Signature IMAGE_LOAD_SIGNATURE or IMAGE_UNLOAD_SIGNATURE.
80
81**/
82VOID
83PeCoffLoaderExtraActionCommon (
84 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
85 IN UINTN Signature
86 )
87{
88 BOOLEAN InterruptState;
89 UINTN Dr0;
90 UINTN Dr1;
91 UINTN Dr2;
92 UINTN Dr3;
93 UINTN Dr7;
94 UINTN Cr4;
95 UINTN NewDr7;
96 UINT8 LoadImageMethod;
97 UINT8 DebugAgentStatus;
98 IA32_DESCRIPTOR IdtDescriptor;
99 IA32_IDT_GATE_DESCRIPTOR OriginalIdtEntry;
100 BOOLEAN IdtEntryHooked;
101 UINT32 RegEdx;
102
103 ASSERT (ImageContext != NULL);
104
105 if (ImageContext->PdbPointer != NULL) {
106 DEBUG((EFI_D_ERROR, " PDB = %a\n", ImageContext->PdbPointer));
107 }
108
109 //
110 // Disable interrupts and save the current interrupt state
111 //
112 InterruptState = SaveAndDisableInterrupts ();
113
114 IdtEntryHooked = FALSE;
115 LoadImageMethod = PcdGet8 (PcdDebugLoadImageMethod);
116 if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_IO_HW_BREAKPOINT) {
117 //
118 // If the CPU does not support Debug Extensions(CPUID:01 EDX:BIT2)
119 // then force use of DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3
120 //
121 AsmCpuid (1, NULL, NULL, NULL, &RegEdx);
122 if ((RegEdx & BIT2) == 0) {
123 LoadImageMethod = DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3;
124 }
125 }
126 AsmReadIdtr (&IdtDescriptor);
127 if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3) {
128 if (!CheckDebugAgentHandler (&IdtDescriptor, SOFT_INT_VECTOR_NUM)) {
129 //
130 // Do not trigger INT3 if Debug Agent did not setup IDT entries.
131 //
132 return;
133 }
134 } else {
135 if (!CheckDebugAgentHandler (&IdtDescriptor, IO_HW_BREAKPOINT_VECTOR_NUM)) {
136 //
137 // Save and update IDT entry for INT1
138 //
139 SaveAndUpdateIdtEntry1 (&IdtDescriptor, &OriginalIdtEntry);
140 IdtEntryHooked = TRUE;
141 }
142 }
143
144 //
145 // Save Debug Register State
146 //
147 Dr0 = AsmReadDr0 ();
148 Dr1 = AsmReadDr1 ();
149 Dr2 = AsmReadDr2 ();
150 Dr3 = AsmReadDr3 ();
151 Dr7 = AsmReadDr7 () | BIT10; // H/w sets bit 10, some simulators don't
152 Cr4 = AsmReadCr4 ();
153
154 //
155 // DR0 = Signature
156 // DR1 = The address of the Null-terminated ASCII string for the PE/COFF image's PDB file name
157 // DR2 = The pointer to the ImageContext structure
158 // DR3 = IO_PORT_BREAKPOINT_ADDRESS
159 // DR7 = Disables all HW breakpoints except for DR3 I/O port access of length 1 byte
160 // CR4 = Make sure DE(BIT3) is set
161 //
162 AsmWriteDr7 (BIT10);
163 AsmWriteDr0 (Signature);
164 AsmWriteDr1 ((UINTN) ImageContext->PdbPointer);
165 AsmWriteDr2 ((UINTN) ImageContext);
166 AsmWriteDr3 (IO_PORT_BREAKPOINT_ADDRESS);
167
168 if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_IO_HW_BREAKPOINT) {
169 AsmWriteDr7 (0x20000480);
170 AsmWriteCr4 (Cr4 | BIT3);
171 //
172 // Do an IN from IO_PORT_BREAKPOINT_ADDRESS to generate a HW breakpoint until the port
173 // returns a read value other than DEBUG_AGENT_IMAGE_WAIT
174 //
175 do {
176 DebugAgentStatus = IoRead8 (IO_PORT_BREAKPOINT_ADDRESS);
177 } while (DebugAgentStatus == DEBUG_AGENT_IMAGE_WAIT);
178
179 } else if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3) {
180 //
181 // Generate a software break point.
182 //
183 CpuBreakpoint ();
184 }
185
186 //
187 // Restore Debug Register State only when Host didn't change it inside exception handler.
188 // E.g.: User halts the target and sets the HW breakpoint while target is
189 // in the above exception handler
190 //
191 NewDr7 = AsmReadDr7 () | BIT10; // H/w sets bit 10, some simulators don't
192 if (!IsDrxEnabled (0, NewDr7) && (AsmReadDr0 () == 0 || AsmReadDr0 () == Signature)) {
193 //
194 // If user changed Dr3 (by setting HW bp in the above exception handler,
195 // we will not set Dr0 to 0 in GO/STEP handler because the break cause is not IMAGE_LOAD/_UNLOAD.
196 //
197 AsmWriteDr0 (Dr0);
198 }
199 if (!IsDrxEnabled (1, NewDr7) && (AsmReadDr1 () == (UINTN) ImageContext->PdbPointer)) {
200 AsmWriteDr1 (Dr1);
201 }
202 if (!IsDrxEnabled (2, NewDr7) && (AsmReadDr2 () == (UINTN) ImageContext)) {
203 AsmWriteDr2 (Dr2);
204 }
205 if (!IsDrxEnabled (3, NewDr7) && (AsmReadDr3 () == IO_PORT_BREAKPOINT_ADDRESS)) {
206 AsmWriteDr3 (Dr3);
207 }
208 if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_IO_HW_BREAKPOINT) {
209 if (AsmReadCr4 () == (Cr4 | BIT3)) {
210 AsmWriteCr4 (Cr4);
211 }
212 if (NewDr7 == 0x20000480) {
213 AsmWriteDr7 (Dr7);
214 }
215 } else if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3) {
216 if (NewDr7 == BIT10) {
217 AsmWriteDr7 (Dr7);
218 }
219 }
220 //
221 // Restore original IDT entry for INT1 if it was hooked.
222 //
223 if (IdtEntryHooked) {
224 RestoreIdtEntry1 (&IdtDescriptor, &OriginalIdtEntry);
225 }
226 //
227 // Restore the interrupt state
228 //
229 SetInterruptState (InterruptState);
230}
231#endif
232
233/**
234 Performs additional actions after a PE/COFF image has been loaded and relocated.
235
236 @param ImageContext Pointer to the image context structure that describes the
237 PE/COFF image that has already been loaded and relocated.
238
239**/
240VOID
241EFIAPI
242PeCoffLoaderRelocateImageExtraAction (
243 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
244 )
245{
246#ifdef VBOX_SOURCE_DEBUG_ENABLE
247 PeCoffLoaderExtraActionCommon (ImageContext, IMAGE_LOAD_SIGNATURE);
248#endif
249
250#ifdef VBOX
251# if ARCH_BITS == 32
252 vboxImageEvtEmitOne(ImageContext, EFI_IMAGE_EVT_CMD_START_LOAD32);
253# else
254 vboxImageEvtEmitOne(ImageContext, EFI_IMAGE_EVT_CMD_START_LOAD64);
255# endif
256#endif
257}
258
259/**
260 Performs additional actions just before a PE/COFF image is unloaded. Any resources
261 that were allocated by PeCoffLoaderRelocateImageExtraAction() must be freed.
262
263 @param ImageContext Pointer to the image context structure that describes the
264 PE/COFF image that is being unloaded.
265
266**/
267VOID
268EFIAPI
269PeCoffLoaderUnloadImageExtraAction (
270 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
271 )
272{
273#ifdef VBOX_SOURCE_DEBUG_ENABLE
274 PeCoffLoaderExtraActionCommon (ImageContext, IMAGE_UNLOAD_SIGNATURE);
275#endif
276
277#ifdef VBOX
278# if ARCH_BITS == 32
279 vboxImageEvtEmitOne(ImageContext, EFI_IMAGE_EVT_CMD_START_UNLOAD32);
280# else
281 vboxImageEvtEmitOne(ImageContext, EFI_IMAGE_EVT_CMD_START_UNLOAD64);
282# endif
283#endif
284}
285
286#ifdef VBOX
287VOID
288EFIAPI
289VBoxPeCoffLoaderMoveImageExtraAction(
290 IN PHYSICAL_ADDRESS OldBase,
291 IN PHYSICAL_ADDRESS NewBase
292 )
293{
294#if ARCH_BITS == 32
295 ASMOutU32(EFI_PORT_IMAGE_EVENT, EFI_IMAGE_EVT_CMD_START_RELOC32);
296#else
297 ASMOutU32(EFI_PORT_IMAGE_EVENT, EFI_IMAGE_EVT_CMD_START_RELOC64);
298#endif
299 vboxImageEvtU64(EFI_IMAGE_EVT_CMD_ADDR0, NewBase);
300 vboxImageEvtU64(EFI_IMAGE_EVT_CMD_ADDR1, OldBase);
301 ASMOutU32(EFI_PORT_IMAGE_EVENT, EFI_IMAGE_EVT_CMD_COMPLETE);
302}
303#endif
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette