Skip to content

Commit ea6c4ae

Browse files
authored
Add Arm64EC support (microsoft#338)
This change adds Arm64EC detours support. It bumps the toolset version to 143 from 142 since 142 does not support Arm64EC officially. It adds a new Arm64EC target. It passes Arm64EC-specific compilation flag /arm64EC and linker flag /machine:arm64x or /machine:arm64ec in right places.
1 parent eed910d commit ea6c4ae

File tree

18 files changed

+348
-91
lines changed

18 files changed

+348
-91
lines changed

samples/commem/commem.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,10 @@ int main(int argc, char **argv)
8686

8787
DetourTransactionBegin();
8888
DetourUpdateThread(GetCurrentThread());
89-
DetourAttach(&(PVOID&)RealIStreamWrite, MineIStreamWrite);
89+
if (DetourAttach(&(PVOID&)RealIStreamWrite, MineIStreamWrite) != NO_ERROR) {
90+
printf("commem: DetourAttach failed.\n");
91+
return 1;
92+
}
9093
DetourTransactionCommit();
9194

9295
printf("commem: Calling Write w/o after attach.\n");

samples/common.mak

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,17 @@ CFLAGS=$(CFLAGS) /D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE
6161

6262
CFLAGS=$(CFLAGS) /D_$(DETOURS_TARGET_PROCESSOR:X64=AMD64)_ # redundant with windows.h except for midl proxies
6363

64+
!ELSEIF "$(DETOURS_TARGET_PROCESSOR)" == "ARM64"
65+
66+
ASM=armasm64
67+
68+
!ELSEIF "$(DETOURS_TARGET_PROCESSOR)" == "ARM64EC"
69+
70+
ASM=ml64
71+
CFLAGS=/arm64EC $(CFLAGS)
72+
LIBFLAGS=$(LIBFLAGS) /machine:arm64x
73+
LINKFLAGS=$(LINKFLAGS) /machine:arm64ec softintrin.lib
74+
6475
!ENDIF
6576

6677
DEPS = $(LIBD)\syelog.lib $(LIBD)\detours.lib

samples/cping/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ MIDLFLAGS=$(MIDLFLAGS) /x64
7070
MIDLFLAGS=$(MIDLFLAGS) /arm32
7171
!ELSEIF "$(DETOURS_TARGET_PROCESSOR)" == "ARM64"
7272
MIDLFLAGS=$(MIDLFLAGS) /arm64
73+
!ELSEIF "$(DETOURS_TARGET_PROCESSOR)" == "ARM64EC"
74+
MIDLFLAGS=$(MIDLFLAGS) /x64
7375
!ENDIF
7476

7577
OBJS = \

samples/cping/cping.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,15 @@
3030
#include <detours.h>
3131
#include "iping.h"
3232

33-
// ARM64 ReadTimeStampCounter is a function.
33+
// ARM64/ARM64EC ReadTimeStampCounter is a function.
3434
// ARM ReadTimeStampCounter is a declared function but not implemented.
3535
// old IA64: ReadTimeStampCounter nonexisant.
3636
// new IA64: ReadTimeStampCounter is a macro.
3737
// old x86; ReadTimeStampCounter is a function.
3838
// new x86: ReadTimeStampCounter is a macro.
3939
// AMD64: ReadTimeStampCounter is a macro.
4040

41-
#if defined(_ARM64_) || defined(ReadTimeStampCounter)
41+
#if defined(_ARM64_) || defined(_ARM64EC_) || defined(ReadTimeStampCounter)
4242
#define GetTimeStamp() ReadTimeStampCounter()
4343
#elif defined(_X86_) || defined(_AMD64_)
4444
extern "C"

samples/disas/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ dirs:
3636
$(OBJD)\disasm.obj : x86.cpp
3737
cl $(CFLAGS) /Fe$@ /FAcs /Fa$(OBJD)\x86.lst \
3838
/Fd$(@R).pdb /Fo$(OBJD)\disasm.obj /c x86.cpp
39-
!ELSEIF "$(DETOURS_TARGET_PROCESSOR)" == "X64"
39+
!ELSEIF "$(DETOURS_TARGET_PROCESSOR)" == "X64" || "$(DETOURS_TARGET_PROCESSOR)" == "ARM64EC"
4040
$(OBJD)\disasm.obj : x64.asm
4141
$(ASM) $(AFLAGS) /Fo$(OBJD)\disasm.obj /Fl$(OBJD)\x64.lst x64.asm
4242
!ELSEIF "$(DETOURS_TARGET_PROCESSOR)" == "IA64"

samples/dtest/dtarge.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
//
99
#include <stdio.h>
1010
#include <windows.h>
11+
#include <detours.h>
1112
#include "dtarge.h"
1213

1314
DWORD_PTR WINAPI Target0()

samples/dtest/dtarge.h

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,49 +12,49 @@
1212
typedef DWORD DWORD_PTR;
1313
#endif
1414

15-
DWORD_PTR WINAPI Target0();
16-
DWORD_PTR WINAPI Target1(DWORD_PTR v1);
17-
DWORD_PTR WINAPI Target2(DWORD_PTR v1, DWORD_PTR v2);
18-
DWORD_PTR WINAPI Target3(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3);
19-
DWORD_PTR WINAPI Target4(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4);
20-
DWORD_PTR WINAPI Target5(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4,
15+
DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI Target0();
16+
DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI Target1(DWORD_PTR v1);
17+
DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI Target2(DWORD_PTR v1, DWORD_PTR v2);
18+
DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI Target3(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3);
19+
DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI Target4(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4);
20+
DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI Target5(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4,
2121
DWORD_PTR v5);
22-
DWORD_PTR WINAPI Target6(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4,
22+
DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI Target6(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4,
2323
DWORD_PTR v5, DWORD_PTR v6);
24-
DWORD_PTR WINAPI Target7(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4,
24+
DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI Target7(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4,
2525
DWORD_PTR v5, DWORD_PTR v6, DWORD_PTR v7);
26-
DWORD_PTR WINAPI Target8(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4,
26+
DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI Target8(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4,
2727
DWORD_PTR v5, DWORD_PTR v6, DWORD_PTR v7, DWORD_PTR v8);
28-
DWORD_PTR WINAPI Target9(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4,
28+
DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI Target9(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4,
2929
DWORD_PTR v5, DWORD_PTR v6, DWORD_PTR v7, DWORD_PTR v8,
3030
DWORD_PTR v9);
31-
DWORD_PTR WINAPI Target10(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4,
31+
DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI Target10(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4,
3232
DWORD_PTR v5, DWORD_PTR v6, DWORD_PTR v7, DWORD_PTR v8,
3333
DWORD_PTR v9, DWORD_PTR v10);
34-
DWORD_PTR WINAPI Target11(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4,
34+
DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI Target11(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4,
3535
DWORD_PTR v5, DWORD_PTR v6, DWORD_PTR v7, DWORD_PTR v8,
3636
DWORD_PTR v9, DWORD_PTR v10, DWORD_PTR v11);
37-
DWORD_PTR WINAPI Target12(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4,
37+
DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI Target12(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4,
3838
DWORD_PTR v5, DWORD_PTR v6, DWORD_PTR v7, DWORD_PTR v8,
3939
DWORD_PTR v9, DWORD_PTR v10, DWORD_PTR v11, DWORD_PTR v12);
40-
DWORD_PTR WINAPI Target13(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4,
40+
DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI Target13(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4,
4141
DWORD_PTR v5, DWORD_PTR v6, DWORD_PTR v7, DWORD_PTR v8,
4242
DWORD_PTR v9, DWORD_PTR v10, DWORD_PTR v11, DWORD_PTR v12,
4343
DWORD_PTR v13);
44-
DWORD_PTR WINAPI Target14(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4,
44+
DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI Target14(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4,
4545
DWORD_PTR v5, DWORD_PTR v6, DWORD_PTR v7, DWORD_PTR v8,
4646
DWORD_PTR v9, DWORD_PTR v10, DWORD_PTR v11, DWORD_PTR v12,
4747
DWORD_PTR v13, DWORD_PTR v14);
48-
DWORD_PTR WINAPI Target15(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4,
48+
DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI Target15(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4,
4949
DWORD_PTR v5, DWORD_PTR v6, DWORD_PTR v7, DWORD_PTR v8,
5050
DWORD_PTR v9, DWORD_PTR v10, DWORD_PTR v11, DWORD_PTR v12,
5151
DWORD_PTR v13, DWORD_PTR v14, DWORD_PTR v15);
52-
DWORD_PTR WINAPI Target16(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4,
52+
DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI Target16(DWORD_PTR v1, DWORD_PTR v2, DWORD_PTR v3, DWORD_PTR v4,
5353
DWORD_PTR v5, DWORD_PTR v6, DWORD_PTR v7, DWORD_PTR v8,
5454
DWORD_PTR v9, DWORD_PTR v10, DWORD_PTR v11, DWORD_PTR v12,
5555
DWORD_PTR v13, DWORD_PTR v14, DWORD_PTR v15, DWORD_PTR v16);
56-
DWORD_PTR WINAPI TargetV(DWORD_PTR v1, ...);
57-
DWORD_PTR WINAPI TargetR(DWORD_PTR v1, ...);
56+
DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI TargetV(DWORD_PTR v1, ...);
57+
DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI TargetR(DWORD_PTR v1, ...);
5858

5959
//
6060
///////////////////////////////////////////////////////////////// End of File.

samples/dtest/dtest.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
#include <detours.h>
1919
#include "dtarge.h"
2020

21-
DWORD_PTR WINAPI LocalTarget1(DWORD_PTR v1);
21+
DECLSPEC_HYBRID_PATCHABLE DWORD_PTR WINAPI LocalTarget1(DWORD_PTR v1);
2222

2323
////////////////////////////////////////////////////// Multi-Argument Detours.
2424
//

samples/einst/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
# ARM64 does not like base addresses below 4GB.
1313
# Append two extra zeros for it.
1414
#
15-
!if "$(DETOURS_TARGET_PROCESSOR)" == "ARM64"
15+
!if "$(DETOURS_TARGET_PROCESSOR)" == "ARM64" || "$(DETOURS_TARGET_PROCESSOR)" == "ARM64EC"
1616
EDLL1X_BASE=0x710000000
1717
EDLL2X_BASE=0x720000000
1818
EDLL3X_BASE=0x730000000

samples/findfunc/Makefile

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@
1010
!include ..\common.mak
1111

1212
# ARM64 does not like base addresses below 4GB.
13-
# Append two extra zeros for it.
14-
#
15-
!if "$(DETOURS_TARGET_PROCESSOR)" == "ARM64"
16-
TARGET_BASE=0x190000000
17-
EXTEND_BASE=0x1a0000000
18-
!else
19-
TARGET_BASE=0x1900000
20-
EXTEND_BASE=0x1a00000
21-
!endif
13+
# Append two extra zeros for it.
14+
#
15+
!if "$(DETOURS_TARGET_PROCESSOR)" == "ARM64" || "$(DETOURS_TARGET_PROCESSOR)" == "ARM64EC"
16+
TARGET_BASE=0x190000000
17+
EXTEND_BASE=0x1a0000000
18+
!else
19+
TARGET_BASE=0x1900000
20+
EXTEND_BASE=0x1a00000
21+
!endif
2222

2323
LIBS=$(LIBS) kernel32.lib
2424

samples/member/member.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
class CMember
4141
{
4242
public:
43-
void Target(void);
43+
DECLSPEC_HYBRID_PATCHABLE void Target(void);
4444
};
4545

4646
void CMember::Target(void)

src/Makefile

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,22 @@ CFLAGS=$(CFLAGS) /DWIN32_LEAN_AND_MEAN /D_WIN32_WINNT=0x501
2828
CFLAGS=$(CFLAGS) /wd4163 # intrinsic rdtebex not available; using newer Windows headers with older compiler
2929
!ENDIF
3030

31+
!IF "$(DETOURS_TARGET_PROCESSOR)" == "ARM64EC"
32+
CFLAGS=/arm64EC $(CFLAGS)
33+
!ENDIF
34+
3135
!if defined(DETOURS_WIN_7) && defined(DETOURS_CL_17_OR_NEWER)
3236
CFLAGS=$(CFLAGS) /D_USING_V110_SDK71_
3337
!elseif defined(DETOURS_ANALYZE)
3438
CFLAGS=$(CFLAGS) /analyze
3539
!endif
3640

41+
LIBFLAGS=/nologo
42+
43+
!IF "$(DETOURS_TARGET_PROCESSOR)" == "ARM64EC"
44+
LIBFLAGS=$(LIBFLAGS) /machine:arm64x
45+
!ENDIF
46+
3747
OBJS = \
3848
$(OBJD)\detours.obj \
3949
$(OBJD)\modules.obj \
@@ -90,7 +100,7 @@ $(OBJD)\detours.bsc : $(OBJS)
90100
bscmake /v /n /o $@ $(OBJS:.obj=.sbr)
91101

92102
$(LIBD)\detours.lib : $(OBJS)
93-
link /lib /out:$@ /nologo $(OBJS)
103+
link /lib $(LIBFLAGS) /out:$@ $(OBJS)
94104

95105
$(INCD)\detours.h : detours.h
96106
copy detours.h $@

src/detours.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2143,6 +2143,15 @@ LONG WINAPI DetourAttachEx(_Inout_ PVOID *ppPointer,
21432143
DETOUR_TRACE((" ppldTarget=%p, code=%p [gp=%p]\n",
21442144
ppldTarget, pbTarget, pTargetGlobals));
21452145
#else // DETOURS_IA64
2146+
#if defined(_M_ARM64EC)
2147+
if (RtlIsEcCode(reinterpret_cast<DWORD64>(*ppPointer))) {
2148+
DETOUR_TRACE(("*ppPointer is an Arm64EC address (ppPointer=%p). "
2149+
"An Arm64EC address cannot be legitimately detoured with an x64 jmp. "
2150+
"Mark the target function with __declspec(hybrid_patchable) to make it detour-able. "
2151+
"We still allow an Arm64EC function to be detoured with an x64 jmp to make it easy (crash) to debug.\n", ppPointer));
2152+
DETOUR_BREAK();
2153+
}
2154+
#endif
21462155
pbTarget = (PBYTE)DetourCodeFromPointer(pbTarget, NULL);
21472156
pDetour = DetourCodeFromPointer(pDetour, NULL);
21482157
#endif // !DETOURS_IA64

src/detours.h

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,15 @@
8383
#undef DETOURS_32BIT
8484
#undef DETOURS_64BIT
8585

86+
#ifndef DECLSPEC_HYBRID_PATCHABLE
87+
#define DECLSPEC_HYBRID_PATCHABLE DECLSPEC_CHPE_PATCHABLE
88+
#endif
89+
8690
#if defined(_X86_)
8791
#define DETOURS_X86
8892
#define DETOURS_OPTION_BITS 64
8993

90-
#elif defined(_AMD64_)
94+
#elif defined(_AMD64_) || defined(_ARM64EC_)
9195
#define DETOURS_X64
9296
#define DETOURS_OPTION_BITS 32
9397

@@ -102,7 +106,7 @@
102106
#define DETOURS_ARM64
103107

104108
#else
105-
#error Unknown architecture (x86, amd64, ia64, arm, arm64)
109+
#error Unknown architecture (x86, amd64, ia64, arm, arm64, arm64ec)
106110
#endif
107111

108112
#ifdef _WIN64
@@ -381,10 +385,10 @@ extern const GUID DETOUR_EXE_RESTORE_GUID;
381385
extern const GUID DETOUR_EXE_HELPER_GUID;
382386

383387
#define DETOUR_TRAMPOLINE_SIGNATURE 0x21727444 // Dtr!
384-
typedef struct _DETOUR_TRAMPOLINE DETOUR_TRAMPOLINE, *PDETOUR_TRAMPOLINE;
385-
386-
#ifndef DETOUR_MAX_SUPPORTED_IMAGE_SECTION_HEADERS
387-
#define DETOUR_MAX_SUPPORTED_IMAGE_SECTION_HEADERS 32
388+
typedef struct _DETOUR_TRAMPOLINE DETOUR_TRAMPOLINE, *PDETOUR_TRAMPOLINE;
389+
390+
#ifndef DETOUR_MAX_SUPPORTED_IMAGE_SECTION_HEADERS
391+
#define DETOUR_MAX_SUPPORTED_IMAGE_SECTION_HEADERS 32
388392
#endif // !DETOUR_MAX_SUPPORTED_IMAGE_SECTION_HEADERS
389393

390394
/////////////////////////////////////////////////////////// Binary Structures.
@@ -594,8 +598,8 @@ PVOID WINAPI DetourCopyInstruction(_In_opt_ PVOID pDst,
594598
BOOL WINAPI DetourSetCodeModule(_In_ HMODULE hModule,
595599
_In_ BOOL fLimitReferencesToModule);
596600
PVOID WINAPI DetourAllocateRegionWithinJumpBounds(_In_ LPCVOID pbTarget,
597-
_Out_ PDWORD pcbAllocatedSize);
598-
BOOL WINAPI DetourIsFunctionImported(_In_ PBYTE pbCode,
601+
_Out_ PDWORD pcbAllocatedSize);
602+
BOOL WINAPI DetourIsFunctionImported(_In_ PBYTE pbCode,
599603
_In_ PBYTE pbAddress);
600604

601605
///////////////////////////////////////////////////// Loaded Binary Functions.

system.mak

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ DETOURS_TARGET_PROCESSOR=$(DETOURS_TARGET_PROCESSOR:x=X)
5252
DETOURS_TARGET_PROCESSOR=$(DETOURS_TARGET_PROCESSOR:y=Y)
5353
DETOURS_TARGET_PROCESSOR=$(DETOURS_TARGET_PROCESSOR:z=Z)
5454

55+
!IF "$(DETOURS_TARGET_PROCESSOR)" == "WIN32"
56+
DETOURS_TARGET_PROCESSOR = X86
57+
!ENDIF
58+
5559
!IF "$(DETOURS_TARGET_PROCESSOR)" == "AMD64"
5660
DETOURS_TARGET_PROCESSOR = X64
5761
!ENDIF
@@ -90,7 +94,9 @@ DETOURS_OPTION_BITS=64
9094
!ELSEIF "$(DETOURS_TARGET_PROCESSOR)" == "ARM"
9195
#!MESSAGE Building for 32-bit ARM.
9296
!ELSEIF "$(DETOURS_TARGET_PROCESSOR)" == "ARM64"
93-
#!MESSAGE Building for 64-bit ARM.
97+
#!MESSAGE Building for 64-bit ARM64.
98+
!ELSEIF "$(DETOURS_TARGET_PROCESSOR)" == "ARM64EC"
99+
#!MESSAGE Building for 64-bit ARM64EC.
94100
!ELSE
95101
!MESSAGE Note: To select the target processor architecture set either
96102
!MESSAGE PROCESSOR_ARCHITECTURE or DETOURS_TARGET_PROCESSOR.

0 commit comments

Comments
 (0)