-
Notifications
You must be signed in to change notification settings - Fork 56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature request: Support ARM64 #68
Comments
I don't object, but I don't have the time nor a setup I could test. I'd happily accept PRs. |
It also can't be tested on GitHub Actions (there is no ARM runner available). |
True, this is a bit thinking/preparing in advance 😉 Btw, the Msys2 project has a self-hosted runner if it helps: https://github.com/msys2-arm There are cca 900 packages available, drmingw being the missing puzzle to try out building e.g darktable and gimp. |
So. I tried, the clangarm64 build in MSYS2 is failing:
This is outside my expertise, it's about the ARM64 framing. I had this same issue when trying to port ProcessHacker/PEView to ARM64 :-( |
I don't have the ARM64 expertise neither. From Googling around it does seem that ARM64 also has the concept of frame pointer, so it shouldn't be too difficult to hook it up. https://docs.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?view=msvc-170 describes this but it's not crystal clear. This is the CONTEXT structure definition for ARM64 from https://sourceforge.net/p/mingw-w64/mingw-w64/ci/master/tree/mingw-w64-headers/include/winnt.h: typedef struct DECLSPEC_ALIGN(16) _CONTEXT {
ULONG ContextFlags; /* 000 */
/* CONTEXT_INTEGER */
ULONG Cpsr; /* 004 */
union
{
struct
{
DWORD64 X0; /* 008 */
DWORD64 X1; /* 010 */
DWORD64 X2; /* 018 */
DWORD64 X3; /* 020 */
DWORD64 X4; /* 028 */
DWORD64 X5; /* 030 */
DWORD64 X6; /* 038 */
DWORD64 X7; /* 040 */
DWORD64 X8; /* 048 */
DWORD64 X9; /* 050 */
DWORD64 X10; /* 058 */
DWORD64 X11; /* 060 */
DWORD64 X12; /* 068 */
DWORD64 X13; /* 070 */
DWORD64 X14; /* 078 */
DWORD64 X15; /* 080 */
DWORD64 X16; /* 088 */
DWORD64 X17; /* 090 */
DWORD64 X18; /* 098 */
DWORD64 X19; /* 0a0 */
DWORD64 X20; /* 0a8 */
DWORD64 X21; /* 0b0 */
DWORD64 X22; /* 0b8 */
DWORD64 X23; /* 0c0 */
DWORD64 X24; /* 0c8 */
DWORD64 X25; /* 0d0 */
DWORD64 X26; /* 0d8 */
DWORD64 X27; /* 0e0 */
DWORD64 X28; /* 0e8 */
DWORD64 Fp; /* 0f0 */
DWORD64 Lr; /* 0f8 */
} DUMMYSTRUCTNAME;
DWORD64 X[31]; /* 008 */
} DUMMYUNIONNAME;
/* CONTEXT_CONTROL */
DWORD64 Sp; /* 100 */
DWORD64 Pc; /* 108 */
/* CONTEXT_FLOATING_POINT */
NEON128 V[32]; /* 110 */
DWORD Fpcr; /* 310 */
DWORD Fpsr; /* 314 */
/* CONTEXT_DEBUG_REGISTERS */
DWORD Bcr[ARM64_MAX_BREAKPOINTS]; /* 318 */
DWORD64 Bvr[ARM64_MAX_BREAKPOINTS]; /* 338 */
DWORD Wcr[ARM64_MAX_WATCHPOINTS]; /* 378 */
DWORD64 Wvr[ARM64_MAX_WATCHPOINTS]; /* 380 */
} CONTEXT, *PCONTEXT; Here are a few examples of invoking StacklWalk64 on ARM64:
Here's an (untested) attempt: diff --git a/src/common/log.cpp b/src/common/log.cpp
index ef50b82..df170c4 100644
--- a/src/common/log.cpp
+++ b/src/common/log.cpp
@@ -167,17 +167,24 @@ dumpStack(HANDLE hProcess, HANDLE hThread, const CONTEXT *pContext)
} else {
// NOLINTNEXTLINE(clang-analyzer-core.NullDereference)
assert((pContext->ContextFlags & CONTEXT_FULL) == CONTEXT_FULL);
-#ifndef _WIN64
+#if defined(_M_IX86)
MachineType = IMAGE_FILE_MACHINE_I386;
dumpContext(pContext);
StackFrame.AddrPC.Offset = pContext->Eip;
StackFrame.AddrStack.Offset = pContext->Esp;
StackFrame.AddrFrame.Offset = pContext->Ebp;
-#else
+#elif defined(_M_AMD64)
MachineType = IMAGE_FILE_MACHINE_AMD64;
StackFrame.AddrPC.Offset = pContext->Rip;
StackFrame.AddrStack.Offset = pContext->Rsp;
StackFrame.AddrFrame.Offset = pContext->Rbp;
+#elif defined(_M_ARM64)
+ MachineType = IMAGE_FILE_MACHINE_ARM64;
+ StackFrame.AddrPC.Offset = pContext->Pc;
+ StackFrame.AddrStack.Offset = pContext->Sp;
+ StackFrame.AddrFrame.Offset = pContext->Fp;
+#else
+#error Unsupported machine
#endif
}
StackFrame.AddrPC.Mode = AddrModeFlat; You'll also need to update There are probably other places in DrMingw source one sees PS: For the record, another alternative I've often considered is to hook https://github.com/ianlancetaylor/libbacktrace into DrMingw. This is far superior to manual frame walking, as it can use the DWARF call stack unwind information. And I suppose it would naturally work on Arm64 too. Alas is a tad too much work than I can afford to invest. I'm also not sure how well it would work unwinding call stack of DLLs build with Microsoft compilers. So not an easy/quick fix. |
Cool. Either StackWalk64 is not returning, or perhaps it's the symbol walking / resolution is failing. You'll need to add a few printfs to narrow the issue down. If the problem is in DbgHelp.DLL, remember there are usually multiple sources of this DLL: one comes with Windows itself, other comes with WinDBG, so it's worth trying both versions to see if it helps. Note the registers are 64bits, so you should use |
@jrfonseca I got further. The whole package recipe is compiling in MSYS2 CLANGARM64. Unfortunately I'm working with their version (which is not the latest), because the current MSYS2 patches are really complicated to port. But for now, I got the code compiling. The changes I've done to the MSYS2 version are the same as these: https://github.com/jrfonseca/drmingw/compare/master...hmartinez82:ClangARM64?expand=1 My current situation is that most of the /tests/apps are crashing drmingw itself once it's launched to handle the exceptions Here's an example of one that is working, int_divide_by_zero.exe: https://pastebin.com/wgNhujH9
If I close drmingw itself at that moment, it's launched again trying to handle itself. DebugView is printing this (even for tests that work):
I wonder if this lack of libdwarf is the issue. |
I wonder if the hangs are due to loading symbols from Microsoft symbol server. You can try to set Microsoft DLLs such as You need to narrow down the issue. The difficulty is lack of tools on Arm64. I think the best approach is adding printfs. I recommend you to add a macro like #define CHECK_POINT() \
OutputDebug("drmingw: %s : %u\n", __FILE__, __LINE__) and sprinkle, entering/leaving functions, first the top level functions, then callees, etc, so you can narrow down which function is being called and not returning. You can also try using catchsegv instead of drmingw, which allows you to use normal printfs. Another alternative is tell Clang to generate PDB debug info, and then debug DrMinGW by attaching Windbg. I also recommend double checking that WinDBG works well as post-mortem debugg. That is, you can also install windbg as post mortem debugger, and you can then try with the samples causing troubles to DrMinGW and confirm that the trouble is truly specific to DrMingw, and not, for example, DbgHelp, or some other Windows component. |
I have Visual Studio native in ARM64 running in my machine. I didn't know you could get PDBs from Clang when using the GCC frontend 😮. I'll try that soon. |
It's noted in the readme of llvm-mingw:
Though it may have been improved on git HEAD. |
Meanwhile, at least I got the latest drmingw in a PR for MSYS2 msys2/MINGW-packages#11977 |
So #70 closes this? |
I believe so. |
👍 Not sure if the LLVM 15 release (and imminent packaging for MSYS2) will affect this though: "Switched the MinGW target to use SEH instead of DWARF for unwind information." |
Unfortunately DrMingw has never been capable to unwind stack using MinGW's debugging information. It's been a long standing wish item (which could be achieved, for example, by integrating libbacktrace.) I don't have time myself, but I'd accept PRs if anybody was willing to try. Be it on Arm or x86, DrMinGW requires |
@kmilos , @hmartinez82 , FYI, I got Arm binaries generated by GitHub, using llvm-mingw. You can get them from here. I couldn't test them properly though. I have no Arm hardware. Full system Windows Arm emulation with QEMU is dreadfully slow. I got Windows Arm user mode emulation using QEMU + Arm container plus WINE inside the Arm container, but WINE on ARM's implementation of the debugging API used by drmingw/catchsegv.exe is pretty broken, so I can't actually run any tests. If you have Arm, could you please give it a try and make sure they are usable? Known issues:
|
I have a feeling I've seen a related bug report somewhere but can't find it. Maybe @mstorsjo knows how to handle this? |
(First commenting on a few things I noted mentioned here before.)
Yes, I think it probably has. When I added regression testing for LLDB in llvm-mingw (in mstorsjo/llvm-mingw@6dbfbec) I did test both DWARF and PDB, and it runs fine on i686, x86_64 and aarch64 (while armv7 has a few known issues), at least for the trivial testcase I test there, at least with LLDB (haven't tested it with WinDBG recently). I guess I should update that comment.
Actually, this was for the 32 bit ARM target. For ARM64, it has already been using SEH for unwind info (instead of DWARF) since 2019.
Yeah, this has come up a few times - it has been reported in mstorsjo/llvm-mingw#140, which I fixed in https://reviews.llvm.org/D85183. However, that fix was only for string tables, while MS rc.exe does support string literals concatenated from multiple literal strings in a few more places, and windres supports it essentially anywhere. I think llvm/llvm-project#51286 is about that issue too. In the fix in https://reviews.llvm.org/D85183 I mentioned that I do have a fix for this, but it felt more risky and messy and hadn't been needed for any code in the wild yet at that point. If someone wants to have a look, I could rebase my branch with unsubmitted hacks for llvm-rc and publish it somewhere. |
Yeah, I think it would be useful if By the way, thanks for your replies and your work on |
@jrfonseca It's loading correctly and it's in fact ARM64 |
Thanks for checking, @hmartinez82. |
Available
mingw-w64
toolchains foraarch64
:https://github.com/mstorsjo/llvm-mingw/releases
https://www.msys2.org/docs/environments/ (I guess based on/pretty much the same as the above)
The text was updated successfully, but these errors were encountered: