aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2019-11-01 09:32:23 +0100
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2019-11-01 09:32:23 +0100
commit9b36f4154135ae85c99c07c248af6678c87904ec (patch)
tree5d4a1116d0a9b581e95022241e8097fb81b99292
parent8d04453e5d34168daee5221afd5a1d0b4498d499 (diff)
parentc8a963b2450d739e6fb9f1a4c7485bfb458cc65b (diff)
downloadsparse-9b36f4154135ae85c99c07c248af6678c87904ec.tar.gz
Merge branch 'cmodel'
Add support for -mcmodel & -f{pic,PIC,pie,PIE}. This is motivated by the kernel using the predefine macros __riscv_cmodel_medlow & __riscv_cmodel_medany.
-rw-r--r--lib.c110
-rw-r--r--lib.h15
2 files changed, 125 insertions, 0 deletions
diff --git a/lib.c b/lib.c
index 75a4f987..84b5be6a 100644
--- a/lib.c
+++ b/lib.c
@@ -310,6 +310,8 @@ unsigned long fdump_ir;
int fmem_report = 0;
unsigned long long fmemcpy_max_count = 100000;
unsigned long fpasses = ~0UL;
+int fpic = 0;
+int fpie = 0;
int funsigned_char = UNSIGNED_CHAR;
int preprocess_only;
@@ -326,6 +328,7 @@ static int arch_msize_long = 0;
int arch_m64 = ARCH_M64_DEFAULT;
int arch_big_endian = ARCH_BIG_ENDIAN;
int arch_mach = MACH_NATIVE;
+int arch_cmodel = CMODEL_UNKNOWN;
#define CMDLINE_INCLUDE 20
@@ -468,6 +471,26 @@ static char **handle_switch_m(char *arg, char **next)
arch_big_endian = 1;
} else if (!strcmp(arg, "mlittle-endian")) {
arch_big_endian = 0;
+ } else if (!strncmp(arg, "mcmodel", 7)) {
+ arg += 7;
+ if (*arg++ != '=')
+ die("missing argument for -mcmodel");
+ else if (!strcmp(arg, "kernel"))
+ arch_cmodel = CMODEL_KERNEL;
+ else if (!strcmp(arg, "large"))
+ arch_cmodel = CMODEL_LARGE;
+ else if (!strcmp(arg, "medany"))
+ arch_cmodel = CMODEL_MEDANY;
+ else if (!strcmp(arg, "medium"))
+ arch_cmodel = CMODEL_MEDIUM;
+ else if (!strcmp(arg, "medlow"))
+ arch_cmodel = CMODEL_MEDLOW;
+ else if (!strcmp(arg, "small"))
+ arch_cmodel = CMODEL_SMALL;
+ else if (!strcmp(arg, "tiny"))
+ arch_cmodel = CMODEL_TINY;
+ else
+ die("invalid argument for -mcmodel=%s", arg);
}
return next;
}
@@ -483,6 +506,23 @@ static void handle_arch_msize_long_finalize(void)
static void handle_arch_finalize(void)
{
handle_arch_msize_long_finalize();
+
+ if (fpie > fpic)
+ fpic = fpie;
+
+ switch (arch_mach) {
+ case MACH_ARM64:
+ if (arch_cmodel == CMODEL_UNKNOWN)
+ arch_cmodel = CMODEL_SMALL;
+ break;
+ case MACH_RISCV32:
+ case MACH_RISCV64:
+ if (arch_cmodel == CMODEL_UNKNOWN)
+ arch_cmodel = CMODEL_MEDLOW;
+ if (fpic)
+ arch_cmodel = CMODEL_PIC;
+ break;
+ }
}
static const char *match_option(const char *arg, const char *prefix)
@@ -592,6 +632,12 @@ static int handle_switches(const char *ori, const char *opt, const struct flag *
return 0;
}
+static int handle_switch_setval(const char *arg, const char *opt, const struct flag *flag, int options)
+{
+ *(flag->flag) = flag->mask;
+ return 1;
+}
+
#define OPTNUM_ZERO_IS_INF 1
#define OPTNUM_UNLIMITED 2
@@ -940,6 +986,10 @@ static struct flag fflags[] = {
{ "tabstop=", NULL, handle_ftabstop },
{ "mem2reg", NULL, handle_fpasses, PASS_MEM2REG },
{ "optim", NULL, handle_fpasses, PASS_OPTIM },
+ { "pic", &fpic, handle_switch_setval, 1 },
+ { "PIC", &fpic, handle_switch_setval, 2 },
+ { "pie", &fpie, handle_switch_setval, 1 },
+ { "PIE", &fpie, handle_switch_setval, 2 },
{ "signed-char", &funsigned_char, NULL, OPT_INVERSE },
{ "unsigned-char", &funsigned_char, NULL, },
{ },
@@ -1198,6 +1248,55 @@ static void predefined_ctype(const char *name, struct symbol *type, int flags)
predefined_width(name, bits);
}
+static void predefined_cmodel(void)
+{
+ const char *pre, *suf;
+ const char *def = NULL;
+ switch (arch_mach) {
+ case MACH_ARM64:
+ pre = "__AARCH64_CMODEL_";
+ suf = "__";
+ switch (arch_cmodel) {
+ case CMODEL_LARGE:
+ def = "LARGE";
+ break;
+ case CMODEL_SMALL:
+ def = "SMALL";
+ break;
+ case CMODEL_TINY:
+ def = "TINY";
+ break;
+ default:
+ break;
+ }
+ break;
+ case MACH_RISCV32:
+ case MACH_RISCV64:
+ pre = "__riscv_cmodel_";
+ suf = "";
+ switch (arch_cmodel) {
+ case CMODEL_MEDLOW:
+ def = "medlow";
+ break;
+ case CMODEL_MEDANY:
+ def = "medany";
+ break;
+ case CMODEL_PIC:
+ def = "pic";
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (!def)
+ return;
+ add_pre_buffer("#weak_define %s%s%s 1\n", pre, def, suf);
+}
+
static void predefined_macros(void)
{
predefine("__CHECKER__", 0, "1");
@@ -1382,6 +1481,17 @@ static void predefined_macros(void)
predefine("__i386", 1, "1");
break;
}
+
+ if (fpic) {
+ predefine("__pic__", 0, "%d", fpic);
+ predefine("__PIC__", 0, "%d", fpic);
+ }
+ if (fpie) {
+ predefine("__pie__", 0, "%d", fpie);
+ predefine("__PIE__", 0, "%d", fpie);
+ }
+
+ predefined_cmodel();
}
static void create_builtin_stream(void)
diff --git a/lib.h b/lib.h
index 18c97b4f..f6dea8ca 100644
--- a/lib.h
+++ b/lib.h
@@ -199,12 +199,27 @@ extern int fmem_report;
extern unsigned long fdump_ir;
extern unsigned long long fmemcpy_max_count;
extern unsigned long fpasses;
+extern int fpic;
+extern int fpie;
extern int funsigned_char;
extern int arch_m64;
extern int arch_big_endian;
extern int arch_mach;
+enum {
+ CMODEL_UNKNOWN,
+ CMODEL_KERNEL,
+ CMODEL_LARGE,
+ CMODEL_MEDANY,
+ CMODEL_MEDIUM,
+ CMODEL_MEDLOW,
+ CMODEL_PIC,
+ CMODEL_SMALL,
+ CMODEL_TINY,
+};
+extern int arch_cmodel;
+
extern void dump_macro_definitions(void);
extern struct symbol_list *sparse_initialize(int argc, char **argv, struct string_list **files);
extern struct symbol_list *__sparse(char *filename);