Fix: set soinfo_data's vdso flag correctly in base address statedump
[lttng-ust.git] / liblttng-ust / lttng-ust-statedump.c
1 /*
2 * Copyright (C) 2013 Paul Woegerer <paul_woegerer@mentor.com>
3 * Copyright (C) 2015 Antoine Busque <abusque@efficios.com>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 #define _LGPL_SOURCE
21 #define _GNU_SOURCE
22 #include <link.h>
23
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <unistd.h>
27 #include <limits.h>
28 #include <stdlib.h>
29 #include <errno.h>
30 #include <stdint.h>
31 #include <stddef.h>
32 #include <stdio.h>
33
34 #include <usterr-signal-safe.h>
35 #include "lttng-tracer-core.h"
36 #include "lttng-ust-statedump.h"
37
38 #define TRACEPOINT_DEFINE
39 #define TRACEPOINT_CREATE_PROBES
40 #define TP_SESSION_CHECK
41 #include "lttng-ust-statedump-provider.h"
42
43 struct dl_iterate_data {
44 void *owner;
45 int exec_found;
46 };
47
48 struct soinfo_data {
49 void *owner;
50 void *base_addr_ptr;
51 const char *resolved_path;
52 int vdso;
53 off_t size;
54 time_t mtime;
55 };
56
57 typedef void (*tracepoint_cb)(struct lttng_session *session, void *priv);
58
59 /*
60 * Trace statedump event into all sessions owned by the caller thread
61 * for which statedump is pending.
62 */
63 static
64 int trace_statedump_event(tracepoint_cb tp_cb, void *owner, void *priv)
65 {
66 struct cds_list_head *sessionsp;
67 struct lttng_session *session;
68
69 /*
70 * UST lock nests within dynamic loader lock.
71 */
72 if (ust_lock()) {
73 ust_unlock();
74 return 1;
75 }
76
77 sessionsp = _lttng_get_sessions();
78 cds_list_for_each_entry(session, sessionsp, node) {
79 if (session->owner != owner)
80 continue;
81 if (!session->statedump_pending)
82 continue;
83 tp_cb(session, priv);
84 }
85 ust_unlock();
86 return 0;
87 }
88
89 static
90 void trace_soinfo_cb(struct lttng_session *session, void *priv)
91 {
92 struct soinfo_data *so_data = (struct soinfo_data *) priv;
93
94 tracepoint(lttng_ust_statedump, soinfo,
95 session, so_data->base_addr_ptr,
96 so_data->resolved_path, so_data->size,
97 so_data->mtime);
98 }
99
100 static
101 void trace_start_cb(struct lttng_session *session, void *priv)
102 {
103 tracepoint(lttng_ust_statedump, start, session);
104 }
105
106 static
107 void trace_end_cb(struct lttng_session *session, void *priv)
108 {
109 tracepoint(lttng_ust_statedump, end, session);
110 }
111
112 static
113 int trace_baddr(struct soinfo_data *so_data)
114 {
115 struct stat sostat;
116
117 if (so_data->vdso || stat(so_data->resolved_path, &sostat)) {
118 sostat.st_size = 0;
119 sostat.st_mtime = -1;
120 }
121
122 so_data->size = sostat.st_size;
123 so_data->mtime = sostat.st_mtime;
124
125 return trace_statedump_event(trace_soinfo_cb, so_data->owner, so_data);
126 }
127
128 static
129 int trace_statedump_start(void *owner)
130 {
131 return trace_statedump_event(trace_start_cb, owner, NULL);
132 }
133
134 static
135 int trace_statedump_end(void *owner)
136 {
137 return trace_statedump_event(trace_end_cb, owner, NULL);
138 }
139
140 static
141 int extract_soinfo_events(struct dl_phdr_info *info, size_t size, void *_data)
142 {
143 int j;
144 struct dl_iterate_data *data = _data;
145
146 for (j = 0; j < info->dlpi_phnum; j++) {
147 struct soinfo_data so_data;
148 char resolved_path[PATH_MAX];
149 void *base_addr_ptr;
150
151 if (info->dlpi_phdr[j].p_type != PT_LOAD)
152 continue;
153
154 /* Calculate virtual memory address of the loadable segment */
155 base_addr_ptr = (void *) info->dlpi_addr +
156 info->dlpi_phdr[j].p_vaddr;
157
158 if ((info->dlpi_name == NULL || info->dlpi_name[0] == 0)) {
159 /*
160 * Only the first phdr without a dlpi_name
161 * encountered is considered as the program
162 * executable. The rest are vdsos.
163 */
164 if (!data->exec_found) {
165 ssize_t path_len;
166 data->exec_found = 1;
167
168 /*
169 * Use /proc/self/exe to resolve the
170 * executable's full path.
171 */
172 path_len = readlink("/proc/self/exe",
173 resolved_path,
174 PATH_MAX - 1);
175 if (path_len <= 0)
176 break;
177
178 resolved_path[path_len] = '\0';
179 so_data.vdso = 0;
180 } else {
181 snprintf(resolved_path, PATH_MAX - 1, "[vdso]");
182 so_data.vdso = 1;
183 }
184 } else {
185 /*
186 * For regular dl_phdr_info entries check if
187 * the path to the SO really exists. If not,
188 * treat as vdso and use dlpi_name as 'path'.
189 */
190 if (!realpath(info->dlpi_name, resolved_path)) {
191 snprintf(resolved_path, PATH_MAX - 1, "[%s]",
192 info->dlpi_name);
193 so_data.vdso = 1;
194 } else {
195 so_data.vdso = 0;
196 }
197 }
198
199 so_data.owner = data->owner;
200 so_data.base_addr_ptr = base_addr_ptr;
201 so_data.resolved_path = resolved_path;
202 return trace_baddr(&so_data);
203 }
204
205 return 0;
206 }
207
208 /*
209 * Generate a statedump of base addresses of all shared objects loaded
210 * by the traced application, as well as for the application's
211 * executable itself.
212 */
213 static
214 int do_baddr_statedump(void *owner)
215 {
216 struct dl_iterate_data data;
217
218 if (getenv("LTTNG_UST_WITHOUT_BADDR_STATEDUMP"))
219 return 0;
220
221 data.owner = owner;
222 data.exec_found = 0;
223 /*
224 * Iterate through the list of currently loaded shared objects and
225 * generate events for loadable segments using
226 * extract_soinfo_events.
227 */
228 dl_iterate_phdr(extract_soinfo_events, &data);
229
230 return 0;
231 }
232
233 /*
234 * Generate a statedump of a given traced application. A statedump is
235 * delimited by start and end events. For a given (process, session)
236 * pair, begin/end events are serialized and will match. However, in a
237 * session, statedumps from different processes may be
238 * interleaved. The vpid context should be used to identify which
239 * events belong to which process.
240 */
241 int do_lttng_ust_statedump(void *owner)
242 {
243 trace_statedump_start(owner);
244 do_baddr_statedump(owner);
245 trace_statedump_end(owner);
246
247 return 0;
248 }
249
250 void lttng_ust_statedump_init(void)
251 {
252 __tracepoints__init();
253 __tracepoints__ptrs_init();
254 __lttng_events_init__lttng_ust_statedump();
255 }
256
257 void lttng_ust_statedump_destroy(void)
258 {
259 __lttng_events_exit__lttng_ust_statedump();
260 __tracepoints__ptrs_destroy();
261 __tracepoints__destroy();
262 }
This page took 0.035243 seconds and 5 git commands to generate.