From e9a5632e8daf47aa1f5b76895d7bbb00d630ccec Mon Sep 17 00:00:00 2001
From: Alexander Boyko <boy1284@gmail.com>
Date: Fri, 25 Sep 2026 15:35:11 +0200
Subject: [PATCH] arm64: support an X86_64 target on an ARM64 host
To: devel@lists.crash-utility.osci.io

Allow "make target=X86_64" on an arm64 host to analyze x86_64 dumpfiles,
mirroring the existing "make target=ARM64" support on an x86_64 host.

The only host dependency was in the LKCD dump headers, which embed a
"struct pt_regs" from <asm/ptrace.h>.  The arm64 uapi header exports
"struct user_pt_regs" instead, so add lkcd_x86_64_pt_regs.h, a copy of
the x86_64 uapi definition used only when the X86_64 target is built on
a non-x86_64 host.

Also make the sticky target logic host aware, and reject live system
debugging of an X86/X86_64 binary on an arm64 host.

Assisted-by: Github Copilot CLI:claude-opus-5
Signed-off-by: Alexander Boyko <boy1284@gmail.com>
---
 Makefile              |  2 +-
 README                |  2 ++
 configure.c           | 26 ++++++++++++++++++++--
 filesys.c             |  6 +++++
 lkcd_vmdump_v1.h      |  4 ++++
 lkcd_vmdump_v2_v3.h   |  8 +++++++
 lkcd_x86_64_pt_regs.h | 52 +++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 97 insertions(+), 3 deletions(-)

diff --git a/Makefile b/Makefile
index 46c43a4..22154af 100644
--- a/Makefile
+++ b/Makefile
@@ -98,7 +98,7 @@ GENERIC_HFILES=defs.h xen_hyper_defs.h xen_dom0.h
 MCORE_HFILES=va_server.h vas_crash.h
 REDHAT_HFILES=netdump.h diskdump.h makedumpfile.h xendump.h kvmdump.h qemu-load.h vmcore.h
 LKCD_DUMP_HFILES=lkcd_vmdump_v1.h lkcd_vmdump_v2_v3.h lkcd_dump_v5.h \
-        lkcd_dump_v7.h lkcd_dump_v8.h
+        lkcd_dump_v7.h lkcd_dump_v8.h lkcd_x86_64_pt_regs.h
 LKCD_OBSOLETE_HFILES=lkcd_fix_mem.h
 LKCD_TRACE_HFILES=lkcd_x86_trace.h
 IBM_HFILES=ibm_common.h
diff --git a/README b/README
index 69232eb..5c4d8f2 100644
--- a/README
+++ b/README
@@ -113,6 +113,8 @@
      riscv64 dumpfiles may be built by typing "make target=RISCV64".
   o  On an x86_64 host, an x86_64 binary that can be used to analyze
      loongarch64 dumpfiles may be built by typing "make target=LOONGARCH64".
+  o  On an arm64 host, an arm64 binary that can be used to analyze
+     x86_64 dumpfiles may be built by typing "make target=X86_64".
 
   Traditionally when vmcores are compressed via the makedumpfile(8) facility
   the libz compression library is used, and by default the crash utility
diff --git a/configure.c b/configure.c
index fd7b533..79c1dc7 100644
--- a/configure.c
+++ b/configure.c
@@ -151,6 +151,7 @@ void add_extra_lib(char *);
 #define TARGET_CFLAGS_S390X  "TARGET_CFLAGS="
 #define TARGET_CFLAGS_PPC64  "TARGET_CFLAGS=-m64"
 #define TARGET_CFLAGS_X86_64 "TARGET_CFLAGS="
+#define TARGET_CFLAGS_X86_64_ON_ARM64  "TARGET_CFLAGS="
 #define TARGET_CFLAGS_ARM            "TARGET_CFLAGS=-D_FILE_OFFSET_BITS=64"
 #define TARGET_CFLAGS_ARM_ON_X86     "TARGET_CFLAGS=-D_FILE_OFFSET_BITS=64"
 #define TARGET_CFLAGS_ARM_ON_X86_64  "TARGET_CFLAGS=-m32 -D_FILE_OFFSET_BITS=64"
@@ -182,6 +183,7 @@ void add_extra_lib(char *);
 #define GDB_TARGET_MIPS_ON_X86_64  "GDB_CONF_FLAGS=--target=mipsel-elf-linux CFLAGS=-m32 CXXFLAGS=-m32"
 #define GDB_TARGET_RISCV64_ON_X86_64  "GDB_CONF_FLAGS=--target=riscv64-unknown-linux-gnu"
 #define GDB_TARGET_LOONGARCH64_ON_X86_64  "GDB_CONF_FLAGS=--target=loongarch64-unknown-linux-gnu"
+#define GDB_TARGET_X86_64_ON_ARM64  "GDB_CONF_FLAGS=--target=x86_64-pc-linux-gnu"
      
 /*
  *  The original plan was to allow the use of a particular version
@@ -474,6 +476,12 @@ get_current_configuration(struct supported_gdb_version *sp)
 			 *  Build an ARM64 crash binary on an X86_64 host.
 			 */
 			target_data.target = ARM64;
