Add library load/unload tracking events
[lttng-ust.git] / liblttng-ust-dl / lttng-ust-dl.c
CommitLineData
b13d93c2
PW
1/*
2 * Copyright (C) 2013 Paul Woegerer <paul.woegerer@mentor.com>
8e2aed3f 3 * Copyright (C) 2015 Antoine Busque <abusque@efficios.com>
97c7c238 4 * Copyright (C) 2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
b13d93c2
PW
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; version 2.1 of
9 * the License.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#define _GNU_SOURCE
1ddceb36 22#define _LGPL_SOURCE
13436238 23#include <limits.h>
8e2aed3f 24#include <stdio.h>
13436238 25#include <sys/types.h>
8e2aed3f
AB
26#include <unistd.h>
27
28#include <lttng/ust-dlfcn.h>
29#include <lttng/ust-elf.h>
97c7c238 30#include <lttng/ust-events.h>
171fcc6f 31#include <helper.h>
eb2b066f 32#include "usterr-signal-safe.h"
b13d93c2 33
8e2aed3f
AB
34/* Include link.h last else it conflicts with ust-dlfcn. */
35#include <link.h>
b13d93c2 36
13436238 37#define TRACEPOINT_DEFINE
6d4658aa 38#include "ust_dl.h"
13436238 39
b13d93c2
PW
40static void *(*__lttng_ust_plibc_dlopen)(const char *filename, int flag);
41static int (*__lttng_ust_plibc_dlclose)(void *handle);
b13d93c2
PW
42
43static
44void *_lttng_ust_dl_libc_dlopen(const char *filename, int flag)
45{
46 if (!__lttng_ust_plibc_dlopen) {
47 __lttng_ust_plibc_dlopen = dlsym(RTLD_NEXT, "dlopen");
8e2aed3f 48 if (!__lttng_ust_plibc_dlopen) {
b13d93c2
PW
49 fprintf(stderr, "%s\n", dlerror());
50 return NULL;
51 }
52 }
53 return __lttng_ust_plibc_dlopen(filename, flag);
54}
55
56static
57int _lttng_ust_dl_libc_dlclose(void *handle)
58{
59 if (!__lttng_ust_plibc_dlclose) {
60 __lttng_ust_plibc_dlclose = dlsym(RTLD_NEXT, "dlclose");
8e2aed3f 61 if (!__lttng_ust_plibc_dlclose) {
b13d93c2
PW
62 fprintf(stderr, "%s\n", dlerror());
63 return -1;
64 }
65 }
66 return __lttng_ust_plibc_dlclose(handle);
67}
68
69static
03db42de 70void lttng_ust_dl_dlopen(void *so_base, const char *so_name, void *ip)
b13d93c2 71{
13436238 72 char resolved_path[PATH_MAX];
8e2aed3f
AB
73 struct lttng_ust_elf *elf;
74 uint64_t memsz;
83215d66 75 uint8_t *build_id = NULL;
8e2aed3f 76 size_t build_id_len;
83215d66 77 char *dbg_file = NULL;
8e2aed3f
AB
78 uint32_t crc;
79 int has_build_id = 0, has_debug_link = 0;
80 int ret;
b13d93c2 81
13436238
PW
82 if (!realpath(so_name, resolved_path)) {
83 ERR("could not resolve path '%s'", so_name);
84 return;
b13d93c2 85 }
b13d93c2 86
8e2aed3f
AB
87 elf = lttng_ust_elf_create(resolved_path);
88 if (!elf) {
89 ERR("could not acces file %s", resolved_path);
13436238 90 return;
b13d93c2 91 }
13436238 92
8e2aed3f
AB
93 ret = lttng_ust_elf_get_memsz(elf, &memsz);
94 if (ret) {
95 goto end;
96 }
97 ret = lttng_ust_elf_get_build_id(
98 elf, &build_id, &build_id_len, &has_build_id);
99 if (ret) {
100 goto end;
101 }
102 ret = lttng_ust_elf_get_debug_link(
103 elf, &dbg_file, &crc, &has_debug_link);
104 if (ret) {
105 goto end;
106 }
107
6d4658aa 108 tracepoint(lttng_ust_dl, dlopen,
c5c4fd82
MD
109 ip, so_base, resolved_path, memsz,
110 has_build_id, has_debug_link);
8e2aed3f
AB
111
112 if (has_build_id) {
113 tracepoint(lttng_ust_dl, build_id,
114 ip, so_base, build_id, build_id_len);
8e2aed3f
AB
115 }
116
117 if (has_debug_link) {
118 tracepoint(lttng_ust_dl, debug_link,
119 ip, so_base, dbg_file, crc);
8e2aed3f
AB
120 }
121
122end:
83215d66
MD
123 free(dbg_file);
124 free(build_id);
8e2aed3f 125 lttng_ust_elf_destroy(elf);
13436238 126 return;
b13d93c2
PW
127}
128
129void *dlopen(const char *filename, int flag)
130{
8e2aed3f
AB
131 void *handle;
132
133 handle = _lttng_ust_dl_libc_dlopen(filename, flag);
bd703713 134 if (__tracepoint_ptrs_registered && handle) {
b13d93c2 135 struct link_map *p = NULL;
8e2aed3f
AB
136 int ret;
137
138 ret = dlinfo(handle, RTLD_DI_LINKMAP, &p);
139 if (ret != -1 && p != NULL && p->l_addr != 0) {
97c7c238
MD
140 lttng_ust_dl_dlopen((void *) p->l_addr,
141 p->l_name,
171fcc6f 142 LTTNG_UST_CALLER_IP());
8e2aed3f 143 }
b13d93c2 144 }
97c7c238 145 lttng_ust_dl_update(LTTNG_UST_CALLER_IP());
b13d93c2
PW
146 return handle;
147}
148
149int dlclose(void *handle)
150{
97c7c238
MD
151 int ret;
152
e7953e6e 153 if (__tracepoint_ptrs_registered) {
b13d93c2 154 struct link_map *p = NULL;
8e2aed3f
AB
155
156 ret = dlinfo(handle, RTLD_DI_LINKMAP, &p);
157 if (ret != -1 && p != NULL && p->l_addr != 0) {
158 tracepoint(lttng_ust_dl, dlclose,
171fcc6f 159 LTTNG_UST_CALLER_IP(),
8e2aed3f
AB
160 (void *) p->l_addr);
161 }
b13d93c2 162 }
97c7c238
MD
163 ret = _lttng_ust_dl_libc_dlclose(handle);
164 lttng_ust_dl_update(LTTNG_UST_CALLER_IP());
165 return ret;
b13d93c2 166}
This page took 0.038488 seconds and 4 git commands to generate.