diff --git a/cc.c b/cc.c
index f3955bb..bc69a8a 100644
--- a/cc.c
+++ b/cc.c
@@ -15,9 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with M2-Planet. If not, see .
*/
-#include
-#include
-#include
+
#include"cc.h"
/* The core functions */
@@ -37,12 +35,15 @@ void init_macro_env(char* sym, char* value, char* source, int num);
void preprocess();
void output_tokens(struct token_list *i, FILE* out);
int strtoint(char *a);
+void spawn_processes(int debug_flag, char* preprocessed_file, char* destination, char** envp);
int main(int argc, char** argv, char** envp)
{
+ FUZZING = FALSE;
MAX_STRING = 4096;
PREPROCESSOR_MODE = FALSE;
FILE* in = stdin;
+ FILE* tempfile;
FILE* destination_file = stdout;
init_macro_env("__M2__", "42", "__INTERNAL_M2__", 0); /* Setup __M2__ */
char* name;
@@ -121,6 +122,12 @@ int main(int argc, char** argv, char** envp)
fputs("M2-Mesoplanet v1.10.0\n", stderr);
exit(EXIT_SUCCESS);
}
+ else if(match(argv[i], "--fuzz"))
+ {
+ /* Set fuzzing */
+ FUZZING = TRUE;
+ i += 1;
+ }
else
{
fputs("UNKNOWN ARGUMENT\n", stdout);
@@ -165,8 +172,19 @@ int main(int argc, char** argv, char** envp)
}
else
{
- /* TODO Put tempfile and spawning info here */
- output_tokens(global_token, destination_file);
+ char* filename = calloc(100, sizeof(char));
+ strcpy(filename, "/tmp/M2-Mesoplanet-XXXXXX");
+ i = mkstemp(filename);
+ tempfile = fdopen(i, "rw");
+ if(NULL != tempfile)
+ {
+ output_tokens(global_token, tempfile);
+ }
+ else
+ {
+ fputs("unable to get a tempfile for M2-Mesoplanet output\n", stderr);
+ exit(EXIT_FAILURE);
+ }
}
return EXIT_SUCCESS;
}
diff --git a/cc_env.c b/cc_env.c
index f17d29f..188e954 100644
--- a/cc_env.c
+++ b/cc_env.c
@@ -22,6 +22,9 @@
void init_macro_env(char* sym, char* value, char* source, int num);
char* env_lookup(char* variable);
+char* Architecture;
+int WORDSIZE;
+
void setup_env()
{
char* ARCH = NULL;
@@ -41,24 +44,35 @@ void setup_env()
if(NULL != hold) ARCH = hold;
/* Set desired architecture */
- if(match("x86", ARCH))
+ WORDSIZE = 32;
+ if(match("knight-native", ARCH)) Architecture = "knight-native";
+ else if(match("knight-posix", ARCH)) Architecture = "knight-posix";
+ else if(match("x86", ARCH))
{
+ Architecture = "x86";
init_macro_env("__i386__", "1", "--architecture", 0);
}
else if(match("amd64", ARCH))
{
+ Architecture = "amd64";
+ WORDSIZE = 64;
init_macro_env("__x86_64__", "1", "--architecture", 0);
}
else if(match("armv7l", ARCH))
{
+ Architecture = "armv7l";
init_macro_env("__arm__", "1", "--architecture", 0);
}
else if(match("aarch64", ARCH))
{
+ Architecture = "aarch64";
+ WORDSIZE = 64;
init_macro_env("__aarch64__", "1", "--architecture", 0);
}
else if(match("riscv64", ARCH))
{
+ Architecture = "riscv64";
+ WORDSIZE = 64;
init_macro_env("__riscv", "1", "--architecture", 0);
init_macro_env("__riscv_xlen", "64", "--architecture", 1);
}
diff --git a/cc_globals.c b/cc_globals.c
index 9ea68b3..2bed24f 100644
--- a/cc_globals.c
+++ b/cc_globals.c
@@ -38,4 +38,8 @@ int MAX_STRING;
int PREPROCESSOR_MODE;
/* enable spawn behavior to be effective */
+char* PATH;
char* M2LIBC_PATH;
+
+/* So we don't shoot ourself in the face */
+int FUZZING;
diff --git a/cc_globals.h b/cc_globals.h
index 2498a01..b714df1 100644
--- a/cc_globals.h
+++ b/cc_globals.h
@@ -33,10 +33,16 @@ extern char* hold_string;
extern int string_index;
/* Allow us to have a single settable max string */
-extern int MAX_STRING;
+extern long MAX_STRING;
/* enable preprocessor-only mode */
extern int PREPROCESSOR_MODE;
/* enable spawn behavior to be effective */
+extern char* PATH;
extern char* M2LIBC_PATH;
+extern char* Architecture;
+extern int WORDSIZE;
+
+/* So we don't shoot ourself in the face */
+extern int FUZZING;
diff --git a/cc_spawn.c b/cc_spawn.c
new file mode 100644
index 0000000..7c52a16
--- /dev/null
+++ b/cc_spawn.c
@@ -0,0 +1,312 @@
+/* Copyright (C) 2016 Jeremiah Orians
+ * Copyright (C) 2020 deesix
+ * This file is part of M2-Planet.
+ *
+ * M2-Planet 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * M2-Planet 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with M2-Planet. If not, see .
+ */
+
+#include"cc.h"
+#include
+#include
+#define MAX_ARRAY 256
+
+char* env_lookup(char* variable);
+
+/* Function to find a character in a string */
+char* find_char(char* string, char a)
+{
+ if(0 == string[0])
+ {
+ return NULL;
+ }
+
+ while(a != string[0])
+ {
+ string = string + 1;
+
+ if(0 == string[0])
+ {
+ return string;
+ }
+ }
+
+ return string;
+}
+
+/* Find the full path to an executable */
+char* find_executable(char* name)
+{
+ if(match("", name))
+ {
+ return NULL;
+ }
+
+ if(('.' == name[0]) || ('/' == name[0]))
+ {
+ /* assume names that start with . or / are relative or absolute */
+ return name;
+ }
+
+ char* trial = calloc(MAX_STRING, sizeof(char));
+ char* MPATH = calloc(MAX_STRING, sizeof(char)); /* Modified PATH */
+ require(MPATH != NULL, "Memory initialization of MPATH in find_executable failed\n");
+ strcpy(MPATH, PATH);
+ FILE* t;
+ char* next = find_char(MPATH, ':');
+ int index;
+ int offset;
+ int mpath_length;
+ int name_length;
+ int trial_length;
+
+ while(NULL != next)
+ {
+ /* Reset trial */
+ trial_length = strlen(trial);
+
+ for(index = 0; index < trial_length; index = index + 1)
+ {
+ trial[index] = 0;
+ }
+
+ next[0] = 0;
+ /* prepend_string(MPATH, prepend_string("/", name)) */
+ mpath_length = strlen(MPATH);
+
+ for(index = 0; index < mpath_length; index = index + 1)
+ {
+ require(MAX_STRING > index, "Element of PATH is too long\n");
+ trial[index] = MPATH[index];
+ }
+
+ trial[index] = '/';
+ offset = strlen(trial);
+ name_length = strlen(name);
+
+ for(index = 0; index < name_length; index = index + 1)
+ {
+ require(MAX_STRING > index, "Element of PATH is too long\n");
+ trial[index + offset] = name[index];
+ }
+
+ /* Try the trial */
+ trial_length = strlen(trial);
+ require(trial_length < MAX_STRING, "COMMAND TOO LONG!\nABORTING HARD\n");
+ t = fopen(trial, "r");
+
+ if(NULL != t)
+ {
+ fclose(t);
+ return trial;
+ }
+
+ MPATH = next + 1;
+ next = find_char(MPATH, ':');
+ }
+
+ return NULL;
+}
+
+int _execute(char* name, char** array, char** envp)
+{
+ int status; /* i.e. return code */
+ /* Get the full path to the executable */
+ char* program = find_executable(name);
+
+ /* Check we can find the executable */
+ if(NULL == program)
+ {
+ fputs("WHILE EXECUTING ", stderr);
+ fputs(name, stderr);
+ fputs(" NOT FOUND!\nABORTING HARD\n", stderr);
+ exit(EXIT_FAILURE);
+ }
+
+ int f = fork();
+
+ /* Ensure fork succeeded */
+ if(f == -1)
+ {
+ fputs("WHILE EXECUTING ", stderr);
+ fputs(name, stderr);
+ fputs("fork() FAILED\nABORTING HARD\n", stderr);
+ exit(EXIT_FAILURE);
+ }
+ else if(f == 0)
+ {
+ /* Child */
+ /**************************************************************
+ * Fuzzing produces random stuff; we don't want it running *
+ * dangerous commands. So we just don't execve. *
+ **************************************************************/
+ if(FALSE == FUZZING)
+ {
+ /* We are not fuzzing */
+ /* execve() returns only on error */
+ execve(program, array, envp);
+ }
+
+ /* Prevent infinite loops */
+ _exit(EXIT_FAILURE);
+ }
+
+ /* Otherwise we are the parent */
+ /* And we should wait for it to complete */
+ waitpid(f, &status, 0);
+ if((status & 0x7f) != 0)
+ {
+ fputs("Subprocess: ", stderr);
+ fputs(name, stderr);
+ fputs(" exited with error code\nAborting for safety\n", stderr);
+ exit(status & 0x7f);
+ }
+ return (status & 0xff00) >> 8;
+}
+
+void insert_array(char** array, int index, char* string)
+{
+ int size = strlen(string);
+ array[index] = calloc(size+2, sizeof(char));
+ strcpy(array[index], string);
+}
+
+
+int spawn_hex2(char* input, char* output, char* architecture, char** envp, int debug)
+{
+ /* TODO FINISH */
+ char** array = calloc(MAX_ARRAY, sizeof(char*));
+ insert_array(array, 0, "--file");
+ insert_array(array, 1, input);
+ insert_array(array, 2, "--output");
+ insert_array(array, 3, output);
+ insert_array(array, 4, "--architecture");
+ insert_array(array, 5, architecture);
+ int r = _execute("hex2", array, envp);
+ return r;
+}
+
+
+int spawn_M1(char* input, char* debug_file, char* output, char* architecture, char** envp, int debug_flag)
+{
+ char** array = calloc(MAX_ARRAY, sizeof(char*));
+ insert_array(array, 0, "--file");
+ insert_array(array, 1, input);
+ if(debug_flag)
+ {
+ insert_array(array, 2, "--file");
+ insert_array(array, 3, debug_file);
+ insert_array(array, 4, "--output");
+ insert_array(array, 5, output);
+ insert_array(array, 6, "--architecture");
+ insert_array(array, 7, architecture);
+ }
+ else
+ {
+ insert_array(array, 2, "--output");
+ insert_array(array, 3, output);
+ insert_array(array, 4, "--architecture");
+ insert_array(array, 5, architecture);
+ }
+ int r = _execute("M1", array, envp);
+ return r;
+}
+
+
+int spawn_blood_elf(char* input, char* output, char* architecture, char** envp, int large_flag)
+{
+ char** array = calloc(MAX_ARRAY, sizeof(char*));
+ insert_array(array, 0, "--file");
+ insert_array(array, 1, input);
+ insert_array(array, 2, "--output");
+ insert_array(array, 3, output);
+ insert_array(array, 4, "--architecture");
+ insert_array(array, 5, architecture);
+ if(large_flag) insert_array(array, 6, "--64");
+ int r = _execute("blood-elf", array, envp);
+ return r;
+}
+
+int spawn_M2(char* input, char* output, char* architecture, char** envp, int debug_flag)
+{
+ char** array = calloc(MAX_ARRAY, sizeof(char*));
+ insert_array(array, 0, "--file");
+ insert_array(array, 1, input);
+ insert_array(array, 2, "--output");
+ insert_array(array, 3, output);
+ insert_array(array, 4, "--architecture");
+ insert_array(array, 5, architecture);
+ if(debug_flag) insert_array(array, 6, "--debug");
+ int r = _execute("M2-Planet", array, envp);
+ return r;
+}
+
+void spawn_processes(int debug_flag, char* preprocessed_file, char* destination, char** envp)
+{
+ int large_flag = FALSE;
+ if(WORDSIZE > 32) large_flag = TRUE;
+
+ char* M2_output = calloc(100, sizeof(char));
+ strcpy(M2_output, "/tmp/M2-Planet-XXXXXX");
+ int i = mkstemp(M2_output);
+ if(-1 != i)
+ {
+ spawn_M2(preprocessed_file, M2_output, Architecture, envp, debug_flag);
+ }
+ else
+ {
+ fputs("unable to get a tempfile for M2-Planet output\n", stderr);
+ exit(EXIT_FAILURE);
+ }
+
+ char* blood_output = "";
+ if(debug_flag)
+ {
+ blood_output = calloc(100, sizeof(char));
+ strcpy(blood_output, "/tmp/blood-elf-XXXXXX");
+ i = mkstemp(blood_output);
+ if(-1 != i)
+ {
+ spawn_blood_elf(M2_output, blood_output, Architecture, envp, large_flag);
+ }
+ else
+ {
+ fputs("unable to get a tempfile for blood-elf output\n", stderr);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ char* M1_output = calloc(100, sizeof(char));
+ strcpy(M1_output, "/tmp/M1-macro-XXXXXX");
+ i = mkstemp(M1_output);
+ if(-1 != i)
+ {
+ spawn_M1(M2_output, blood_output, M1_output, Architecture, envp, debug_flag);
+ }
+ else
+ {
+ fputs("unable to get a tempfile for M1 output\n", stderr);
+ exit(EXIT_FAILURE);
+ }
+
+ /* We no longer need the M2-Planet tempfile output */
+ remove(M2_output);
+ /* Nor the blood-elf output anymore if it exists */
+ if(!match("", blood_output)) remove(blood_output);
+
+ /* Build the final binary */
+ spawn_hex2(M1_output, destination, Architecture, envp, debug_flag);
+
+ /* clean up after ourselves*/
+ remove(M1_output);
+}