Fix: baddr_statedump tracepoint registration
[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
PW
20#define _GNU_SOURCE
21#include <dlfcn.h>
22#include <link.h>
23
24#include <sys/types.h>
25#include <sys/stat.h>
b13d93c2
PW
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>
b13d93c2 33
9e166115
MD
34#include <usterr-signal-safe.h>
35#include "lttng-tracer-core.h"
13436238
PW
36#include "lttng-ust-baddr.h"
37
b13d93c2 38#define TRACEPOINT_DEFINE
95c25348 39#include "ust_baddr_statedump.h"
b13d93c2 40
5aed31fc
MD
41struct extract_data {
42 void *owner;
43 void *exec_baddr; /* executable base address */
44};
45
46/*
47 * Trace baddr into all sessions for which statedump is pending owned by
48 * the caller thread.
49 */
37dddb65 50static
5aed31fc
MD
51int trace_baddr(void *base_addr_ptr,
52 const char *resolved_path,
53 int vdso,
54 void *owner)
95c25348 55{
37dddb65 56 struct cds_list_head *sessionsp;
5aed31fc
MD
57 struct lttng_session *session;
58 struct stat sostat;
59
60 if (vdso || stat(resolved_path, &sostat)) {
61 sostat.st_size = 0;
62 sostat.st_mtime = -1;
63 }
64 /*
65 * UST lock nests within dynamic loader lock.
66 */
67 if (ust_lock()) {
68 /*
69 * Stop iteration on headers if need to exit.
70 */
71 ust_unlock();
72 return 1;
73 }
74
75 sessionsp = _lttng_get_sessions();
76 cds_list_for_each_entry(session, sessionsp, node) {
77 if (session->owner != owner)
78 continue;
79 if (!session->statedump_pending)
80 continue;
81 tracepoint(ust_baddr_statedump, soinfo,
82 session, base_addr_ptr,
83 resolved_path, sostat.st_size,
84 sostat.st_mtime);
85 }
86 ust_unlock();
87 return 0;
88}
89
90static
91int extract_soinfo_events(struct dl_phdr_info *info, size_t size, void *_data)
92{
93 int j;
94 struct extract_data *data = _data;
95 void *owner = data->owner;
37dddb65 96
95c25348
PW
97 for (j = 0; j < info->dlpi_phnum; j++) {
98 char resolved_path[PATH_MAX];
95c25348 99 void *base_addr_ptr;
5aed31fc 100 int vdso = 0;
95c25348
PW
101
102 if (info->dlpi_phdr[j].p_type != PT_LOAD)
103 continue;
104
105 /* Calculate virtual memory address of the loadable segment */
106 base_addr_ptr = (void *) info->dlpi_addr
107 + info->dlpi_phdr[j].p_vaddr;
108
95c25348 109 if ((info->dlpi_name == NULL || info->dlpi_name[0] == 0)
5aed31fc
MD
110 && !data->exec_baddr) {
111 /*
112 * Only the first phdr encountered is considered
113 * as the program executable. The following
114 * could be e.g. vdso. Don't mistakenly dump
115 * them as being the program executable.
116 */
117 data->exec_baddr = base_addr_ptr;
95c25348 118 /*
5aed31fc
MD
119 * Deal with program executable outside of phdr
120 * iteration.
95c25348 121 */
5aed31fc
MD
122 break;
123 }
124 if (info->dlpi_name == NULL || info->dlpi_name[0] == 0) {
125 /* Found vDSO. */
126 snprintf(resolved_path, PATH_MAX - 1, "[vdso]");
127 vdso = 1;
95c25348
PW
128 } else {
129 /*
130 * For regular dl_phdr_info entries we have to check if
5aed31fc 131 * the path to the shared object really exists.
95c25348
PW
132 */
133 if (!realpath(info->dlpi_name, resolved_path)) {
5aed31fc 134 /* Path unknown, put the 'path' into brackets */
95c25348 135 snprintf(resolved_path, PATH_MAX - 1, "[%s]",
5aed31fc
MD
136 info->dlpi_name);
137 vdso = 1;
95c25348
PW
138 }
139 }
5aed31fc 140 if (trace_baddr(base_addr_ptr, resolved_path, vdso, owner)) {
3327ac33
MD
141 return 1;
142 }
95c25348
PW
143 /*
144 * We are only interested in the base address (lowest virtual
145 * address associated with the memory image), skip the rest
146 */
147 break;
148 }
149 return 0;
150}
151
5aed31fc
MD
152static
153void dump_exec_baddr(struct extract_data *data)
154{
155 void *owner = data->owner;
156 Dl_info dl_info = { 0 };
157 void *base_addr_ptr;
158 char resolved_path[PATH_MAX];
159
160 base_addr_ptr = data->exec_baddr;
161 if (!base_addr_ptr)
162 return;
163 /*
164 * We have to use Dl_info to determine the executable full path.
165 */
166 if (!dladdr(base_addr_ptr, &dl_info))
167 return;
168 if (!realpath(dl_info.dli_fname, resolved_path))
169 return;
170 trace_baddr(base_addr_ptr, resolved_path, 0, owner);
171}
172
37dddb65 173int lttng_ust_baddr_statedump(void *owner)
95c25348 174{
5aed31fc
MD
175 struct extract_data data;
176
ca7643d6
PW
177 if (getenv("LTTNG_UST_WITHOUT_BADDR_STATEDUMP"))
178 return 0;
5aed31fc
MD
179
180 data.owner = owner;
181 data.exec_baddr = NULL;
95c25348
PW
182 /*
183 * Iterate through the list of currently loaded shared objects and
37dddb65
MD
184 * generate events for loadable segments using
185 * extract_soinfo_events.
95c25348 186 */
5aed31fc
MD
187 dl_iterate_phdr(extract_soinfo_events, &data);
188 /*
189 * We cannot call dladdr() from within phdr iteration, without
190 * causing constructor vs dynamic loader vs multithread internal
191 * deadlocks, so dump the executable outside of the phdr
192 * iteration.
193 */
194 dump_exec_baddr(&data);
95c25348
PW
195 return 0;
196}
bd703713
PW
197
198void lttng_ust_baddr_statedump_init(void)
199{
200 __tracepoints__init();
201 __tracepoints__ptrs_init();
202}
203
204void lttng_ust_baddr_statedump_destroy(void)
205{
206 __tracepoints__ptrs_destroy();
207 __tracepoints__destroy();
208}
This page took 0.032578 seconds and 4 git commands to generate.