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 <afish@apple.com>
Reviewed-by: Jeff Fan <jeff.fan@intel.com>

git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16068 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Anderw Fish 2014-09-09 06:50:51 +00:00 committed by vanjeff
parent 19ee4a9049
commit 07da1ac8c4
7 changed files with 109 additions and 264 deletions

View File

@ -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] NewVectorAddr New vector handler address.
@param[in] VectorNum Index of vector. @param[in] VectorNum Index of vector.
@param[in] OldVectorAddr Old vector handler address.
**/ **/
VOID VOID
EFIAPI EFIAPI
AsmVectorNumFixup ( AsmVectorNumFixup (
IN VOID *VectorBase, IN VOID *NewVectorAddr,
IN UINT8 VectorNum IN UINT8 VectorNum,
IN VOID *OldVectorAddr
); );
/** /**

View File

@ -119,7 +119,7 @@ InitializeCpuInterruptHandlers (
(VOID *) TemplateMap.ExceptionStart, (VOID *) TemplateMap.ExceptionStart,
TemplateMap.ExceptionStubHeaderSize TemplateMap.ExceptionStubHeaderSize
); );
AsmVectorNumFixup ((VOID *) InterruptEntry, (UINT8) Index); AsmVectorNumFixup ((VOID *) InterruptEntry, (UINT8) Index, (VOID *) TemplateMap.ExceptionStart);
InterruptEntry += TemplateMap.ExceptionStubHeaderSize; InterruptEntry += TemplateMap.ExceptionStubHeaderSize;
} }

View File

@ -166,7 +166,11 @@ UpdateIdtTable (
(VOID *) TemplateMap->HookAfterStubHeaderStart, (VOID *) TemplateMap->HookAfterStubHeaderStart,
TemplateMap->ExceptionStubHeaderSize TemplateMap->ExceptionStubHeaderSize
); );
AsmVectorNumFixup ((VOID *) mReservedVectors[Index].HookAfterStubHeaderCode, (UINT8) Index); AsmVectorNumFixup (
(VOID *) mReservedVectors[Index].HookAfterStubHeaderCode,
(UINT8) Index,
(VOID *) TemplateMap->HookAfterStubHeaderStart
);
// //
// Go on the following code // Go on the following code
// //

View File

@ -632,7 +632,7 @@ ASM_PFX(AsmGetTemplateAddressMap):
popl %ebp popl %ebp
ret ret
#------------------------------------------------------------------------------------- #-------------------------------------------------------------------------------------
# AsmVectorNumFixup (*VectorBase, VectorNum); # AsmVectorNumFixup (*NewVectorAddr, VectorNum, *OldVectorAddr);
#------------------------------------------------------------------------------------- #-------------------------------------------------------------------------------------
ASM_GLOBAL ASM_PFX(AsmVectorNumFixup) ASM_GLOBAL ASM_PFX(AsmVectorNumFixup)
ASM_PFX(AsmVectorNumFixup): ASM_PFX(AsmVectorNumFixup):

View File

@ -434,7 +434,7 @@ AsmGetTemplateAddressMap proc near public
AsmGetTemplateAddressMap ENDP AsmGetTemplateAddressMap ENDP
;------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------
; AsmVectorNumFixup (*VectorBase, VectorNum); ; AsmVectorNumFixup (*NewVectorAddr, VectorNum, *OldVectorAddr);
;------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------
AsmVectorNumFixup proc near public AsmVectorNumFixup proc near public
mov eax, dword ptr [esp + 8] mov eax, dword ptr [esp + 8]

View File

@ -23,265 +23,79 @@
ASM_GLOBAL ASM_PFX(CommonExceptionHandler) 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 #EXTRN ASM_PFX(mDoFarReturnFlag):QWORD # Do far return flag
.text .text
# #ifdef __APPLE__
# exception handler stub table # macros are different between GNU and Xcode as.
# .macro IDT_MACRO
Exception0Handle: push $0
.byte 0x6a # push #VectorNum #else
.byte 0 .macro IDT_MACRO arg
pushq %rax push \arg
.byte 0x48, 0xB8 #endif
.quad ASM_PFX(CommonInterruptEntry) jmp ASM_PFX(CommonInterruptEntry)
jmp *%rax .endm
Exception1Handle:
.byte 0x6a # push #VectorNum AsmIdtVectorBegin:
.byte 1 IDT_MACRO $0
pushq %rax IDT_MACRO $1
.byte 0x48, 0xB8 IDT_MACRO $2
.quad ASM_PFX(CommonInterruptEntry) IDT_MACRO $3
jmp *%rax IDT_MACRO $4
Exception2Handle: IDT_MACRO $5
.byte 0x6a # push #VectorNum IDT_MACRO $6
.byte 2 IDT_MACRO $7
pushq %rax IDT_MACRO $8
.byte 0x48, 0xB8 IDT_MACRO $9
.quad ASM_PFX(CommonInterruptEntry) IDT_MACRO $10
jmp *%rax IDT_MACRO $11
Exception3Handle: IDT_MACRO $12
.byte 0x6a # push #VectorNum IDT_MACRO $13
.byte 3 IDT_MACRO $14
pushq %rax IDT_MACRO $15
.byte 0x48, 0xB8 IDT_MACRO $16
.quad ASM_PFX(CommonInterruptEntry) IDT_MACRO $17
jmp *%rax IDT_MACRO $18
Exception4Handle: IDT_MACRO $19
.byte 0x6a # push #VectorNum IDT_MACRO $20
.byte 4 IDT_MACRO $21
pushq %rax IDT_MACRO $22
.byte 0x48, 0xB8 IDT_MACRO $23
.quad ASM_PFX(CommonInterruptEntry) IDT_MACRO $24
jmp *%rax IDT_MACRO $25
Exception5Handle: IDT_MACRO $26
.byte 0x6a # push #VectorNum IDT_MACRO $27
.byte 5 IDT_MACRO $28
pushq %rax IDT_MACRO $29
.byte 0x48, 0xB8 IDT_MACRO $30
.quad ASM_PFX(CommonInterruptEntry) IDT_MACRO $31
jmp *%rax AsmIdtVectorEnd:
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
HookAfterStubHeaderBegin: HookAfterStubHeaderBegin:
.byte 0x6a # push .byte 0x6a # push
VectorNum: PatchVectorNum:
.byte 0 # 0 will be fixed .byte 0 # 0 will be fixed
pushq %rax .byte 0xe9 # jmp ASM_PFX(HookAfterStubHeaderEnd)
.byte 0x48, 0xB8 # movq ASM_PFX(HookAfterStubHeaderEnd), %rax PatchFuncAddress:
.quad ASM_PFX(HookAfterStubHeaderEnd) .set HOOK_ADDRESS, ASM_PFX(HookAfterStubHeaderEnd) - . - 4
jmp *%rax .long HOOK_ADDRESS # will be fixed
ASM_GLOBAL ASM_PFX(HookAfterStubHeaderEnd) ASM_GLOBAL ASM_PFX(HookAfterStubHeaderEnd)
ASM_PFX(HookAfterStubHeaderEnd): ASM_PFX(HookAfterStubHeaderEnd):
pushq %rax
movq %rsp, %rax movq %rsp, %rax
andl $0x0fffffff0, %esp # make sure 16-byte aligned for exception context andl $0x0fffffff0, %esp # make sure 16-byte aligned for exception context
subq $0x18, %rsp # reserve room for filling exception data later subq $0x18, %rsp # reserve room for filling exception data later
pushq %rcx pushq %rcx
movq 8(%rax), %rcx movq 8(%rax), %rcx
pushq %rax bt %ecx, ASM_PFX(mErrorCodeFlag)(%rip)
movabsl ASM_PFX(mErrorCodeFlag), %eax
bt %ecx, %eax
popq %rax
jnc NoErrorData jnc NoErrorData
pushq (%rsp) # push additional rcx to make stack alignment pushq (%rsp) # push additional rcx to make stack alignment
NoErrorData: NoErrorData:
xchgq (%rsp), %rcx # restore rcx, save Exception Number in stack 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 ; # CommonInterruptEntry ;
@ -291,7 +105,6 @@ NoErrorData:
ASM_GLOBAL ASM_PFX(CommonInterruptEntry) ASM_GLOBAL ASM_PFX(CommonInterruptEntry)
ASM_PFX(CommonInterruptEntry): ASM_PFX(CommonInterruptEntry):
cli cli
popq %rax
# #
# All interrupt handlers are invoked through interrupt gates, so # All interrupt handlers are invoked through interrupt gates, so
# IF flag automatically cleared at the entry point # IF flag automatically cleared at the entry point
@ -304,7 +117,7 @@ ASM_PFX(CommonInterruptEntry):
cmp $32, %ecx # Intel reserved vector for exceptions? cmp $32, %ecx # Intel reserved vector for exceptions?
jae NoErrorCode jae NoErrorCode
pushq %rax pushq %rax
movabsl ASM_PFX(mErrorCodeFlag), %eax movl ASM_PFX(mErrorCodeFlag)(%rip), %eax
bt %ecx, %eax bt %ecx, %eax
popq %rax popq %rax
jc CommonInterruptEntry_al_0000 jc CommonInterruptEntry_al_0000
@ -553,7 +366,7 @@ ErrorCode:
DoReturn: DoReturn:
pushq %rax 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 cmpq $0, %rax # Check if need to do far return instead of IRET
popq %rax popq %rax
jz DoIret jz DoIret
@ -566,7 +379,11 @@ DoReturn:
movq (%rax), %rax # restore rax movq (%rax), %rax # restore rax
popfq # restore EFLAGS popfq # restore EFLAGS
.byte 0x48 # prefix to composite "retq" with next "retf" .byte 0x48 # prefix to composite "retq" with next "retf"
#ifdef __APPLE__
.byte 0xCB
#else
retf # far return retf # far return
#endif
DoIret: DoIret:
iretq iretq
@ -577,21 +394,43 @@ DoIret:
# comments here for definition of address map # comments here for definition of address map
ASM_GLOBAL ASM_PFX(AsmGetTemplateAddressMap) ASM_GLOBAL ASM_PFX(AsmGetTemplateAddressMap)
ASM_PFX(AsmGetTemplateAddressMap): ASM_PFX(AsmGetTemplateAddressMap):
pushq %rbp
movq %rsp, %rbp
movabsq $Exception0Handle, %rax leaq AsmIdtVectorBegin(%rip), %rax
movq %rax, (%rcx) movq %rax, (%rcx)
movq $(Exception1Handle - Exception0Handle), 0x08(%rcx) .set ENTRY_SIZE, ASM_PFX(HookAfterStubHeaderEnd) - HookAfterStubHeaderBegin
movabsq $HookAfterStubHeaderBegin, %rax movq $(ENTRY_SIZE), 0x08(%rcx)
leaq HookAfterStubHeaderBegin(%rip), %rax
movq %rax, 0x10(%rcx) movq %rax, 0x10(%rcx)
popq %rbp
ret 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_GLOBAL ASM_PFX(AsmVectorNumFixup)
ASM_PFX(AsmVectorNumFixup): ASM_PFX(AsmVectorNumFixup):
movq %rdx, %rax pushq %rbp
movb %al, (VectorNum - HookAfterStubHeaderBegin)(%rcx) 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 ret
#END #END

View File

@ -378,7 +378,7 @@ AsmGetTemplateAddressMap PROC
AsmGetTemplateAddressMap ENDP AsmGetTemplateAddressMap ENDP
;------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------
; AsmVectorNumFixup (*VectorBase, VectorNum); ; AsmVectorNumFixup (*NewVectorAddr, VectorNum, *OldVectorAddr);
;------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------
AsmVectorNumFixup PROC AsmVectorNumFixup PROC
mov rax, rdx mov rax, rdx