main.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. /* Copyright (C) 2002-2015 Free Software Foundation, Inc.
  2. Contributed by Andy Vaught and Paul Brook <paul@nowt.org>
  3. This file is part of the GNU Fortran runtime library (libgfortran).
  4. Libgfortran is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 3, or (at your option)
  7. any later version.
  8. Libgfortran is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. Under Section 7 of GPL version 3, you are granted additional
  13. permissions described in the GCC Runtime Library Exception, version
  14. 3.1, as published by the Free Software Foundation.
  15. You should have received a copy of the GNU General Public License and
  16. a copy of the GCC Runtime Library Exception along with this program;
  17. see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  18. <http://www.gnu.org/licenses/>. */
  19. #include "libgfortran.h"
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <limits.h>
  23. #include <errno.h>
  24. #ifdef HAVE_UNISTD_H
  25. #include <unistd.h>
  26. #endif
  27. /* Stupid function to be sure the constructor is always linked in, even
  28. in the case of static linking. See PR libfortran/22298 for details. */
  29. void
  30. stupid_function_name_for_static_linking (void)
  31. {
  32. return;
  33. }
  34. /* This will be 0 for little-endian
  35. machines and 1 for big-endian machines. */
  36. int big_endian = 0;
  37. /* Figure out endianness for this machine. */
  38. static void
  39. determine_endianness (void)
  40. {
  41. union
  42. {
  43. GFC_LOGICAL_8 l8;
  44. GFC_LOGICAL_4 l4[2];
  45. } u;
  46. u.l8 = 1;
  47. if (u.l4[0])
  48. big_endian = 0;
  49. else if (u.l4[1])
  50. big_endian = 1;
  51. else
  52. runtime_error ("Unable to determine machine endianness");
  53. }
  54. static int argc_save;
  55. static char **argv_save;
  56. static const char *exe_path;
  57. static bool please_free_exe_path_when_done;
  58. /* Save the path under which the program was called, for use in the
  59. backtrace routines. */
  60. void
  61. store_exe_path (const char * argv0)
  62. {
  63. #ifndef DIR_SEPARATOR
  64. #define DIR_SEPARATOR '/'
  65. #endif
  66. char *cwd, *path;
  67. /* This can only happen if store_exe_path is called multiple times. */
  68. if (please_free_exe_path_when_done)
  69. free ((char *) exe_path);
  70. /* Reading the /proc/self/exe symlink is Linux-specific(?), but if
  71. it works it gives the correct answer. */
  72. #ifdef HAVE_READLINK
  73. ssize_t len, psize = 256;
  74. while (1)
  75. {
  76. path = xmalloc (psize);
  77. len = readlink ("/proc/self/exe", path, psize);
  78. if (len < 0)
  79. {
  80. free (path);
  81. break;
  82. }
  83. else if (len < psize)
  84. {
  85. path[len] = '\0';
  86. exe_path = strdup (path);
  87. free (path);
  88. please_free_exe_path_when_done = true;
  89. return;
  90. }
  91. /* The remaining option is len == psize. */
  92. free (path);
  93. psize *= 4;
  94. }
  95. #endif
  96. /* If the path is absolute or on a simulator where argv is not set. */
  97. #ifdef __MINGW32__
  98. if (argv0 == NULL
  99. || ('A' <= argv0[0] && argv0[0] <= 'Z' && argv0[1] == ':')
  100. || ('a' <= argv0[0] && argv0[0] <= 'z' && argv0[1] == ':')
  101. || (argv0[0] == '/' && argv0[1] == '/')
  102. || (argv0[0] == '\\' && argv0[1] == '\\'))
  103. #else
  104. if (argv0 == NULL || argv0[0] == DIR_SEPARATOR)
  105. #endif
  106. {
  107. exe_path = argv0;
  108. please_free_exe_path_when_done = false;
  109. return;
  110. }
  111. #ifdef HAVE_GETCWD
  112. size_t cwdsize = 256;
  113. while (1)
  114. {
  115. cwd = xmalloc (cwdsize);
  116. if (getcwd (cwd, cwdsize))
  117. break;
  118. else if (errno == ERANGE)
  119. {
  120. free (cwd);
  121. cwdsize *= 4;
  122. }
  123. else
  124. {
  125. free (cwd);
  126. cwd = NULL;
  127. break;
  128. }
  129. }
  130. #else
  131. cwd = NULL;
  132. #endif
  133. if (!cwd)
  134. {
  135. exe_path = argv0;
  136. please_free_exe_path_when_done = false;
  137. return;
  138. }
  139. /* exe_path will be cwd + "/" + argv[0] + "\0". This will not work
  140. if the executable is not in the cwd, but at this point we're out
  141. of better ideas. */
  142. size_t pathlen = strlen (cwd) + 1 + strlen (argv0) + 1;
  143. path = xmalloc (pathlen);
  144. snprintf (path, pathlen, "%s%c%s", cwd, DIR_SEPARATOR, argv0);
  145. free (cwd);
  146. exe_path = path;
  147. please_free_exe_path_when_done = true;
  148. }
  149. /* Return the full path of the executable. */
  150. char *
  151. full_exe_path (void)
  152. {
  153. return (char *) exe_path;
  154. }
  155. #ifndef HAVE_STRTOK_R
  156. static char*
  157. gfstrtok_r (char *str, const char *delim,
  158. char **saveptr __attribute__ ((unused)))
  159. {
  160. return strtok (str, delim);
  161. }
  162. #define strtok_r gfstrtok_r
  163. #endif
  164. char *addr2line_path;
  165. /* Find addr2line and store the path. */
  166. void
  167. find_addr2line (void)
  168. {
  169. #ifdef HAVE_ACCESS
  170. #define A2L_LEN 11
  171. char *path = secure_getenv ("PATH");
  172. if (!path)
  173. return;
  174. char *tp = strdup (path);
  175. if (!tp)
  176. return;
  177. size_t n = strlen (path);
  178. char *ap = xmalloc (n + A2L_LEN);
  179. char *saveptr;
  180. for (char *str = tp;; str = NULL)
  181. {
  182. char *token = strtok_r (str, ":", &saveptr);
  183. if (!token)
  184. break;
  185. size_t toklen = strlen (token);
  186. memcpy (ap, token, toklen);
  187. memcpy (ap + toklen, "/addr2line", A2L_LEN);
  188. if (access (ap, R_OK|X_OK) == 0)
  189. {
  190. addr2line_path = strdup (ap);
  191. break;
  192. }
  193. }
  194. free (tp);
  195. free (ap);
  196. #endif
  197. }
  198. /* Set the saved values of the command line arguments. */
  199. void
  200. set_args (int argc, char **argv)
  201. {
  202. argc_save = argc;
  203. argv_save = argv;
  204. store_exe_path (argv[0]);
  205. }
  206. iexport(set_args);
  207. /* Retrieve the saved values of the command line arguments. */
  208. void
  209. get_args (int *argc, char ***argv)
  210. {
  211. *argc = argc_save;
  212. *argv = argv_save;
  213. }
  214. /* Initialize the runtime library. */
  215. static void __attribute__((constructor))
  216. init (void)
  217. {
  218. /* Figure out the machine endianness. */
  219. determine_endianness ();
  220. /* Must be first */
  221. init_variables ();
  222. init_units ();
  223. set_fpu ();
  224. init_compile_options ();
  225. #ifdef DEBUG
  226. /* Check for special command lines. */
  227. if (argc > 1 && strcmp (argv[1], "--help") == 0)
  228. show_variables ();
  229. /* if (argc > 1 && strcmp(argv[1], "--resume") == 0) resume(); */
  230. #endif
  231. if (options.backtrace == 1)
  232. find_addr2line ();
  233. random_seed_i4 (NULL, NULL, NULL);
  234. }
  235. /* Cleanup the runtime library. */
  236. static void __attribute__((destructor))
  237. cleanup (void)
  238. {
  239. close_units ();
  240. if (please_free_exe_path_when_done)
  241. free ((char *) exe_path);
  242. free (addr2line_path);
  243. }