]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgcc/libgcov-driver-system.c
Update copyright years.
[thirdparty/gcc.git] / libgcc / libgcov-driver-system.c
CommitLineData
d6d3f033
RX
1/* Routines required for instrumenting a program. */
2/* Compile this one with gcc. */
5624e564 3/* Copyright (C) 1989-2015 Free Software Foundation, Inc.
d6d3f033
RX
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
17Under Section 7 of GPL version 3, you are granted additional
18permissions described in the GCC Runtime Library Exception, version
193.1, as published by the Free Software Foundation.
20
21You should have received a copy of the GNU General Public License and
22a copy of the GCC Runtime Library Exception along with this program;
23see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24<http://www.gnu.org/licenses/>. */
25
26/* A utility function for outputing errors. */
27
28static int __attribute__((format(printf, 1, 2)))
29gcov_error (const char *fmt, ...)
30{
31 int ret;
32 va_list argp;
33 va_start (argp, fmt);
34 ret = vfprintf (stderr, fmt, argp);
35 va_end (argp);
36 return ret;
37}
38
39/* Make sure path component of the given FILENAME exists, create
40 missing directories. FILENAME must be writable.
41 Returns zero on success, or -1 if an error occurred. */
42
43static int
44create_file_directory (char *filename)
45{
46#if !defined(TARGET_POSIX_IO) && !defined(_WIN32)
47 (void) filename;
48 return -1;
49#else
50 char *s;
51
52 s = filename;
53
54 if (HAS_DRIVE_SPEC(s))
55 s += 2;
56 if (IS_DIR_SEPARATOR(*s))
57 ++s;
58 for (; *s != '\0'; s++)
59 if (IS_DIR_SEPARATOR(*s))
60 {
61 char sep = *s;
62 *s = '\0';
63
64 /* Try to make directory if it doesn't already exist. */
65 if (access (filename, F_OK) == -1
66#ifdef TARGET_POSIX_IO
67 && mkdir (filename, 0755) == -1
68#else
69 && mkdir (filename) == -1
70#endif
71 /* The directory might have been made by another process. */
72 && errno != EEXIST)
73 {
74 gcov_error ("profiling:%s:Cannot create directory\n", filename);
75 *s = sep;
76 return -1;
77 };
78
79 *s = sep;
80 };
81 return 0;
82#endif
83}
84
85static void
6dc33097 86allocate_filename_struct (struct gcov_filename *gf)
d6d3f033
RX
87{
88 const char *gcov_prefix;
d6d3f033 89 size_t prefix_length;
6dc33097 90 int strip = 0;
d6d3f033 91
d6d3f033
RX
92 {
93 /* Check if the level of dirs to strip off specified. */
94 char *tmp = getenv("GCOV_PREFIX_STRIP");
95 if (tmp)
96 {
6dc33097 97 strip = atoi (tmp);
d6d3f033 98 /* Do not consider negative values. */
6dc33097
NS
99 if (strip < 0)
100 strip = 0;
d6d3f033
RX
101 }
102 }
6dc33097 103 gf->strip = strip;
d6d3f033
RX
104
105 /* Get file name relocation prefix. Non-absolute values are ignored. */
106 gcov_prefix = getenv("GCOV_PREFIX");
6dc33097
NS
107 prefix_length = gcov_prefix ? strlen (gcov_prefix) : 0;
108
109 /* Remove an unnecessary trailing '/' */
110 if (prefix_length && IS_DIR_SEPARATOR (gcov_prefix[prefix_length - 1]))
111 prefix_length--;
d6d3f033
RX
112
113 /* If no prefix was specified and a prefix stip, then we assume
114 relative. */
6dc33097 115 if (!prefix_length && gf->strip)
d6d3f033
RX
116 {
117 gcov_prefix = ".";
118 prefix_length = 1;
119 }
6dc33097 120 gf->prefix = prefix_length;
d6d3f033 121
6dc33097
NS
122 /* Allocate and initialize the filename scratch space. */
123 gf->filename = (char *) xmalloc (gf->max_length + prefix_length + 2);
124 if (prefix_length)
125 memcpy (gf->filename, gcov_prefix, prefix_length);
d6d3f033
RX
126}
127
128/* Open a gcda file specified by GI_FILENAME.
129 Return -1 on error. Return 0 on success. */
130
131static int
6dc33097
NS
132gcov_exit_open_gcda_file (struct gcov_info *gi_ptr,
133 struct gcov_filename *gf)
d6d3f033 134{
6dc33097
NS
135 const char *fname = gi_ptr->filename;
136 char *dst = gf->filename + gf->prefix;
d6d3f033 137
d6d3f033
RX
138 fname = gi_ptr->filename;
139
d6d3f033
RX
140 /* Build relocated filename, stripping off leading
141 directories from the initial filename if requested. */
6dc33097 142 if (gf->strip > 0)
d6d3f033 143 {
6dc33097
NS
144 const char *probe = fname;
145 int level;
d6d3f033 146
6dc33097
NS
147 /* Remove a leading separator, without counting it. */
148 if (IS_DIR_SEPARATOR (*probe))
149 probe++;
d6d3f033 150
6dc33097
NS
151 /* Skip selected directory levels. If we fall off the end, we
152 keep the final part. */
153 for (level = gf->strip; *probe && level; probe++)
154 if (IS_DIR_SEPARATOR (*probe))
d6d3f033 155 {
6dc33097
NS
156 fname = probe;
157 level--;
d6d3f033
RX
158 }
159 }
160
161 /* Update complete filename with stripped original. */
6dc33097 162 if (gf->prefix)
d6d3f033 163 {
6dc33097
NS
164 /* Avoid to add multiple drive letters into combined path. */
165 if (HAS_DRIVE_SPEC(fname))
166 fname += 2;
167
168 if (!IS_DIR_SEPARATOR (*fname))
169 *dst++ = '/';
d6d3f033 170 }
6dc33097 171 strcpy (dst, fname);
d6d3f033 172
6dc33097 173 if (!gcov_open (gf->filename))
d6d3f033
RX
174 {
175 /* Open failed likely due to missed directory.
176 Create directory and retry to open file. */
6dc33097 177 if (create_file_directory (gf->filename))
d6d3f033 178 {
6dc33097 179 fprintf (stderr, "profiling:%s:Skip\n", gf->filename);
d6d3f033
RX
180 return -1;
181 }
6dc33097 182 if (!gcov_open (gf->filename))
d6d3f033 183 {
6dc33097 184 fprintf (stderr, "profiling:%s:Cannot open\n", gf->filename);
d6d3f033
RX
185 return -1;
186 }
187 }
188
189 return 0;
190}