Revert "Turn base address dump into experimental feature"
[lttng-ust.git] / liblttng-ust / lttng-ust-baddr.c
CommitLineData
b13d93c2
PW
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
5aed31fc 19#define _LGPL_SOURCE
b13d93c2 20#define _GNU_SOURCE
b13d93c2
PW
21#include <link.h>
22
23#include <sys/types.h>
24#include <sys/stat.h>
b13d93c2
PW
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>
b13d93c2 32
9e166115
MD
33#include <usterr-signal-safe.h>
34#include "lttng-tracer-core.h"
13436238
PW
35#include "lttng-ust-baddr.h"
36
b13d93c2 37#define TRACEPOINT_DEFINE
f0cc794d
MD
38#define TRACEPOINT_CREATE_PROBES
39#define TP_SESSION_CHECK
95c25348 40#include "ust_baddr_statedump.h"
b13d93c2 41
5aed31fc
MD
42struct 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 */
37dddb65 51static
5aed31fc
MD
52int trace_baddr(void *base_addr_ptr,
53 const char *resolved_path,
54 int vdso,
55 void *owner)
95c25348 56{
37dddb65 57 struct cds_list_head *sessionsp;
5aed31fc
MD
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
91static
92int 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;
37dddb65 97
95c25348
PW
98 for (j = 0; j < info->dlpi_phnum; j++) {
99 char resolved_path[PATH_MAX];
95c25348 100 void *base_addr_ptr;
5aed31fc 101 int vdso = 0;
95c25348
PW
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
95c25348 110 if ((info->dlpi_name == NULL || info->dlpi_name[0] == 0)
5aed31fc
MD
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;
95c25348 119 /*
5aed31fc
MD
120 * Deal with program executable outside of phdr
121 * iteration.
95c25348 122 */
5aed31fc
MD
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;
95c25348
PW
129 } else {
130 /*
131 * For regular dl_phdr_info entries we have to check if
5aed31fc 132 * the path to the shared object really exists.
95c25348
PW
133 */
134 if (!realpath(info->dlpi_name, resolved_path)) {
5aed31fc 135 /* Path unknown, put the 'path' into brackets */
95c25348 136 snprintf(resolved_path, PATH_MAX - 1, "[%s]",
5aed31fc
MD
137 info->dlpi_name);
138 vdso = 1;
95c25348
PW
139 }
140 }
5aed31fc 141 if (trace_baddr(base_addr_ptr, resolved_path, vdso, owner)) {
3327ac33
MD
142 return 1;
143 }
95c25348
PW
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
5aed31fc
MD
153static
154void dump_exec_baddr(struct extract_data *data)
155{
156 void *owner = data->owner;
5aed31fc 157 void *base_addr_ptr;
6d0c2f84
PW
158 char exe_path[PATH_MAX];
159 ssize_t exe_len;
5aed31fc
MD
160
161 base_addr_ptr = data->exec_baddr;
162 if (!base_addr_ptr)
163 return;
164 /*
6d0c2f84
PW
165 * We have to use /proc/self/exe to determine the executable full
166 * path.
5aed31fc 167 */
6d0c2f84
PW
168 exe_len = readlink("/proc/self/exe", exe_path, sizeof(exe_path) - 1);
169 if (exe_len <= 0)
5aed31fc 170 return;
6d0c2f84
PW
171 exe_path[exe_len] = '\0';
172 trace_baddr(base_addr_ptr, exe_path, 0, owner);
5aed31fc
MD
173}
174
37dddb65 175int lttng_ust_baddr_statedump(void *owner)
95c25348 176{
5aed31fc
MD
177 struct extract_data data;
178
ce46717a 179 if (getenv("LTTNG_UST_WITHOUT_BADDR_STATEDUMP"))
ca7643d6 180 return 0;
5aed31fc
MD
181
182 data.owner = owner;
183 data.exec_baddr = NULL;
95c25348
PW
184 /*
185 * Iterate through the list of currently loaded shared objects and
37dddb65
MD
186 * generate events for loadable segments using
187 * extract_soinfo_events.
95c25348 188 */
5aed31fc
MD
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);
95c25348
PW
197 return 0;
198}
bd703713
PW
199
200void lttng_ust_baddr_statedump_init(void)
201{
202 __tracepoints__init();
203 __tracepoints__ptrs_init();
f0cc794d 204 __lttng_events_init__ust_baddr_statedump();
bd703713
PW
205}
206
207void lttng_ust_baddr_statedump_destroy(void)
208{
f0cc794d 209 __lttng_events_exit__ust_baddr_statedump();
bd703713
PW
210 __tracepoints__ptrs_destroy();
211 __tracepoints__destroy();
212}
This page took 0.033577 seconds and 4 git commands to generate.