From 07da1ac8c46425cb401cc5f356ab77b9cc1c334d Mon Sep 17 00:00:00 2001 From: Anderw Fish Date: Tue, 9 Sep 2014 06:50:51 +0000 Subject: UefiCpuPkg: CpuExceptionHandlerLib: Make self modifying code work with Xcode CpuExceptionHandlerLib has code that contains absolute relocations, not supported by Xcode for X64, and it then copies this code to an alternate location in memory. It is very hard to write IP relative self-modifiying code. I had to update AsmVectorNumFixup() to also patch in the absolute addressess after the code was copied. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Anderw Fish Reviewed-by: Jeff Fan git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16068 6f19259b-4bc3-4df7-8a09-765794883524 --- .../CpuExceptionHandlerLib/CpuExceptionCommon.h | 12 +- .../Library/CpuExceptionHandlerLib/DxeException.c | 2 +- .../CpuExceptionHandlerLib/DxeSmmCpuException.c | 6 +- .../Ia32/ExceptionHandlerAsm.S | 2 +- .../Ia32/ExceptionHandlerAsm.asm | 2 +- .../X64/ExceptionHandlerAsm.S | 347 ++++++--------------- .../X64/ExceptionHandlerAsm.asm | 2 +- 7 files changed, 109 insertions(+), 264 deletions(-) (limited to 'UefiCpuPkg') diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h index 1b899b302..efe77eb09 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h @@ -204,17 +204,19 @@ ArchRestoreExceptionContext ( ); /** - Fix up the vector number in the vector code. + Fix up the vector number and function address in the vector code. - @param[in] VectorBase Base address of the vector handler. - @param[in] VectorNum Index of vector. + @param[in] NewVectorAddr New vector handler address. + @param[in] VectorNum Index of vector. + @param[in] OldVectorAddr Old vector handler address. **/ VOID EFIAPI AsmVectorNumFixup ( - IN VOID *VectorBase, - IN UINT8 VectorNum + IN VOID *NewVectorAddr, + IN UINT8 VectorNum, + IN VOID *OldVectorAddr ); /** diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c index c38f0e10d..6739a2cc3 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c @@ -119,7 +119,7 @@ InitializeCpuInterruptHandlers ( (VOID *) TemplateMap.ExceptionStart, TemplateMap.ExceptionStubHeaderSize ); - AsmVectorNumFixup ((VOID *) InterruptEntry, (UINT8) Index); + AsmVectorNumFixup ((VOID *) InterruptEntry, (UINT8) Index, (VOID *) TemplateMap.ExceptionStart); InterruptEntry += TemplateMap.ExceptionStubHeaderSize; } diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeSmmCpuException.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeSmmCpuException.c index daa6330f5..d1291aa0e 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeSmmCpuException.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeSmmCpuException.c @@ -166,7 +166,11 @@ UpdateIdtTable ( (VOID *) TemplateMap->HookAfterStubHeaderStart, TemplateMap->ExceptionStubHeaderSize ); - AsmVectorNumFixup ((VOID *) mReservedVectors[Index].HookAfterStubHeaderCode, (UINT8) Index); + AsmVectorNumFixup ( + (VOID *) mReservedVectors[Index].HookAfterStubHeaderCode, + (UINT8) Index, + (VOID *) TemplateMap->HookAfterStubHeaderStart + ); // // Go on the following code // diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionHandlerAsm.S b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionHandlerAsm.S index 387b4b26b..e19afbe14 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionHandlerAsm.S +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionHandlerAsm.S @@ -632,7 +632,7 @@ ASM_PFX(AsmGetTemplateAddressMap): popl %ebp ret #------------------------------------------------------------------------------------- -# AsmVectorNumFixup (*VectorBase, VectorNum); +# AsmVectorNumFixup (*NewVectorAddr, VectorNum, *OldVectorAddr); #------------------------------------------------------------------------------------- ASM_GLOBAL ASM_PFX(AsmVectorNumFixup) ASM_PFX(AsmVectorNumFixup): diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionHandlerAsm.asm b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionHandlerAsm.asm index 74d4e8904..3ff01b2a0 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionHandlerAsm.asm +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ExceptionHandlerAsm.asm @@ -434,7 +434,7 @@ AsmGetTemplateAddressMap proc near public AsmGetTemplateAddressMap ENDP ;------------------------------------------------------------------------------------- -; AsmVectorNumFixup (*VectorBase, VectorNum); +; AsmVectorNumFixup (*NewVectorAddr, VectorNum, *OldVectorAddr); ;------------------------------------------------------------------------------------- AsmVectorNumFixup proc near public mov eax, dword ptr [esp + 8] diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.S b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.S index 233dbcbcc..f371fd350 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.S +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.S @@ -23,265 +23,79 @@ ASM_GLOBAL ASM_PFX(CommonExceptionHandler) -ASM_GLOBAL ASM_PFX(CommonInterruptEntry) -ASM_GLOBAL ASM_PFX(HookAfterStubHeaderEnd) -#EXTRN ASM_PFX(mErrorCodeFlag):DWORD # Error code flags for exceptions +#EXTRN ASM_PFX(mErrorCodeFlag):DWORD # Error code flags for exceptions #EXTRN ASM_PFX(mDoFarReturnFlag):QWORD # Do far return flag .text -# -# exception handler stub table -# -Exception0Handle: - .byte 0x6a # push #VectorNum - .byte 0 - pushq %rax - .byte 0x48, 0xB8 - .quad ASM_PFX(CommonInterruptEntry) - jmp *%rax -Exception1Handle: - .byte 0x6a # push #VectorNum - .byte 1 - pushq %rax - .byte 0x48, 0xB8 - .quad ASM_PFX(CommonInterruptEntry) - jmp *%rax -Exception2Handle: - .byte 0x6a # push #VectorNum - .byte 2 - pushq %rax - .byte 0x48, 0xB8 - .quad ASM_PFX(CommonInterruptEntry) - jmp *%rax -Exception3Handle: - .byte 0x6a # push #VectorNum - .byte 3 - pushq %rax - .byte 0x48, 0xB8 - .quad ASM_PFX(CommonInterruptEntry) - jmp *%rax -Exception4Handle: - .byte 0x6a # push #VectorNum - .byte 4 - pushq %rax - .byte 0x48, 0xB8 - .quad ASM_PFX(CommonInterruptEntry) - jmp *%rax -Exception5Handle: - .byte 0x6a # push #VectorNum - .byte 5 - pushq %rax - .byte 0x48, 0xB8 - .quad ASM_PFX(CommonInterruptEntry) - jmp *%rax -Exception6Handle: - .byte 0x6a # push #VectorNum - .byte 6 - pushq %rax - .byte 0x48, 0xB8 - .quad ASM_PFX(CommonInterruptEntry) - jmp *%rax -Exception7Handle: - .byte 0x6a # push #VectorNum - .byte 7 - pushq %rax - .byte 0x48, 0xB8 - .quad ASM_PFX(CommonInterruptEntry) - jmp *%rax -Exception8Handle: - .byte 0x6a # push #VectorNum - .byte 8 - pushq %rax - .byte 0x48, 0xB8 - .quad ASM_PFX(CommonInterruptEntry) - jmp *%rax -Exception9Handle: - .byte 0x6a # push #VectorNum - .byte 9 - pushq %rax - .byte 0x48, 0xB8 - .quad ASM_PFX(CommonInterruptEntry) - jmp *%rax -Exception10Handle: - .byte 0x6a # push #VectorNum - .byte 10 - pushq %rax - .byte 0x48, 0xB8 - .quad ASM_PFX(CommonInterruptEntry) - jmp *%rax -Exception11Handle: - .byte 0x6a # push #VectorNum - .byte 11 - pushq %rax - .byte 0x48, 0xB8 - .quad ASM_PFX(CommonInterruptEntry) - jmp *%rax -Exception12Handle: - .byte 0x6a # push #VectorNum - .byte 12 - pushq %rax - .byte 0x48, 0xB8 - .quad ASM_PFX(CommonInterruptEntry) - jmp *%rax -Exception13Handle: - .byte 0x6a # push #VectorNum - .byte 13 - pushq %rax - .byte 0x48, 0xB8 - .quad ASM_PFX(CommonInterruptEntry) - jmp *%rax -Exception14Handle: - .byte 0x6a # push #VectorNum - .byte 14 - pushq %rax - .byte 0x48, 0xB8 - .quad ASM_PFX(CommonInterruptEntry) - jmp *%rax -Exception15Handle: - .byte 0x6a # push #VectorNum - .byte 15 - pushq %rax - .byte 0x48, 0xB8 - .quad ASM_PFX(CommonInterruptEntry) - jmp *%rax -Exception16Handle: - .byte 0x6a # push #VectorNum - .byte 16 - pushq %rax - .byte 0x48, 0xB8 - .quad ASM_PFX(CommonInterruptEntry) - jmp *%rax -Exception17Handle: - .byte 0x6a # push #VectorNum - .byte 17 - pushq %rax - .byte 0x48, 0xB8 - .quad ASM_PFX(CommonInterruptEntry) - jmp *%rax -Exception18Handle: - .byte 0x6a # push #VectorNum - .byte 18 - pushq %rax - .byte 0x48, 0xB8 - .quad ASM_PFX(CommonInterruptEntry) - jmp *%rax -Exception19Handle: - .byte 0x6a # push #VectorNum - .byte 19 - pushq %rax - .byte 0x48, 0xB8 - .quad ASM_PFX(CommonInterruptEntry) - jmp *%rax -Exception20Handle: - .byte 0x6a # push #VectorNum - .byte 20 - pushq %rax - .byte 0x48, 0xB8 - .quad ASM_PFX(CommonInterruptEntry) - jmp *%rax -Exception21Handle: - .byte 0x6a # push #VectorNum - .byte 21 - pushq %rax - .byte 0x48, 0xB8 - .quad ASM_PFX(CommonInterruptEntry) - jmp *%rax -Exception22Handle: - .byte 0x6a # push #VectorNum - .byte 22 - pushq %rax - .byte 0x48, 0xB8 - .quad ASM_PFX(CommonInterruptEntry) - jmp *%rax -Exception23Handle: - .byte 0x6a # push #VectorNum - .byte 23 - pushq %rax - .byte 0x48, 0xB8 - .quad ASM_PFX(CommonInterruptEntry) - jmp *%rax -Exception24Handle: - .byte 0x6a # push #VectorNum - .byte 24 - pushq %rax - .byte 0x48, 0xB8 - .quad ASM_PFX(CommonInterruptEntry) - jmp *%rax -Exception25Handle: - .byte 0x6a # push #VectorNum - .byte 25 - pushq %rax - .byte 0x48, 0xB8 - .quad ASM_PFX(CommonInterruptEntry) - jmp *%rax -Exception26Handle: - .byte 0x6a # push #VectorNum - .byte 26 - pushq %rax - .byte 0x48, 0xB8 - .quad ASM_PFX(CommonInterruptEntry) - jmp *%rax -Exception27Handle: - .byte 0x6a # push #VectorNum - .byte 27 - pushq %rax - .byte 0x48, 0xB8 - .quad ASM_PFX(CommonInterruptEntry) - jmp *%rax -Exception28Handle: - .byte 0x6a # push #VectorNum - .byte 28 - pushq %rax - .byte 0x48, 0xB8 - .quad ASM_PFX(CommonInterruptEntry) - jmp *%rax -Exception29Handle: - .byte 0x6a # push #VectorNum - .byte 29 - pushq %rax - .byte 0x48, 0xB8 - .quad ASM_PFX(CommonInterruptEntry) - jmp *%rax -Exception30Handle: - .byte 0x6a # push #VectorNum - .byte 30 - pushq %rax - .byte 0x48, 0xB8 - .quad ASM_PFX(CommonInterruptEntry) - jmp *%rax -Exception31Handle: - .byte 0x6a # push #VectorNum - .byte 31 - pushq %rax - .byte 0x48, 0xB8 - .quad ASM_PFX(CommonInterruptEntry) - jmp *%rax - +#ifdef __APPLE__ +# macros are different between GNU and Xcode as. +.macro IDT_MACRO + push $0 +#else +.macro IDT_MACRO arg + push \arg +#endif + jmp ASM_PFX(CommonInterruptEntry) +.endm + +AsmIdtVectorBegin: + IDT_MACRO $0 + IDT_MACRO $1 + IDT_MACRO $2 + IDT_MACRO $3 + IDT_MACRO $4 + IDT_MACRO $5 + IDT_MACRO $6 + IDT_MACRO $7 + IDT_MACRO $8 + IDT_MACRO $9 + IDT_MACRO $10 + IDT_MACRO $11 + IDT_MACRO $12 + IDT_MACRO $13 + IDT_MACRO $14 + IDT_MACRO $15 + IDT_MACRO $16 + IDT_MACRO $17 + IDT_MACRO $18 + IDT_MACRO $19 + IDT_MACRO $20 + IDT_MACRO $21 + IDT_MACRO $22 + IDT_MACRO $23 + IDT_MACRO $24 + IDT_MACRO $25 + IDT_MACRO $26 + IDT_MACRO $27 + IDT_MACRO $28 + IDT_MACRO $29 + IDT_MACRO $30 + IDT_MACRO $31 +AsmIdtVectorEnd: + HookAfterStubHeaderBegin: .byte 0x6a # push -VectorNum: +PatchVectorNum: .byte 0 # 0 will be fixed - pushq %rax - .byte 0x48, 0xB8 # movq ASM_PFX(HookAfterStubHeaderEnd), %rax - .quad ASM_PFX(HookAfterStubHeaderEnd) - jmp *%rax + .byte 0xe9 # jmp ASM_PFX(HookAfterStubHeaderEnd) +PatchFuncAddress: + .set HOOK_ADDRESS, ASM_PFX(HookAfterStubHeaderEnd) - . - 4 + .long HOOK_ADDRESS # will be fixed ASM_GLOBAL ASM_PFX(HookAfterStubHeaderEnd) ASM_PFX(HookAfterStubHeaderEnd): + pushq %rax movq %rsp, %rax andl $0x0fffffff0, %esp # make sure 16-byte aligned for exception context subq $0x18, %rsp # reserve room for filling exception data later pushq %rcx movq 8(%rax), %rcx - pushq %rax - movabsl ASM_PFX(mErrorCodeFlag), %eax - bt %ecx, %eax - popq %rax + bt %ecx, ASM_PFX(mErrorCodeFlag)(%rip) jnc NoErrorData pushq (%rsp) # push additional rcx to make stack alignment NoErrorData: xchgq (%rsp), %rcx # restore rcx, save Exception Number in stack - pushq (%rax) # push rax into stack to keep code consistence + movq (%rax), %rax # restore rax #---------------------------------------; # CommonInterruptEntry ; @@ -291,7 +105,6 @@ NoErrorData: ASM_GLOBAL ASM_PFX(CommonInterruptEntry) ASM_PFX(CommonInterruptEntry): cli - popq %rax # # All interrupt handlers are invoked through interrupt gates, so # IF flag automatically cleared at the entry point @@ -304,7 +117,7 @@ ASM_PFX(CommonInterruptEntry): cmp $32, %ecx # Intel reserved vector for exceptions? jae NoErrorCode pushq %rax - movabsl ASM_PFX(mErrorCodeFlag), %eax + movl ASM_PFX(mErrorCodeFlag)(%rip), %eax bt %ecx, %eax popq %rax jc CommonInterruptEntry_al_0000 @@ -553,7 +366,7 @@ ErrorCode: DoReturn: pushq %rax - movabsq ASM_PFX(mDoFarReturnFlag), %rax + movq ASM_PFX(mDoFarReturnFlag)(%rip), %rax cmpq $0, %rax # Check if need to do far return instead of IRET popq %rax jz DoIret @@ -566,7 +379,11 @@ DoReturn: movq (%rax), %rax # restore rax popfq # restore EFLAGS .byte 0x48 # prefix to composite "retq" with next "retf" +#ifdef __APPLE__ + .byte 0xCB +#else retf # far return +#endif DoIret: iretq @@ -577,22 +394,44 @@ DoIret: # comments here for definition of address map ASM_GLOBAL ASM_PFX(AsmGetTemplateAddressMap) ASM_PFX(AsmGetTemplateAddressMap): + pushq %rbp + movq %rsp, %rbp + + leaq AsmIdtVectorBegin(%rip), %rax + movq %rax, (%rcx) + .set ENTRY_SIZE, ASM_PFX(HookAfterStubHeaderEnd) - HookAfterStubHeaderBegin + movq $(ENTRY_SIZE), 0x08(%rcx) + leaq HookAfterStubHeaderBegin(%rip), %rax + movq %rax, 0x10(%rcx) - movabsq $Exception0Handle, %rax - movq %rax, (%rcx) - movq $(Exception1Handle - Exception0Handle), 0x08(%rcx) - movabsq $HookAfterStubHeaderBegin, %rax - movq %rax, 0x10(%rcx) - ret + popq %rbp + ret #------------------------------------------------------------------------------------- -# AsmVectorNumFixup (*VectorBase, VectorNum); +# VOID +# EFIAPI +# AsmVectorNumFixup ( +# IN VOID *NewVectorAddr, // RCX +# IN UINT8 VectorNum // RDX +# IN VOID *OldVectorAddr, // R8 +# ); #------------------------------------------------------------------------------------- ASM_GLOBAL ASM_PFX(AsmVectorNumFixup) ASM_PFX(AsmVectorNumFixup): - movq %rdx, %rax - movb %al, (VectorNum - HookAfterStubHeaderBegin)(%rcx) - ret + pushq %rbp + movq %rsp, %rbp + +# Patch vector # + movb %dl, (PatchVectorNum - HookAfterStubHeaderBegin)(%rcx) + +# Patch Function address + subq %rcx, %r8 # Calculate the offset value + movl (PatchFuncAddress - HookAfterStubHeaderBegin)(%rcx), %eax + addq %r8, %rax + movl %eax, (PatchFuncAddress - HookAfterStubHeaderBegin)(%rcx) + + popq %rbp + ret #END diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.asm b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.asm index 59bec5985..cd21ec4c9 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.asm +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.asm @@ -378,7 +378,7 @@ AsmGetTemplateAddressMap PROC AsmGetTemplateAddressMap ENDP ;------------------------------------------------------------------------------------- -; AsmVectorNumFixup (*VectorBase, VectorNum); +; AsmVectorNumFixup (*NewVectorAddr, VectorNum, *OldVectorAddr); ;------------------------------------------------------------------------------------- AsmVectorNumFixup PROC mov rax, rdx -- cgit v1.2.3