aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2019-10-27 11:35:09 +0100
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2019-10-30 09:52:14 +0100
commit2c06f143fa63394dbdfa07f3f9d00b24b7c902c5 (patch)
tree6c19c53230ab117d2bf82f64b64ea7e50962d1dc
parent0a35fa5b1ce9be51c0a2f557fdfe75fabdf58a23 (diff)
downloadsparse-2c06f143fa63394dbdfa07f3f9d00b24b7c902c5.tar.gz
arch: add an option to specify the desired arch: --arch=<arch>
Sparse is universal in the sense that the same executable can be used for all architectures. For this, most arch-specific setting can be set with an option and the default values are taken from the host machine. This is working nicely for native targets. However, for cross- compilation, while seeming to work relatively well (thanks to the kernel build system using -m32/-m64 for all archs, for example) things can never work 100% correctly. For example, in the case an X86-64 host machine is used for an ARM target, the kernel build system will call sparse with -m32, Sparse will 'autodetect' the target arch as i386 (x86-64 + -m32) and will then predefine the macro __i386__. Most of the time this is not a problem (at least for the kernel) unless, of course, if the code contains something like: #ifdef __i386__ ... #elif __arm__ ... So, add an option --arch=<arch> to specify the target architecture. The native arch is still used if no such flag is given. Reported-by: Ben Dooks <ben.dooks@codethink.co.uk> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r--lib.c68
-rw-r--r--sparse.18
-rw-r--r--validation/arch/arm.c27
-rw-r--r--validation/arch/arm64.c23
-rw-r--r--validation/arch/mips32.c29
-rw-r--r--validation/arch/riscv64.c27
6 files changed, 182 insertions, 0 deletions
diff --git a/lib.c b/lib.c
index 58c12c77..91ecc12c 100644
--- a/lib.c
+++ b/lib.c
@@ -1046,6 +1046,73 @@ static char **handle_switch_x(char *arg, char **next)
}
+static char **handle_arch(char *arg, char **next)
+{
+ static const struct arch {
+ const char *name;
+ char mach;
+ char bits;
+ bool big_endian:1;
+ } archs[] = {
+ { "aarch64", MACH_ARM64, 64, 0 },
+ { "arm64", MACH_ARM64, 64, 0 },
+ { "arm", MACH_ARM, 32, 0 },
+ { "i386", MACH_I386, 32, 0 },
+ { "m68k", MACH_M68K, 32, 0 },
+ { "mips", MACH_MIPS32, 0, 1 },
+ { "powerpc", MACH_PPC32, 0, 1 },
+ { "ppc", MACH_PPC32, 0, 1 },
+ { "riscv", MACH_RISCV32, 0, 0 },
+ { "s390x", MACH_S390X, 64, 1 },
+ { "s390", MACH_S390, 32, 1 },
+ { "sparc", MACH_SPARC32, 0, 1 },
+ { "x86_64", MACH_X86_64, 64, 0 },
+ { "x86-64", MACH_X86_64, 64, 0 },
+ { NULL },
+ };
+ const struct arch *p;
+
+ if (*arg++ != '=')
+ die("missing argument for --arch option");
+
+ for (p = &archs[0]; p->name; p++) {
+ size_t len = strlen(p->name);
+ if (strncmp(p->name, arg, len) == 0) {
+ const char *suf = arg + len;
+ int bits = p->bits;
+
+ arch_mach = p->mach;
+ if (bits == 0) {
+ if (!strcmp(suf, "")) {
+ bits = 32;
+ } else if (!strcmp(suf, "32")) {
+ bits = 32;
+ } else if (!strcmp(suf, "64")) {
+ bits = 64;
+ arch_mach += 1;
+ } else {
+ die("invalid architecture: %s", arg);
+ }
+ } else {
+ if (strcmp(suf, ""))
+ die("invalid architecture: %s", arg);
+ }
+
+ // adjust the arch size (but keep x32 & llp64)
+ if (bits == 32)
+ arch_m64 = ARCH_LP32;
+ else if (bits == 64 && arch_m64 == ARCH_LP32)
+ arch_m64 = ARCH_LP64;
+ if (p->big_endian)
+ arch_big_endian = 1;
+
+ break;
+ }
+ }
+
+ return next;
+}
+
static char **handle_version(char *arg, char **next)
{
printf("%s\n", SPARSE_VERSION);
@@ -1078,6 +1145,7 @@ struct switches {
static char **handle_long_options(char *arg, char **next)
{
static struct switches cmd[] = {
+ { "arch", handle_arch, 1 },
{ "param", handle_param, 1 },
{ "version", handle_version },
{ NULL, NULL }
diff --git a/sparse.1 b/sparse.1
index beb48442..be38f688 100644
--- a/sparse.1
+++ b/sparse.1
@@ -423,6 +423,14 @@ Sparse does not issue these warnings by default.
.
.SH MISC OPTIONS
.TP
+.B \-\-arch=\fIARCH\fR
+Specify the target architecture.
+For architectures having both a 32-bit and a 64-bit variant (mips, powerpc,
+riscv & sparc) the architecture name can be suffixed with \fI32\fR or \fI64\fR.
+
+The default architecture & size is the one of the machine used to build Sparse.
+.
+.TP
.B \-gcc-base-dir \fIdir\fR
Look for compiler-provided system headers in \fIdir\fR/include/ and \fIdir\fR/include-fixed/.
.
diff --git a/validation/arch/arm.c b/validation/arch/arm.c
new file mode 100644
index 00000000..4eb804de
--- /dev/null
+++ b/validation/arch/arm.c
@@ -0,0 +1,27 @@
+__arm__
+__aarch64__
+__i386__
+__x86_64__
+__LP64__
+__BYTE_ORDER__
+__SIZEOF_INT__
+__SIZEOF_LONG__
+__SIZE_TYPE__
+
+/*
+ * check-name: arch/arm
+ * check-command: sparse --arch=arm -E $file
+ *
+ * check-output-start
+
+1
+__aarch64__
+__i386__
+__x86_64__
+__LP64__
+1234
+4
+4
+unsigned int
+ * check-output-end
+ */
diff --git a/validation/arch/arm64.c b/validation/arch/arm64.c
new file mode 100644
index 00000000..12f839cc
--- /dev/null
+++ b/validation/arch/arm64.c
@@ -0,0 +1,23 @@
+__aarch64__
+__x86_64__
+__LP64__
+__BYTE_ORDER__
+__SIZEOF_INT__
+__SIZEOF_LONG__
+__SIZE_TYPE__
+
+/*
+ * check-name: arch/arm64
+ * check-command: sparse --arch=arm64 -E $file
+ *
+ * check-output-start
+
+1
+__x86_64__
+1
+1234
+4
+8
+unsigned long
+ * check-output-end
+ */
diff --git a/validation/arch/mips32.c b/validation/arch/mips32.c
new file mode 100644
index 00000000..339218b6
--- /dev/null
+++ b/validation/arch/mips32.c
@@ -0,0 +1,29 @@
+__mips__
+__mips
+__mips64__
+__i386__
+__x86_64__
+__LP64__
+__BYTE_ORDER__
+__SIZEOF_INT__
+__SIZEOF_LONG__
+__SIZE_TYPE__
+
+/*
+ * check-name: arch/mips32
+ * check-command: sparse --arch=mips32 -E $file
+ *
+ * check-output-start
+
+1
+32
+__mips64__
+__i386__
+__x86_64__
+__LP64__
+4321
+4
+4
+unsigned int
+ * check-output-end
+ */
diff --git a/validation/arch/riscv64.c b/validation/arch/riscv64.c
new file mode 100644
index 00000000..9da7a7de
--- /dev/null
+++ b/validation/arch/riscv64.c
@@ -0,0 +1,27 @@
+__riscv
+__riscv_xlen
+__i386__
+__x86_64__
+__LP64__
+__BYTE_ORDER__
+__SIZEOF_INT__
+__SIZEOF_LONG__
+__SIZE_TYPE__
+
+/*
+ * check-name: arch/riscv64
+ * check-command: sparse --arch=riscv64 -E $file
+ *
+ * check-output-start
+
+1
+64
+__i386__
+__x86_64__
+1
+1234
+4
+8
+unsigned long
+ * check-output-end
+ */