1/* Wrapper for ar/ranlib/nm to pass the LTO plugin. 2 Copyright (C) 2011-2015 Free Software Foundation, Inc. 3 Contributed by Andi Kleen. 4 5This file is part of GCC. 6 7GCC is free software; you can redistribute it and/or modify it under 8the terms of the GNU General Public License as published by the Free 9Software Foundation; either version 3, or (at your option) any later 10version. 11 12GCC is distributed in the hope that it will be useful, but WITHOUT ANY 13WARRANTY; without even the implied warranty of MERCHANTABILITY or 14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15for more details. 16 17You should have received a copy of the GNU General Public License 18along with GCC; see the file COPYING3. If not see 19<http://www.gnu.org/licenses/>. */ 20 21#include "config.h" 22#include "system.h" 23#include "libiberty.h" 24#include "file-find.h" 25 26#ifndef PERSONALITY 27#error "Please set personality" 28#endif 29 30/* The exec prefix as derived at compile-time from --prefix. */ 31 32static const char standard_exec_prefix[] = STANDARD_EXEC_PREFIX; 33 34/* The libexec prefix as derived at compile-time from --prefix. */ 35 36static const char standard_libexec_prefix[] = STANDARD_LIBEXEC_PREFIX; 37 38/* The bindir prefix as derived at compile-time from --prefix. */ 39 40static const char standard_bin_prefix[] = STANDARD_BINDIR_PREFIX; 41 42/* A relative path to be used in finding the location of tools 43 relative to this program. */ 44 45static const char *const tooldir_base_prefix = TOOLDIR_BASE_PREFIX; 46 47/* The exec prefix as relocated from the location of this program. */ 48 49static const char *self_exec_prefix; 50 51/* The libexec prefix as relocated from the location of this program. */ 52 53static const char *self_libexec_prefix; 54 55/* The tools prefix as relocated from the location of this program. */ 56 57static const char *self_tooldir_prefix; 58 59/* The name of the machine that is being targeted. */ 60 61static const char *const target_machine = DEFAULT_TARGET_MACHINE; 62 63/* The target version. */ 64 65static const char *const target_version = DEFAULT_TARGET_VERSION; 66 67/* The collection of target specific path prefixes. */ 68 69static struct path_prefix target_path; 70 71/* The collection path prefixes. */ 72 73static struct path_prefix path; 74 75/* The directory separator. */ 76 77static const char dir_separator[] = { DIR_SEPARATOR, 0 }; 78 79static void 80setup_prefixes (const char *exec_path) 81{ 82 const char *self; 83 84 self = getenv ("GCC_EXEC_PREFIX"); 85 if (!self) 86 self = exec_path; 87 else 88 self = concat (self, "gcc-" PERSONALITY, NULL); 89 90 /* Relocate the exec prefix. */ 91 self_exec_prefix = make_relative_prefix (self, 92 standard_bin_prefix, 93 standard_exec_prefix); 94 if (self_exec_prefix == NULL) 95 self_exec_prefix = standard_exec_prefix; 96 97 /* Relocate libexec prefix. */ 98 self_libexec_prefix = make_relative_prefix (self, 99 standard_bin_prefix, 100 standard_libexec_prefix); 101 if (self_libexec_prefix == NULL) 102 self_libexec_prefix = standard_libexec_prefix; 103 104 105 /* Build the relative path to the target-specific tool directory. */ 106 self_tooldir_prefix = concat (tooldir_base_prefix, target_machine, 107 dir_separator, NULL); 108 self_tooldir_prefix = concat (self_exec_prefix, target_machine, 109 dir_separator, target_version, dir_separator, 110 self_tooldir_prefix, NULL); 111 112 /* Add the target-specific tool bin prefix. */ 113 prefix_from_string (concat (self_tooldir_prefix, "bin", NULL), &target_path); 114 115 /* Add the target-specific libexec prefix. */ 116 self_libexec_prefix = concat (self_libexec_prefix, target_machine, 117 dir_separator, target_version, 118 dir_separator, NULL); 119 prefix_from_string (self_libexec_prefix, &target_path); 120 121 /* Add path as a last resort. */ 122 prefix_from_env ("PATH", &path); 123} 124 125int 126main (int ac, char **av) 127{ 128 const char *exe_name; 129 char *plugin; 130 int k, status, err; 131 const char *err_msg; 132 const char **nargv; 133 bool is_ar = !strcmp (PERSONALITY, "ar"); 134 int exit_code = FATAL_EXIT_CODE; 135 int i; 136 137 setup_prefixes (av[0]); 138 139 /* Not using getopt for now. */ 140 for (i = 0; i < ac; i++) 141 if (!strncmp (av[i], "-B", 2)) 142 { 143 const char *arg = av[i] + 2; 144 const char *end; 145 size_t len; 146 147 memmove (av + i, av + i + 1, sizeof (char *) * ((ac + 1) - i)); 148 ac--; 149 if (*arg == 0) 150 { 151 arg = av[i]; 152 if (!arg) 153 { 154 fprintf (stderr, "Usage: gcc-ar [-B prefix] ar arguments ...\n"); 155 exit (EXIT_FAILURE); 156 } 157 memmove (av + i, av + i + 1, sizeof (char *) * ((ac + 1) - i)); 158 ac--; 159 i++; 160 } 161 /* else it's a joined argument */ 162 163 len = strlen (arg); 164 if (len > 0) 165 len--; 166 end = arg + len; 167 168 /* Always add a dir separator for the prefix list. */ 169 if (end > arg && !IS_DIR_SEPARATOR (*end)) 170 { 171 static const char dir_separator_str[] = { DIR_SEPARATOR, 0 }; 172 arg = concat (arg, dir_separator_str, NULL); 173 } 174 175 add_prefix_begin (&path, arg); 176 add_prefix_begin (&target_path, arg); 177 break; 178 } 179 180 181 /* Find the GCC LTO plugin */ 182 plugin = find_a_file (&target_path, LTOPLUGINSONAME, R_OK); 183 if (!plugin) 184 { 185 fprintf (stderr, "%s: Cannot find plugin '%s'\n", av[0], LTOPLUGINSONAME); 186 exit (1); 187 } 188 189 /* Find the wrapped binutils program. */ 190 exe_name = find_a_file (&target_path, PERSONALITY, X_OK); 191 if (!exe_name) 192 { 193 const char *real_exe_name = PERSONALITY; 194#ifdef CROSS_DIRECTORY_STRUCTURE 195 real_exe_name = concat (target_machine, "-", PERSONALITY, NULL); 196#endif 197 exe_name = find_a_file (&path, real_exe_name, X_OK); 198 if (!exe_name) 199 { 200 fprintf (stderr, "%s: Cannot find binary '%s'\n", av[0], 201 real_exe_name); 202 exit (1); 203 } 204 } 205 206 /* Create new command line with plugin */ 207 nargv = XCNEWVEC (const char *, ac + 4); 208 nargv[0] = exe_name; 209 nargv[1] = "--plugin"; 210 nargv[2] = plugin; 211 if (is_ar && av[1] && av[1][0] != '-') 212 av[1] = concat ("-", av[1], NULL); 213 for (k = 1; k < ac; k++) 214 nargv[2 + k] = av[k]; 215 nargv[2 + k] = NULL; 216 217 /* Run utility */ 218 /* ??? the const is misplaced in pex_one's argv? */ 219 err_msg = pex_one (PEX_LAST|PEX_SEARCH, 220 exe_name, 221 CONST_CAST2 (char * const *, const char **, nargv), 222 concat ("gcc-", exe_name, NULL), 223 NULL,NULL, &status, &err); 224 if (err_msg) 225 fprintf (stderr, "Error running %s: %s\n", exe_name, err_msg); 226 else if (status) 227 { 228 if (WIFSIGNALED (status)) 229 { 230 int sig = WTERMSIG (status); 231 fprintf (stderr, "%s terminated with signal %d [%s]%s\n", 232 exe_name, sig, strsignal (sig), 233 WCOREDUMP (status) ? ", core dumped" : ""); 234 } 235 else if (WIFEXITED (status)) 236 exit_code = WEXITSTATUS (status); 237 } 238 else 239 exit_code = SUCCESS_EXIT_CODE; 240 241 return exit_code; 242} 243