Home | History | Annotate | Line # | Download | only in gcc
      1  1.1  mrg /* Implementation of file prefix remapping support (-f*-prefix-map options).
      2  1.1  mrg    Copyright (C) 2017-2022 Free Software Foundation, Inc.
      3  1.1  mrg 
      4  1.1  mrg    This program is free software; you can redistribute it and/or modify it
      5  1.1  mrg    under the terms of the GNU General Public License as published by the
      6  1.1  mrg    Free Software Foundation; either version 3, or (at your option) any
      7  1.1  mrg    later version.
      8  1.1  mrg 
      9  1.1  mrg    This program is distributed in the hope that it will be useful,
     10  1.1  mrg    but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  1.1  mrg    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12  1.1  mrg    GNU General Public License for more details.
     13  1.1  mrg 
     14  1.1  mrg    You should have received a copy of the GNU General Public License
     15  1.1  mrg    along with this program; see the file COPYING3.  If not see
     16  1.1  mrg    <http://www.gnu.org/licenses/>.  */
     17  1.1  mrg 
     18  1.1  mrg #include "config.h"
     19  1.1  mrg #include "system.h"
     20  1.1  mrg #include "coretypes.h"
     21  1.1  mrg #include "diagnostic.h"
     22  1.1  mrg #include "file-prefix-map.h"
     23  1.1  mrg 
     24  1.1  mrg /* Structure recording the mapping from source file and directory names at
     25  1.1  mrg    compile time to those to be embedded in the compilation result (debug
     26  1.1  mrg    information, the __FILE__ macro expansion, etc).  */
     27  1.1  mrg struct file_prefix_map
     28  1.1  mrg {
     29  1.1  mrg   const char *old_prefix;
     30  1.1  mrg   const char *new_prefix;
     31  1.1  mrg   size_t old_len;
     32  1.1  mrg   size_t new_len;
     33  1.1  mrg   struct file_prefix_map *next;
     34  1.1  mrg };
     35  1.1  mrg 
     36  1.1  mrg /* Record a file prefix mapping in the specified map.  ARG is the argument to
     37  1.1  mrg    -f*-prefix-map and must be of the form OLD=NEW.  OPT is the option name
     38  1.1  mrg    for diagnostics.  */
     39  1.1  mrg static void
     40  1.1  mrg add_prefix_map (file_prefix_map *&maps, const char *arg, const char *opt)
     41  1.1  mrg {
     42  1.1  mrg   file_prefix_map *map;
     43  1.1  mrg   const char *p, *old;
     44  1.1  mrg   size_t oldlen;
     45  1.1  mrg 
     46  1.1  mrg   /* Note: looking for the last '='. The thinking is we can control the paths
     47  1.1  mrg      inside our projects but not where the users build them.  */
     48  1.1  mrg   p = strrchr (arg, '=');
     49  1.1  mrg   if (!p)
     50  1.1  mrg     {
     51  1.1  mrg       error ("invalid argument %qs to %qs", arg, opt);
     52  1.1  mrg       return;
     53  1.1  mrg     }
     54  1.1  mrg   if (*arg == '$')
     55  1.1  mrg     {
     56  1.1  mrg       char *env = xstrndup (arg + 1, p - (arg + 1));
     57  1.1  mrg       old = getenv(env);
     58  1.1  mrg       if (!old)
     59  1.1  mrg 	{
     60  1.1  mrg 	  warning (0, "environment variable %qs not set in argument to "
     61  1.1  mrg 		   "%s", env, opt);
     62  1.1  mrg 	  free(env);
     63  1.1  mrg 	  return;
     64  1.1  mrg 	}
     65  1.1  mrg       oldlen = strlen(old);
     66  1.1  mrg       free(env);
     67  1.1  mrg     }
     68  1.1  mrg   else
     69  1.1  mrg     {
     70  1.1  mrg       old = xstrndup (arg, p - arg);
     71  1.1  mrg       oldlen = p - arg;
     72  1.1  mrg     }
     73  1.1  mrg   map = XNEW (file_prefix_map);
     74  1.1  mrg   map->old_prefix = old;
     75  1.1  mrg   map->old_len = oldlen;
     76  1.1  mrg   p++;
     77  1.1  mrg   map->new_prefix = xstrdup (p);
     78  1.1  mrg   map->new_len = strlen (p);
     79  1.1  mrg   map->next = maps;
     80  1.1  mrg   maps = map;
     81  1.1  mrg }
     82  1.1  mrg 
     83  1.1  mrg /* Perform user-specified mapping of filename prefixes.  Return the
     84  1.1  mrg    GC-allocated new name corresponding to FILENAME or FILENAME if no
     85  1.1  mrg    remapping was performed.  */
     86  1.1  mrg 
     87  1.1  mrg static const char *
     88  1.1  mrg remap_filename (file_prefix_map *maps, const char *filename)
     89  1.1  mrg {
     90  1.1  mrg   file_prefix_map *map;
     91  1.1  mrg   char *s;
     92  1.1  mrg   const char *name;
     93  1.1  mrg   size_t name_len;
     94  1.1  mrg 
     95  1.1  mrg   for (map = maps; map; map = map->next)
     96  1.1  mrg     if (filename_ncmp (filename, map->old_prefix, map->old_len) == 0)
     97  1.1  mrg       break;
     98  1.1  mrg   if (!map)
     99  1.1  mrg     return filename;
    100  1.1  mrg   name = filename + map->old_len;
    101  1.1  mrg   name_len = strlen (name) + 1;
    102  1.1  mrg 
    103  1.1  mrg   s = (char *) ggc_alloc_atomic (name_len + map->new_len);
    104  1.1  mrg   memcpy (s, map->new_prefix, map->new_len);
    105  1.1  mrg   memcpy (s + map->new_len, name, name_len);
    106  1.1  mrg   return s;
    107  1.1  mrg }
    108  1.1  mrg 
    109  1.1  mrg /* NOTE: if adding another -f*-prefix-map option then don't forget to
    110  1.1  mrg    ignore it in DW_AT_producer (dwarf2out.cc).  */
    111  1.1  mrg 
    112  1.1  mrg /* Linked lists of file_prefix_map structures.  */
    113  1.1  mrg static file_prefix_map *macro_prefix_maps; /* -fmacro-prefix-map  */
    114  1.1  mrg static file_prefix_map *debug_prefix_maps; /* -fdebug-prefix-map  */
    115  1.1  mrg static file_prefix_map *profile_prefix_maps; /* -fprofile-prefix-map  */
    116  1.1  mrg 
    117  1.1  mrg /* Record a file prefix mapping for -fmacro-prefix-map.  */
    118  1.1  mrg void
    119  1.1  mrg add_macro_prefix_map (const char *arg)
    120  1.1  mrg {
    121  1.1  mrg   add_prefix_map (macro_prefix_maps, arg, "-fmacro-prefix-map");
    122  1.1  mrg }
    123  1.1  mrg 
    124  1.1  mrg /* Record a file prefix mapping for -fdebug-prefix-map.  */
    125  1.1  mrg void
    126  1.1  mrg add_debug_prefix_map (const char *arg)
    127  1.1  mrg {
    128  1.1  mrg   add_prefix_map (debug_prefix_maps, arg, "-fdebug-prefix-map");
    129  1.1  mrg }
    130  1.1  mrg 
    131  1.1  mrg /* Record a file prefix mapping for all -f*-prefix-map.  */
    132  1.1  mrg void
    133  1.1  mrg add_file_prefix_map (const char *arg)
    134  1.1  mrg {
    135  1.1  mrg   add_prefix_map (macro_prefix_maps, arg, "-ffile-prefix-map");
    136  1.1  mrg   add_prefix_map (debug_prefix_maps, arg, "-ffile-prefix-map");
    137  1.1  mrg   add_prefix_map (profile_prefix_maps, arg, "-ffile-prefix-map");
    138  1.1  mrg }
    139  1.1  mrg 
    140  1.1  mrg /* Record a file prefix mapping for -fprofile-prefix-map.  */
    141  1.1  mrg void
    142  1.1  mrg add_profile_prefix_map (const char *arg)
    143  1.1  mrg {
    144  1.1  mrg   add_prefix_map (profile_prefix_maps, arg, "-fprofile-prefix-map");
    145  1.1  mrg }
    146  1.1  mrg 
    147  1.1  mrg /* Remap using -fmacro-prefix-map.  Return the GC-allocated new name
    148  1.1  mrg    corresponding to FILENAME or FILENAME if no remapping was performed.  */
    149  1.1  mrg const char *
    150  1.1  mrg remap_macro_filename (const char *filename)
    151  1.1  mrg {
    152  1.1  mrg   return remap_filename (macro_prefix_maps, filename);
    153  1.1  mrg }
    154  1.1  mrg 
    155  1.1  mrg /* Original GCC version disabled. The NetBSD version handles regex */
    156  1.1  mrg #if 0
    157  1.1  mrg /* Remap using -fdebug-prefix-map.  Return the GC-allocated new name
    158  1.1  mrg    corresponding to FILENAME or FILENAME if no remapping was performed.  */
    159  1.1  mrg const char *
    160  1.1  mrg remap_debug_filename (const char *filename)
    161  1.1  mrg {
    162  1.1  mrg   return remap_filename (debug_prefix_maps, filename);
    163  1.1  mrg }
    164  1.1  mrg #endif
    165  1.1  mrg 
    166  1.1  mrg /*****
    167  1.1  mrg  ***** The following code is a NetBSD extension that allows regex and
    168  1.1  mrg  ***** \[0-9] substitutition arguments.
    169  1.1  mrg  *****/
    170  1.1  mrg 
    171  1.1  mrg /* Perform user-specified mapping of debug filename prefixes.  Return
    172  1.1  mrg    the new name corresponding to FILENAME.  */
    173  1.1  mrg 
    174  1.1  mrg static const char *
    175  1.1  mrg remap_debug_prefix_filename (const char *filename)
    176  1.1  mrg {
    177  1.1  mrg   file_prefix_map *map;
    178  1.1  mrg   char *s;
    179  1.1  mrg   const char *name;
    180  1.1  mrg   size_t name_len;
    181  1.1  mrg 
    182  1.1  mrg   for (map = debug_prefix_maps; map; map = map->next)
    183  1.1  mrg     if (filename_ncmp (filename, map->old_prefix, map->old_len) == 0)
    184  1.1  mrg       break;
    185  1.1  mrg   if (!map)
    186  1.1  mrg     return filename;
    187  1.1  mrg   name = filename + map->old_len;
    188  1.1  mrg   name_len = strlen (name) + 1;
    189  1.1  mrg   s = (char *) alloca (name_len + map->new_len);
    190  1.1  mrg   memcpy (s, map->new_prefix, map->new_len);
    191  1.1  mrg   memcpy (s + map->new_len, name, name_len);
    192  1.1  mrg   return ggc_strdup (s);
    193  1.1  mrg }
    194  1.1  mrg 
    195  1.1  mrg #include <regex.h>
    196  1.1  mrg 
    197  1.1  mrg typedef struct debug_regex_map
    198  1.1  mrg {
    199  1.1  mrg   regex_t re;
    200  1.1  mrg   const char *sub;
    201  1.1  mrg   struct debug_regex_map *next;
    202  1.1  mrg } debug_regex_map;
    203  1.1  mrg 
    204  1.1  mrg /* Linked list of such structures.  */
    205  1.1  mrg debug_regex_map *debug_regex_maps;
    206  1.1  mrg 
    207  1.1  mrg 
    208  1.1  mrg /* Record a debug file regex mapping.  ARG is the argument to
    209  1.1  mrg    -fdebug-regex-map and must be of the form OLD=NEW.  */
    210  1.1  mrg 
    211  1.1  mrg void
    212  1.1  mrg add_debug_regex_map (const char *arg)
    213  1.1  mrg {
    214  1.1  mrg   debug_regex_map *map;
    215  1.1  mrg   const char *p;
    216  1.1  mrg   char *old;
    217  1.1  mrg   char buf[1024];
    218  1.1  mrg   regex_t re;
    219  1.1  mrg   int e;
    220  1.1  mrg 
    221  1.1  mrg   p = strchr (arg, '=');
    222  1.1  mrg   if (!p)
    223  1.1  mrg     {
    224  1.1  mrg       error ("invalid argument %qs to -fdebug-regex-map", arg);
    225  1.1  mrg       return;
    226  1.1  mrg     }
    227  1.1  mrg 
    228  1.1  mrg   old = xstrndup (arg, p - arg);
    229  1.1  mrg   if ((e = regcomp(&re, old, REG_EXTENDED)) != 0)
    230  1.1  mrg     {
    231  1.1  mrg       regerror(e, &re, buf, sizeof(buf));
    232  1.1  mrg       warning (0, "regular expression compilation for %qs in argument to "
    233  1.1  mrg 	       "-fdebug-regex-map failed: %qs", old, buf);
    234  1.1  mrg       free(old);
    235  1.1  mrg       return;
    236  1.1  mrg     }
    237  1.1  mrg   free(old);
    238  1.1  mrg 
    239  1.1  mrg   map = XNEW (debug_regex_map);
    240  1.1  mrg   map->re = re;
    241  1.1  mrg   p++;
    242  1.1  mrg   map->sub = xstrdup (p);
    243  1.1  mrg   map->next = debug_regex_maps;
    244  1.1  mrg   debug_regex_maps = map;
    245  1.1  mrg }
    246  1.1  mrg 
    247  1.1  mrg extern "C" ssize_t regasub(char **, const char *,
    248  1.1  mrg   const regmatch_t *rm, const char *);
    249  1.1  mrg 
    250  1.1  mrg /* Perform user-specified mapping of debug filename regular expressions.  Return
    251  1.1  mrg    the new name corresponding to FILENAME.  */
    252  1.1  mrg 
    253  1.1  mrg static const char *
    254  1.1  mrg remap_debug_regex_filename (const char *filename)
    255  1.1  mrg {
    256  1.1  mrg   debug_regex_map *map;
    257  1.1  mrg   char *s;
    258  1.1  mrg   regmatch_t rm[10];
    259  1.1  mrg 
    260  1.1  mrg   for (map = debug_regex_maps; map; map = map->next)
    261  1.1  mrg     if (regexec (&map->re, filename, 10, rm, 0) == 0
    262  1.1  mrg        && regasub (&s, map->sub, rm, filename) >= 0)
    263  1.1  mrg       {
    264  1.1  mrg 	 const char *name = ggc_strdup(s);
    265  1.1  mrg 	 free(s);
    266  1.1  mrg 	 return name;
    267  1.1  mrg       }
    268  1.1  mrg   return filename;
    269  1.1  mrg }
    270  1.1  mrg 
    271  1.1  mrg const char *
    272  1.1  mrg remap_debug_filename (const char *filename)
    273  1.1  mrg {
    274  1.1  mrg    return remap_debug_regex_filename (remap_debug_prefix_filename (filename));
    275  1.1  mrg }
    276  1.1  mrg 
    277  1.1  mrg /* Remap using -fprofile-prefix-map.  Return the GC-allocated new name
    278  1.1  mrg    corresponding to FILENAME or FILENAME if no remapping was performed.  */
    279  1.1  mrg const char *
    280  1.1  mrg remap_profile_filename (const char *filename)
    281  1.1  mrg {
    282  1.1  mrg   return remap_filename (profile_prefix_maps, filename);
    283  1.1  mrg }
    284