aboutsummaryrefslogtreecommitdiffstats
path: root/erts/etc/common/erlexec.c
diff options
context:
space:
mode:
Diffstat (limited to 'erts/etc/common/erlexec.c')
-rw-r--r--erts/etc/common/erlexec.c274
1 files changed, 143 insertions, 131 deletions
diff --git a/erts/etc/common/erlexec.c b/erts/etc/common/erlexec.c
index 709c6f02d1..08e326b33b 100644
--- a/erts/etc/common/erlexec.c
+++ b/erts/etc/common/erlexec.c
@@ -1,18 +1,19 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2013. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2017. All Rights Reserved.
*
- * The contents of this file are subject to the Erlang Public License,
- * Version 1.1, (the "License"); you may not use this file except in
- * compliance with the License. You should have received a copy of the
- * Erlang Public License along with this software. If not, it can be
- * retrieved online at http://www.erlang.org/.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*
* %CopyrightEnd%
*/
@@ -22,19 +23,15 @@
* additions required for Windows NT.
*/
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
+#include "etc_common.h"
-#include "sys.h"
#include "erl_driver.h"
-#include <stdlib.h>
-#include <stdarg.h>
#include "erl_misc_utils.h"
#ifdef __WIN32__
# include "erl_version.h"
# include "init_file.h"
+# include <Shlobj.h>
#endif
#define NO 0
@@ -64,6 +61,7 @@
static const char plusM_au_allocs[]= {
'u', /* all alloc_util allocators */
'B', /* binary_alloc */
+ 'I', /* literal_alloc */
'D', /* std_alloc */
'E', /* ets_alloc */
'F', /* fix_alloc */
@@ -72,6 +70,8 @@ static const char plusM_au_allocs[]= {
'R', /* driver_alloc */
'S', /* sl_alloc */
'T', /* temp_alloc */
+ 'X', /* exec_alloc */
+ 'Z', /* test_alloc */
'\0'
};
@@ -119,6 +119,8 @@ static char *plusM_other_switches[] = {
"Ym",
"Ytp",
"Ytt",
+ "Iscs",
+ "Xscs",
NULL
};
@@ -128,12 +130,15 @@ static char *pluss_val_switches[] = {
"bwt",
"cl",
"ct",
+ "ecio",
"fwi",
"tbt",
"wct",
"wt",
"ws",
"ss",
+ "ssdcpu",
+ "ssdio",
"pp",
"ub",
NULL
@@ -142,6 +147,11 @@ static char *pluss_val_switches[] = {
static char *plush_val_switches[] = {
"ms",
"mbs",
+ "pds",
+ "max",
+ "maxk",
+ "maxel",
+ "mqd",
"",
NULL
};
@@ -155,6 +165,8 @@ static char *plusr_val_switches[] = {
/* +z arguments with values */
static char *plusz_val_switches[] = {
"dbbl",
+ "dntgc",
+ "ebwt",
NULL
};
@@ -168,19 +180,9 @@ static char *plusz_val_switches[] = {
#endif
#define SMP_SUFFIX ".smp"
-#define DEBUG_SUFFIX ".debug"
-#define EMU_TYPE_SUFFIX_LENGTH strlen(DEBUG_SUFFIX)
-
-/*
- * Define flags for different memory architectures.
- */
-#define EMU_TYPE_SMP 0x0001
-
-#ifdef __WIN32__
-#define EMU_TYPE_DEBUG 0x0004
-#endif
void usage(const char *switchname);
+static void usage_format(char *format, ...);
void start_epmd(char *epmd);
void error(char* format, ...);
@@ -188,9 +190,7 @@ void error(char* format, ...);
* Local functions.
*/
-#if !defined(ERTS_HAVE_SMP_EMU)
-static void usage_notsup(const char *switchname);
-#endif
+static void usage_notsup(const char *switchname, const char *alt);
static char **build_args_from_env(char *env_var);
static char **build_args_from_string(char *env_var);
static void initial_argv_massage(int *argc, char ***argv);
@@ -204,7 +204,7 @@ static void *erealloc(void *p, size_t size);
static void efree(void *p);
static char* strsave(char* string);
static int is_one_of_strings(char *str, char *strs[]);
-static char *write_str(char *to, char *from);
+static char *write_str(char *to, const char *from);
static void get_home(void);
static void add_epmd_port(void);
#ifdef __WIN32__
@@ -238,9 +238,8 @@ static int verbose = 0; /* If non-zero, print some extra information. */
static int start_detached = 0; /* If non-zero, the emulator should be
* started detached (in the background).
*/
-static int emu_type = 0; /* If non-zero, start beam.ARCH or beam.ARCH.exe
- * instead of beam or beam.exe, where ARCH is defined by flags. */
-static int emu_type_passed = 0; /* Types explicitly set */
+static int start_smp_emu = 1; /* Start the smp emulator. */
+static const char* emu_type = 0; /* Type of emulator (lcnt, valgrind, etc) */
#ifdef __WIN32__
static char *start_emulator_program = NULL; /* For detachec mode -
@@ -335,11 +334,11 @@ free_env_val(char *value)
}
/*
- * Add the architecture suffix to the program name if needed,
- * except on Windows, where we insert it just before ".DLL".
+ * Add the type and architecture suffix to the program name if needed.
+ * On Windows, we insert it just before ".DLL".
*/
static char*
-add_extra_suffixes(char *prog, int type)
+add_extra_suffixes(char *prog)
{
char *res;
char *p;
@@ -349,16 +348,10 @@ add_extra_suffixes(char *prog, int type)
int dll = 0;
#endif
- if (!type) {
- return prog;
- }
-
len = strlen(prog);
- /* Worst-case allocation */
- p = emalloc(len +
- EMU_TYPE_SUFFIX_LENGTH +
- + 1);
+ /* Allocate enough extra space for suffixes */
+ p = emalloc(len + 100);
res = p;
p = write_str(p, prog);
@@ -375,13 +368,11 @@ add_extra_suffixes(char *prog, int type)
}
#endif
-#ifdef __WIN32__
- if (type & EMU_TYPE_DEBUG) {
- p = write_str(p, DEBUG_SUFFIX);
- type &= ~(EMU_TYPE_DEBUG);
+ if (emu_type) {
+ p = write_str(p, ".");
+ p = write_str(p, emu_type);
}
-#endif
- if (type == EMU_TYPE_SMP) {
+ if (start_smp_emu) {
p = write_str(p, SMP_SUFFIX);
}
#ifdef __WIN32__
@@ -470,15 +461,9 @@ int main(int argc, char **argv)
* Construct the path of the executable.
*/
cpuinfo = erts_cpu_info_create();
- /* '-smp auto' is default */
-#ifdef ERTS_HAVE_SMP_EMU
- if (erts_get_cpu_configured(cpuinfo) > 1)
- emu_type |= EMU_TYPE_SMP;
-#endif
#if defined(__WIN32__) && defined(WIN32_ALWAYS_DEBUG)
- emu_type_passed |= EMU_TYPE_DEBUG;
- emu_type |= EMU_TYPE_DEBUG;
+ emu_type = "debug";
#endif
/* We need to do this before the ordinary processing. */
@@ -503,54 +488,32 @@ int main(int argc, char **argv)
if (strcmp(argv[i+1], "auto") == 0) {
i++;
- smp_auto:
- emu_type_passed |= EMU_TYPE_SMP;
-#ifdef ERTS_HAVE_SMP_EMU
- if (erts_get_cpu_configured(cpuinfo) > 1)
- emu_type |= EMU_TYPE_SMP;
- else
-#endif
- emu_type &= ~EMU_TYPE_SMP;
- }
- else if (strcmp(argv[i+1], "enable") == 0) {
+ } else if (strcmp(argv[i+1], "enable") == 0) {
i++;
smp_enable:
- emu_type_passed |= EMU_TYPE_SMP;
-#ifdef ERTS_HAVE_SMP_EMU
- emu_type |= EMU_TYPE_SMP;
-#else
- usage_notsup("-smp enable");
-#endif
- }
- else if (strcmp(argv[i+1], "disable") == 0) {
+ ;
+ } else if (strcmp(argv[i+1], "disable") == 0) {
i++;
smp_disable:
- emu_type_passed |= EMU_TYPE_SMP;
- emu_type &= ~EMU_TYPE_SMP;
- }
- else {
+ usage_notsup("-smp disable", " Use \"+S 1\" instead.");
+ } else {
smp:
-
- emu_type_passed |= EMU_TYPE_SMP;
-#ifdef ERTS_HAVE_SMP_EMU
- emu_type |= EMU_TYPE_SMP;
-#else
- usage_notsup("-smp");
-#endif
+ ;
}
} else if (strcmp(argv[i], "-smpenable") == 0) {
goto smp_enable;
} else if (strcmp(argv[i], "-smpauto") == 0) {
- goto smp_auto;
+ ;
} else if (strcmp(argv[i], "-smpdisable") == 0) {
goto smp_disable;
-#ifdef __WIN32__
- } else if (strcmp(argv[i], "-debug") == 0) {
- emu_type_passed |= EMU_TYPE_DEBUG;
- emu_type |= EMU_TYPE_DEBUG;
-#endif
} else if (strcmp(argv[i], "-extra") == 0) {
break;
+ } else if (strcmp(argv[i], "-emu_type") == 0) {
+ if (i + 1 >= argc) {
+ usage(argv[i]);
+ }
+ emu_type = argv[i+1];
+ i++;
}
}
i++;
@@ -563,13 +526,17 @@ int main(int argc, char **argv)
if (strcmp(malloc_lib, "libc") != 0)
usage("+MYm");
}
- emu = add_extra_suffixes(emu, emu_type);
+ emu = add_extra_suffixes(emu);
emu_name = strsave(emu);
erts_snprintf(tmpStr, sizeof(tmpStr), "%s" DIRSEP "%s" BINARY_EXT, bindir, emu);
emu = strsave(tmpStr);
- add_Eargs(emu); /* Will be argv[0] -- necessary! */
-
+ s = get_env("ESCRIPT_NAME");
+ if(s) {
+ add_Eargs(s); /* argv[0] = scriptname*/
+ } else {
+ add_Eargs(emu); /* argv[0] = erl or cerl */
+ }
/*
* Add the bindir to the path (unless it is there already).
*/
@@ -713,7 +680,7 @@ int main(int argc, char **argv)
* on itself here. We'll avoid doing that.
*/
if (strcmp(argv[i], "-make") == 0) {
- add_args("-noshell", "-noinput", "-s", "make", "all", NULL);
+ add_args("-noshell", "-noinput", "-s", "make", "all_or_nothing", NULL);
add_Eargs("-B");
haltAfterwards = 1;
i = argc; /* Skip rest of command line */
@@ -781,6 +748,24 @@ int main(int argc, char **argv)
get_start_erl_data((char *) NULL);
}
#endif
+ else if (strcmp(argv[i], "-start_epmd") == 0) {
+ if (i+1 >= argc)
+ usage("-start_epmd");
+
+ if (strcmp(argv[i+1], "true") == 0) {
+ /* The default */
+ no_epmd = 0;
+ }
+ else if (strcmp(argv[i+1], "false") == 0) {
+ no_epmd = 1;
+ }
+ else
+ usage_format("Expected boolean argument for \'-start_epmd\'.\n");
+
+ add_arg(argv[i]);
+ add_arg(argv[i+1]);
+ i++;
+ }
else
add_arg(argv[i]);
@@ -806,6 +791,7 @@ int main(int argc, char **argv)
case 'a':
case 'A':
case 'b':
+ case 'C':
case 'e':
case 'i':
case 'n':
@@ -825,12 +811,33 @@ int main(int argc, char **argv)
add_Eargs(argv[i+1]);
i++;
break;
+ case 'I':
+ if (argv[i][2] == 'O' && (argv[i][3] == 't' || argv[i][3] == 'p')) {
+ if (argv[i][4] != '\0')
+ goto the_default;
+ argv[i][0] = '-';
+ add_Eargs(argv[i]);
+ add_Eargs(argv[i+1]);
+ i++;
+ break;
+ }
+ if (argv[i][2] == 'O' && argv[i][3] == 'P' &&
+ (argv[i][4] == 't' || argv[i][4] == 'p')) {
+ if (argv[i][5] != '\0')
+ goto the_default;
+ argv[i][0] = '-';
+ add_Eargs(argv[i]);
+ add_Eargs(argv[i+1]);
+ i++;
+ break;
+ }
+ usage(argv[i]);
+ break;
case 'S':
if (argv[i][2] == 'P') {
if (argv[i][3] != '\0')
goto the_default;
}
-#ifdef ERTS_DIRTY_SCHEDULERS
else if (argv[i][2] == 'D') {
char* type = argv[i]+3;
if (strncmp(type, "cpu", 3) != 0 &&
@@ -842,7 +849,6 @@ int main(int argc, char **argv)
(argv[i][3] == 'i' && argv[i][5] != '\0'))
goto the_default;
}
-#endif
else if (argv[i][2] != '\0')
goto the_default;
if (i+1 >= argc)
@@ -879,6 +885,19 @@ int main(int argc, char **argv)
}
add_Eargs(argv[i]);
break;
+ case 'c':
+ argv[i][0] = '-';
+ if (argv[i][2] == '\0' && i+1 < argc) {
+ if (strcmp(argv[i+1], "true") == 0
+ || strcmp(argv[i+1], "false") == 0) {
+ add_Eargs(argv[i]);
+ add_Eargs(argv[i+1]);
+ i++;
+ break;
+ }
+ }
+ add_Eargs(argv[i]);
+ break;
case 'M': {
int x;
for (x = 0; plusM_au_allocs[x]; x++)
@@ -999,7 +1018,7 @@ int main(int argc, char **argv)
start_epmd(epmd_prog);
#if (! defined(__WIN32__)) && defined(DEBUG)
- if (start_detached) {
+ if (start_detached && get_env("ERL_CONSOLE_MODE")) {
/* Start the emulator within an xterm.
* Move up all arguments and insert
* "xterm -e " first.
@@ -1123,7 +1142,11 @@ int main(int argc, char **argv)
{
execv(emu, Eargsp);
}
- error("Error %d executing \'%s\'.", errno, emu);
+ if (errno == ENOENT) {
+ error("The emulator \'%s\' does not exist.", emu);
+ } else {
+ error("Error %d executing \'%s\'.", errno, emu);
+ }
return 1;
#endif
}
@@ -1138,25 +1161,16 @@ usage_aux(void)
#ifdef __WIN32__
"[-start_erl [datafile]] "
#endif
- "[-smp "
-#ifdef ERTS_HAVE_SMP_EMU
- "[enable|"
-#endif
- "auto|disable"
-#ifdef ERTS_HAVE_SMP_EMU
- "]"
-#endif
- "] "
- "[-make] [-man [manopts] MANPAGE] [-x] [-emu_args] "
- "[-args_file FILENAME] [+A THREADS] [+a SIZE] [+B[c|d|i]] [+c] "
- "[+h HEAP_SIZE_OPTION] [+K BOOLEAN] "
+ "[-make] [-man [manopts] MANPAGE] [-x] [-emu_args] [-start_epmd BOOLEAN] "
+ "[-args_file FILENAME] [+A THREADS] [+a SIZE] [+B[c|d|i]] [+c [BOOLEAN]] "
+ "[+C MODE] [+h HEAP_SIZE_OPTION] [+K BOOLEAN] "
"[+l] [+M<SUBSWITCH> <ARGUMENT>] [+P MAX_PROCS] [+Q MAX_PORTS] "
"[+R COMPAT_REL] "
"[+r] [+rg READER_GROUPS_LIMIT] [+s SCHEDULER_OPTION] "
"[+S NO_SCHEDULERS:NO_SCHEDULERS_ONLINE] "
"[+SP PERCENTAGE_SCHEDULERS:PERCENTAGE_SCHEDULERS_ONLINE] "
"[+T LEVEL] [+V] [+v] "
- "[+W<i|w>] [+z MISC_OPTION] [args ...]\n");
+ "[+W<i|w|e>] [+z MISC_OPTION] [args ...]\n");
exit(1);
}
@@ -1167,14 +1181,12 @@ usage(const char *switchname)
usage_aux();
}
-#if !defined(ERTS_HAVE_SMP_EMU)
static void
-usage_notsup(const char *switchname)
+usage_notsup(const char *switchname, const char *alt)
{
- fprintf(stderr, "Argument \'%s\' not supported.\n", switchname);
+ fprintf(stderr, "Argument \'%s\' not supported.%s\n", switchname, alt);
usage_aux();
}
-#endif
static void
usage_format(char *format, ...)
@@ -1323,7 +1335,7 @@ is_one_of_strings(char *str, char *strs[])
return 0;
}
-static char *write_str(char *to, char *from)
+static char *write_str(char *to, const char *from)
{
while (*from)
*(to++) = *(from++);
@@ -1520,17 +1532,16 @@ static void get_parameters(int argc, char** argv)
static void
get_home(void)
{
- int len;
- char tmpstr[MAX_PATH+1];
+ wchar_t *profile;
char* homedrive;
char* homepath;
homedrive = get_env("HOMEDRIVE");
homepath = get_env("HOMEPATH");
if (!homedrive || !homepath) {
- if (len = GetWindowsDirectory(tmpstr,MAX_PATH)) {
- home = emalloc(len+1);
- strcpy(home,tmpstr);
+ if (SHGetKnownFolderPath(&FOLDERID_Profile, 0, NULL, &profile) == S_OK) {
+ home = utf16_to_utf8(profile);
+ /* CoTaskMemFree(profile); */
} else
error("HOMEDRIVE or HOMEPATH is not set and GetWindowsDir failed");
} else {
@@ -1850,6 +1861,7 @@ read_args_file(char *filename)
#undef SAVE_CHAR
}
+
typedef struct {
char **argv;
int argc;
@@ -2173,18 +2185,18 @@ static WCHAR *utf8_to_utf16(unsigned char *bytes)
res = target = emalloc((num + 1) * sizeof(WCHAR));
while (*bytes) {
if (((*bytes) & ((unsigned char) 0x80)) == 0) {
- unipoint = (Uint) *bytes;
+ unipoint = (unsigned int) *bytes;
++bytes;
} else if (((*bytes) & ((unsigned char) 0xE0)) == 0xC0) {
unipoint =
- (((Uint) ((*bytes) & ((unsigned char) 0x1F))) << 6) |
- ((Uint) (bytes[1] & ((unsigned char) 0x3F)));
+ (((unsigned int) ((*bytes) & ((unsigned char) 0x1F))) << 6) |
+ ((unsigned int) (bytes[1] & ((unsigned char) 0x3F)));
bytes += 2;
} else if (((*bytes) & ((unsigned char) 0xF0)) == 0xE0) {
unipoint =
- (((Uint) ((*bytes) & ((unsigned char) 0xF))) << 12) |
- (((Uint) (bytes[1] & ((unsigned char) 0x3F))) << 6) |
- ((Uint) (bytes[2] & ((unsigned char) 0x3F)));
+ (((unsigned int) ((*bytes) & ((unsigned char) 0xF))) << 12) |
+ (((unsigned int) (bytes[1] & ((unsigned char) 0x3F))) << 6) |
+ ((unsigned int) (bytes[2] & ((unsigned char) 0x3F)));
if (unipoint > 0xFFFF) {
unipoint = (unsigned int) '?';
}
@@ -2203,7 +2215,7 @@ static WCHAR *utf8_to_utf16(unsigned char *bytes)
static int put_utf8(WCHAR ch, unsigned char *target, int sz, int *pos)
{
- Uint x = (Uint) ch;
+ unsigned int x = (unsigned int) ch;
if (x < 0x80) {
if (*pos >= sz) {
return -1;