dec7e82d6e9c84afb065a1d33ec9ea0f53760c5c
[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 <link.h>
22
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <unistd.h>
26 #include <limits.h>
27 #include <stdlib.h>
28 #include <errno.h>
29 #include <stdint.h>
30 #include <stddef.h>
31 #include <stdio.h>
32
33 #include <usterr-signal-safe.h>
34 #include "lttng-tracer-core.h"
35 #include "lttng-ust-baddr.h"
36
37 #define TRACEPOINT_DEFINE
38 #define TRACEPOINT_CREATE_PROBES
39 #define TP_SESSION_CHECK
40 #include "ust_baddr_statedump.h"
41
42 struct extract_data {
43 void *owner;
44 void *exec_baddr; /* executable base address */
45 };
46
47 /*
48 * Trace baddr into all sessions for which statedump is pending owned by
49 * the caller thread.
50 */
51 static
52 int trace_baddr(void *base_addr_ptr,
53 const char *resolved_path,
54 int vdso,
55 void *owner)
56 {
57 struct cds_list_head *sessionsp;
58 struct lttng_session *session;
59 struct stat sostat;
60
61 if (vdso || stat(resolved_path, &sostat)) {
62 sostat.st_size = 0;
63 sostat.st_mtime = -1;
64 }
65 /*
66 * UST lock nests within dynamic loader lock.
67 */
68 if (ust_lock()) {
69 /*
70 * Stop iteration on headers if need to exit.
71 */
72 ust_unlock();
73 return 1;
74 }
75
76 sessionsp = _lttng_get_sessions();
77 cds_list_for_each_entry(session, sessionsp, node) {
78 if (session->owner != owner)
79 continue;
80 if (!session->statedump_pending)
81 continue;
82 tracepoint(ust_baddr_statedump, soinfo,
83 session, base_addr_ptr,
84 resolved_path, sostat.st_size,
85 sostat.st_mtime);
86 }
87 ust_unlock();
88 return 0;
89 }
90
91 static
92 int extract_soinfo_events(struct dl_phdr_info *info, size_t size, void *_data)
93 {
94 int j;
95 struct extract_data *data = _data;
96 void *owner = data->owner;
97
98 for (j = 0; j < info->dlpi_phnum; j++) {
99 char resolved_path[PATH_MAX];
100 void *base_addr_ptr;
101 int vdso = 0;
102
103 if (info->dlpi_phdr[j].p_type != PT_LOAD)
104 continue;
105
106 /* Calculate virtual memory address of the loadable segment */
107 base_addr_ptr = (void *) info->dlpi_addr
108 + info->dlpi_phdr[j].p_vaddr;
109
110 if ((info->dlpi_name == NULL || info->dlpi_name[0] == 0)
111 && !data->exec_baddr) {
112 /*
113 * Only the first phdr encountered is considered
114 * as the program executable. The following
115 * could be e.g. vdso. Don't mistakenly dump
116 * them as being the program executable.
117 */
118 data->exec_baddr = base_addr_ptr;
119 /*
120 * Deal with program executable outside of phdr
121 * iteration.
122 */
123 break;
124 }
125 if (info->dlpi_name == NULL || info->dlpi_name[0] == 0) {
126 /* Found vDSO. */
127 snprintf(resolved_path, PATH_MAX - 1, "[vdso]");
128 vdso = 1;
129 } else {
130 /*
131 * For regular dl_phdr_info entries we have to check if
132 * the path to the shared object really exists.
133 */
134 if (!realpath(info->dlpi_name, resolved_path)) {
135 /* Path unknown, put the 'path' into brackets */
136 snprintf(resolved_path, PATH_MAX - 1, "[%s]",
137 info->dlpi_name);
138 vdso = 1;
139 }
140 }
141 if (trace_baddr(base_addr_ptr, resolved_path, vdso, owner)) {
142 return 1;
143 }
144 /*
145 * We are only interested in the base address (lowest virtual
146 * address associated with the memory image), skip the rest
147 */
148 break;
149 }
150 return 0;
151 }
152
153 static
154 void dump_exec_baddr(struct extract_data *data)
155 {
156 void *owner = data->owner;
157 void *base_addr_ptr;
158 char exe_path[PATH_MAX];
159 ssize_t exe_len;
160
161 base_addr_ptr = data->exec_baddr;
162 if (!base_addr_ptr)
163 return;
164 /*
165 * We have to use /proc/self/exe to determine the executable full
166 * path.
167 */
168 exe_len = readlink("/proc/self/exe", exe_path, sizeof(exe_path) - 1);
169 if (exe_len <= 0)
170 return;
171 exe_path[exe_len] = '\0';
172 trace_baddr(base_addr_ptr, exe_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_WITH_EXPERIMENTAL_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.032558 seconds and 3 git commands to generate.