Fix: baddr_statedump tracepoint registration
[lttng-ust.git] / liblttng-ust / lttng-ust-baddr.c
1 /*
2 * Copyright (C) 2013 Paul Woegerer <paul_woegerer@mentor.com>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #define _LGPL_SOURCE
20 #define _GNU_SOURCE
21 #include <dlfcn.h>
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-baddr.h"
37
38 #define TRACEPOINT_DEFINE
39 #define TRACEPOINT_CREATE_PROBES
40 #define TP_SESSION_CHECK
41 #include "ust_baddr_statedump.h"
42
43 struct extract_data {
44 void *owner;
45 void *exec_baddr; /* executable base address */
46 };
47
48 /*
49 * Trace baddr into all sessions for which statedump is pending owned by
50 * the caller thread.
51 */
52 static
53 int trace_baddr(void *base_addr_ptr,
54 const char *resolved_path,
55 int vdso,
56 void *owner)
57 {
58 struct cds_list_head *sessionsp;
59 struct lttng_session *session;
60 struct stat sostat;
61
62 if (vdso || stat(resolved_path, &sostat)) {
63 sostat.st_size = 0;
64 sostat.st_mtime = -1;
65 }
66 /*
67 * UST lock nests within dynamic loader lock.
68 */
69 if (ust_lock()) {
70 /*
71 * Stop iteration on headers if need to exit.
72 */
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 tracepoint(ust_baddr_statedump, soinfo,
84 session, base_addr_ptr,
85 resolved_path, sostat.st_size,
86 sostat.st_mtime);
87 }
88 ust_unlock();
89 return 0;
90 }
91
92 static
93 int extract_soinfo_events(struct dl_phdr_info *info, size_t size, void *_data)
94 {
95 int j;
96 struct extract_data *data = _data;
97 void *owner = data->owner;
98
99 for (j = 0; j < info->dlpi_phnum; j++) {
100 char resolved_path[PATH_MAX];
101 void *base_addr_ptr;
102 int vdso = 0;
103
104 if (info->dlpi_phdr[j].p_type != PT_LOAD)
105 continue;
106
107 /* Calculate virtual memory address of the loadable segment */
108 base_addr_ptr = (void *) info->dlpi_addr
109 + info->dlpi_phdr[j].p_vaddr;
110
111 if ((info->dlpi_name == NULL || info->dlpi_name[0] == 0)
112 && !data->exec_baddr) {
113 /*
114 * Only the first phdr encountered is considered
115 * as the program executable. The following
116 * could be e.g. vdso. Don't mistakenly dump
117 * them as being the program executable.
118 */
119 data->exec_baddr = base_addr_ptr;
120 /*
121 * Deal with program executable outside of phdr
122 * iteration.
123 */
124 break;
125 }
126 if (info->dlpi_name == NULL || info->dlpi_name[0] == 0) {
127 /* Found vDSO. */
128 snprintf(resolved_path, PATH_MAX - 1, "[vdso]");
129 vdso = 1;
130 } else {
131 /*
132 * For regular dl_phdr_info entries we have to check if
133 * the path to the shared object really exists.
134 */
135 if (!realpath(info->dlpi_name, resolved_path)) {
136 /* Path unknown, put the 'path' into brackets */
137 snprintf(resolved_path, PATH_MAX - 1, "[%s]",
138 info->dlpi_name);
139 vdso = 1;
140 }
141 }
142 if (trace_baddr(base_addr_ptr, resolved_path, vdso, owner)) {
143 return 1;
144 }
145 /*
146 * We are only interested in the base address (lowest virtual
147 * address associated with the memory image), skip the rest
148 */
149 break;
150 }
151 return 0;
152 }
153
154 static
155 void dump_exec_baddr(struct extract_data *data)
156 {
157 void *owner = data->owner;
158 Dl_info dl_info = { 0 };
159 void *base_addr_ptr;
160 char resolved_path[PATH_MAX];
161
162 base_addr_ptr = data->exec_baddr;
163 if (!base_addr_ptr)
164 return;
165 /*
166 * We have to use Dl_info to determine the executable full path.
167 */
168 if (!dladdr(base_addr_ptr, &dl_info))
169 return;
170 if (!realpath(dl_info.dli_fname, resolved_path))
171 return;
172 trace_baddr(base_addr_ptr, resolved_path, 0, owner);
173 }
174
175 int lttng_ust_baddr_statedump(void *owner)
176 {
177 struct extract_data data;
178
179 if (getenv("LTTNG_UST_WITHOUT_BADDR_STATEDUMP"))
180 return 0;
181
182 data.owner = owner;
183 data.exec_baddr = NULL;
184 /*
185 * Iterate through the list of currently loaded shared objects and
186 * generate events for loadable segments using
187 * extract_soinfo_events.
188 */
189 dl_iterate_phdr(extract_soinfo_events, &data);
190 /*
191 * We cannot call dladdr() from within phdr iteration, without
192 * causing constructor vs dynamic loader vs multithread internal
193 * deadlocks, so dump the executable outside of the phdr
194 * iteration.
195 */
196 dump_exec_baddr(&data);
197 return 0;
198 }
199
200 void lttng_ust_baddr_statedump_init(void)
201 {
202 __tracepoints__init();
203 __tracepoints__ptrs_init();
204 __lttng_events_init__ust_baddr_statedump();
205 }
206
207 void lttng_ust_baddr_statedump_destroy(void)
208 {
209 __lttng_events_exit__ust_baddr_statedump();
210 __tracepoints__ptrs_destroy();
211 __tracepoints__destroy();
212 }
This page took 0.036954 seconds and 4 git commands to generate.