+		} else if ((target_data.target == ARM64) &&
+			(name_to_target((char *)target_data.target_as_param) == X86_64)) {
+			/*
+			 *  Build an X86_64 crash binary on an ARM64 host.
+			 */
+			target_data.target = X86_64;
 		} else if ((target_data.target == X86_64) &&
 			(name_to_target((char *)target_data.target_as_param) == PPC64)) {
 			/*
@@ -570,9 +578,19 @@ get_current_configuration(struct supported_gdb_version *sp)
 		    (target_data.initial_gdb_target != X86))
 			arch_mismatch(sp);
 
+		if ((target_data.initial_gdb_target == X86_64) &&
+		    (target_data.target != X86_64) &&
+		    (target_data.host == ARM64)) {
+			if (target_data.target == ARM64)
+				target_data.target = X86_64;
+			else
+				arch_mismatch(sp);
+		}
+
 		if ((target_data.initial_gdb_target == ARM64) &&
 		    (target_data.target != ARM64)) {
-			if (target_data.target == X86_64) 
+			if ((target_data.target == X86_64) &&
+			    (target_data.host == X86_64))
 				target_data.target = ARM64;
 			else
 				arch_mismatch(sp);
@@ -787,7 +805,11 @@ build_configure(struct supported_gdb_version *sp)
                 break;
 	case X86_64:
                 target = TARGET_X86_64;
-                target_CFLAGS = TARGET_CFLAGS_X86_64;
+		if (target_data.host == ARM64) {
+			target_CFLAGS = TARGET_CFLAGS_X86_64_ON_ARM64;
+			gdb_conf_flags = GDB_TARGET_X86_64_ON_ARM64;
+		} else
+			target_CFLAGS = TARGET_CFLAGS_X86_64;
                 break;
 	case ARM:
                 target = TARGET_ARM;
diff --git a/filesys.c b/filesys.c
index 7ff4787..41e60b2 100644
--- a/filesys.c
+++ b/filesys.c
@@ -4574,4 +4574,10 @@ check_live_arch_mismatch(void)
 	if (machine_type("PPC"))
 		error(FATAL, "compiled for the PPC architecture\n");
 #endif
+#ifdef __aarch64__
+	if (machine_type("X86_64"))
+		error(FATAL, "compiled for the X86_64 architecture\n");
+	if (machine_type("X86"))
+		error(FATAL, "compiled for the X86 architecture\n");
+#endif
 }
diff --git a/lkcd_vmdump_v1.h b/lkcd_vmdump_v1.h
index 3ffb219..0540a1f 100644
--- a/lkcd_vmdump_v1.h
+++ b/lkcd_vmdump_v1.h
@@ -35,8 +35,12 @@
 #endif
 #ifndef IA64
 typedef unsigned int u32;
+#if defined(X86_64) && !defined(__x86_64__)
+#include "lkcd_x86_64_pt_regs.h"        /* for pt_regs                      */
+#else
 #include <asm/ptrace.h>                 /* for pt_regs                      */
 #endif
+#endif
 
 /* necessary header definitions in all cases */
 #define DUMP_KIOBUF_NUMBER  0xdeadbeef  /* special number for kiobuf maps   */
diff --git a/lkcd_vmdump_v2_v3.h b/lkcd_vmdump_v2_v3.h
index f215446..e62a322 100644
--- a/lkcd_vmdump_v2_v3.h
+++ b/lkcd_vmdump_v2_v3.h
@@ -55,7 +55,11 @@
 
 /* necessary header files */
 typedef unsigned int u32;
+#if defined(X86_64) && !defined(__x86_64__)
+#include "lkcd_x86_64_pt_regs.h"                 /* for pt_regs             */
+#else
 #include <asm/ptrace.h>                          /* for pt_regs             */
+#endif
 
 /* definitions */
 #define DUMP_ASM_MAGIC_NUMBER     0xdeaddeadULL  /* magic number            */
@@ -104,8 +108,12 @@ typedef struct _dump_header_asm_s {
 
 #ifndef IA64
 typedef unsigned int u32;
+#if defined(X86_64) && !defined(__x86_64__)
+#include "lkcd_x86_64_pt_regs.h"                 /* for pt_regs             */
+#else
 #include <asm/ptrace.h>                          /* for pt_regs             */
 #endif
+#endif
 
 /* definitions */
 #define DUMP_ASM_MAGIC_NUMBER     0xdeaddeadULL  /* magic number            */
diff --git a/lkcd_x86_64_pt_regs.h b/lkcd_x86_64_pt_regs.h
new file mode 100644
index 0000000..db9da42
--- /dev/null
+++ b/lkcd_x86_64_pt_regs.h
@@ -0,0 +1,52 @@
+/* lkcd_x86_64_pt_regs.h - core analysis suite
+ *
+ * Copyright (C) 2025 Hewlett Packard Enterprise Development LP
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/*
+ *  The LKCD dump headers embed the host kernel's "struct pt_regs", which is
+ *  normally picked up from <asm/ptrace.h>.  When the X86_64 target is built
+ *  on a non-x86_64 host, that header describes the host architecture and does
+ *  not export an x86_64 "struct pt_regs" at all, so the definition below is
+ *  used instead.  It is a copy of the x86_64 uapi definition, which keeps the
+ *  LKCD dump header layout identical to a native x86_64 build.
+ */
+
+#ifndef _LKCD_X86_64_PT_REGS_H
+#define _LKCD_X86_64_PT_REGS_H
+
+struct pt_regs {
+	unsigned long r15;
+	unsigned long r14;
+	unsigned long r13;
+	unsigned long r12;
+	unsigned long rbp;
+	unsigned long rbx;
+	unsigned long r11;
+	unsigned long r10;
+	unsigned long r9;
+	unsigned long r8;
+	unsigned long rax;
+	unsigned long rcx;
+	unsigned long rdx;
+	unsigned long rsi;
+	unsigned long rdi;
+	unsigned long orig_rax;
+	unsigned long rip;
+	unsigned long cs;
+	unsigned long eflags;
+	unsigned long rsp;
+	unsigned long ss;
+};
+
+#endif /* _LKCD_X86_64_PT_REGS_H */
-- 
2.54.0 (Apple Git-157)

